javascript贪吃蛇游戏设计与实现

时间:2021-05-26

本文为大家分享了javascript实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下

效果图

设计

贪吃蛇游戏是一款休闲益智类游戏。既简单又耐玩。该游戏通过控制蛇头方向吃蛋,从而使得蛇变得越来越长。

玩法:

点击屏幕控制蛇的移动方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能咬到自己的身体,更不能咬自己的尾巴,等到了一定的分数,游戏胜利。

设计:

首先需要创建一个棋盘,然后需要生成一条贪吃蛇,接着随机生成食物。每当蛇吃到食物的时候,随机生成新的食物,蛇头吃到自己的身体的时候游戏结束。

棋盘设计:

元素 :行数,列数,基础细胞(可表现为空,食物,蛇身体);

属性 :创建棋盘,清空棋盘;

基础细胞设计:

属性 :重设颜色,重设大小;

食物:

需求 : 需要在棋盘剩余空白位置随机位置生成食物;

贪吃蛇:

元素 : 位置集合(数组),移动速率,移动方向

需求: 初始随机生成只有一节的贪吃蛇,定时器函数(根据移动方向求得下一个要移动到的位置,需要注意的是到达边界后进行特殊处理。判断下个位置是否为蛇本身,如果是蛇就吃到自己,游戏结束。接着将下个位置添加到蛇位置集合内,最后判断下个位置 是否与食物相同,如果相同,则重现生成新的食物,否则移除蛇尾)。

方向控制:

本游戏使用点击屏幕,控制蛇移动方向。

实现

cell.js

/* * @Author: ls * @Date: 2020-09-01 18:23:09 * @LastEditTime: 2020-09-16 14:23:37 * @LastEditors: Please set LastEditors * @Description: 基础细胞类 * @FilePath: \snake\assets\cell.js */cc.Class({ extends: cc.Component, properties: {}, onLoad() {}, /** * @param {*} cellColor */ setCellColor(cellColor = new cc.color(255, 255, 255, 255)) { this.node.getChildByName('color').color = cellColor; }, /** * @param {*} cellSize */ setCellPos(cellSize = new cc.v2(20, 20)) { this.node.width = cellSize.x; this.node.height = cellSize.y; },});

guideCtrl.js

/* * @Author: ls * @Date: 2020-09-03 18:09:18 * @LastEditTime: 2020-09-14 08:55:47 * @LastEditors: Please set LastEditors * @Description: 引导类 * @FilePath: \snake\assets\guideCtrl.js */cc.Class({ extends: cc.Component, properties: { step: [cc.Node], startToggle: cc.Toggle, }, onLoad() { this.startGuide(); this.startToggle.isChecked = false; }, /** * 开始引导 */ startGuide() { if (!this.step.length) { this.node.destroy(); return; } for (let index = 0, length = this.step.length; index < length; index++) { this.step[index].active = false; } this._step = 0; this.step[0].active = true; }, /** * 下一个引导页面 */ nextGuide() { this._step++; if (this._step < this.step.length - 1) { this.step[this._step].active = true; this.step[this._step - 1].active = false; if (this._step === this.step.length - 2) { this.step[this._step + 1].active = true; } } else { this.node.active = false; } }, callback: function (toggle) { cc.sys.localStorage.setItem('isStart', toggle.isChecked); },});

gameCtrl.js

