基于canvas实现贪吃蛇游戏

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #map {
        display: block;
        margin: 0 auto;
        background-color: rgb(0, 135, 189);
      }
    </style>
  </head>
  <body>
    <canvas id="map" width="600" height="600"></canvas>
  </body>
  <script>
    const map = document.querySelector("#map");//获取canvas标签
    const tools = map.getContext("2d"); //设置2d视图
    let x = Math.floor(Math.random() * 20); //设置初次加载时食物随机出现的位置
    let y = Math.floor(Math.random() * 20);
    //设置数次加载时蛇的位置
    let snake = [
      { x: 3, y: 1 },
      { x: 2, y: 1 },
      { x: 1, y: 1 },
    ];
    let isEated = false;
    //给window设置键盘按下监听事件,但是蛇不能掉头即不能按完下之后再按上
    window.addEventListener("keydown", function (event) {
      switch (event.keyCode) {
        case 38: //上
          if (directionX === 0 && directionY === 1) {
          } else {
            directionX = 0;
            directionY = -1;
          }
          break;
        case 40: //下
          if (directionX === 0 && directionY === -1) {
          } else {
            directionX = 0;
            directionY = 1;
          }
          break;
        case 37: //左
          if (directionX === 1 && directionY === 0) {
          } else {
            directionX = -1;
            directionY = 0;
          }
          break;
        case 39: //右
          if (directionX === -1 && directionY === 0) {
          } else {
            directionX = 1;
            directionY = 0;
          }
          break;
      }
    });
    //设置蛇的默认前进方向
    let directionX = 1;
    let directionY = 0;
    let GameOver = false;
    setInterval(() => {
        //如果蛇头和蛇身的值相同则判定为蛇吃到自己
      for (var i = 0; i < snake.length - 1; i++) {
        if (snake[0].x === snake[i + 1].x && snake[0].y === snake[i + 1].y) {
          GameOver = true;
        }
      }
      //如果蛇头位置超过20或小于0则判定触边且重置蛇的位置,return的作用是结束画布渲染
      if (
        snake[0].x >= 20 ||
        snake[0].y >= 20 ||
        snake[0].x < 0 ||
        snake[0].y < 0 ||
        GameOver
      ) {
        alert("游戏结束,你的得分为" + (snake.length - 3) + "分");
        //重置蛇的位置
        snake = [
          { x: 3, y: 1 },
          { x: 2, y: 1 },
          { x: 1, y: 1 },
        ];
        directionX = 1;
        directionY = 0;
        GameOver=false
        return;
      }
      //重置画布
      tools.clearRect(0, 0, 600, 600);
      //网格线moveTo为开始的坐标lineTo为结束的坐标,+0.5是为了画出1px的线
      for (var i = 1; i < 20; i++) {
        tools.moveTo(0, 30 * i + 0.5);
        tools.lineTo(600, 30 * i + 0.5);
        tools.moveTo(30 * i + 0.5, 0);
        tools.lineTo(30 * i + 0.5, 600);
      }
      tools.strokeStyle = "white";
      //渲染网格
      tools.stroke();
      //旧蛇头
      let oldHead = snake[0];
      //新蛇头即前进的方向directionX为正则向X正轴前进directionY为正则向Y正轴前进
      let newHead = {
        x: oldHead.x + directionX,
        y: oldHead.y + directionY,
      };
      //加入新的蛇头
      snake.unshift(newHead);
      //画出蛇以及设置蛇身的颜色和蛇头的颜色*30的原因是因为我们设置的格子是30*30的
      for (var i = 0; i < snake.length; i++) {
        if (i === 0) {
          tools.fillStyle = "#ff0033";
        } else {
          tools.fillStyle = "#333399";
        }
        tools.fillRect(snake[i].x * 30, snake[i].y * 30, 30, 30);
      }
      //当蛇头触碰到食物时让isEated的值为true,当没碰到的时候删除蛇尾已实现吃食物变长,不吃食物则移动的效果
      if (snake[0].x === x && snake[0].y === y) {
        isEated = true;
      } else {
        isEated = false;
        snake.pop(oldHead);
      }
      //isEated的值为true意味着食物已经被吃下重新设置食物的位置
      if (isEated) {
        x = Math.floor(Math.random() * 20);
        y = Math.floor(Math.random() * 20);
      }
      //填充食物的颜色和位置
      tools.fillStyle = "#cccc00";
      tools.fillRect(x * 30, y * 30, 30, 30);
    }, 120);
  </script>
</html>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值