블록 핑퐁 게임
// 게임 상태
let isRunning = false;
let isPaused = false;
let score = 0;
// 바(패들) 설정
const paddle = {
width: 100,
height: 15,
x: canvas.width / 2 - 50,
y: canvas.height - 30,
speed: 7,
dx: 0
};
// 공 설정
const ball = {
x: canvas.width / 2,
y: canvas.height - 45,
radius: 10,
speed: 5,
dx: 4,
dy: -4
};
// 블록 설정
const blockRowCount = 5;
const blockColCount = 8;
const blockWidth = 80;
const blockHeight = 25;
const blockPadding = 10;
const blockOffsetTop = 40;
const blockOffsetLeft = 35;
let blocks = [];
function createBlocks() {
blocks = [];
for (let r = 0; r < blockRowCount; r++) {
for (let c = 0; c < blockColCount; c++) {
blocks.push({
x: blockOffsetLeft + c * (blockWidth + blockPadding),
y: blockOffsetTop + r * (blockHeight + blockPadding),
status: 1
});
}
}
}
// 그리기 함수들
function drawPaddle() {
ctx.fillStyle = '#0095DD';
ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
}
function drawBall() {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = '#FF5733';
ctx.fill();
ctx.closePath();
}
function drawBlocks() {
blocks.forEach(block => {
if (block.status === 1) {
ctx.fillStyle = '#4CAF50';
ctx.fillRect(block.x, block.y, blockWidth, blockHeight);
}
});
}
function drawScore() {
document.getElementById('scoreValue').textContent = score;
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// 메인 게임 루프
function draw() {
clear();
drawPaddle();
drawBall();
drawBlocks();
drawScore();
}
function update() {
if (!isRunning || isPaused) return;
// 바 이동
paddle.x += paddle.dx;
if (paddle.x < 0) paddle.x = 0;
if (paddle.x + paddle.width > canvas.width) paddle.x = canvas.width - paddle.width;
// 공 이동
ball.x += ball.dx;
ball.y += ball.dy;
// 벽 충돌
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
ball.dx *= -1;
}
if (ball.y - ball.radius < 0) {
ball.dy *= -1;
}
// 바와 충돌
if (
ball.y + ball.radius > paddle.y &&
ball.x > paddle.x &&
ball.x < paddle.x + paddle.width
) {
ball.dy *= -1;
// 각도 조정(간단하게)
let hitPoint = (ball.x - (paddle.x + paddle.width / 2)) / (paddle.width / 2);
ball.dx = ball.speed * hitPoint;
}
// 바닥에 떨어짐
if (ball.y + ball.radius > canvas.height) {
isRunning = false;
alert('게임 오버! 점수: ' + score);
resetGame();
return;
}
// 블록 충돌
blocks.forEach(block => {
if (
block.status === 1 &&
ball.x > block.x &&
ball.x < block.x + blockWidth &&
ball.y - ball.radius < block.y + blockHeight &&
ball.y + ball.radius > block.y
) {
ball.dy *= -1;
block.status = 0;
score += 10;
}
});
draw();
requestAnimationFrame(update);
}
// 키보드 이벤트
function keyDownHandler(e) {
if (e.key === 'ArrowRight') {
paddle.dx = paddle.speed;
} else if (e.key === 'ArrowLeft') {
paddle.dx = -paddle.speed;
}
}
function keyUpHandler(e) {
if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
paddle.dx = 0;
}
}
document.addEventListener('keydown', keyDownHandler);
document.addEventListener('keyup', keyUpHandler);
// 버튼 이벤트
const startButton = document.getElementById('startButton');
const pauseButton = document.getElementById('pauseButton');
const restartButton = document.getElementById('restartButton');
startButton.onclick = function() {
if (!isRunning) {
isRunning = true;
isPaused = false;
update();
}
};
pauseButton.onclick = function() {
isPaused = !isPaused;
if (!isPaused) update();
};
restartButton.onclick = function() {
resetGame();
};
function resetGame() {
score = 0;
paddle.x = canvas.width / 2 - paddle.width / 2;
ball.x = canvas.width / 2;
ball.y = canvas.height - 45;
ball.dx = 4;
ball.dy = -4;
isRunning = false;
isPaused = false;
createBlocks();
draw();
}
// 마우스 이동으로 바 조작
canvas.addEventListener('mousemove', function(e) {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
paddle.x = mouseX - paddle.width / 2;
if (paddle.x < 0) paddle.x = 0;
if (paddle.x + paddle.width > canvas.width) paddle.x = canvas.width - paddle.width;
});
// 초기화
createBlocks();
draw();
});