HTML

[벽돌깨기]html 캔버스로 게임 만들기 - 6(벽돌 만들기)

애드망3 2020. 10. 23. 08:30

벽돌깨기란 이름이 무색하게 벽돌이 등장하지 않았습니다

2차원 배열을 통해서 여러 개의 벽돌을 구현할 예정입니다

 

벽돌 만들기

var brickRowCount = 3;
var brickColumnCount = 5;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;

각각 벽돌 배열 행의 수, 열의 수, 벽돌의 가로길이, 세로 길이, 벽돌이 서로 닿지 않게 하기 위한 패딩

캔버스의 끝 벽에 닿지 않기 위한 오프셋(간격 기능)입니다

 

벽돌을 for문을 통해서 생성합니다

행과 열에 지정한 수만큼 벽돌이 서로 닿지 않게 일정한 간격을 두고 생성됩니다

var bricks = [];
for(var c=0; c<brickColumnCount; c++) {
    bricks[c] = [];
    for(var r=0; r<brickRowCount; r++) {
        bricks[c][r] = { x: 0, y: 0 };
    }
}

bricks[c]는 brickColumnCount 수만큼 열을 먼저 만듭니다

bricks[c][r] = { x: 0, y: 0 };을 통해서 이중 배열을 만들고 그 안에 x, y 좌표가 0인 배열을 생성합니다

만든 벽돌 그리기

벽돌을 만들고 만든 벽돌을 캔버스 안에 배치를 해야 합니다

방법은 만든 벽돌 배열을 호출하고 호출한 각각의 벽돌마다 겹치지 않는 좌표값을 주면 됩니다

우선 벽돌 그리는 방법입니다

function drawBricks() {
    for(var c=0; c<brickColumnCount; c++) {
        for(var r=0; r<brickRowCount; r++) {
            bricks[c][r].x = 0;
            bricks[c][r].y = 0;
            ctx.beginPath();
            ctx.rect(0, 0, brickWidth, brickHeight);
            ctx.fillStyle = '#0095DD';
            ctx.fill();
            ctx.closePath();
        }
    }
}

 

다시 for문을 통해서 배열을 호출하고 좌표를 재설정하고 벽돌을 그립니다

ctx.rect(0, 0, brickWidth, brickHeight); 지정된 너비와 높이를 가진 벽돌들이 같은 위치에 생겨납니다

다른 위치에 블록 만들기 위해서 brickX, brickY 변수를 통해서 벽돌의 위치를 변경해줍니다

var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;

위와 같이 새로운 변수를 만듭니다

function drawBricks() {
    for(var c=0; c<brickColumnCount; c++) {
        for(var r=0; r<brickRowCount; r++) {
            var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
            var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
            bricks[c][r].x = brickX;
            bricks[c][r].y = brickY;
            ctx.beginPath();
            ctx.rect(brickX, brickY, brickWidth, brickHeight);
            ctx.fillStyle = '#0095DD';
            ctx.fill();
            ctx.closePath();
        }
    }
}

drawBricks() 함수 안에 brickX, brickY 변수를 넣고 벽돌을 그리던 rect 함수의 x, y 좌표의 0 대신

brickX, brickY 변수를 넣어서 벽돌의 위치가 변하게 합니다

 

for문을 돌면서 c, r의 값이 변하기 때문에 벽돌들은 겹치지 않고 일정한 간격으로 생성됩니다

요약

코드 전체

<!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;
    var brickRowCount = 3;
    var brickColumnCount = 5;
    var brickWidth = 75;
    var brickHeight = 20;
    var brickPadding = 10;
    var brickOffsetTop = 30;
    var brickOffsetLeft = 30;
    
    var bricks = [];
    for(var c=0; c<brickColumnCount; c++) {
        bricks[c] = [];
        for(var r=0; r<brickRowCount; r++) {
            bricks[c][r] = { x: 0, y: 0 };
        }
    }
    
    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 drawBricks() {
        for(var c=0; c<brickColumnCount; c++) {
            for(var r=0; r<brickRowCount; r++) {
                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
                bricks[c][r].x = brickX;
                bricks[c][r].y = brickY;
                ctx.beginPath();
                ctx.rect(brickX, brickY, brickWidth, brickHeight);
                ctx.fillStyle = '#0095DD';
                ctx.fill();
                ctx.closePath();
            }
        }
    }

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

        if(y + dy < ballRadius) {
            dy = -dy;
        } else if(y + dy > canvas.height-ballRadius) {
            if(x > paddleX && x < paddleX + paddleWidth) {
                dy = -dy;
            } else {
                clearInterval(game);
                alert('GAME OVER');
                document.location.reload();
            }
        }

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

        x += dx;
        y += dy;
    }

    var game = setInterval(draw, 10);

</script>

</body>
</html>