Недавно осваивать JavaScript начал и мой сын. И сейчас он с удовольствием читает книгу Ника Моргана Javascript для детей. Самые любопытные могут скачать и почитать эту книгу тут:
Читая с сыном книгу Ника Моргана Javascript для детей, не могла не начать сохранять себе в коллекцию игры c этой книги. Первой игрой была Игра Виселица (Hangman). Игра написана самыми простыми циклами и набором переменных, без функций, с помощью сигнальных диалогов.
Змейка – финальная игра книги. Это итог накопленных в книге знаний. В ней используется весь выученный материал: циклы, объекты, методы, конструкторы, события…
А вот и полный код игры:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Змейка!</title> </head> <body> <canvas id="canvas" width="400" height="400"></canvas> <script src="https://code.jquery.com/jquery-2.1.0.js"></script> <script> // Настройка «холста» var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // Получаем ширину и высоту элемента canvas var width = canvas.width; var height = canvas.height; // Вычисляем ширину и высоту в ячейках var blockSize = 10; var widthInBlocks = width / blockSize; var heightInBlocks = height / blockSize; // Устанавливаем счет 0 var score = 0; // Рисуем рамку var drawBorder = function () { ctx.fillStyle = "Gray"; ctx.fillRect(0, 0, width, blockSize); ctx.fillRect(0, height - blockSize, width, blockSize); ctx.fillRect(0, 0, blockSize, height); ctx.fillRect(width - blockSize, 0, blockSize, height); }; // Выводим счет игры в левом верхнем углу var drawScore = function () { ctx.font = "20px Courier"; ctx.fillStyle = "Black"; ctx.textAlign = "left"; ctx.textBaseline = "top"; ctx.fillText("Счет: " + score, blockSize, blockSize); }; // Отменяем действие setInterval и печатаем сообщение «Конец игры» var gameOver = function () { clearInterval(intervalId); ctx.font = "60px Courier"; ctx.fillStyle = "Black"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText("Конец игры", width / 2, height / 2); }; // Рисуем окружность (используя функцию из главы 14) var circle = function (x, y, radius, fillCircle) { ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2, false); if (fillCircle) { ctx.fill(); } else { ctx.stroke(); } }; // Задаем конструктор Block (ячейка) var Block = function (col, row) { this.col = col; this.row = row; }; // Рисуем квадрат в позиции ячейки Block.prototype.drawSquare = function (color) { var x = this.col * blockSize; var y = this.row * blockSize; ctx.fillStyle = color; ctx.fillRect(x, y, blockSize, blockSize); }; // Рисуем круг в позиции ячейки Block.prototype.drawCircle = function (color) { var centerX = this.col * blockSize + blockSize / 2; var centerY = this.row * blockSize + blockSize / 2; ctx.fillStyle = color; circle(centerX, centerY, blockSize / 2, true); }; // Проверяем, находится ли эта ячейка в той же позиции, что и ячейка // otherBlock Block.prototype.equal = function (otherBlock) { return this.col === otherBlock.col && this.row === otherBlock.row; }; // Задаем конструктор Snake (змейка) var Snake = function () { this.segments = [ new Block(7, 5), new Block(6, 5), new Block(5, 5) ]; this.direction = "right"; this.nextDirection = "right"; }; // Рисуем квадратик для каждого сегмента тела змейки Snake.prototype.draw = function () { for (var i = 0; i < this.segments.length; i++) { this.segments[i].drawSquare("Blue"); } }; // Создаем новую голову и добавляем ее к началу змейки, // чтобы передвинуть змейку в текущем направлении Snake.prototype.move = function () { var head = this.segments[0]; var newHead; this.direction = this.nextDirection; if (this.direction === "right") { newHead = new Block(head.col + 1, head.row); } else if (this.direction === "down") { newHead = new Block(head.col, head.row + 1); } else if (this.direction === "left") { newHead = new Block(head.col - 1, head.row); } else if (this.direction === "up") { newHead = new Block(head.col, head.row - 1); } if (this.checkCollision(newHead)) { gameOver(); return; } this.segments.unshift(newHead); if (newHead.equal(apple.position)) { score++; apple.move(); } else { this.segments.pop(); } }; // Проверяем, не столкнулась ли змейка со стеной или собственным // телом Snake.prototype.checkCollision = function (head) { var leftCollision = (head.col === 0); var topCollision = (head.row === 0); var rightCollision = (head.col === widthInBlocks - 1); var bottomCollision = (head.row === heightInBlocks - 1); var wallCollision = leftCollision || topCollision || rightCollision || bottomCollision; var selfCollision = false; for (var i = 0; i < this.segments.length; i++) { if (head.equal(this.segments[i])) { selfCollision = true; } } return wallCollision || selfCollision; }; // Задаем следующее направление движения змейки на основе нажатой // клавиши Snake.prototype.setDirection = function (newDirection) { if (this.direction === "up" && newDirection === "down") { return; } else if (this.direction === "right" && newDirection === "left") { return; } else if (this.direction === "down" && newDirection === "up") { return; } else if (this.direction === "left" && newDirection === "right") { return; } this.nextDirection = newDirection; }; // Задаем конструктор Apple (яблоко) var Apple = function () { this.position = new Block(10, 10); }; // Рисуем кружок в позиции яблока Apple.prototype.draw = function () { this.position.drawCircle("LimeGreen"); }; // Перемещаем яблоко в случайную позицию Apple.prototype.move = function () { var randomCol = Math.floor(Math.random() * (widthInBlocks - 2)) + 1; var randomRow = Math.floor(Math.random() * (heightInBlocks - 2)) + 1; this.position = new Block(randomCol, randomRow); }; // Создаем объект-змейку и объект-яблоко var snake = new Snake(); var apple = new Apple(); // Запускаем функцию анимации через setInterval var intervalId = setInterval(function () { ctx.clearRect(0, 0, width, height); drawScore(); snake.move(); snake.draw(); apple.draw(); drawBorder(); }, 100); // Преобразуем коды клавиш в направления var directions = { 37: "left", 38: "up", 39: "right", 40: "down" }; // Задаем обработчик события keydown (клавиши-стрелки) $("body").keydown(function (event) { var newDirection = directions[event.keyCode]; if (newDirection !== undefined) { snake.setDirection(newDirection); } }); </script> </body> </html> |
Цитата из книги, как комментарий к игре:
Этот код состоит из нескольких частей. В первой части создаются и настраиваются необходимые в коде игры переменные, включая «холст», контекст рисования, ширину и высоту «холста». Далее, идет код отдельных функций: drawBorder, drawScore, gameOver и circle.
После начинается код конструктора Block, за которым следуют его методы drawSquare, drawCircle и equal. Затем идет код конструктора Snake и все его методы. Далее, следует конструктор Apple и его методы draw и move.Наконец, в итоге начинается код, который запускает игру и обеспечивает ее выполнение. Сначала мы создаем объект-змейку snake
и объект-яблоко apple. Затем с помощью setInterval мы запускаем анимацию игры. Обратите внимание, что при вызове setInterval мы
сохранили ID интервала в переменной intervalId, чтобы иметь возможность отменить его выполнение в функции gameOver.
Функция, переданная setInterval в качестве аргумента, вызывается на каждом шаге игры. Она отвечает за отображение на «холсте»
всей графики и за обновление состояния игры. Она очищает «холст» и затем рисует змейку, яблоко и рамку. Также она вызывает метод объекта – змейки move, передвигающий змейку на один шаг в текущем направлении. После вызова setInterval идет код для отслеживания событий клавиатуры и установки направления движения змейки.
Как и прежде, вам следует поместить весь этот код внутрь элемента script в HTML-документе. Чтобы запустить игру, просто загрузите файл
snake.html в браузер и управляйте змейкой с помощью клавиш-стрелок.
Если при нажатии на клавиши ничего не происходит, может понадобиться кликнуть мышкой внутри окна браузера, чтобы он мог отслеживать события клавиатуры.
Если игра не работает, возможно, в ваш JavaScript-код закралась ошибка. Сведения об ошибках отображаются в консоли — посмотрите, нет ли
там каких-нибудь сообщений. В случае, если выяснить, в чем проблема, так и не получилось, внимательно, строка за строкой сверьте ваш код с кодом, приведенным выше.
Ну, как вам игра? Сколько очков сможете набрать?