- 자바스크립트: Snake 게임 만들기 1 – 블럭 움직이기
- 자바스크립트: Snake 게임 만들기 2 – 블럭이 스스로 움직이도록 만들기, 사과(먹이) 만들기
- 자바스크립트: Snake 게임 만들기 3 – 뱀 몸체 만들기, 마무리 (完)
스네이크 게임이란 고전게임으로 뱀이 여기저기를 돌아다니면서 사과(먹이)를 먹으면 뱀의 길이가 점점 늘어나고, 뱀이 꼬여서 몸이 부딪히면 게임 오버되는 방식으로 진행됩니다. 이 스네이크 게임의 현대화된 버전이 slither.io 라고 보시면 됩니다.
유튜브를 보다 보니 이 게임을 만드는 영상이 있어서 따라해보았습니다. 이 영상은 자바스크립트보다는 알고리즘에 중점을 둔 영상이고 말하는 속도가 빨라 알아들을 수 없어 제 수준에서는 분석이 좀 많이 필요하다고 생각하였습니다. 그래서 시리즈로 나눠 스네이크 게임을 만들어보는 글을 연재해보도록 하겠습니다.
HTML5 뼈대 만들기
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> </body> </html>
캔버스 만들기
먼저 캔버스를 만들어보도록 하겠습니다. 외부 라이브러리를 사용하지 않는 이상 자바에서 대부분의 게임용 애니메이션은 캔버스 위에서 진행된다고 봐도 무방합니다. 캔버스를 이용해 점, 선, 면 등을 다양하게 그릴 수 있습니다. HTML 부분을 만들고 <body>
부분에 <canvas>
태그를 삽입합니다.
<body> <canvas id="game-canvas" width="400" height="400"></canvas> </body>
위의 코드는 아이디로 game-canvas 를 가지는 가로, 세로 400px(픽셀)의 캔버스를 만들겠다는 의미입니다. 이 단계에서는 아무것도 보이지 않으며 이 캔버스를 자바스크립트에서 조작해 캔버스에 각종 그림을 그립니다.
캔버스를 자바스크립트로 가져오기
캔버스는 자바스크립트에서 다룰 수 있습니다. document.getElementById
를 이용해 캔버스 DOM을 변수에 저장합니다. 그리고 그 캔버스에서 ‘2d 컨텍스트’라는 것을 가져와 변수로 저장합니다. 2d 컨텐츠를 다루는 렌더링 컨텍스트를 다룰 수 있게 합니다.3d 등 다른 컨텍스트도 있다고 합니다만 여기서 만드는 스네이크 게임은 2차원 게임이므로 2d 컨텐츠를 가져옵니다.
<body> <canvas id="game-canvas" width="400" height="400"></canvas> <script> const canvas = document.getElementById("game-canvas") const ctx = canvas.getContext("2d") </script> </body>
키보드 이벤트 부여, 15fps로 게임 렌더링
먼저 블럭을 움직이려면 키보드 방향키에 이벤트가 부여되야 합니다. 이것은 addEventListener
로 지정합니다. 그리고 2d 컨텍스트는 정지된 그림을 렌더링하므로 게임을 초당 15프레임으로 다시 그리도록 지정하여 애니메이션을 구현하도록 합니다. setInterval
을 이용하면 해당 ms(밀리세컨드)마다 지정된 함수를 반복적으로 실행합니다.
window.onload = () => { document.addEventListener("keydown", keyPush) setInterval(game, 1000 / 15) }
1000ms 는 1초이며, 이것을 15로 나눈 값은 1초당 15번 실행하겠다는 의미입니다.
keyPush
, game
함수는 이후에 구현합니다.
x, y 포지션 변수 생성, 그리드 사이즈 및 타일 개수 변수 생성
현재 블럭의 위치를 저장하는 위치 변수를 생성합니다. 위치 변수는 값이 지속적으로 변해야 하므로 let
으로 선언합니다.
또한 캔버스의 그리드 사이즈를 px로 선언하고, 캔버스의 타일 개수도 설정합니다. 20px의 그리드가 20개 있으면 20*20 = 400px가 됩니다.
let positionX = 0, positionY = 0 const gridSize = 20, tileCount = 20
키보드 이벤트의 keyPush 함수 구현
방향키를 누르면 블럭이 ‘한 칸’ 이동하는 이벤트 함수를 구현하도록 하겠습니다.
function keyPush(evt) { switch(evt.keyCode) { case 37: positionX += -1; positionY += 0; break; case 38: positionX += 0; positionY += -1; break; case 39: positionX += 1; positionY += 0; break; case 40: positionX += 0; positionY += 1; break; } }
evt.keyCode
에는 현재 눌린 키코드가 들어 있습니다. 왼쪽 방향키부터 시계 방향으로 37
(왼쪽), 38
(위), 39
(오른쪽), 40
(아래)으로 할당되어 있습니다. switch
분기문을 이용해 각 코드에 대한 이벤트를 부여합니다.
왼쪽이면 x방향으로 한 칸 뒤로 가야 하므로 -1, 그 반대인 오른쪽은 x방향으로 1… 이런 식으로 움직이는 방향을 구현했습니다.
게임 함수 구현
15fps로 실행될 game
함수를 만듭니다.
function game() { // ........... // }
캔버스 초기화 및 배경색 지정
game 함수 안에 다음 코드를 삽입합니다.
ctx.fillStyle = "black" ctx.fillRect(0, 0, canvas.width, canvas.height)
검은색 배경의 사각형을 캔버스 전체에 그린다는 의미입니다.
이 코드는 반드시 game
함수 안에 삽입되어야 합니다. 바깥에 삽입하면 처음 한 번만 그리기 작업을 수행하는데, game
함수가 렌더링 될 때 아래와 같이 지워지지 않는 자국을 남깁니다.
블럭 그리기
ctx.fillStyle = "lime" ctx.fillRect(positionX * gridSize, positionY * gridSize, gridSize - 2, gridSize - 2)
크기에서 각각-2
를 하는 이유는 구분선을 표시하기 위함입니다.
가장자리 처리하기
만약 블럭이 왼쪽 가장자리에서 왼쪽으로 이동한다면 오른쪽 끝으로, 위쪽 가장자리에서 위쪽으로 이동한다면 아래쪽 끝으로 하는 등 가장자리에서 수행할 동작을 지정합니다.
if(positionX < 0) { positionX = tileCount - 1 } if(positionX > tileCount - 1) { positionX = 0 } if(positionY < 0) { positionY = tileCount - 1 } if(positionY > tileCount - 1) { positionY = 0 }
position X, Y
는 0
부터 시작하여 19
(=tileCount - 1
)에서 끝납니다.
이번에 완성된 전체 코드는 다음과 같습니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <canvas id="game-canvas" width="400" height="400"></canvas> <script> const canvas = document.getElementById("game-canvas") const ctx = canvas.getContext("2d") window.onload = () => { document.addEventListener("keydown", keyPush) setInterval(game, 1000 / 15) } let positionX = 0, positionY = 0 const gridSize = 20, tileCount = 20 function game() { if(positionX < 0) { positionX = tileCount - 1 } if(positionX > tileCount - 1) { positionX = 0 } if(positionY < 0) { positionY = tileCount - 1 } if(positionY > tileCount - 1) { positionY = 0 } ctx.fillStyle = "black" ctx.fillRect(0, 0, canvas.width, canvas.height) ctx.fillStyle = "lime" ctx.fillRect(positionX * gridSize, positionY * gridSize, gridSize - 2, gridSize - 2) } function keyPush(evt) { switch(evt.keyCode) { case 37: positionX += -1; positionY += 0; break; case 38: positionX += 0; positionY += -1; break; case 39: positionX += 1; positionY += 0; break; case 40: positionX += 0; positionY += 1; break; } } </script> </body> </html>
- 자바스크립트: Snake 게임 만들기 1 – 블럭 움직이기
- 자바스크립트: Snake 게임 만들기 2 – 블럭이 스스로 움직이도록 만들기, 사과(먹이) 만들기
- 자바스크립트: Snake 게임 만들기 3 – 뱀 몸체 만들기, 마무리 (完)
0개의 댓글