크롬 공룡 게임 만들기(2/4): 공룡과 장애물 만들기
이제 본격적으로 main.js를 작성해 보자.
공룡 게임에 사용되는 유닛에는 크게 공룡과 장애물이 있다. 이런 등장 요소의 속성을 객체로 정리해 두면 편리하다.
객체란 관련된 데이터와 함수(객체 안에 있을 때는 보통 프로퍼티와 메소드라고 부른다)의 집합이라고 보면 된다.
생각해 보면 게임에서 공룡은 한 마리만 있으면 되지만, 장애물은 여러 개가 있어야 할 뿐만 아니라 각각의 속성이 다를 수 있다. 쿠키런에서 1단 점프를 해야 하는 장애물과 2단 점프를 해야 하는 장애물이 있는 것 처럼.. 이렇게 비슷한 여러 객체를 만들어야 할 때 사용하는 것이 클래스다. 클래스를 쿠키 틀이라고 한다면 객체는 그 쿠키 틀로 찍어낸 쿠키 반죽이라고 할 수 있겠다. 쿠키 틀을 하나만 구비해 놓으면 쿠키를 하나하나 빚을 필요 없이 틀로 찍어내기만 하면 된다. 이게 클래스와 객체의 관계다.
var dino = {
x: 10,
y: 200, //공룡 등장 좌표
width: 50,
height: 50, //공룡 크기
draw() {
ctx.fillStyle = "green";
ctx.fillRect(this.x, this.y, this.width, this.height);
},
};
class Cactus {
constructor() {
this.x = 500;
this.y = 200;
this.width = 50;
this.height = 50;
}
draw() {
ctx.fillStyle = "red";
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
보다시피 dino라는 객체와 Cactus라는 클래스를 만들었다. 공룡은 초록색, 장애물은 빨간색 정사각형이다.
draw 메소드에 있는 fillStyle과 fillRect는 CanvasRenderingContext2D의 API다. API는 외울 필요는 없지만 어떤게 존재하는지는 알아야 하기 때문에 눈에 보이는 대로 기억해 놔야겠다.
공룡과 장애물을 만들었으니 이제 게임 진행에 맞게 애니메이션을 만들어 볼 차례다.
요소가 움직이는 효과를 내려면 해당 요소의 위치를 조금씩 변경하는 과정을 반복해야 한다. 게임 세상에서는 시간이 아니라 프레임 단위로 이벤트들이 발생하기 때문에, 프레임마다 실행할 함수를 작성해 보았다. 지금 사용한건 requestAnimationFrame라는 브라우저에서 기본적으로 제공하는 함수지만, 본격적인 게임 개발을 위해서는 따로 라이브러리를 사용하는게 낫다.
var timer = 0;
var cactuses = [];
function executePerFrame() {
requestAnimationFrame(executePerFrame);
timer++;
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (timer % 120 === 0) {
var cactus = new Cactus();
cactuses.push(cactus);
}
cactuses.forEach((a) => {
a.x--;
a.draw();
});
dino.draw();
}
executePerFrame();
120 프레임(내 컴퓨터가 60프레임이라는 가정 하에 2초)마다 장애물을 생성해 array에 집어넣고, array에 있는 장애물들을 한 번에 draw한다.
뭔 함수를 정의하다 말고 자기 자신을 호출하지? 하는 생각이 들면서 코드의 구조가 이상하게 느껴질 수 있는데, requestAnimationFrame()이 브라우저에게 수행하기를 원하는 애니메이션을 알리고 다음 리페인트가 진행되기 전에 해당 애니메이션을 업데이트하는 함수를 호출하게 하기 때문이다. 리페인트 이전에 실행할 콜백을 인자로 받기 때문에 자기 자신을 인자로 전달해 줘야 내가 실행시킬 코드(즉, 함수의 body)가 반복해서 호출되는 것이다.
이번에는 공룡과 장애물을 만들어 움직이게 하는 것까지 해봤다. 지금까지의 코드를 실행하면
이렇게 장애물이 생성되고 공룡이 장애물을 지나다니는 것을 볼 수 있다.
뭘 하려는지는 알겠지만 게임이라고 하기엔 많이 부족해 보인다. 다음에는 공룡을 점프시켜 장애물을 피할 수 있도록 해보겠다.