snake javascriptの内容

snake javascriptの内容

htmlファイルとcssファイル、jsファイルの三つからなります。

index.html



Snake Game

Score: 0




————————
style.css
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f5f5f5;
}

.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}

canvas {
border: 1px solid #ccc;
}

.score {
font-size: 24px;
font-weight: bold;
margin-top: 20px;
}

#restart-btn {
margin-top: 20px;
padding: 10px 20px;
font-size: 16px;
background-color: #4CAF50;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}

————————————
game.js

// Snake
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 head = this.getHead();
this.body.unshift(head);
}

getHead() {
return { …this.body[0] };
}

checkCollision(canvasWidth, canvasHeight) {
const head = this.getHead();
//
if (head.x < 0 || head.x >= canvasWidth || head.y < 0 || head.y >= canvasHeight) {
return true;
}
//
return this.body.slice(1).some(segment => segment.x === head.x && segment.y === head.y);
}
}

// Food
class Food {
constructor(canvasWidth, canvasHeight, blockSize) {
this.pos = { x: 0, y: 0 };
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.blockSize = blockSize;
this.respawn();
}

respawn() {
const maxX = Math.floor(this.canvasWidth / this.blockSize) – 1;
const maxY = Math.floor(this.canvasHeight / this.blockSize) – 1;
this.pos.x = Math.floor(Math.random() * maxX) * this.blockSize;
this.pos.y = Math.floor(Math.random() * maxY) * this.blockSize;
}

getPos() {
return { …this.pos };
}
}

// Game
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.intervalId = null;
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”;
this.canvas.style.margin = “0 auto”;
document.addEventListener(“keydown”, this.handleInput.bind(this));
this.draw();

const restartBtn = document.getElementById(“restart-btn”);
restartBtn.addEventListener(“click”, () => {
this.restart();
});

}

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() {
}

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()) {
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 * this.blockSize === foodPos.x && head.y * this.blockSize === foodPos.y) {
this.snake.grow();
this.food.respawn();
this.score++;
this.updateScore();
}
}

draw() {
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
this.ctx.fillStyle = “#4CAF50”;

this.snake.body.forEach(segment => {
this.ctx.fillRect(segment.x * this.blockSize, segment.y * this.blockSize, this.blockSize, this.blockSize);
});

this.ctx.fillStyle = “#f44336”;
this.ctx.fillRect(this.food.pos.x, this.food.pos.y, this.blockSize, this.blockSize);
}

handleInput(event) {
switch (event.keyCode) {
case 38: // up arrow
this.snake.direction = “up”;
break;
case 40: // down arrow
this.snake.direction = “down”;
break;
case 37: // left arrow
this.snake.direction = “left”;
break;
case 39: // right arrow
this.snake.direction = “right”;
break;
}
}

updateScore() {
const scoreElem = document.getElementById(“score”);
scoreElem.textContent = this.score;
}
}

//
const canvas = document.getElementById(“canvas”);
const game = new Game(canvas, 400, 400, 10);

game.start();

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です