게임 조작 방법
방향키를 이용해 욕심쟁이 뱀을 상하 좌우로 움직일 수 있습니다. 탐욕스러운 뱀은 음식을 먹고 나면 길이가 자랍니다.
게임의 구체적인 구현
게임의 난이도는 욕심쟁이 뱀의 움직임을 시뮬레이션하는 방법입니다. 블록이라면 당연히 매우 간단합니다. 그런데 뱀의 길이가 길어지면 각 블록의 움직임을 어떻게 제어할 수 있을까요
?
뱀의 움직임을 관찰해보면 뱀의 머리부터 꼬리까지 다음 순간의 각 블록의 위치가 이전 블록의 위치와 같다는 것을 알 수 있습니다. 현재 순간
위치. 따라서 우리가 해야 할 일은 뱀 머리의 움직임을 제어하는 것뿐입니다. 다른 부분의 위치도 유추해 볼 수 있습니다.
또 주목해야 할 문제는
욕심쟁이 뱀이 먹이를 먹은 후 새로 추가된 블록을 어디에 배치해야 하는지입니다.
답은 다음 순간에는 새로 추가된 블록이 현재 순간의 끝에 나타나야 한다는 것입니다.
따라서 음식을 먹은 후 뱀의 각 위치를 업데이트하기 전에 블록을 추가하고 현재 순간의 꼬리 위치로 위치를 설정해야 합니다.
그러면 새로 추가된 블록을 제외한 모든 블록의 위치가 현재 순간에 업데이트됩니다.
index.html
snake.js
코드는 다음과 같습니다.
var canvas; var ctx; var timer; //measures var x_cnt = 15; var y_cnt = 15; var unit = 48; var box_x = 0; var box_y = 0; var box_width = 15 * unit; var box_height = 15 * unit; var bound_left = box_x; var bound_right = box_x + box_width; var bound_up = box_y; var bound_down = box_y + box_height; //images var image_sprite; //objects var snake; var food; var food_x; var food_y; //functions function Role(sx, sy, sw, sh, direction, status, speed, image, flag) { this.x = sx; this.y = sy; this.w = sw; this.h = sh; this.direction = direction; this.status = status; this.speed = speed; this.image = image; this.flag = flag; } function transfer(keyCode) { switch (keyCode) { case 37: return 1; case 38: return 3; case 39: return 2; case 40: return 0; } } function addFood() { //food_x=box_x+Math.floor(Math.random()*(box_width-unit)); //food_y=box_y+Math.floor(Math.random()*(box_height-unit)); food_x = unit * Math.floor(Math.random() * x_cnt); food_y = unit * Math.floor(Math.random() * y_cnt); food = new Role(food_x, food_y, unit, unit, 0, 0, 0, image_sprite, true); } function play(event) { var keyCode; if (event == null) { keyCode = window.event.keyCode; window.event.preventDefault(); } else { keyCode = event.keyCode; event.preventDefault(); } var cur_direction = transfer(keyCode); snake[0].direction = cur_direction; } function update() { //add a new part to the snake before move the snake if (snake[0].x == food.x && snake[0].y == food.y) { var length = snake.length; var tail_x = snake[length - 1].x; var tail_y = snake[length - 1].y; var tail = new Role(tail_x, tail_y, unit, unit, snake[length - 1].direction, 0, 0, image_sprite, true); snake.push(tail); addFood(); } //modify attributes //move the head switch (snake[0].direction) { case 0: //down snake[0].y += unit; if (snake[0].y > bound_down - unit) snake[0].y = bound_down - unit; break; case 1: //left snake[0].x -= unit; if (snake[0].x < bound_left) snake[0].x = bound_left; break; case 2: //right snake[0].x += unit; if (snake[0].x > bound_right - unit) snake[0].x = bound_right - unit; break; case 3: //up snake[0].y -= unit; if (snake[0].y < bound_up) snake[0].y = bound_up; break; } //move other part of the snake for (var i = snake.length - 1; i >= 0; i--) { if (i > 0) //snake[i].direction=snake[i-1].direction; { snake[i].x = snake[i - 1].x; snake[i].y = snake[i - 1].y; } } } function drawScene() { ctx.clearRect(box_x, box_y, box_width, box_height); ctx.strokeStyle = "rgb(0,0,0"; ctx.strokeRect(box_x, box_y, box_width, box_height); //detection collisions //draw images for (var i = 0; i < snake.length; i++) { ctx.drawImage(image_sprite, snake[i].x, snake[i].y); } ctx.drawImage(image_sprite, food.x, food.y); } function init() { canvas = document.getElementById("scene"); ctx = canvas.getContext('2d'); //images image_sprite = new Image(); image_sprite.src = "images/sprite.png"; image_sprite.onLoad = function () {} //ojects snake = new Array(); var head = new Role(0 * unit, 0 * unit, unit, unit, 5, 0, 1, image_sprite, true); snake.push(head); window.addEventListener('keydown', play, false); addFood(); setInterval(update, 300); //note setInterval(drawScene, 30); }