HTML

[벽돌깨기]html 캔버스로 게임 만들기 - 4(패들과 키보드 조작)

애드망3 2020. 10. 16. 08:30
function drawPaddle() {
    ctx.beginPath();
    ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
}

공의 움직임의 구현이 끝났습니다

이제는 패들(Paddle)을 통해서 공의 움직임을 바꿀 수 있게

패들을 만들고 만든 패들을 키보드 조작을 통해서 움직일 수 있게 하도록 하겠습니다

 

패들(Paddle) 만들기

패들은 공의 움직임을 바꿔주는 용도로 크기가 정해져 있습니다

막대기 모양으로 일정한 너비와 높이를 가지고 있습니다

var paddleHeight = 10;
var paddleWidth = 75;
var paddleX = (canvas.width-paddleWidth)/2;

paddleWidth(너비)가 75px , paddleHeight(높이)가 10px이고

패들의 시작 위치는 canvas에서 패들의 너비를 빼고 난 후 나누기 2를 한 위치입니다

너비를 빼는 이유는 X축의 가운데 지점에 패들을 오게 하기 위해서입니다

너비를 빼지 않으면 패들의 끝부분이 가운데에 위치합니다

왼쪽은 너비를 빼지 않은 경우 오른쪽은 뺀 경우 입니다

function drawPaddle() {
    ctx.beginPath();
    ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
}

drawPaddle() 함수를 위와 같이 만들고 drawBall() 함수 밑에 추가했습니다

패들(Paddle) 조작

패들을 키보드 조작에 맞춰서 움직일 수 있게 하는 방법입니다

키보드 조작을 하면 왼쪽 혹은 오른쪽으로 움직이게 하기 위해서 버튼을 누르는 것을

변수 blooean 타입으로 정의합니다 각각 왼쪽과 오른쪽을 나타내는 변수입니다

var rightPressed = false;
var leftPressed = false;

버튼을 누르는 keydown 이벤트와 버튼을 누른 후 버튼이 올라올 때 발생하는 keyup이벤트를 만들어줍니다

위치는 rightPresssed, leftPressed 변수 밑에 만들어 줍니다

document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);

위와 같이 코드를 만들어줍니다

keyDownHandler(), keyUpHandler() 함수는 지금 없기 때문에 아래와 같이 만들어줍니다

위치는 addEventListener 밑에 만들어 줍니다

function keyDownHandler(e) {
    if(e.keyCode == 39) {
        rightPressed = true;
    }
    else if(e.keyCode == 37) {
        leftPressed = true;
    }
}

function keyUpHandler(e) {
    if(e.keyCode == 39) {
        rightPressed = false;
    }
    else if(e.keyCode == 37) {
        leftPressed = false;
    }
}

keyDownHandler, keyUpHandler는 키를 누르면 변수에 담긴 값이 true가 되고 키를 때면 false가 됩니다

e는 event를 나타내고 e.keyCode는 각각 좌측 방향키(37), 우측 방향키(39) 버튼의 값입니다

draw() 함수 안에 공 움직이기 때와 마찬가지로 방향키를 눌렀을 때 움직이는 조건문을 넣어줍니다

if(rightPressed) {
    paddleX += 7;
}
else if(leftPressed) {
    paddleX -= 7;
}

오른쪽 방향키를 누르면 X축 좌표 기준 7px만큼 움직이고 반대로

왼쪽 방향키를 누르면 X축 좌표 기준 -7px만큼 움직이게 됩니다

하지만 이대로 사용하면 패들이 캔버스 밖으로 벗어나기 때문에

충돌처리처럼 패들이 캔버스 크기 내에서만 이동 가능하게 약간의 수정을 해야 합니다

if(rightPressed && paddleX < canvas.width-paddleWidth) {
    paddleX += 7;
}
else if(leftPressed && paddleX > 0) {
    paddleX -= 7;
}

 

&&은 and 조건으로 rightPressed가 true이면서

paddleX의 값이 캔버스 너비에서 패들 너비를 뺀 값 보다 작아야 paddleX += 7; 구문이 실행됩니다

캔버스 너비에서 패들 너비를 빼는 이유는 패들의 끝이 캔버스의 끝이 닿을 때 멈춰야 하기 때문입니다

else if의 조건도 leftPressed가 ture이면서 paddleX의 값은 0보다 커야 paddleX -= 7; 부분이 실행됩니다

 

draw 함수안 패들 조건문 위치입니다

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawBall();
    drawPaddle();
    
    if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
        dx = -dx;
    }
    if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
        dy = -dy;
    }
    
    if(rightPressed && paddleX < canvas.width-paddleWidth) {
        paddleX += 7;
    }
    else if(leftPressed && paddleX > 0) {
        paddleX -= 7;
    }
    
    x += dx;
    y += dy;
}

요약

코드 전체

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>벽돌깨기</title>
    <style>
    	* { padding: 0; margin: 0; }
    	canvas { background: #eee; display: block; margin: 0 auto; }
    </style>
</head>
<body>

<canvas id="myCanvas" width="480" height="320"></canvas>

<script>
	var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    var x = canvas.width/2;
    var y = canvas.height-30;
    var dx = 2;
    var dy = -2;
    var ballRadius = 10;
    var paddleHeight = 10;
    var paddleWidth = 75;
    var paddleX = (canvas.width-paddleWidth)/2;
    var rightPressed = false;
    var leftPressed = false;
    
    document.addEventListener('keydown', keyDownHandler, false);
    document.addEventListener('keyup', keyUpHandler, false);

    function keyDownHandler(e) {
        if(e.keyCode == 39) {
            rightPressed = true;
        }
        else if(e.keyCode == 37) {
            leftPressed = true;
        }
    }

    function keyUpHandler(e) {
        if(e.keyCode == 39) {
            rightPressed = false;
        }
        else if(e.keyCode == 37) {
            leftPressed = false;
        }
    }

    function drawBall() {
        ctx.beginPath();
        ctx.arc(x, y, ballRadius, 0, Math.PI*2);
        ctx.fillStyle = '#0095DD';
        ctx.fill();
        ctx.closePath();
    }

    function drawPaddle() {
        ctx.beginPath();
        ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
        ctx.fillStyle = '#0095DD';
        ctx.fill();
        ctx.closePath();
    }

    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawBall();
        drawPaddle();
        if(x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
            dx = -dx;
        }

        if(y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
            dy = -dy;
        }

        if(rightPressed && paddleX < canvas.width-paddleWidth) {
            paddleX += 7;
        }
        else if(leftPressed && paddleX > 0) {
            paddleX -= 7;
        }

        x += dx;
        y += dy;
    }

    setInterval(draw, 10);

</script>

</body>
</html>