
作为电子游戏史上最具生命力的经典之一,贪吃蛇自1976年Gremlin平台的《Blockade》诞生以来,历经诺基亚手机时代全球普及,到如今衍生出3D大逃杀、多人竞技等30余种变体,其核心玩法始终围绕"空间限制下的生存博弈"展开。本文将以JavaScript+HTML5 Canvas技术栈为基础,结合现代游戏开发理念,提供一套完整的贪吃蛇实现方案。
游戏采用链表结构管理蛇身,每个节点包含坐标与视觉元素:
javascript1class SnakeNode {
2 constructor(x, y, type) {
3 this.x = x;
4 this.y = y;
5 this.type = type; // 'head'/'body'/'tail'
6 this.next = null;
7 }
8}
9
10class Snake {
11 constructor() {
12 this.head = new SnakeNode(5, 5, 'head');
13 this.tail = this.head;
14 this.length = 1;
15 this.direction = {x: 1, y: 0}; // 初始向右
16 }
17
18 addSegment(x, y) {
19 const newNode = new SnakeNode(x, y, 'body');
20 this.tail.next = newNode;
21 this.tail = newNode;
22 this.length++;
23 }
24}食物生成采用泊松盘采样算法避免重叠:
javascript1function generateFood(snake) {
2 let food;
3 do {
4 food = {
5 x: Math.floor(Math.random() * 20),
6 y: Math.floor(Math.random() * 20)
7 };
8 } while (snake.positions.some(pos =>
9 pos.x === food.x && pos.y === food.y
10 ));
11 return food;
12}实现三维空间碰撞检测(含边界、自碰撞、特殊障碍物):
javascript1function checkCollision(snake, food, map) {
2 const head = snake.head;
3
4 // 边界检测
5 if (head.x < 0 || head.x >= 20 ||
6 head.y < 0 || head.y >= 20) {
7 return 'wall';
8 }
9
10 // 自碰撞检测
11 const positions = [];
12 let current = snake.head;
13 while (current) {
14 positions.push({x: current.x, y: current.y});
15 current = current.next;
16 }
17
18 if (positions.slice(1).some(pos =>
19 pos.x === head.x && pos.y === head.y
20 )) {
21 return 'self';
22 }
23
24 // 特殊障碍物检测(如传送门、加速带)
25 if (map.specialTiles.some(tile =>
26 tile.x === head.x && tile.y === head.y
27 )) {
28 return 'special';
29 }
30
31 return null; // 无碰撞
32}javascript1function adjustSpeed(score) {
2 const speedTiers = [
3 {threshold: 0, speed: 200},
4 {threshold: 50, speed: 180},
5 {threshold: 150, speed: 150}
6 ];
7
8 const tier = speedTiers.find(t => score >= t.threshold) ||
9 speedTiers[speedTiers.length - 1];
10 return tier.speed;
11}javascript1function render3D(ctx, snake, food) {
2 // 透视投影矩阵计算
3 const perspective = 500;
4 const centerX = ctx.canvas.width / 2;
5 const centerY = ctx.canvas.height / 2;
6
7 function project(x, y, z) {
8 const factor = perspective / (perspective + z);
9 return {
10 x: centerX + x * factor,
11 y: centerY + y * factor
12 };
13 }
14
15 // 绘制3D蛇身(简化版)
16 let current = snake.head;
17 let prevPos = project(0, 0, 0);
18 while (current) {
19 const pos = project(
20 (current.x - 10) * 20,
21 (current.y - 10) * 20,
22 current.length * 10
23 );
24 ctx.fillRect(pos.x, pos.y, 20, 20);
25 current = current.next;
26 }
27}javascript1const canvas = document.getElementById('gameCanvas');
2const ctx = canvas.getContext('2d');
3const game = {
4 snake: new Snake(),
5 food: generateFood(),
6 score: 0,
7 speed: 200,
8 isPaused: false,
9
10 update() {
11 if (this.isPaused) return;
12
13 // 移动蛇身
14 const newHead = {
15 x: this.snake.head.x + this.snake.direction.x,
16 y: this.snake.head.y + this.snake.direction.y
17 };
18
19 // 碰撞检测
20 const collision = checkCollision(this.snake, this.food, map);
21 if (collision) {
22 if (collision === 'food') {
23 this.snake.addSegment(newHead.x, newHead.y);
24 this.food = generateFood();
25 this.score += 10;
26 this.speed = adjustSpeed(this.score);
27 } else {
28 this.gameOver();
29 }
30 return;
31 }
32
33 // 更新蛇位置
34 const newSnake = new SnakeNode(newHead.x, newHead.y, 'head');
35 newSnake.next = this.snake.head;
36 this.snake.head = newSnake;
37
38 // 移除尾节点(未吃到食物时)
39 if (!(newHead.x === this.food.x && newHead.y === this.food.y)) {
40 let current = this.snake.head;
41 while (current.next.next) {
42 current = current.next;
43 }
44 current.next = null;
45 }
46 },
47
48 render() {
49 ctx.clearRect(0, 0, canvas.width, canvas.height);
50
51 // 绘制游戏区域
52 ctx.fillStyle = '#f0f0f0';
53 ctx.fillRect(0, 0, canvas.width, canvas.height);
54
55 // 绘制蛇和食物
56 let current = this.snake.head;
57 while (current) {
58 ctx.fillStyle = current === this.snake.head ? 'green' : 'lime';
59 ctx.fillRect(current.x * 20, current.y * 20, 20, 20);
60 current = current.next;
61 }
62
63 ctx.fillStyle = 'red';
64 ctx.fillRect(this.food.x * 20, this.food.y * 20, 20, 20);
65
66 // 显示分数
67 ctx.fillStyle = 'black';
68 ctx.font = '20px Arial';
69 ctx.fillText(`Score: ${this.score}`, 10, 30);
70 },
71
72 gameLoop() {
73 this.update();
74 this.render();
75 setTimeout(() => this.gameLoop(), this.speed);
76 }
77};
78
79// 启动游戏
80game.gameLoop();从1976年像素点构成的简单围栏,到如今支持千万级用户在线对战的《贪吃蛇大作战》,这款经典游戏的技术实现始终在进化。本文提供的代码框架既保留了核心玩法精髓,又融入了现代游戏开发的前沿技术,可作为开发者探索游戏AI、网络同步、3D渲染等领域的理想实验场。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。