/* * @Author: ls * @Date: 2020-09-01 15:44:33 * @LastEditTime: 2020-09-16 14:23:18 * @LastEditors: Please set LastEditors * @Description: 游戏导演类 * @FilePath: \snake\assets\gameController.js */var noneColor = new cc.color(120, 120, 120, 255);var foodColor = new cc.color(254, 168, 23, 255);var snakeColor = new cc.color(243, 60, 66, 255);cc.Class({ extends: cc.Component, properties: { // 棋盘 node_grid: cc.Node, // 分数 lab_score: cc.Label, // 最好分数 lab_best: cc.Label, // 开始 node_start: cc.Node, // 新人引导 node_guide: cc.Node, // 结束 node_over: cc.Node, // 基础类 cellPrefab: cc.Prefab, // 移动速度 mSpeed: 5, // 列数 colCount: 30, // 行数 rowCount: 30, }, onLoad() { // 初始化方向 // 静止、上、下、左、右 // (0,0)、(0,1)、(0,-1)、(-1,0)、(1,0) this._direction = { x: 0, y: 0 }; // 初始化细胞大小 this._cellSize = { x: 10, y: 10 }; this._map = []; this.initCellPool(); this.onCreateMap(); // 显示开始游戏界面 this.showStartGame(); }, /** * 初始化细胞对象池 */ initCellPool() { this.cellPool = new cc.NodePool(); let initCount = this.rowCount * this.colCount; for (let i = 0; i < initCount; i++) { let cell = cc.instantiate(this.cellPrefab); // 创建节点 this.cellPool.put(cell); // 通过 put 接口放入对象池 } }, /** * 创建地图 */ onCreateMap() { this._map = []; let node_bg = this.node_grid.getChildByName('background'); this._cellSize = { x: node_bg.width / this.rowCount, y: node_bg.height / this.colCount }; for (var y = 0; y < this.colCount; y++) { for (let x = 0; x < this.rowCount; x++) { var obj = {}; obj.x = x; obj.y = y; obj.node = this.createCell(node_bg, x, y); this._map.push(obj); } } }, /** * 从对象池请求对象 * @param {*} parentNode */ createCell: function (parentNode, x, y) { let cell = null; if (this.cellPool.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象 cell = this.cellPool.get(); } else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建 cell = cc.instantiate(this.cellPrefab); } cell.getComponent('cell').setCellPos(this._cellSize); cell.x = this._cellSize.x * x; cell.y = this._cellSize.y * y; cell.parent = parentNode; return cell; }, /** * 还原地图 */ clearMap() { for (let index = 0, length = this._map.length; index < length; index++) { this._map[index].node.getComponent('cell').setCellColor(noneColor); } }, /** * 显示开始界面 */ showStartGame() { this.node_over.active = false; this.node_start.active = true; }, /** * 显示结束界面 */ showOverGame() { this.node_start.active = false; this.node_over.active = true; }, /** * 游戏开始 */ startGame() { this.node_guide.active = false; this.node_over.active = false; this.node_start.active = false; this.lab_score.node.active = true; this.lab_best.node.active = true; this.node_grid.active = true; // 是否首次进入界面 if (!cc.sys.localStorage.getItem('isStart')) { this.node_guide.active = true; } this._score = 0; // 更新最高分数 this.updateBest(); this._canControl = true; this._direction = { x: 1, y: 0 }; this._snakeGrid = []; this._foodGrid = {}; // 初始化触摸事件 this.openTouchEvent(); this.clearMap(); this.onCreateSnake(); this.onCreateFood(); // 开启移动 this.schedule(this.move, 1 / this.mSpeed); }, /** * 更新分数 */ updateBest() { this._best = cc.sys.localStorage.getItem('best'); if (this._best) { if (this._best < this._score) { this._best = this._score; cc.sys.localStorage.setItem('best', this._best); } } else { this._best = this._score; cc.sys.localStorage.setItem('best', this._best); } this.lab_best.string = this._best; }, /** * 游戏结束 */ gameOver() { // 是否能控制 蛇改变移动方向 this._canControl = false; this.unschedule(this.move); this.closeTouchEvent(); this.clearMap(); this.showOverGame(); }, /** * 创建蛇 */ onCreateSnake() { let x = ~~(Math.random() * this.rowCount); let y = ~~(Math.random() * this.colCount); for (let index = 0, length = this._map.length; index < length; index++) { if (this._map[index].x === x && this._map[index].y === y) { this._map[index].node.getComponent('cell').setCellColor(snakeColor); this._snakeGrid.push(this._map[index]); } } }, /** * 创建食物 */ onCreateFood() { if (this._map.length !== this._snakeGrid.length) { let r = ~~(Math.random() * (this._map.length - this._snakeGrid.length)); let subGrid = []; for (let i = 0; i < this._map.length; i++) { subGrid.push(this._map[i]); } for (let m = 0; m < subGrid.length; m++) { for (let n = 0; n < this._snakeGrid.length; n++) { if (subGrid[m].x === this._snakeGrid[n].x && subGrid[m].y === this._snakeGrid[n].y) { subGrid.splice(m, 1); if (m > 0) { m--; } } } } for (let index = 0; index < subGrid.length; index++) { if (index === r) { this._foodGrid = subGrid[index]; this._foodGrid.node.getComponent('cell').setCellColor(foodColor); // 增加分数 this._score++; this.lab_score.string = this._score; } } } }, /** * 打开触摸 */ openTouchEvent() { var self = this; this.node.on( cc.Node.EventType.TOUCH_START, function (touch) { if (self._canControl) { self._canControl = false; let touchPos = self.node.convertToNodeSpaceAR(touch.getLocation()); self._direction = self.getTouchDirection(touchPos); this.scheduleOnce(function () { self._canControl = true; }, 1 / this.mSpeed); } }, this ); }, /** * 关闭触摸 */ closeTouchEvent() { this.node.off(cc.Node.EventType.TOUCH_START, this); }, /** * 获取选择的方向 * @param {* 触摸位置} touchPos */ getTouchDirection(touchPos) { // 获取向量长度 function getABS(pos) { return Math.sqrt(pos.x * pos.x + pos.y * pos.y); } // 获取横向 方向 function getLandscape(touchPos) { if (touchPos.x > 0) { cc.log('更改为 向 右 移动'); return { x: 1, y: 0 }; } else { cc.log('更改为 向 左 移动'); return { x: -1, y: 0 }; } } // 获取竖向 方向 function getPortrait(touchPos) { if (touchPos.y > 0) { cc.log('更改为 向 上 移动'); return { x: 0, y: 1 }; } else { cc.log('更改为 向 下 移动'); return { x: 0, y: -1 }; } } if (getABS(this._direction) === 1) { cc.log('蛇 正在移动'); if (this._direction.y === 1) { cc.log('蛇 正在向 上 移动'); return getLandscape(touchPos); } else if (this._direction.y === -1) { cc.log('蛇 正在向 下 移动'); return getLandscape(touchPos); } else if (this._direction.x === -1) { cc.log('蛇 正在向 左 移动'); return getPortrait(touchPos); } else if (this._direction.x === 1) { cc.log('蛇 正在向 右 移动'); return getPortrait(touchPos); } } else { cc.log('蛇 未开始 或 停止了移动。此时修改方向无效!'); } }, /** * 移动 */ move() { let nextGrid = {}; nextGrid.x = this._snakeGrid[this._snakeGrid.length - 1].x + this._direction.x; nextGrid.y = this._snakeGrid[this._snakeGrid.length - 1].y + this._direction.y; if (this._direction.x === 1) { // 向右 if (nextGrid.x > this.colCount - 1) { nextGrid.x = 0; } } else if (this._direction.x === -1) { // 向左 if (nextGrid.x < 0) { nextGrid.x = this.colCount - 1; } } else if (this._direction.y === 1) { // 向上 if (nextGrid.y > this.rowCount - 1) { nextGrid.y = 0; } } else if (this._direction.y === -1) { // 向下 if (nextGrid.y < 0) { nextGrid.y = this.rowCount - 1; } } for (let m = 0, l = this._map.length; m < l; m++) { if (this._map[m].x === nextGrid.x && this._map[m].y === nextGrid.y) { nextGrid = this._map[m]; } } for (let n = 0, length = this._snakeGrid.length; n < length; n++) { if (nextGrid.x === this._snakeGrid[n].x && nextGrid.y === this._snakeGrid[n].y) { this.gameOver(); // return false; } } nextGrid.node.getComponent('cell').setCellColor(snakeColor); this._snakeGrid.push(nextGrid); if (nextGrid.x === this._foodGrid.x && nextGrid.y === this._foodGrid.y) { this.onCreateFood(); } else { let startGrid = this._snakeGrid.shift(); startGrid.node.getComponent('cell').setCellColor(noneColor); } },});

完整代码:js贪吃蛇游戏

更多有趣的经典小游戏实现专题,分享给大家:

C++经典小游戏汇总

python经典小游戏汇总

python俄罗斯方块游戏集合

JavaScript经典游戏 玩不停

java经典小游戏汇总

javascript经典小游戏汇总

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章