我自己也写过一个贪食蛇的小游戏,不过是对dom的操作,微信小游戏是采用js语法基于canvas的开发。为了省事在网上直接搜了一个基于canvas的贪食蛇实现。
非常感谢作者: 不是加多宝的宝 (来自简书)
文章地址:https://www.jianshu.com/p/ba5031c20cde
不过作者的代码如果想完全在小游戏中使用需要做一些修改,比如eval的支持问题,alert的支持问题,还有就是源代码的事件是键盘事件,蛇的宽高太小等。我对源代码做了上述部分的修改,下面是目录结构和代码,大家可以创建项目,复制代码演示:
根目录:
js目录:
libs目录保持不变,采用快速生成会自动生成这个目录;
libs目录:
game.js
import './js/libs/weapp-adapter'
import './js/libs/symbol'
import Main from './js/main'
js/main.js
var c = canvas.getContext('2d')
console.log(canvas)
var mWidth = canvas.width; //当前可视区域的宽,即canvas的宽
var mHeight = canvas.height; //当前可视区域的高,即canvas的高
var unit = 15; //设定每个格子的边长
var mwid = mWidth / unit; //计算当前横向格子数量
var mhei = mHeight / unit; //计算当前竖向格子数量
var point = point = {x : 0 , y : 0}; //记录食物的坐标的变量初始化
var score = 0; //记录成绩的变量初始化
//注意本对象,并不改变其在画布上的样子,只是负责改变状态,改变样子的另有方法
//蛇对象
var shake = {
startX: 3,
//开始头x坐标
startY: 0,
//开始头y坐标
currOri: 'right',
//初始化方向
ori: [['left', 'right'], ['up', 'down']],
//相逆方向数组
oriss: ['left', 'right', 'up', 'down'],
//所有允许的方向,用来判断方向合法性,在canChangeOri方法
mes: [{
x: 3,
y: 0
},
{
x: 2,
y: 0
},
{
x: 1,
y: 0
}],
//初始化蛇的身体坐标,初始长度3
//坐标为格子坐标非像素坐标
//添加一个身体的方法
add: function () {
//判断当前尾部方向
var last = this.mes[this.mes.length - 1]; //获取最后一个身体
var plast = this.mes[this.mes.length - 2]; //获取倒数第二个身体
var px = last.x - plast.x;
var py = last.y - plast.y; //根据计算最后两个身体的坐标差,来计算添加身体应在的方向
//计算新加元素位置
var newEle = {
x: last.x + px,
y: last.y + py
}; //创建一个新身体
this.mes.push(newEle); //将新身体假如身体数组
},
//移动方向方法,下面几个方法类似,只是方向不同
moveup: function () {
var pre = this.mes[0]; //记录第一个身体,即头部的坐标
this.mes[0] = {
x: pre.x,
y: pre.y - 1
}; //让头部的坐标像上移动一格
this.move(pre); //调用移动身体的方法
},
movedown: function () {
var pre = this.mes[0];
this.mes[0] = {
x: pre.x,
y: pre.y + 1
};
this.move(pre);
},
moveleft: function () {
var pre = this.mes[0];
this.mes[0] = {
x: pre.x - 1,
y: pre.y
};
this.move(pre);
},
moveright: function () {
var pre = this.mes[0];
this.mes[0] = {
x: pre.x + 1,
y: pre.y
};
this.move(pre);
},
//移动身体
move: function (pre) { //参数为之前第一个身体,即头部的位置对象
var tmp;
for (var i = 1; i < this.mes.length; i++) { //遍历每一个身体节点
tmp = this.mes[i];
this.mes[i] = pre;
pre = tmp;
} //并且把每个节点的左边变化成前一个节点的坐标,达到依次向前的目的
},
//改变方向
changeOri: function (ori) {
if (this.oriss.indexOf(ori) == -1) { //判断方向是否在允许方向内
return;
}
if (!this.canChangeOri(ori)) { //判断改变方向是否合法
return;
}
this.currOri = ori; //如果上面两个都通过,改变方向
},
//判断改变的方向是否合法
canChangeOri: function (ori) { //参数为方向字符串 例如:left
if (ori == this.currOri) { //判断方向是否为当前方向,如果是则无需操作
return false;
}
var oris = null;
for (var i in this.ori) { //判断是否改变方向为当前方向的逆方向
if (this.ori[i].indexOf(this.currOri) != -1) {
oris = this.ori[i];
break;
}
}
if (oris.indexOf(ori) != -1) {
return false;
}
return true;
},
//判断是否碰撞到了自己
isCrashSelf: function () {
var head = this.mes[0]; //获取头节点
for (var i = 1; i < this.mes.length; i++) { //遍历身体节点
if (this.mes[i].x == head.x && this.mes[i].y == head.y) { //判断头结点是否碰撞身体
return true;
}
}
return false;
},
//判断是否撞墙
isCrashWell: function (width, height) { //参数为横竖的格子数量
var head = this.mes[0]; //获取头节点
if (head.x < 0 || head.y < 0) { //判断是否撞左上墙
return true;
}
if (head.x > (width - 1) || head.y > (height - 1)) { //判断是否撞右下墙
return true;
}
return false;
},
//处理吃东西
handleAdd: function () {
var head = this.mes[0]; //获取头节点
if (head.x == point.x && head.y == point.y) { //判断头节点是否碰撞食物节点,食物在外定义
this.add(); //调用添加身体
getPoint(); //生成一个节点
setPoint(); //画一个节点
score++; //加分
//s.innerHTML = score; //显示分数
}
}
}
//生成点
function getPoint() {
point.x = Math.floor(Math.random( ) * mwid);
point.y = Math.floor(Math.random( ) * mhei);
}
//画点
function setPoint() {
c.rect(point.x * unit, point.y * unit, unit, unit);
}
//画蛇
function setShake() {
for (var i = 0; i < shake.mes.length; i++) {
//c.fullStyle = '#ffffff';
c.strokeStyle = 'red';
c.rect(shake.mes[i].x * unit, shake.mes[i].y * unit, unit, unit);
}
c.stroke();
}
//清屏
function clear() {
c.clearRect(0, 0, mWidth, mHeight);
}
//开始游戏
var looper=null;
function startGame() {
clearInterval(looper); //终止游戏主循环
//初始化状态
shake.mes = [{
x: 3,
y: 0
},
{
x: 2,
y: 0
},
{
x: 1,
y: 0
}];
shake.currOri = 'right';
c.beginPath(); //开始画笔
getPoint(); //设置点
setPoint();
setShake(); //话蛇
//画
c.stroke();
//游戏主循环
looper = setInterval(function () {
//var method = 'move' + shake.currOri + '()'; //调用方向函数
//eval('shake.' + method); //执行方向方法
/*
移动
*/
//ori: [['left', 'right'], ['up', 'down']],
if (shake.currOri =="left"){
shake.moveleft();
} else if (shake.currOri == "right"){
shake.moveright();
} else if (shake.currOri == "up"){
shake.moveup();
} else if (shake.currOri == "down"){
shake.movedown();
}
clear(); //清理屏幕
c.beginPath(); //开始绘制
shake.handleAdd(); //处理吃东西
setPoint(point); //设置点
setShake(); //画蛇
if (shake.isCrashWell(mwid, mhei)) { //是否撞墙,未使用是否吃自己。想用调用shake.isCrashSelf方法。
clearInterval(looper);
//console.log('you die');
//console.log('you die , and your score is ' + score);
/*
提示
*/
wx.showModal({
title: '提示',
content: '游戏结束 , 你的分数是 ' + score,
success: function (res) {
if (res.confirm) {
console.log('用户点击确定')
startGame()
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
},
200);
}
/*
启动
*/
wx.showModal({
title: '提示',
content: '是否开始游戏 ',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定')
startGame()
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
//键盘监听
// window.onkeyup = function (key) {
// var ori = '';
// switch (key.keyCode) {
// case 65:
// ori = 'left';
// break;
// case 68:
// ori = 'right';
// break;
// case 87:
// ori = 'up';
// break;
// case 83:
// ori = 'down';
// break;
// }
// if (ori == '') {
// return;
// }
// //改变蛇走向
// shake.changeOri(ori);
// }
/*
方向
*/
var startX=0;
var startY = 0;
var moveEndX = 0;
var moveEndY = 0;
wx.onTouchStart(function (e) {
//pageX
//pageY
//console.log(e.touches[0])
startX = e.changedTouches[0].pageX;
startY = e.changedTouches[0].pageY;
})
wx.onTouchMove(function (e) {
// console.log(e.touches[0])
})
wx.onTouchEnd(function (e) {
//console.log(e.changedTouches[0])
moveEndX = e.changedTouches[0].pageX;
moveEndY = e.changedTouches[0].pageY;
var X = moveEndX - startX;
var Y = moveEndY - startY;
if (Math.abs(X) > Math.abs(Y) && X > 0) {
console.log("right");
shake.changeOri("right");
}
else if (Math.abs(X) > Math.abs(Y) && X < 0) {
console.log(" left");
shake.changeOri("left");
}
else if (Math.abs(Y) > Math.abs(X) && Y > 0) {
console.log("down");
shake.changeOri("down");
}
else if (Math.abs(Y) > Math.abs(X) && Y < 0) {
console.log("up");
shake.changeOri("up");
}
else {
console.log("just touch");
}
})
wx.onTouchCancel(function (e) {
console.log(e.touches)
})
模拟器中效果:
也可以点击编辑器预览按钮扫描二维码真机试玩。