開発環境
- OS X El Capitan - Apple (OS)
- Emacs (Text Editor)
- JavaScript (プログラミング言語)
- jQuery (Library)
- Safari(Web browser)
Javascript for Kids (Nick Morgan 著、Angus Croll 寄稿、Miran Lipovaca イラスト、No Starch Press)のPart 3(Canvas)、Chapter 17(Making a Snake Game: Part 2)、PROGRAMMING CHALLENGES、#1(MAKING THE GAME BIGGER)、#2(COLORING THE SNAKE)、#3(MAKING THE GAME SPEED UP AS YOU PLAY)、#4(FIXING THE APPLE.MOVE METHOD)(No. 5084)を取り組んでみる。
PROGRAMMING CHALLENGES、#1(MAKING THE GAME BIGGER)、#2(COLORING THE SNAKE)、#3(MAKING THE GAME SPEED UP AS YOU PLAY)、#4(FIXING THE APPLE>MOVE METHOD)(No. 5084)
コード(Emacs)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Snake!</title>
</head>
<body>
<canvas id="canvas0" width="600" height="600"></canvas>
<script src="sample.js"></script>
</body>
</html>
(function () {
'use strict';
var Block,
Snake,
Apple,
directions,
score = 0,
animation_time = 100,
flag = true,
occupied = [],
body = document.querySelector('body'),
canvas = document.querySelector('#canvas0'),
ctx = canvas.getContext('2d'),
width = canvas.width,
height = canvas.height,
block_size = 10,
width_in_blocks = width / block_size,
height_in_blocks = height / block_size,
circle,
snake,
apple,
intervalId,
clearRect,
drawBorder,
drawScore,
gameOver,
gameClear,
gameLoop;
directions = {
37: 'left',
38: 'up',
39: 'right',
40: 'down',
};
body.onkeydown = function (event) {
var new_direction = directions[event.keyCode];
if (new_direction !== undefined) {
snake.setDirection(new_direction);
}
};
Block = function (col, row) {
this.col = col;
this.row = row;
};
Block.prototype.drawSquare = function (color) {
var x = this.col * block_size,
y = this.row * block_size;
ctx.fillStyle = color;
ctx.fillRect(x, y, block_size, block_size);
};
Block.prototype.drawCircle = function (color) {
var center_x = this.col * block_size + block_size,
center_y = this.row * block_size + block_size;
ctx.fillStyle = color;
circle(center_x, center_y, block_size / 2, true);
};
Block.prototype.equal = function (other) {
return this.col === other.col && this.row === other.row;
};
Snake = function () {
this.segments = [
new Block(7, 5),
new Block(6, 5),
new Block(5, 5)
];
this.direction = 'right';
this.next_direction = 'right';
};
Snake.prototype.draw = function () {
var i,
max;
this.segments[0].drawSquare('green');
for (i = 1, max = this.segments.length; i < max; i += 1) {
if (i % 2 === 1) {
this.segments[i].drawSquare('blue');
} else {
this.segments[i].drawSquare('yellow');
}
}
};
Snake.prototype.move = function () {
var head = this.segments[0],
new_head;
this.direction = this.next_direction;
if (this.direction === 'right') {
new_head = new Block(head.col + 1, head.row);
} else if (this.direction === 'down') {
new_head = new Block(head.col, head.row + 1);
} else if (this.direction === 'left') {
new_head = new Block(head.col - 1, head.row);
} else if (this.direction === 'up') {
new_head = new Block(head.col, head.row - 1);
}
if (this.checkCollision(new_head)) {
gameOver();
return;
}
this.segments.unshift(new_head);
if (new_head.equal(apple.position)) {
score += 1;
if (animation_time > 5) {
animation_time -= 1;
}
occupied.push(apple.position);
if (occupied.length ===
(width_in_blocks - 2) * (height_in_blocks - 2)) {
gameClear();
} else {
apple.move();
}
} else {
this.segments.pop();
}
};
Snake.prototype.checkCollision = function (head) {
var left_collision = (head.col === 0),
top_collision = (head.row === 0),
right_collision = (head.col === width_in_blocks - 1),
bottom_collision = (head.row === height_in_blocks - 1),
wall_collision,
self_collision = false,
i,
max;
wall_collision = left_collision || top_collision ||
right_collision || bottom_collision;
for (i = 0, max = this.segments.length; i < max; i += 1) {
if (head.equal(this.segments[i])) {
self_collision = true;
}
}
return wall_collision || self_collision;
};
Snake.prototype.setDirection = function (new_direction) {
if (this.direction === 'up' && new_direction === 'down') {
return;
}
if (this.direction === 'right' && new_direction === 'left') {
return;
}
if (this.direction === 'down' && new_direction === 'up') {
return;
}
if (this.direction === 'left' && new_direction === 'right') {
return;
}
this.next_direction = new_direction;
};
Apple = function () {
this.position = new Block(10, 10);
};
Apple.prototype.draw = function () {
this.position.drawCircle('LimeGreen');
};
drawBorder = function () {
ctx.fillStyle = 'gray';
ctx.fillRect(0, 0, width, block_size);
ctx.fillRect(0, height - block_size, width, block_size);
ctx.fillRect(0, 0, block_size, height);
ctx.fillRect(width - block_size, 0, block_size, height);
};
Apple.prototype.move = function () {
var random_col,
random_row,
block,
flag = true,
i,
max;
while (flag) {
random_col = Math.floor(Math.random() * (width_in_blocks - 2));
random_row = Math.floor(Math.random() * (height_in_blocks - 2));
block = new Block(random_row, random_col);
for (i = 0, max = occupied.length; i < max; i += 1) {
if (occupied[i].equal(block)) {
break;
}
}
if (i === max) {
break;
}
}
this.position = block;
};
drawScore = function () {
ctx.font = '20px Courier';
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText('Score: ' + score, block_size, block_size);
};
gameOver = function () {
flag = false;
clearInterval(intervalId);
ctx.font = '60px Courier';
ctx.fillStyle = 'black';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Game Over', width / 2, height / 2);
};
gameClear = function () {
flag = false;
clearInterval(intervalId);
ctx.font = '60px Courier';
ctx.fillStyle = 'black';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Congratulations!', width / 2, height / 2);
};
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();
}
};
snake = new Snake();
apple = new Apple();
gameLoop = function () {
ctx.clearRect(0, 0, width, height);
drawScore();
snake.move();
snake.draw();
apple.draw();
drawBorder();
if (flag) {
setTimeout(gameLoop, animation_time);
}
};
gameLoop();
}());
0 コメント:
コメントを投稿