本文为大家分享了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经典小游戏汇总