這個(gè)中秋可是悲催,別人放假,我還得在家辦公寫項(xiàng)目,帶娃的時(shí)間都沒有,這不,娃要纏著陪她玩積木游戲,哎,心中有事,陪娃都陪不好,咋整,靈機(jī)一動(dòng),先搞個(gè)小游戲讓娃耍個(gè)把小時(shí),畢竟孩子長時(shí)間對著電腦不好,寫個(gè)貪吃蛇吧,能玩很久。
先看一下簡單的界面是這樣的:
網(wǎng)頁游戲,比較簡單,一個(gè)頁面就搞定了,代碼是這樣的,直接生成一個(gè) html 就能玩了。
創(chuàng)建一個(gè)簡單的貪吃蛇網(wǎng)頁游戲,使用 HTML、CSS 和 JavaScript 三件套,簡單高效。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #333;
margin: 0;
}
canvas {
border: 1px solid #fff;
background-color: #000;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const tileCount = canvas.width / gridSize;
let snake = [{ x: 10, y: 10 }];
let food = { x: 5, y: 5 };
let direction = { x: 0, y: 0 };
let nextDirection = { x: 0, y: 0 };
let speed = 200;
function gameLoop() {
// Update snake direction
direction = nextDirection;
// Move snake
const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
snake.unshift(head);
// Check for food collision
if (head.x === food.x && head.y === food.y) {
placeFood();
} else {
snake.pop();
}
// Check for wall collision
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
gameOver();
return;
}
// Check for self collision
for (let i = 1; i < snake.length; i++) {
if (snake[i].x === head.x && snake[i].y === head.y) {
gameOver();
return;
}
}
drawGame();
}
function drawGame() {
// Clear canvas
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw snake
ctx.fillStyle = 'lime';
snake.forEach(part => {
ctx.fillRect(part.x * gridSize, part.y * gridSize, gridSize, gridSize);
});
// Draw food
ctx.fillStyle = 'red';
ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize, gridSize);
}
function placeFood() {
food.x = Math.floor(Math.random() * tileCount);
food.y = Math.floor(Math.random() * tileCount);
// Make sure food doesn't appear on the snake
for (let i = 0; i < snake.length; i++) {
if (snake[i].x === food.x && snake[i].y === food.y) {
placeFood();
}
}
}
function changeDirection(event) {
switch (event.keyCode) {
case 37: // Left arrow
if (direction.x === 0) {
nextDirection = { x: -1, y: 0 };
}
break;
case 38: // Up arrow
if (direction.y === 0) {
nextDirection = { x: 0, y: -1 };
}
break;
case 39: // Right arrow
if (direction.x === 0) {
nextDirection = { x: 1, y: 0 };
}
break;
case 40: // Down arrow
if (direction.y === 0) {
nextDirection = { x: 0, y: 1 };
}
break;
}
}
function gameOver() {
alert('Game Over!');
snake = [{ x: 10, y: 10 }];
direction = { x: 0, y: 0 };
nextDirection = { x: 0, y: 0 };
placeFood();
}
document.addEventListener('keydown', changeDirection);
setInterval(gameLoop, speed);
placeFood();
</script>
</body>
</html>
前端三件套:
HTML:包含一個(gè) <canvas>
元素,貪吃蛇游戲?qū)?huì)在這個(gè)畫布上渲染。
CSS:簡單地設(shè)置了畫布的外觀。
JavaScript:游戲邏輯,包括:
gameLoop
函數(shù):負(fù)責(zé)蛇的移動(dòng)、碰撞檢測、食物生成等。drawGame
函數(shù):繪制蛇和食物。placeFood
函數(shù):隨機(jī)放置食物在畫布上。changeDirection
函數(shù):監(jiān)聽鍵盤事件,改變蛇的移動(dòng)方向。gameOver
函數(shù):處理游戲結(jié)束的邏輯。下面再詳細(xì)解釋一下這個(gè)小游戲的實(shí)現(xiàn)邏輯:
這個(gè)貪吃蛇游戲使用 HTML、CSS 和 JavaScript 編寫,代碼實(shí)現(xiàn)的邏輯和流程如下:
<canvas id="gameCanvas" width="400" height="400"></canvas>
<canvas>
元素作為游戲畫布,游戲會(huì)在這個(gè)區(qū)域繪制蛇、食物等內(nèi)容。id="gameCanvas"
以便在 JavaScript 中通過 document.getElementById
獲取它。width
和 height
屬性定義了畫布的尺寸為 400x400 像素。body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #333;
margin: 0;
}
canvas {
border: 1px solid #fff;
background-color: #000;
}
JavaScript 部分包含了游戲的核心邏輯,包括蛇的移動(dòng)、食物的生成、碰撞檢測、繪制和用戶輸入的處理。
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const tileCount = canvas.width / gridSize;
let snake = [{ x: 10, y: 10 }];
let food = { x: 5, y: 5 };
let direction = { x: 0, y: 0 };
let nextDirection = { x: 0, y: 0 };
let speed = 200;
canvas
:獲取畫布元素。ctx
:獲取畫布的 2D 渲染上下文,用于繪制圖形。gridSize
:網(wǎng)格大小,每個(gè)網(wǎng)格 20x20 像素。tileCount
:計(jì)算畫布中網(wǎng)格的數(shù)量,canvas.width / gridSize
(這里為 20x20 個(gè)網(wǎng)格)。snake
:蛇的初始位置,初始為一個(gè)對象數(shù)組,蛇頭位置在 {x: 10, y: 10}
。food
:食物的初始位置 {x: 5, y: 5}
。direction
和 nextDirection
:蛇的當(dāng)前移動(dòng)方向和下一個(gè)移動(dòng)方向。speed
:控制游戲循環(huán)的速度,單位是毫秒。function gameLoop() {
// Update snake direction
direction = nextDirection;
// Move snake
const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
snake.unshift(head);
// Check for food collision
if (head.x === food.x && head.y === food.y) {
placeFood();
} else {
snake.pop();
}
// Check for wall collision
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
gameOver();
return;
}
// Check for self collision
for (let i = 1; i < snake.length; i++) {
if (snake[i].x === head.x && snake[i].y === head.y) {
gameOver();
return;
}
}
drawGame();
}
gameLoop
是游戲的主循環(huán)函數(shù),使用 setInterval
在一定時(shí)間間隔內(nèi)重復(fù)調(diào)用,實(shí)現(xiàn)游戲的實(shí)時(shí)更新。x
和 y
坐標(biāo),將新頭部添加到 snake
數(shù)組的開頭。placeFood
生成新的食物位置;否則,移除蛇尾(snake.pop()
),維持蛇的長度。gameOver
函數(shù)結(jié)束游戲。gameOver
函數(shù)結(jié)束游戲。drawGame
函數(shù)更新畫布。function drawGame() {
// Clear canvas
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw snake
ctx.fillStyle = 'lime';
snake.forEach(part => {
ctx.fillRect(part.x * gridSize, part.y * gridSize, gridSize, gridSize);
});
// Draw food
ctx.fillStyle = 'red';
ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize, gridSize);
}
drawGame
函數(shù)負(fù)責(zé)繪制游戲的每一幀。snake
數(shù)組,在蛇每個(gè)部分的位置上繪制一個(gè)綠色矩形。food
的位置繪制一個(gè)紅色矩形。function placeFood() {
food.x = Math.floor(Math.random() * tileCount);
food.y = Math.floor(Math.random() * tileCount);
// Make sure food doesn't appear on the snake
for (let i = 0; i < snake.length; i++) {
if (snake[i].x === food.x && snake[i].y === food.y) {
placeFood();
}
}
}
placeFood
隨機(jī)在畫布上放置食物。placeFood
重新生成位置。function changeDirection(event) {
switch (event.keyCode) {
case 37: // Left arrow
if (direction.x === 0) {
nextDirection = { x: -1, y: 0 };
}
break;
case 38: // Up arrow
if (direction.y === 0) {
nextDirection = { x: 0, y: -1 };
}
break;
case 39: // Right arrow
if (direction.x === 0) {
nextDirection = { x: 1, y: 0 };
}
break;
case 40: // Down arrow
if (direction.y === 0) {
nextDirection = { x: 0, y: 1 };
}
break;
}
}
changeDirection
函數(shù)監(jiān)聽鍵盤事件,更新蛇的移動(dòng)方向。function gameOver() {
alert('Game Over!');
snake = [{ x: 10, y: 10 }];
direction = { x: 0, y: 0 };
nextDirection = { x: 0, y: 0 };
placeFood();
}
gameOver
函數(shù)在蛇撞墻或自身時(shí)調(diào)用,顯示“游戲結(jié)束”信息,并重置游戲狀態(tài)。document.addEventListener('keydown', changeDirection);
setInterval(gameLoop, speed);
placeFood();
changeDirection
函數(shù)。setInterval
定期調(diào)用 gameLoop
,使游戲持續(xù)運(yùn)行。placeFood
函數(shù)生成初始食物位置。gameLoop
) 不斷更新蛇的位置、檢查碰撞、繪制游戲元素,形成動(dòng)畫效果。好了,現(xiàn)在可以靜靜的寫項(xiàng)目了,專心致志,效率翻倍。
更多建議: