微信小程序-贪食蛇

作者: codingZero | 来源:发表于2017-01-17 16:19 被阅读2774次

    很久很久以前,差不多大半年前吧,笔者发布了一篇关于OC版贪食蛇开发的文章,时隔多月,微信小程序横空出世,于是闲来无事的我又写了一个小程序版

    下面这段话请务必阅读

    笔者是做iOS的,而小程序大部分都是前端的知识,笔者之前没有做过类似开发,所以代码写的相当烂,很多东西都是一边查资料一边写的,请各位轻喷,阿门!

    进入正题

    页面布局

    关于小程序笔者就不做介绍了,官方有详细文档,我们还是先来看张图吧

    就是这个样子的,游戏界面跟之前的OC版是差不多的,以笔者的水平,只能设计成这样了,毕竟不是专业的,话说这蛇怎么长的像个J(和)B(谐)啊😂

    先来看看用来添加组件的wxml文件

    <view class="backView">
      <canvas canvas-id="snakeCanvas" class="canvas"/>
    </view>
    <view class="controlView">
        <button class="btnClass" bindtap="changeDirection" id="up">up</button>
        <view style="display:flex; height:33.33%">
            <button class="btnClass" bindtap="changeDirection" id="left">left</button>
            <button class="btnClass" bindtap="startGame" >{{btnTitle}}</button>
            <button class="btnClass" bindtap="changeDirection" id="right">right</button>
        </view>
        <button class="btnClass" bindtap="changeDirection" id="down">down</button>
    </view>
    

    内容是相当简单滴,上面一个view,里面放一个画布,下面一个view,里面放5个按钮

    再来看看wxss布局

    内容不多,其实笔者对CSS也不是很了解,很多年前学习过,然而早随着💩排出去了,也许还有更优的布局方式,不过凑合着用吧

    功能实现

    布局还是很简单的,虽然不熟,但是多尝试几下还是可以弄出来的,接下来功能逻辑的实现才是重点,编程语言当然是js了。

    话说笔者当年学js的时候,可是写了满满一本的笔记,然而......算了,过去的就让他过去吧,往事不提也罢。

    思路其实与OC版的一样

    蛇:创建一个点坐标数组,然后以坐标点为中心在画布上画矩形
    食物:随机一个坐标点,该点不能在蛇身上,否则重新随机
    蛇的移动:把蛇尾的坐标移到蛇头前面就行了
    吃到食物:每次蛇移动完毕后,如果蛇头的坐标与食物的坐标一样,则蛇增长
    蛇的增长:在蛇尾后面加一个点坐标即可
    游戏结束:蛇头越界或撞到自己身体即游戏结束

    创建蛇
    //创建蛇,初始为5节,nodeWH为矩形的边长
    function createSnake(){
      nodes.splice(0, nodes.length) //清空数组
      for (var i = 4; i >= 0; i--) {
        var node = new Node(nodeWH * (i + 0.5), nodeWH * 0.5)
        nodes.push(node);
      }
    }
    
    创建食物
    function createFood(){
      //矩形的边长为10,画布宽度为250,高度为350,所以x只能取5-245,y只能取5-345
      var x = parseInt(Math.random() * 24) * nodeWH + nodeWH * 0.5
      var y = parseInt(Math.random() * 34) * nodeWH + nodeWH * 0.5
    
      //如果食物的坐标在蛇身上,则重新创建
      for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i]
        if (node.x == x && node.y == y) {
          createFood()
          return
        }
      }
      //Node为自定义的类,有两个属性x和y,表示坐标
      food = new Node(x,y)
    }
    
    蛇的移动

    蛇的移动是有方向的,所以用一个变量direction来记录蛇的移动方向,游戏开始时,默认是向右移动。

    上面有说到蛇的移动就是把蛇尾的坐标移到蛇头前面,但是这个前面并不是固定的,而是根据方向来判断的,如果向右移动则右边为前方,以此类推

    吃到食物与蛇增长

    每次移动完毕后,判断蛇头的坐标是否与食物的坐标相等就OK了,吃到食物后蛇的长度会增加,并且要创建一个新的食物

    function isEatedFood(){
      var head = nodes[0]
      if (head.x == food.x && head.y == food.y) {
        score++
        nodes.push(lastPoint)
        createFood()
      }
    }
    

    上面的代码中,lastPoint就是蛇每次移动前,蛇尾的坐标,如果移动后吃到食物,那么直接在移动前的蛇尾处加上一节即可

    游戏结束

    每次移动后,都要判断蛇头是否超过画布,或者撞到自己的身体

    function isDestroy(){
      var head = nodes[0]
      //判断是否撞到自己身体
      for (var i = 1; i < nodes.length; i++) {
        var node = nodes[i]
        if (head.x == node.x && head.y == node.y) {
          gameOver()
        }
      }
      //判断水平方向是否越界
      if (head.x < 5 || head.x > 245) {
        gameOver()
      }
      //判断垂直方向是否越界
      if (head.y < 5 || head.y > 345) {
        gameOver()
      }
    }
    
    界面绘制

    每次移动都要绘制,所以需要一个定时器,笔者用的setInterval

    function move(){
      lastPoint = nodes[nodes.length - 1]
      var node = nodes[0]
      var newNode = {x: node.x, y: node.y}
      switch (direction) {
        case 'up':
          newNode.y -= nodeWH;
        break;
        case 'left':
          newNode.x -= nodeWH;
        break;
        case 'right':
          newNode.x += nodeWH;
        break;
        case 'down':
          newNode.y += nodeWH;
        break;
      } 
      nodes.pop()
      nodes.unshift(newNode)
      moveEnd()
    }
    
    function startGame() {
      if (isGameOver) {
        direction = 'right'
        createSnake()
        createFood()
        score = 0
        isGameOver = false
      }
      timer = setInterval(move,300)
    }
    

    网上说setInterval的性能并不怎么好,建议用requestAnimationFrame,但是很遗憾,笔者不会用,准确的说是不知道怎么暂停

    var animateId = 0
    function move(){
        .
        .
        .
        animateId = requestAnimationFrame(move)
    }
    function startGame(){
        .
        .
        .
        animateId = requestAnimationFrame(move)
    }
    

    使用上面的方法可以实现蛇的移动与界面重绘,然而每次执行animateId都会被赋予新的值,所以使用cancelAnimationFrame(animateId)无法暂停,如果有懂前端开发的大神请指导下

    差不多整个逻辑就是这样的,喜欢研究的可以自己尝试下,需要源码的请自行下载,不要问我怎么打开,不要问我怎么打开,不要问我怎么打开!!!

    相关文章

      网友评论

      • 牛掰1234567:向你学习
      • iOS小王子:孙子加油,你是最吊的。你爹看好你 @codingZero 😬
      • a2934a679386:很棒,学习了
      • HelloYeah:牛擦
      • 4fcbca33706f:小程序就是封闭版的webapp,微信就是封闭的浏览器,别抽热闹了,Google才是未来
        4fcbca33706f: @十顿十 不是,我说的移动端浏览器的webapp
        46fdc45388ac:因为chrome么
        46fdc45388ac:为什么说google才是未来呢
      • 前端开发博客:赞,没想到还能写出游戏,厉害了
      • RM_乾笙:您的文章写得不错,您觉得微信小程序的前景怎样呢?
      • RM_乾笙:瞬间火了
      • 知晓程序:你好!我们是爱范儿旗下专注于小程序生态的公众号知晓程序(微信号 zxcx0101)。我们很赞赏你的文章,希望能获得转载授权。授权后,你的文章将会在知晓程序社区(minapp.com)、爱范儿、AppSo 等渠道发布,我们会注明来源和作者姓名。

        非常感谢~~~
        codingZero:@知晓程序 恩 好的
      • smartphp:转向时的逻辑是什么?
        codingZero:如果本来是右移的,此时向下转,就是移除蛇尾,并在蛇头下方添加一个点坐标,其他方向类似,详情可以看源码

      本文标题:微信小程序-贪食蛇

      本文链接:https://www.haomeiwen.com/subject/ifbmbttx.html