在微信小游戏中开发一个贪食蛇

我自己也写过一个贪食蛇的小游戏,不过是对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)
})

模拟器中效果:

也可以点击编辑器预览按钮扫描二维码真机试玩。

猜你喜欢

转载自my.oschina.net/tbd/blog/1649337