Javascript로 미니게임 만들기3

서기영·2022년 4월 25일

충돌함수 구현

function isCollisionRectToRect(rectA, rectB) {
    // a의 왼쪽과 b의 오른쪽
    // a의 오른쪽과 b의 왼쪽
    // a의 아래쪽과 b의 위쪽
    // a의 위쪽과 b의 아래쪽
    if (rectA.left > rectB.right ||
        rectA.right < rectB.left ||
        rectA.top > rectB.bottom ||
        rectA.bottom < rectB.top) {
            return false;
        }
    return true;
}

사각형A, 사각형B를 비교하여 두 사각형이 겹치는 부분이 있을 때 true를 반환하도록 설계했다.

우선 객체의 property(left, right, top, bottom)을 비교해야 하기 때문에
우리가 이미 생성한 공과 막대에 대한 object를 만들어보자.

let ball = {
	left: arcPosX - arcRadius,
	right: arcPosX + arcRadius,
    top: arcPosY - arcRadius,
    bottom: arcPosY + arcRadius
}

let paddle = {
	left: barPosX,
    right: barPosX + barWidth,
    top: barPosY,
    bottom: barPosY + barHeight

다음으로 막대의 움직임을 구현할 차례이다.

바는 canvas내에서 좌우로만 움직일 수 있고 공과 충돌시 공을 튕겨내야한다.

document.addEventListener('keydown', keyDownEventHandler);

function keyDownEventHandler(e) {
    if (e.key == "ArrowRight" && barPosX + barWidth < canvas.width) {
        barPosX += moveBarRate;
        
    }
    else if (e.key == "ArrowLeft" && barPosX > 0) {
        barPosX -= moveBarRate;
    }
    paddle.left = barPosX;
    paddle.right = barPosX + barWidth;
}

이제 update()에서 위 함수를 호출해보자.

function update() {
    if (arcPosX - arcRadius < 0) {	// 오른쪽 벽에 닿을 때
        arcMoveDirX = 1;
    }
    else if (arcPosX + arcRadius > canvas.width) {	// 왼쪽 벽에 닿을 때
        arcMoveDirX = -1;
    }        
    if (arcPosY - arcRadius < 0 ) {	// 위쪽 벽에 닿을 때
        arcMoveDirY = 1;
    }        
    else if (arcPosY + arcRadius > canvas.height) {	// 아래쪽 벽에 닿을 때
        arcMoveDirY = -1;
    }
    
    arcPosX += arcMoveDirX * arcMoveRateX;
    arcPosY += arcMoveDirY * arcMoveRateY;
    
    // 볼 위치 이동
   [ball.left, ball.right, ball.bottom, ball.top] = [arcPosX - arcRadius, arcPosX + arcRadius, arcPosY + arcRadius, arcPosY - arcRadius]; 

    
    if (isCollisionRectToRect(ball, paddle)) {	// 충돌 시 Y축으로의 진행방향을 바꾼다. 
        arcMoveDirY = -1;
    }
    
}

update함수가 호출되면서 ball이 이동할때, ball의 위치를 이동시켜주어야지만 충돌함수가 제대로 작동할 수 있다.

마지막으로, 벽돌을 생성하는 코드는 다음과 같다.

let brickColumn = 4;
let brickRow = 5;
let brickWidth = 50;
let brickHeight = 20;

let bricks = [];
// brick의 클래스화로 동일한 속성으로 인해 반복되는 코드의 양을 줄인다. 
class Brick {
    constructor(left, top, right, bottom) {
        this.left = left; 
        this.top = top; 
        this.right = right;
        this.bottom = bottom;
        this.hitCount = 2;
        this.color = 'yellow'; 
    }
    draw() {
        context.rect(this.left, this.top, brickWidth, brickHeight);
        context.fillStyle = this.color;
        context.fill();
    }
}

function setBricks() {
    for (let i = 0; i < brickColumn; i++) {
        for(let j = 0; j < brickRow; j++) {
            let brick = new Brick(50 + j * (brickWidth + 10), 20 + i * (brickHeight + 10), 50 + j * (brickWidth + 10) + brickWidth, 20 + i * (brickHeight + 10) + brickHeight);
            bricks.push(brick);
        }
    }
}

function drawBricks() {
    for (let ele of bricks) {
        context.beginPath();
        if (ele.hitCount > 0) ele.draw();
        context.closePath();
    }
}

setBricks();

function draw(){
    context.clearRect(0, 0, canvas.width, canvas.height);

    drawBar();
    drawArc();
    // (추가)
    drawBricks();
}

다음에는 공이 벽돌에 충돌하는 이벤트와 몇가지 장애물을 추가해보겠다.

profile
진정한 배움은 가르침과 기록을 오가며 실현된다.

0개의 댓글