Javascriptの練習:蛇がえさを食べて長くなるゲーム
ReactをやってもAngularをやっても躓いてしまうので、Back to Basicをいうことで、Javascriptに立ち返っております。
まずは、Kindleで「ゲームを作りながら楽しく学べるHTML+CSS+Javascript」を読みながら作ってみました。
出来たゲームはこちらの、蛇がえさを食べると長くなっていくゲームです。
https://www.wsmeguro.jp/tools/js/snake/
ポイントは、以下の2つで動き出したら、壁に当たるか、自分の体に触れるまで止まらない。ということですね。
・setIntervalで1秒に5回再表示させること(キー入力がアクションのキーにならない)
・キー入力はkeyCodeが覚えている
難点は、例えば、上に向かっている時、更新の合間の0.2秒間に上と下を打鍵すると、最初の上は反応されず下だけに反応するため自分の体に当たったとしてゲームオーバーになります。setIntervalで方向を覚えておいて、合間に行われた打鍵で処理を分ける必要がありますが、今回はここまでにします。
配列に対するforEachとかすっかり忘れていましたので、いい勉強になりました。
ソースコードは以下の通りです。
引用元、5-1 Canvasを使った基礎的なゲーム
田中 賢一郎. ゲームを作りながら楽しく学べるHTML5+CSS+JavaScriptプログラミング[改訂版] (Japanese Edition) (p.168). Kindle 版.
著者からのメッセージの一つ「ゲームで遊ぶのも楽しいかもしれませんが、自分で作って改造するのも同じくらい楽しいものです。そんな楽しさを通して、プログラミングのスキルを身に着けていただきたいと思っています。」
<!DOCTYPE html> <html lang=”en”> <head> <meta charset=”UTF-8″> <meta name=”viewport” content=”width=device-width, initial-scale=1.0″> <meta http-equiv=”X-UA-Compatible” content=”ie=edge”> <link rel=”icon” type=”image/png” href=”https://www.wsmeguro.jp/logo/favicon.png”> <link rel=”stylesheet” href=”index.css”> <title>A Snake Bites Foods</title> </head> <body onload=”init()”> <canvas width=”600″ height=”600″ id=”field” style=”background: #cce2e3″></canvas> <script src=”index.js” async defer></script> </body> </html>
"use strick";
var W, H, S = 20;
var snake = [], foods = [];
var keyCode = 0;
var point = 0;
var timer = NaN;
var ctx;
function Point(x, y) {
this.x = x;
this.y = y;
}
function init() {
var canvas = document.getElementById('field');
W = canvas.width / S;
H = canvas.height / S;
ctx = canvas.getContext('2d');
ctx.font = "20px sans-serif";
snake.push(new Point(W / 2, H / 2));
for (var i = 0; i < 10; i++) {
addFood();
}
timer = setInterval("tick()", 200);
window.onkeydown = keydown;
}
function addFood() {
while (true) {
var x = Math.floor(Math.random() * W);
var y = Math.floor(Math.random() * H);
if (isHit(foods, x, y) || isHit(snake, x, y)) {
continue;
}
foods.push(new Point(x, y));
break;
}
}
function isHit(data, x, y) {
for (var i = 0; i < data.length; i++) {
if (data[i].x == x && data[i].y == y) {
return true;
}
}
return false;
}
function moveFood(x, y) {
foods = foods.filter(function (p) {
return (p.x != x || p.y != y);
});
addFood();
}
function tick() {
var x = snake[0].x;
var y = snake[0].y;
switch (keyCode) {
case 37: x--; break;
case 38: y--; break;
case 39: x++; break;
case 40: y++; break;
default: paint(); return;
}
if (isHit(snake, x, y) || x < 0 || x >= W || y < 0 || y >= H) {
clearInterval(timer);
paint();
return;
}
snake.unshift(new Point(x, y));
if (isHit(foods, x, y)) {
point += 10;
moveFood(x, y);
} else {
snake.pop();
}
paint();
}
function paint() {
ctx.clearRect(0, 0, W * S, H * S);
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillText(point, S, S * 2)
ctx.fillStyle = "#42873a";
foods.forEach(function (p) {
ctx.fillText("+", p.x * S, (p.y + 1) * S);
});
ctx.fillStyle = "#794059";
snake.forEach(function (p) {
ctx.fillText("*", p.x * S, (p.y + 1) * S);
});
}
function keydown(event) {
keyCode = event.keyCode;
}