2

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

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

例如:

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 游戏中的冲突吗?

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

谢谢

4

5 回答 5

2

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

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

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

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

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

于 2013-01-28T15:26:02.653 回答
2

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

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

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

如果您的调用occupySpace返回 false,则没有任何点匹配并且您是安全的,如果它返回 true,那么您就会发生碰撞。

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

您不需要传递对象的所有点,只需要传递最外面的点。

于 2013-01-28T15:32:52.380 回答
1

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 网格单元中的对象。

于 2013-01-28T15:29:25.890 回答
0

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

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

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

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

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

于 2013-01-28T15:24:09.193 回答
0

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

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

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

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

于 2013-01-28T15:27:05.567 回答