javascript game (3)

잡담

이번에는 지난 시간에 만들었던 공이 움직이는 기능에다가 공이 벽에 닿았을 경우 Bounce! Bounce! 할 수 있도록 수정해 보겠다.

지난 포스팅이 궁금하면 다음 아래 링크를 참고하기 바란다.

  1. 캔버스 생성과 그리기
  2. 공 움직이기

벽에 공 튀기기

어떻게 튕기게 할 수 있을까? 세게 던지면 튕겨 나온다 우리는 좌표에 관심을 가져야 한다.

간단한 충돌 감지

일단 공이 벽에 부딪혔다고 가정하자. 그럼 어떠한 일이 일어나야 할까? 공의 방향이 바뀌면 된다. 간단하네

앞에서 우리는 ctx.arc()를 통해 공을 그릴 때 공의 반지름을 10으로 하드코딩 했었는데 이를 변수로 바꾸도록 하자. 왜냐고? 안그러면 벽에 부딪힐 때 공이 벽 안으로 들어가게 보이는걸 방지하기 위해서 이다.

1
2
3
4
var ballRadius = 10;
...
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
...

공 튕겨내기

천장과 바닥에 닿았을 때 방향을 바꿔서 공이 진행하도록 만들면 튕겨내는 기분이 들 것 같다. 기분 탓인가? 그럼 어떻게 구현을 해야 할까?

먼저 천장을 생각해 보자. 말이 천장이지, 2D 화면에서 천장은 Y축을 가리킨다. canvas에서 Y축의 좌표가 0이면 천장을 가리키는 셈이다. 그럼 답이 나왔다. 공의 좌표인 y가 0 보다 작으면 천장에 부딪힌 것으로 판단할 수 있겠다. 바로 이렇게.

1
2
3
if (y < 0) {
dy = -dy;
}

y 값이 0보다 작아지면 천장에 부딪힌 것이고, dy의 부호를 바꿔서 Y축으로의 이동 방향을 바꾸면 튕겨 나오는 효과를 볼 수 있다.

MDN의 예제에서는 아래와 같이 나와 있는데, 사실 같은 의미이다.

y + dy < 0 이 되려면, dy의 부호가 음수일 것이고, 공의 방향은 위로 향하고 있다는 의미가 될 것이다. 0보다 작아졌다면 천장에 부딪힌 시점이고, dy 의 부호를 바꿔 반대 방향으로 이동하게 만드는 것이다. 완전히 똑같다.

1
2
3
if(y + dy < 0) {
dy = -dy;
}

그럼 바닥에 부딪혔을 때는 어떻게 처리하면 될까? 천장과 마찬가지로 바닥의 Y좌표에 부딪혔을 경우 dy의 부호를 변경해 주면 된다. 바닥의 Y 좌표는?? 그렇다. canvas.height 가 바로 바닥의 Y좌표이다.

이렇게 해주거나

1
2
3
if (y > canvas.height) {
dy = -dy;
}

이렇게 해주면 된다.

1
2
3
if (y + dy > canvas.height) {
dy = -dy;
}

이제 위의 소스코드를 하나로 합쳐보자.

1
2
3
if (y + dy > canvas.height || y + dy < 0) {
dy = -dy;
}

참 쉽다.

자, 그럼 이제 왼쪽 오른쪽에 부딪혔을 경우에는 어떻게 구현하면 될까? 천장, 바닥과 똑같다. 바로 X축의 좌표를 이용해서 하면 된다.

두 번 설명하면 지루하니깐 바로 소스코드를 보자.

1
2
3
if (x + dx > canvas.width || x + dx < 0 ) {
dx = -dx;
}

참 쉽죠?

이제 위에서 만든 if 문 2개를 draw() 함수 안으로 옮겨보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();

if(x + dx > canvas.width || x + dx < 0) {
dx = -dx;
}
if(y + dy > canvas.height || y + dy < 0) {
dy = -dy;
}

x += dx;
y += dy;
}

그럼, 이제 아래와 같이 통통 튕기는 공을 볼 수 있을 것이다.






자 어떤가! 공이 신나게 통통 튕기지 않는가! 그런데 자세히 보면 공이 벽에 파묻혔다가 튕겨 나오는 기분이다. 절대 기분탓이 아니다. 여기에서 이제 위에서 언급했던 ballRadius 가 등장할 시점이다.

천장, 바닥, 왼쪽, 오른쪽에 부딪힐 때 ballRadius 만큼의 차이를 두면 좀 더 자연스럽게 튕기는 모습을 볼 수 있다. if 문에 다음과 같이 수정을 해보자.

1
2
3
4
5
6
if(x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
dy = -dy;
}

다시 실행을 시켜보면 아래와 같이 좀 더 자연스럽게, 공이 벽에 닿자 마자 튕기는 모습을 볼 수 있다.






나머지는 다음 시간에…





_이 포스트는 MDN 2D Breakout game 의 튜토리얼을 참고한 내용 입니다._