20241204授業
このソースのスコアが動作するように修正して書き直してください。
class Snake {
constructor(x, y) {
this.body = [{ x, y }];
this.direction = “right”;
}
move() {
const head = { …this.body[0] };
switch (this.direction) {
case “up”:
head.y–;
break;
case “down”:
head.y++;
break;
case “left”:
head.x–;
break;
case “right”:
head.x++;
break;
}
this.body.unshift(head);
this.body.pop();
}
grow() {
const tail = { …this.body[this.body.length – 1] };
this.body.push(tail);
}
getHead() {
return { …this.body[0] };
}
checkCollision(canvasWidth, canvasHeight) {
const head = this.getHead();
// 境界線との衝突判定
if (head.x = canvasWidth || head.y = canvasHeight) {
return true;
}
// 自分自身との衝突判定
return this.body.slice(1).some(segment => segment.x === head.x && segment.y === head.y);
}
}
class Food {
constructor(canvasWidth, canvasHeight, blockSize) {
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.blockSize = blockSize;
this.respawn();
}
respawn() {
const maxX = Math.floor(this.canvasWidth / this.blockSize);
const maxY = Math.floor(this.canvasHeight / this.blockSize);
this.pos = {
x: Math.floor(Math.random() * maxX),
y: Math.floor(Math.random() * maxY)
};
}
getPos() {
return { …this.pos };
}
}
class Game {
constructor(canvas, canvasWidth, canvasHeight, blockSize) {
this.canvas = canvas;
this.ctx = canvas.getContext(“2d”);
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.blockSize = blockSize;
this.snake = new Snake(5, 5);
this.food = new Food(canvasWidth, canvasHeight, blockSize);
this.score = 0;
this.isGameOver = false;
this.init();
}
init() {
this.canvas.width = this.canvasWidth;
this.canvas.height = this.canvasHeight;
this.canvas.style.border = “1px solid #ccc”;
this.canvas.style.background = “#fff”;
document.addEventListener(“keydown”, this.handleInput.bind(this));
const restartBtn = document.getElementById(“restart-btn”);
restartBtn.addEventListener(“click”, () => this.restart());
this.updateScore();
}
start() {
let lastFrameTime = performance.now();
let timeSinceLastFrame = 0;
const interval = 100;
const animate = (timestamp) => {
timeSinceLastFrame += timestamp – lastFrameTime;
lastFrameTime = timestamp;
while (timeSinceLastFrame >= interval) {
this.update();
this.draw();
timeSinceLastFrame -= interval;
}
if (!this.isGameOver) {
requestAnimationFrame(animate);
}
};
animate(lastFrameTime);
}
stop() {
this.isGameOver = true;
}
restart() {
this.snake = new Snake(5, 5);
this.food.respawn();
this.score = 0;
this.updateScore();
if (this.isGameOver) {
this.isGameOver = false;
this.start();
}
}
update() {
if (this.isGameOver) return;
this.snake.move();
if (this.snake.checkCollision(this.canvasWidth / this.blockSize, this.canvasHeight / this.blockSize)) {
this.isGameOver = true;
this.stop();
alert(`Game over! Your score is ${this.score}`);
return;
}
const head = this.snake.getHead();
const foodPos = this.food.getPos();
if (head.x === foodPos.x && head.y === foodPos.y) {
this.snake.grow();
this.food.respawn();
this.score++;
this.updateScore();
}
}
draw() {
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// Snake
this.ctx.fillStyle = “#4CAF50”;
this.snake.body.forEach(segment => {
this.ctx.fillRect(
segment.x * this.blockSize,
segment.y * this.blockSize,
this.blockSize,
this.blockSize
);
});
// Food
this.ctx.fillStyle = “#f44336”;
this.ctx.fillRect(
this.food.pos.x * this.blockSize,
this.food.pos.y * this.blockSize,
this.blockSize,
this.blockSize
);
}
handleInput(event) {
switch (event.keyCode) {
case 38: // up arrow
if (this.snake.direction !== “down”) this.snake.direction = “up”;
break;
case 40: // down arrow
if (this.snake.direction !== “up”) this.snake.direction = “down”;
break;
case 37: // left arrow
if (this.snake.direction !== “right”) this.snake.direction = “left”;
break;
case 39: // right arrow
if (this.snake.direction !== “left”) this.snake.direction = “right”;
break;
}
}
updateScore() {
const scoreElem = document.getElementById(“score”);
if (scoreElem) {
scoreElem.textContent = `Score: ${this.score}`;
}
}
}
const canvas = document.getElementById(“canvas”);
const game = new Game(canvas, 400, 400, 10);
game.start();