canvas迷宫小游戏(矩形的碰撞测试)

264 阅读1分钟

canvas中碰撞测试是难度较大的知识点,特别是不规则图形。我们首先学习规则的图形,比如说矩形。

下面是我们实现一个迷宫的小游戏,不考虑代码优化,只是单纯的实现功能,知道碰撞测试实现的原理

image.png

实例代码:

// html
<!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>cancas规则图形碰撞检测</title>
  </head>
  <body>
    <div class="container">
      <canvas class="canvas" id="canvas" width="500" height="500">
        浏览器不支持canvas 更换高版本的浏览器
      </canvas>
      <div class="title">迷宫小游戏</div>
    </div>
  </body>
  <style>
    .container {
      width: 500px;
    }

    .canvas {
      border: 1px solid #999;
    }

    .title {
        text-align: center;
    }
  </style>
  <script src="index.js"></script>
</html>
// js
var walls = [
  { x: 50, y: 50, width: 100, height: 100 },
  { x: 200, y: 100, width: 100, height: 250 },
  { x: 350, y: 50, width: 100, height: 50 },
  { x: 200, y: 150, width: 150, height: 50 },
  { x: 100, y: 250, width: 50, height: 200 },
  { x: 400, y: 200, width: 50, height: 200 }
]

var x = 0,
  y = 0

function main() {
  var canvas = document.getElementById('canvas')
  var ctx = canvas.getContext('2d')
  draw(ctx, x, y)
  handle(canvas, ctx)
}

/**
 * 画迷宫的墙壁
 */
function setWalls(ctx) {
  ctx.save()
  ctx.fillStyle = '#999'
  walls.forEach((item) => {
    ctx.fillRect(item.x, item.y, item.width, item.height)
  })
  ctx.restore()
}

/**
 * 设置动的小方块
 */
function setPlayer(ctx, x, y) {
  ctx.save()
  ctx.fillStyle = '#FB7365'
  ctx.fillRect(x, y, 50, 50)
  ctx.restore()
}

function checkMove() {
  var resuld
  for (var i = 0; i < walls.length; i++) {
    if (!isCollide(walls[i])) {
      resuld = false
      break  // 代表只要找到不满足的一项就退出循环 不然会画在障碍物上面
    } else {
      resuld = true
    }
  }
  return resuld
}

/**
 * 这地意思是在障碍物的上 下 左 右都就代表可以操作
 */
function isCollide(b) {
  return (
    y + 50 <= b.y || y >= b.y + b.height || x + 50 <= b.x || x >= b.x + b.width
  )
}

/**
 * 重绘的画布的元素
 */
function draw(ctx, x, y) {
  setWalls(ctx)
  setPlayer(ctx, x, y)
}

/**
 * 监听play的事件
 */
function handle(canvas, ctx) {
  // 对于canvas元素,它支持javascript所有鼠标事件,但是如果监听键盘事件则并不会生效。
  // 键盘输入事件只发生在当前 拥有焦点的HTML元素上 ,如果没有元素拥有焦点,那么事件将会上移至windows和document对象
  document.onkeydown = function (event) {
    if (event.key == 'ArrowDown' && y < canvas.height - 50) {
      y += 50
      if (checkMove()) {
        ctx.clearRect(0, 0, 500, 500)
        draw(ctx, x, y)
      } else {
        y -= 50
      }
    }
    if (event.key == 'ArrowUp' && y > 0) {
      y -= 50
      if (checkMove()) {
        ctx.clearRect(0, 0, 500, 500)
        draw(ctx, x, y)
      } else {
        y += 50
      }
    }
    if (event.key == 'ArrowRight' && x < (canvas.width - 50)) { 
        x += 50;
        if (checkMove()) {
            ctx.clearRect(0, 0, 500, 500)
            draw(ctx, x, y)
        } else {
            x -= 50;
        }
    }
    if (event.key == 'ArrowLeft' && x > 0) {
        x -= 50;
        if (checkMove()) {
            ctx.clearRect(0, 0, 500, 500)
            draw(ctx, x, y)
        } else {
            x += 50;
        }
    }
  }
}

main()