微信小程序-贪食蛇

Kry0892 7年前
   <p>很久很久以前,差不多大半年前吧,笔者发布了一篇关于OC版贪食蛇开发的文章,时隔多月,微信小程序横空出世,于是闲来无事的我又写了一个小程序版</p>    <h2>下面这段话请务必阅读</h2>    <p>笔者是做iOS的,而小程序大部分都是前端的知识,笔者之前没有做过类似开发,所以代码写的相当烂,很多东西都是一边查资料一边写的,请各位轻喷,阿门!</p>    <h2>进入正题</h2>    <p>页面布局</p>    <p>关于小程序笔者就不做介绍了,官方有详细文档,我们还是先来看张图吧</p>    <p><img src="https://simg.open-open.com/show/81e0a01110e730ce3241e481d4ca1cdc.png"></p>    <p>就是这个样子的,游戏界面跟之前的OC版是差不多的,以笔者的水平,只能设计成这样了,毕竟不是专业的,话说这蛇怎么长的像个J(和)B(谐)啊:joy:</p>    <p>先来看看用来添加组件的wxml文件</p>    <pre>  <code class="language-javascript"><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></code></pre>    <p>内容是相当简单滴,上面一个view,里面放一个画布,下面一个view,里面放5个按钮</p>    <p>再来看看wxss布局</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7d554e5fed881d9f79b2c0211d0a8ec4.png"></p>    <p>内容不多,其实笔者对CSS也不是很了解,很多年前学习过,然而早随着:hankey:排出去了,也许还有更优的布局方式,不过凑合着用吧</p>    <p>功能实现</p>    <p>布局还是很简单的,虽然不熟,但是多尝试几下还是可以弄出来的,接下来功能逻辑的实现才是重点,编程语言当然是js了。</p>    <p>话说笔者当年学js的时候,可是写了满满一本的笔记,然而......算了,过去的就让他过去吧,往事不提也罢。</p>    <p>思路其实与OC版的一样</p>    <p>蛇:创建一个点坐标数组,然后以坐标点为中心在画布上画矩形</p>    <p>食物:随机一个坐标点,该点不能在蛇身上,否则重新随机</p>    <p>蛇的移动:把蛇尾的坐标移到蛇头前面就行了</p>    <p>吃到食物:每次蛇移动完毕后,如果蛇头的坐标与食物的坐标一样,则蛇增长</p>    <p>蛇的增长:在蛇尾后面加一个点坐标即可</p>    <p>游戏结束:蛇头越界或撞到自己身体即游戏结束</p>    <p>创建蛇</p>    <pre>  <code class="language-javascript">//创建蛇,初始为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);    }  }</code></pre>    <p>创建食物</p>    <pre>  <code class="language-javascript">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)  }</code></pre>    <p>蛇的移动</p>    <p>蛇的移动是有方向的,所以用一个变量direction来记录蛇的移动方向,游戏开始时,默认是向右移动。</p>    <p>上面有说到蛇的移动就是把蛇尾的坐标移到蛇头前面,但是这个前面并不是固定的,而是根据方向来判断的,如果向右移动则右边为前方,以此类推</p>    <p>吃到食物与蛇增长</p>    <p>每次移动完毕后,判断蛇头的坐标是否与食物的坐标相等就OK了,吃到食物后蛇的长度会增加,并且要创建一个新的食物</p>    <pre>  <code class="language-javascript">function isEatedFood(){    var head = nodes[0]    if (head.x == food.x && head.y == food.y) {      score++      nodes.push(lastPoint)      createFood()    }  }</code></pre>    <p>上面的代码中,lastPoint就是蛇每次移动前,蛇尾的坐标,如果移动后吃到食物,那么直接在移动前的蛇尾处加上一节即可</p>    <p>游戏结束</p>    <p>每次移动后,都要判断蛇头是否超过画布,或者撞到自己的身体</p>    <pre>  <code class="language-javascript">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()    }  }</code></pre>    <p>界面绘制</p>    <p>每次移动都要绘制,所以需要一个定时器,笔者用的setInterval</p>    <pre>  <code class="language-javascript">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)  }</code></pre>    <p>网上说setInterval的性能并不怎么好,建议用requestAnimationFrame,但是很遗憾,笔者不会用,准确的说是不知道怎么暂停</p>    <pre>  <code class="language-javascript">var animateId = 0  function move(){      .      .      .      animateId = requestAnimationFrame(move)  }  function startGame(){      .      .      .      animateId = requestAnimationFrame(move)  }</code></pre>    <p>使用上面的方法可以实现蛇的移动与界面重绘,然而每次执行animateId都会被赋予新的值,所以使用cancelAnimationFrame(animateId)无法暂停,如果有懂前端开发的大神请指导下</p>    <p>差不多整个逻辑就是这样的,喜欢研究的可以自己尝试下。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/f2e6947b4b70</p>    <p> </p>