我自己也写过一个贪食蛇的小游戏,不过是对dom的操作,微信小游戏是采用js语法基于canvas的开发。为了省事在网上直接搜了一个基于canvas的贪食蛇实现。
非常感谢作者: (来自简书)
文章地址:
不过作者的代码如果想完全在小游戏中使用需要做一些修改,比如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)})
模拟器中效果:
也可以点击编辑器预览按钮扫描二维码真机试玩。