【问题标题】:HTML5 - Collisions [closed]HTML5 - 碰撞[关闭]
【发布时间】:2013-01-11 23:16:28
【问题描述】:

我正在开发一个自上而下的游戏,这个游戏将包含很多简单和复杂的碰撞。

在做了一些研究之后,我了解到我必须始终将我的角色与我的代码中的“对象”进行比较 - 然后检查碰撞计算。

EG:

CheckCollisions(Player, Object);

这意味着我必须将场景中的每个可碰撞对象添加到我的代码中:

CheckCollisions(Player, Building1);
CheckCollisions(Player, Building2);
CheckCollisions(Player, Trash);
CheckCollisions(Player, Bench1);
CheckCollisions(Player, Bench2);
CheckCollisions(Player, Office1);
CheckCollisions(Player, Office2);

首先,我的对象甚至可能不是简单的矩形,它们可能是复杂的形状。其次,其中一些可能有自己的轮换。第三,如果我的场景中有数以万计的可收集对象会怎样?

难道没有更简单的方法来检查 HTML5/JS 游戏中的冲突吗?

这甚至可能吗?我真的只是在寻找一些建议和指示。

谢谢

【问题讨论】:

  • a) 使用循环 b) 这些天浏览器性能非常好 c) 许多对象有更好的碰撞检测算法
  • 对于复杂的形状,请更具体。向我们展示您的 CheckCollisions 代码,以及您为匹配这些案例所做的尝试。
  • 嗨@Bergi,我实际上还没有编写我的CheckCollisions 代码,因为我正在研究最好的方法。当我说“复杂形状”时,我的意思是具有自己的多边形点的形状(例如 - 绘制星形等......)
  • 您也可以查看GameDev.SE(请务必阅读他们的常见问题解答,我不是那里的常客,所以我不完全确定他们的范围是什么)。

标签: javascript html collision


【解决方案1】:

对于游戏中的每个对象都有一个命名变量是非常少见的。通常您将所有对象存储在一个数据结构(如数组)中,当您需要对所有对象执行某些操作时,您会对该数组执行 for 循环。

一些重要的对象,比如玩家角色,可以有一个自己的变量,但它们也应该在“所有对象”数组中,所以你不需要编写特殊的处理来包含玩家角色。

关于性能:当您根据所有内容检查所有内容时,需要执行的碰撞​​检查数量呈二次方增加。但是当您只检查那些已经彼此靠近的对象的碰撞时,您可以减少工作量。在检查碰撞之前,您:

  1. 将比赛场地划分为矩形区域(这些区域必须至少与最大物体一样大)。
  2. 然后将每个对象分配到其左上角所在的区域。
  3. 然后您选取每个区域,并检查其中的每个对象与该区域中的其他对象的碰撞,以及与该区域右侧、向下和右侧三个区域的所有对象的碰撞(对于与区域边界重叠的对象)。

当您有非常复杂的形状时,您还可以通过计算每个形状的边界矩形(它适合的最小矩形)来加速碰撞检测。在检查两个对象之间的碰撞之前,首先检查它们的边界矩形是否相交。否则,复杂的形状就没有机会相交,您可以跳过所有复杂的计算。

【讨论】:

    【解决方案2】:

    到目前为止,每个人都指出,对象数组比单独命名所有对象要好得多。

    一种更简单的碰撞检测方法可能对您有用,即拥有一个跟踪所有占用空间的中心对象。例如,我们暂时称它为LocationTracker

    假设您只使用 x 轴和 y 轴,您可以拥有一个存储 X 和 Y 位置的 Point 对象(如果您想花哨的话,可以使用 timestamp)。每个对象在移动时都会发送一个包含它所占用的所有Points 的数组。比如可以拨打locationTracker.occupySpace(player[i], array(point(3,4), point(4,4), point(5,4))等。

    如果您对 occupySpace 的调用返回 false,则没有任何点匹配并且您是安全的,如果它返回 true,则您发生了冲突。

    这样做的好处是如果您有 x 个对象,而不是每次移动检查 x*x 次,而是检查 x 次最大值。

    您不需要传入对象的所有点,只需传入最外层的点即可。

    【讨论】:

      【解决方案3】:

      1 - 您无需为游戏中的每个对象编写一行代码。将它们放入数组并循环遍历数组:

      var collidableObjects = [Building1, Building2, Trash, Bench1, Bench2,Office1, Office2];
      var CheckAllCollisions = function() {
          for (var i=0; i<collidableObjects.length; i++) {
              CheckCollisions(Player, collidableObjects[i]);
          }
      }
      

      2 - 如果您有复杂的碰撞检查(即旋转的形状、多边形等),您可以先检查一个简单的矩形检查(或半径检查),然后更准确地检查第一个是否返回 true。

      3 - 如果您计划拥有数以万计的对象,您应该拥有更智能的数据集合,例如按 X 坐标排序的对象,这样您就可以快速避免检查大于 Player.X+100 和小于 Player.X- 的所有对象100(使用二分搜索),或者将对象分割成一个网格,然后只检查玩家周围 3x3 网格单元中的对象。

      【讨论】:

        【解决方案4】:

        更好的方法是将所有场景对象放入数组或树结构中,然后

        for( var i=0; i<scene.length; i++ ) {
            scene[i].checkCollision( player );
        }
        

        如果你为每个对象添加一个函数.checkCollision(),你可以在其中处理任何特殊情况。

        将播放器设为矩形是个好主意,这样检查代码就不会变得太复杂。

        使玩家对象的碰撞检查矩形略小于实际精灵;让玩家的生活更轻松。

        【讨论】:

        • 可以在角色周围使用圆形碰撞器而不是矩形吗?谢谢
        • 是的。除非您想编写复杂的 polgon-polygon 碰撞检查,否则任何简单的形状都可以:-)
        【解决方案5】:

        首先,您应该始终将对象放在数组中。这包括敌人、子弹和其他类似的东西。这样,您的游戏就可以随意创建和销毁它们。

        您似乎在谈论碰撞检查的实际频率,而不是碰撞检查方法。为此,我的建议是只对有限数量的对象进行碰撞检查。尝试使用网格,并且只检查与玩家在同一网格块中的对象的碰撞。

        另一件有帮助的事情是在方法本身内部有很多“捷径”。在完成任何复杂的数学运算之前,可以快速轻松地检查这些内容。例如,您可以检查两个对象之间的距离。如果对象比它们的最远角更远,则不必检查碰撞。

        您可以在自己独特的组合中使用这些方法。

        【讨论】:

          猜你喜欢
          • 2014-02-04
          • 2018-04-19
          • 1970-01-01
          • 2013-01-16
          • 1970-01-01
          • 1970-01-01
          • 2021-04-12
          • 1970-01-01
          • 2021-10-17
          相关资源
          最近更新 更多