충돌함수 구현
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();
}
다음에는 공이 벽돌에 충돌하는 이벤트와 몇가지 장애물을 추가해보겠다.