vue2 贪吃蛇的实现思路

前言

之前用原生的JavaScrip写过一次贪吃蛇,逻辑稍显复杂,后面用JQuery做过一个优化,但是整体的效果不是很好,这里我们用vue2来粗略地实现。

思路

要让一条蛇在画板上跑,因此首先我们要新建一个画板元素div,先暂时固定宽高,然后给定一个背景色,样式后面再来优化。

vue2 贪吃蛇的实现思路_第1张图片

然后我们再来放一条蛇,新增一个list的数据,然后初始化它的坐标为(0, 0)、(0, 1)、(0, 2)、(0, 3)、(0, 4),其中x表示每一个元素位于多少行,y表示位于多少列。

this.list = new Array(length).fill(0).map((el, index) => ({ x: 0, y: index })) 

然后我们要v-if渲染到画板上,同时配上位置函数,将每个元素都位置都放好。

getPosotion({ x, y }) {
  return {
    top: `${x * 20}px`,
    left: `${y * 20}px`,
  }
}, 

vue2 贪吃蛇的实现思路_第2张图片

现在我们来让这条蛇元素动起来,很简单,列表中的数据,后一个的坐标来覆盖前一个的坐标即可,而最后一个元素,也就是蛇头,我们固定让它的y自增1就可以了。

const list = [...this.list]
const len = list.length
const head = list[len - 1]

list.forEach((item, index) => {
  if (index < len - 1) {
    const next = list[index + 1]

    ;[item.x, item.y] = [next.x, next.y]
  }
})

head.y += 1 

现在它就动起来了。

vue2 贪吃蛇的实现思路_第3张图片

现在来想一个问题呢,如果定时器一直跑,蛇就跑出画板了,同时我们还不能控制方向,因此我们需要监听键盘的按下事件,同时,我们需要一个current值来保存当前的方向。

addEventListener() {
  document.addEventListener('keydown', ({ keyCode }) => {
     this.current = keyCode
  })
}, 

然后在移动的函数中,根据当前的方向值,来让蛇上下左右移动。

const keyCodes = {
  LEFT: 37,
  TOP: 38,
  RIGHT: 39,
  BOTTOM: 40,
}

switch (this.current) {
  case keyCodes.RIGHT:
    head.y += 1
    break
  case keyCodes.LEFT:
    head.y -= 1
    break
  case keyCodes.BOTTOM:
    head.x += 1
    break
  case keyCodes.TOP:
    head.x -= 1
    break
}

this.list = list 

现在,我们的大蛇可以上下左右移动了。

vue2 贪吃蛇的实现思路_第4张图片

然后再来考虑碰撞问题,无非就是四个边界,还有就是自身也可能发生碰撞,这里直接上代码。边界碰撞只需要判断头部元素的坐标值和边界之间的关系,而自身碰撞,需要头部坐标与除了头部以外的剩余蛇身体部分的坐标做比较,如果有一个相等,some再好不过,那么就是碰撞了自身,游戏将结束。

isImpact() {
  const len = this.list.length
  const { x: headX, y: headY } = this.list[len - 1]
  const { cols, rows } = this.getRowsCols()

  if (this.list.slice(0, len - 1).some(({ x, y }) => x === headX && y === headY)) {
    return true
  }

  if (headY >= cols) {
    return true
  }

  if (headX >= rows) {
    return true
  }

  if (headX < 0) {
    return true
  }

  if (headY < 0) {
    return true
  }

  return false
}, 

这里就是自己撞自己的情况。

vue2 贪吃蛇的实现思路_第5张图片

以上情况都解决之后呢,我们再来考虑生成苹果的情况,蛇嘛,让吃此苹果就行了。逻辑上也很简单,根据画布的情况,随机生成一个苹果,然后我们要判断每一个方向时,只要苹果的坐标和蛇头的坐标满足条件与否。举个栗子,假设蛇往右移动,那么就是currentRIGHTkeycode时,且苹果的x和蛇头的x相同,而蛇头的y + 1是等于苹果的y的话,表明蛇可以吃苹果,然后我们往listpush一个空对象就可以了。为什么是空对象呢,因为下一次移动时,空对象将被上一个对象覆盖。

canEat() {
  const len = this.list.length
  const { x: headX, y: headY } = this.list[len - 1]
  const { x, y } = this.apple

  if (this.current === keyCodes.RIGHT) {
    if (headY + 1 === y && headX === x) {
      return true
    }
  }

  if (this.current === keyCodes.LEFT) {
    if (headY - 1 === y && headX === x) {
      return true
    }
  }

  if (this.current === keyCodes.TOP) {
    if (headX - 1 === x && headY === y) {
      return true
    }
  }

  if (this.current === keyCodes.BOTTOM) {
    if (headX + 1 === x && headY === y) {
      return true
    }
  }

  return false
}, 

一个简单的贪吃蛇就完成了,你可以添加一些得分,或者暂停按钮,或者其它的样式,这里是完整的代码。





 

最后的效果。

vue2 贪吃蛇的实现思路_第6张图片

你可能感兴趣的:(javascript,前端,typescript)