本文实例讲述了JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法。分享给大家供大家参考,具体如下:

检测物体碰撞实际上是需要检测物体是否相交,而实际应用中物体的形状大小各异,如果直接对物体的边缘进行碰撞检测,实际计算过程的代价非常高昂。如果物体的数量太多,比如像网络游戏中,通常少则几千用户,多则上万、几十万用户同时在线,而这些碰撞都要通过服务器检测,这样计算的消耗,即使是大型服务器也会崩溃,所以通常不需要十分精确的碰撞检测情况下,使用包围盒算法,即把物体放在一个多边形中,这个多边形就是包围盒。

基于这样一个概念,通常情况下我们就使用了最简单的几种多边形,比如圆形、矩形等。

先来看看如何使用圆形包围盒算法,圆形包围盒算法就是使用圆形作为包围盒将物体包围起来,检测的时候只需要检测两个圆形是否碰撞即可。检测圆形的碰撞比较容易,假设圆 A 的坐标(x1, y1),半径是 r1,圆 B 的坐标(x2, y2),半径是 r2,则如果满足不等式(y2−y1)2+(x2−x1)2≤(r1+r2)2则表示两个圆发生了碰撞,其实就是圆心之间的距离小于两个圆的半径之和即可,由于计算距离需要用到开方运算,效率较低,所以直接比较距离的平方。

\"\"

关键代码:

    function hitTest( source, target ) {
      /* 源物体和目标物体都包含 x, y 以及 width, height */
      return !(
        Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2)
      );
    }

完整示例代码:

<!DOCTYPE html>
<html lang=\"en\">
<head>
  <  name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">
  <  charset=\"UTF-8\">
  < >盒包围碰撞算法-圆形</ >
  <style>
    #stage {
      border: 1px solid lightgray;
    }
  </style>
</head>
<body>
<h1>是否碰撞:<span class=\"hitTest\">否</span></h1>
<canvas id=\"stage\"></canvas>
</body>
< >
  window.  = function () {
    var stage = document.querySelector(\'#stage\'),
      ctx = stage.getContext(\'2d\');
    stage.width = 400;
    stage.height = 400;
    document.  = function (event) {
      var e = event || window.event || arguments.callee.caller.arguments[0];
      //根据地图数组碰撞将测
      switch (e.keyCode) {
        case 37:
          console.log(\"Left\");
          if (balls[0].x > 0) {
            balls[0].x -= 2;
          }
          break;
        case 38:
          console.log(\"Top\");
          if (balls[0].y > 0) {
            balls[0].y -= 2;
          }
          break;
        case 39:
          console.log(\"Right\");
          if (balls[0].x < stage.width) {
            balls[0].x += 2;
          }
          break;
        case 40:
          console.log(\"Bottom\");
          if (balls[0].y < stage.height) {
            balls[0].y += 2;
          }
          break;
        default:
          return false;
      }
    };
    stage.addEventListener(\'click\', function (event) {
      var x = event.clientX - stage.getBoundingClientRect().left;
      var y = event.clientY - stage.getBoundingClientRect().top;
      balls[0].x = x - balls[0].r/2;
      balls[0].y = y - balls[0].r/2;
    });
    var p  = {
      x: stage.width / 2 - 20,
      y: stage.height / 2 - 20,
      r: 40,
      c: \"red\"
    },balls = [];
    balls.push(p );
    for (var i = 0; i < 10; i++) {
      var ball = {
        x: 60 * i,
        y: 60 * i,
        r: 40,
        c: \"blue\"
      };
      balls.push(ball);
    }
    function createBall(x, y, r, c) {
      ctx.beginPath();
      ctx.fillStyle = c;
      ctx.arc(x, y, r, 0, Math.PI*2);
      ctx.fill();
    }
    function hitTest( source, target ) {
      /* 源物体和目标物体都包含 x, y 以及 width, height */
      return !(
        Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2)
      );
    }
    function update() {
      ctx.globalAlpha=1;
      ctx.clearRect(0, 0, 400, 400);
      document.querySelector(\'.hitTest\').innerHTML = \"否\";
      for (var i = 1, len = balls.length; i < len; i++) {
        createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);
        var flag = hitTest(balls[0],balls[i]);
        if(flag){
          document.querySelector(\'.hitTest\').innerHTML = \"是\";
          ctx.globalAlpha=0.5;
        }
      }
      createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c);
      requestAnimation (update);
    }
    update();
  };
</ >
</html>

这里使用在线HTML/CSS/ 代码运行工具http://tools.jb51.net/code/HtmlJsRun 测试上述代码运行结果如下:

\"\"

github地址:https://github.com/krapnikkk/JS-gameMathematics

更多关于 相关内容感兴趣的读者可查看本站专题:《 数学运算用法总结》、《 数据结构与算法技巧总结》、《 数组操作技巧总结》、《 排序算法总结》、《 遍历算法与技巧总结》、《 查找算法技巧总结》及《 错误与调试技巧总结

希望本文所述对大家 程序设计有所帮助。

收藏 打印