原生微信小程序实现简单的贪食蛇小游戏

1、在页面中做好页面布局以及屏幕事件

可以在index文件夹中写代码,也可以在page目录下新建一个snake文件夹来书写。

.wxml文件:

<!--snake.wxml-->
<!-- bindtouchstart:触摸开始;bindtouchmove:触摸移动;bindtouchend:触摸结束 -->
<view class="control" bindtouchstart="tapStart" bindtouchmove="tapMove" bindtouchend="tapEnd">

  <view class="score">
    <view class="scoredetail">
      <button class="btn-start" bindtap="start">开始游戏♪(´▽`)</button>
    </view>
    <view class="scoredetail">
      <view class="scoredesc">得分(* ̄▽ ̄*)</view>
      <view class="scorenumber">{{score}}</view>
    </view>
  </view>

  <view class="ground">
    <view wx:for="{{ground}}" class="rows" wx:for-item="cols">
      <view wx:for="{{cols}}" class="block block_{{item}}">

      </view>
    </view>
  </view>
  
  <view class="scoredetail">
    <view class="scoredesc">历史最高分数</view>
    <view class="scorenumber">{{maxscore}}</view>
    <button class="reset" bindtap="clear">清空</button>
  </view>
  <modal class="modal" hidden="{{modalHidden}}" no-cancel bindconfirm="modalChange">
    <view> 游戏结束,得分{{score}} </view>
  </modal>
</view>

wxss文件:

.score {
  display: flex;
}

.title {
  flex: 1;
  height: 150rpx;
  line-height: 150rpx;
  background: rgb(0, 102, 255);
  margin: 40rpx 20rpx 40rpx 40rpx;
  text-align: center;
  font-size: 1.5rem;
  color: white;
  border-radius: 8rpx;
}


.scoredetail {
  flex: 1;
  height: 110rpx;
  background: #e9b47e;
  margin: 40rpx 20rpx;
  text-align: center;
  border-radius: 8rpx;
}

.scoredetail:last-child {
  margin-right: 40rpx;
  position: relative;
}

.scoredesc {
  font-size: 0.8rem;
  line-height: 60rpx;
}

.btn-start {
  height: 100%;
  background-color: #e9b47e;
  font-weight: 800;
}

.scorenumber {
  line-height: 70rpx;
}

.ground {
  width: 660rpx;
  height: 840rpx;
  margin-left: 40rpx;
}

.block {
  width: 30rpx;
  height: 30rpx;
  float: left;
  background: #ccc;
}

.rows {
  width: 660rpx;
  height: 30rpx;
}

.control {
  width: 100%;
  height: 100%;
}

.block_1 {
  background: rgb(25, 0, 255);
}

.block_2 {
  background: rgb(255, 0, 0);
}

.reset {
  width: 60px;
  height: 30px;
  font-size: 14px;
  margin: 0;
  position: absolute;
  top: 550px;
  left: 20px;
}

2、js逻辑书写

思路分析:

1.实现随机位置出现食物,点击开始游戏时,“蛇”被创建出来并开始移动。

2.捕捉屏幕滑动事件,设置变向函数,改变蛇的移动方向。

3.蛇吃到食物,分数自增,蛇的方块数自增,可设置吃到多次后给予分数奖励。

4.蛇头碰到墙壁或者蛇的身体时,游戏结束,弹出提示弹窗,比较当前分数与本地储存的最高分数,高于则保存,低于则舍弃。

5.设置事件音效,增强反馈效果。

.js文件:

//snake.js
var app = getApp();

Page({
  data: {
    score: 0, //比分
    maxscore: 0, //最高分
    startx: 0,
    starty: 0,
    endx: 0,
    endy: 0, //以上四个做方向判断
    ground: [], //存储地图每个方块
    rows: 28, //地图纵向长度
    cols: 22, //地图横向长度
    snake: [], //蛇
    food: [], //食物
    direction: '', //方向
    modalHidden: true, //模块隐藏(开)
    timer: '',
    txt: 0, //一个小标记
  },
  // 记录最高分
  onLoad: function () {
    var maxscore = wx.getStorageSync('maxscore');
    if (!maxscore) maxscore = 0
    this.setData({
      maxscore: maxscore
    });

    this.initGround(this.data.rows, this.data.cols); //初始化地图
    this.creatFood(); //初始化食物
  },
  //点击开始游戏
  start: function () {
    if (this.data.txt == 0) { //当txt=0时,允许游戏开始
      this.sound("start")
      this.data.direction = 'right', //初始化移动方向
        this.initSnake(4); //初始化蛇,数字为蛇的长度
      this.move(); //蛇移动
      this.data.txt = 1 //改变txt的值
    }
  },
  //计分器
  storeScore: function () {
    this.sound("AddScore");
    if (this.data.maxscore < this.data.score) {
      this.setData({
        maxscore: this.data.score
      })
      wx.setStorageSync('maxscore', this.data.maxscore)
    }
  },
  // 清空最高分
  clear: function () {
    wx.removeStorageSync('maxscore', this.data.maxscore);
    this.setData({
      maxscore: 0
    });
  },
  //地图
  initGround: function (rows, cols) {
    for (var i = 0; i < rows; i++) {
      var arr = [];
      this.data.ground.push(arr);
      for (var j = 0; j < cols; j++) {
        this.data.ground[i].push(0);
      }
    }
  },
  //蛇
  initSnake: function (len) {
    for (var i = 0; i < len; i++) {
      this.data.ground[0][i] = 1; //前者为蛇的初始纵坐标,后者为蛇的初始横坐标
      this.data.snake.push([0, i]);
    }
  },
  //移动函数
  move: function () {
    var that = this;
    this.data.timer = setInterval(function () {
      that.changeDirection(that.data.direction);
      that.setData({
        ground: that.data.ground
      });
    }, (300)); //蛇的移动速度
  },
  // 触摸开始点
  tapStart: function (event) {
    this.setData({
      startx: event.touches[0].pageX,
      starty: event.touches[0].pageY,
    })
  },
  // 触摸移动事件
  tapMove: function (event) {
    this.setData({
      endx: event.touches[0].pageX,
      endy: event.touches[0].pageY
    })
  },
  // 触摸结束点
  tapEnd: function (event) {
    var heng = (this.data.endx) ? (this.data.endx - this.data.startx) : 0;
    var shu = (this.data.endy) ? (this.data.endy - this.data.starty) : 0;

    if (Math.abs(heng) > 5 || Math.abs(shu) > 5) {
      var direction = (Math.abs(heng) > Math.abs(shu)) ? this.computeDir(1, heng) : this.computeDir(0, shu);
      switch (direction) { //防止反方向移动
        case 'left':
          if (this.data.direction == 'right') return;
          break;
        case 'right':
          if (this.data.direction == 'left') return;
          break;
        case 'top':
          if (this.data.direction == 'bottom') return;
          break;
        case 'bottom':
          if (this.data.direction == 'top') return;
          break;
        default:
      }
      this.setData({
        startx: 0,
        starty: 0,
        endx: 0,
        endy: 0,
        direction: direction
      })

    }
  },
  // 判断触摸移动的方向
  computeDir: function (heng, num) {
    this.sound("Change")
    if (heng) return (num > 0) ? 'right' : 'left';
    return (num > 0) ? 'bottom' : 'top';
  },
  creatFood: function () {
    var x = Math.floor(Math.random() * this.data.rows);
    var y = Math.floor(Math.random() * this.data.cols);
    var ground = this.data.ground;
    ground[x][y] = 2;
    this.setData({
      ground: ground,
      food: [x, y], //随机生成食物的坐标
    });
  },
  //触发变向事件的代码,左、右、上、下
  changeDirection: function (dir) {
    switch (dir) {
      case 'left':
        return this.changeLeft();
        break;
      case 'right':
        return this.changeRight();
        break;
      case 'top':
        return this.changeTop();
        break;
      case 'bottom':
        return this.changeBottom();
        break;
      default:
    }
  },
  // 变向事件,可以被封装
  changeLeft: function () {
    var arr = this.data.snake;
    var len = this.data.snake.length;
    var snakeHEAD = arr[len - 1][1];
    var snakeTAIL = arr[0];
    var ground = this.data.ground;
    ground[snakeTAIL[0]][snakeTAIL[1]] = 0;
    for (var i = 0; i < len - 1; i++) {
      arr[i] = arr[i + 1];
    };
    var x = arr[len - 1][0];
    var y = arr[len - 1][1] - 1;
    arr[len - 1] = [x, y];
    this.checkGame(snakeTAIL);
    for (var i = 1; i < len; i++) {
      ground[arr[i][0]][arr[i][1]] = 1;
    }

    this.setData({
      ground: ground,
      snake: arr
    });
    return true;
  },
  changeRight: function () {
    var arr = this.data.snake;
    var len = this.data.snake.length;
    var snakeHEAD = arr[len - 1][1];
    var snakeTAIL = arr[0];
    var ground = this.data.ground;
    ground[snakeTAIL[0]][snakeTAIL[1]] = 0;
    for (var i = 0; i < len - 1; i++) {
      arr[i] = arr[i + 1];
    };

    var x = arr[len - 1][0];
    var y = arr[len - 1][1] + 1;
    arr[len - 1] = [x, y];
    this.checkGame(snakeTAIL);
    for (var i = 1; i < len; i++) {
      ground[arr[i][0]][arr[i][1]] = 1;
    }

    this.setData({
      ground: ground,
      snake: arr
    });
    return true;
  },
  changeTop: function () {

    var arr = this.data.snake;
    var len = this.data.snake.length;
    var snakeHEAD = arr[len - 1][1];
    var snakeTAIL = arr[0];
    var ground = this.data.ground;
    ground[snakeTAIL[0]][snakeTAIL[1]] = 0;
    for (var i = 0; i < len - 1; i++) {
      arr[i] = arr[i + 1];
    };

    var x = arr[len - 1][0] - 1;
    var y = arr[len - 1][1];
    arr[len - 1] = [x, y];
    this.checkGame(snakeTAIL);
    for (var i = 1; i < len; i++) {
      ground[arr[i][0]][arr[i][1]] = 1;
    }
    this.setData({
      ground: ground,
      snake: arr
    });
    return true;
  },
  changeBottom: function () {

    var arr = this.data.snake;
    var len = this.data.snake.length;
    var snakeHEAD = arr[len - 1];
    var snakeTAIL = arr[0];
    var ground = this.data.ground;

    ground[snakeTAIL[0]][snakeTAIL[1]] = 0;
    for (var i = 0; i < len - 1; i++) {
      arr[i] = arr[i + 1];
    };
    var x = arr[len - 1][0] + 1;
    var y = arr[len - 1][1];
    arr[len - 1] = [x, y];
    this.checkGame(snakeTAIL);
    for (var i = 1; i < len; i++) {
      ground[arr[i][0]][arr[i][1]] = 1;
    }
    this.setData({
      ground: ground,
      snake: arr
    });
    return true;
  },

  // 若蛇头碰到墙或者自己的身体,游戏结束
  checkGame: function (snakeTAIL) {
    var arr = this.data.snake;
    var len = this.data.snake.length;
    var snakeHEAD = arr[len - 1];
    if (snakeHEAD[0] < 0 || snakeHEAD[0] >= this.data.rows || snakeHEAD[1] >= this.data.cols || snakeHEAD[1] < 0) {
      clearInterval(this.data.timer);
      this.sound("ikun");
      this.setData({
        modalHidden: false,
      })
    }
    for (var i = 0; i < len - 1; i++) {
      if (arr[i][0] == snakeHEAD[0] && arr[i][1] == snakeHEAD[1]) {
        clearInterval(this.data.timer);
        this.setData({
          modalHidden: false,
        })
      }
    }
    // 得分规则
    if (snakeHEAD[0] == this.data.food[0] && snakeHEAD[1] == this.data.food[1] && this.data.score % 50 == 0 && this.data.score != 0) //如果分数达到了50的倍数,除了0分以外吃掉食物都可以得到20分
    {
      arr.unshift(snakeTAIL);
      this.setData({
        score: this.data.score + 20 //吃一个食物奖励20分
      });
      this.storeScore();
      this.creatFood();
    }
    if (snakeHEAD[0] == this.data.food[0] && snakeHEAD[1] == this.data.food[1]) { //如果分数不是50的倍数,或者0分时吃掉食物都可以得到10分
      arr.unshift(snakeTAIL);
      this.setData({
        score: this.data.score + 10 //吃一个食物奖励10分
      });
      this.storeScore(); //存储分数
      this.creatFood(); //再次创建食物
    }
  },
  modalChange: function () {
    this.data.txt = 0; //游戏结束时,让txt=0
    this.setData({
      score: 0,
      ground: [],
      snake: [],
      food: [],
      modalHidden: true,
      direction: ''
    })
    this.onLoad();
  },

  // 游戏音效
  sound: function (x) {
    const innerAudioContext = wx.createInnerAudioContext()
    innerAudioContext.autoplay = false // 是否自动开始播放,默认为 false
    innerAudioContext.loop = false // 是否循环播放,默认为 false
    wx.setInnerAudioOption({ // ios在静音状态下能够正常播放音效
      obeyMuteSwitch: false, // 是否遵循系统静音开关,默认为 true。当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音。
      success: function (e) {},
      fail: function (e) {}
    })
    innerAudioContext.src = `/pages/mp3/${x}.mp3`
    innerAudioContext.play()
  }
});

效果图:

 

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值