当前位置: 代码网 > it编程>网页制作>html5 > canvas实现贪食蛇的实践

canvas实现贪食蛇的实践

2022年02月14日 html5 我要评论
canvas实现贪食蛇的实践本文主要介绍了canvas实现贪食蛇的实践,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下... 22-02-14

贪食蛇

数据结构及变量

const canvas = document.getelementbyid("canvas")
const ctx = canvas.getcontext("2d")

const width = 400
const height = 400
const celllength = 20

let foodposition

let initsnake = [
  [0, 0],
  [1, 0],
  [2, 0],
]

let snake = [...initsnake]

let direction = "right"

let canchangedirection = true

canvas 绘制页面

//  背景
function drawbackground() {
  ctx.strokestyle = "#bfbfbf"
  for (let i = 0; i <= height / celllength; i++) {
    ctx.beginpath()
    ctx.moveto(0, celllength * i)
    ctx.lineto(width, celllength * i)
    ctx.stroke()
  }

  for (let i = 0; i <= width / celllength; i++) {
    ctx.beginpath()
    ctx.moveto(celllength * i, 0)
    ctx.lineto(celllength * i, height)
    ctx.stroke()
  }
}

// 蛇
function drawsnake() {
  let step = 100 / (snake.length - 1)
  for (let i = 0; i < snake.length; i++) {
    // 这里做了渐变色的蛇,添加动态色彩。尾部有个最小白色阀值,免得跟背景混为一体
    const percent = math.min(100 - step * i, 90)
    ctx.fillstyle = `hsl(0,0%,${percent}%)`

    ctx.fillrect(
      snake[i][0] * celllength,
      snake[i][1] * celllength,
      celllength,
      celllength
    )
  }
}

// 绘制食物

// 随机生成食物的位置
function generaterandomfood() {
  // 如果没有位置可以生成
  if (snake.length > width * height) {
    return alert("you win")
  }
  const randomx = math.floor(math.random() * (width / celllength))
  const randomy = math.floor(math.random() * (height / celllength))
  // 生成的位置如果跟蛇体积碰撞,则重新生成。
  for (let i = 0; i < snake.length; i++) {
    if (snake[i][0] === randomx && snake[i][1] === randomy) {
      return generaterandomfood()
    }
  }
  foodposition = [randomx, randomy]
}

// 绘制
function drawfood() {
  ctx.fillstyle = "#ff7875"
  ctx.fillrect(
    foodposition[0] * celllength,
    foodposition[1] * celllength,
    celllength,
    celllength
  )
}

蛇的移动

// 蛇的移动
// 确定下一次移动的位置,将这个点push到数组末尾(头的位置),
// 将数组第一项shift出来(尾的位置)

// 吃食物的逻辑
// 如果食物的位置跟下一次移动的位置相同,将这个点加入头部,不推出尾部

function snakemove() {
  let next
  let last = snake[snake.length - 1]
  // 根据方向确定下一个蛇头的位置
  switch (direction) {
    case "up": {
      next = [last[0], last[1] - 1]
      break
    }
    case "down": {
      next = [last[0], last[1] + 1]
      break
    }
    case "left": {
      next = [last[0] - 1, last[1]]
      break
    }
    case "right": {
      next = [last[0] + 1, last[1]]
      break
    }
  }

  // 边缘碰撞
  const boundary =
    next[0] < 0 ||
    next[0] >= width / celllength ||
    next[1] < 0 ||
    next[1] >= height / celllength

  // 自身碰撞
  const selfcollision = snake.some(([x, y]) => next[0] === x && next[1] === y)

  // 碰撞重新开始游戏
  if (boundary || selfcollision) {
    return restart()
  }

  snake.push(next)

  // 如果下一个点是食物的位置,不推出头部
  if (next[0] === foodposition[0] && next[1] === foodposition[1]) {
    generaterandomfood()
    return
  }
  snake.shift()

  canchangedirection = true
}

事件监听

document.addeventlistener("keydown", (e) => {
  switch (e.key) {
    case "arrowup":
      if (direction === "down" || !canchangedirection) return
      direction = "up"
      canchangedirection = false
      break
    case "arrowdown":
      if (direction === "up" || !canchangedirection) return
      direction = "down"
      canchangedirection = false
      break
    case "arrowleft":
      if (direction === "right" || !canchangedirection) return
      direction = "left"
      canchangedirection = false
      break
    case "arrowright":
      if (direction === "left" || !canchangedirection) return
      direction = "right"
      canchangedirection = false
      break
  }
})

requestanimationframe 实现动画

// 默认的requestanimationframe循环应该是60帧,对于这个游戏来说太快了。
// 所以做了限制,5次loop才渲染(蛇移动一格)一次
function animate() {
  let count = 0
  function loop() {
    if (++count > 5) {
      draw()
      count = 0
    }
    requestanimationframe(loop)
  }
  requestanimationframe(loop)
}

bug 解决

// 事件回调
case "arrowup":
  if (direction === "down" |!canchangedirection) return
  direction = "up"
  canchangedirection = false
  break

到此这篇关于canvas实现贪食蛇的实践的文章就介绍到这了,更多相关 canvas贪食蛇内容请搜索代码网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com