我正在尝试为我正在制作的自定义Minecraft客户端设计碰撞检测算法。基本上,整个世界都是由立方体组成,而玩家(或相机)需要能够站立并移动这些立方体。我想要的结果如下图所示:
绿线是玩家的运动矢量。当玩家在其中一个立方体的平面上刷牙时,我希望矢量变为与平面垂直的矢量。但是,矢量应该保持它在平面方向上的所有速度,但是会失去飞向平面的所有速度。
我希望我的问题清楚明了。实现这样的碰撞检测系统的最佳和最有效的方法是什么?此外,像这样的系统是否允许使用简单的重力组件?
编辑:忘记提及,立方体存储在三维数组中,[x,y,z]。
答案 0 :(得分:1)
实现这一目标的一个简单方法是检测球与飞机的碰撞。计算穿透深度,这是球实际经过飞机的距离,然后将球向平面方向推回。
这将具有将球放在飞机表面上的效果。如果你为每一帧做到这一点,那么球将有效地沿着平面滑动,当然假设球的速度矢量与平面的法线不平行。
碰撞检测领域庞大而复杂,根据您的游戏,您必须根据所需的真实程度和性能要求确定哪些足以满足您的要求。你应该总是选择最简单的解决方案来提供足够逼真的反馈,这取决于它通常不一定非常完美的游戏。
基本上你应该将碰撞检测分为两个阶段,通常称为宽阶段和窄阶段。
广泛的阶段可能就像执行快速边界框检查以确定潜在的碰撞一样简单,然后将这些潜在的碰撞提交给窄相碰撞检测,以进行更详细的检查,确定是否确实存在碰撞,碰撞深度。如果您有许多对象,那么宽相位可能会使用某种四叉树索引来仅选择对象附近的块来执行碰撞检测。
答案 1 :(得分:0)
在Axis Aligned多维数据集的世界中,这非常简单。很容易认为你需要精心设计的东西,但实际上它非常简单。这是在编写我自己的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;
}