【问题标题】:Collision detection by sliding against a plane in XNA通过在 XNA 中的平面上滑动来检测碰撞
【发布时间】:2011-06-09 08:21:19
【问题描述】:

我正在尝试为我正在制作的自定义 Minecraft 客户端设计碰撞检测算法。基本上,整个世界都是由立方体组成的,玩家(或相机)需要能够站在这些立方体上并移动。我想要的结果如下图所示:

绿线是玩家的运动向量。当玩家刷到一个立方体的平面时,我希望矢量更改为与平面垂直的矢量。然而,向量应该保持它的所有速度在平面的方向上,但失去所有朝向平面的速度。

我希望我已经把我的问题说清楚了。实现这样的碰撞检测系统的最佳和最有效的方法是什么?另外,这样的系统是否允许使用简单的重力分量?

编辑:忘了说,立方体存储在一个三维数组 [x,y,z] 中。

【问题讨论】:

  • 我喜欢这个问题。我建议您也发布在 gamedev.stackexchange.com 上。我想这是游戏开发中的一个常见问题。
  • @BigDave - 哦,我不知道有专门用于游戏开发的网站。 Stack Exchange 确实在增长。

标签: c# xna collision-detection


【解决方案1】:

实现这一点的一个简单方法是检测球和飞机的碰撞。计算穿透深度,这是球实际经过平面的距离,然后将球推回平面法线方向。

这将产生将球放在飞机表面的效果。如果你对每一帧都这样做,球将有效地沿着平面滑动,当然假设球的速度矢量不平行于平面的法线。

碰撞检测领域庞大而复杂,根据您的游戏,您必须根据所需的逼真度和性能要求来确定满足您的要求的条件。您应该始终寻求最简单的解决方案,提供足够真实的反馈,这取决于游戏,它通常不一定是完美的。

基本上,您应该将碰撞检测分为两个阶段,通常称为宽阶段和窄阶段。

广泛的阶段可以很简单,只需执行快速边界框检查以确定潜在的碰撞,然后将这些潜在的碰撞提交给狭窄的阶段碰撞检测,以进行更详细的检查,以确定是否确实存在碰撞以及碰撞深度。如果您有很多对象,那么广泛阶段可能会使用某种四叉树索引来仅选择对象附近的块来执行碰撞检测。

【讨论】:

  • @Chris Taylor - 是的,我认为它可能就是这么简单。你觉得我应该怎么计算呢?我是否应该只遍历一个立方体子集并检查玩家是否与其中一个相交?
  • @Bevin,我对您的额外问题的回复有点长,所以我只是用更多信息更新了答案。希望这会有所帮助。
  • @Chris Taylor - 好吧,我知道播放器的大小,所以我可以简单地遍历最多 4 个街区外的立方体。这应该为检测提供足够的空间。我如何检测玩家相交的距离,以及将他推出街区的距离?
  • @bevin,你的播放器也是盒子吗?如果是这样,您想查看 box-box 交叉点,或者最接近您的玩家形状的形状。
  • @Chris Taylor - 好吧,我只是打算让玩家用一个点表示,然后使用与该点的距离来检查碰撞。
【解决方案2】:

在轴对齐立方体的世界中,这真的很容易。很容易认为你需要一些复杂的东西,但实际上它真的很简单。这是我编写自己的 Minecraft 克隆后的经验。

方法如下:

position.X += velocity.X;
if(colliding())
  position.X -= velocity.X;

position.Y += velocity.Y;
if(colliding())
  position.Y -= velocity.Y;

position.Z += velocity.Z;
if(colliding())
  position.Z -= velocity.Z;

这是确定是否发生碰撞的代码:

bool colliding()
{
  int minX = Position.X - size.X / 2;
  int minY = Position.Y - size.Y / 2;
  int minZ = Position.Z - size.Z / 2;

  int maxX = Position.X + size.X / 2;
  int maxY = Position.Y + size.Y / 2;
  int maxZ = Position.Z + size.Z / 2;

  for (int x = minX; x <= maxX; x++)
    for (int y = minY; y <= maxY; y++)
      for (int z = minZ; z <= maxZ; z++)
      {
        if(blockType[x, y, z] != 0)
          return true;
      }

   return false;
}

【讨论】:

  • 如果播放器未对齐,这将不起作用。如果玩家只与其中一个平面轻微相交怎么办?然后他将被推得比必要的更远。
  • 为了碰撞,玩家可以被视为一个非旋转轴对齐的盒子。它工作正常。我知道你的意思,但玩家并没有注意到。我鼓励 OP 试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 2016-07-20
  • 2011-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多