我目前的实现如下:
if (shapesCollide) {
if (velocity.y > 0) entity.position.y = other.position.y - entity.size.y;
else entity.position.y = other.position.y + other.size.y;
velocity.y = 0;
if (velocity.x > 0) entity.position.x = other.position.x - entity.size.x;
else entity.position.x = other.position.x + other.size.x;
velocity.x = 0;
}
然而,当两个轴上发生运动时,这会导致奇怪的处理 - 例如,让entity
向下移动到object
的左边,然后移动它与object
碰撞,将正确解决水平碰撞,但会打破垂直运动。
我以前只是去了
if (shapesCollide) {
position = oldPosition;
velocity = { 0, 0 };
}
但这导致了另一个多轴问题:如果我让我的entity
在object
上面休息,它将无法移动,因为引力引起的运动将不断抵消两种速度。我也尝试分别考虑两个轴,但是只要在考虑到两个速度时发生碰撞,这就会导致问题。
解决两个轴碰撞的最佳解决方案是什么?
我假设实体可以被认为是或多或少的圆形,并且该大小是实体的半径?
我们可能需要一点矢量数学来解决这个问题。 (我不知道c ++中的平方根函数,所以请注意sqrt。)尝试使用此替换if(shapesCollide)中的代码并查看它是如何工作的。
float rEntity = sqrt(entity.size.x * entity.size.x + entity.size.y * entity.size.y);
float rOther = sqrt(other.size.x * other.size.x + other.size.y * other.size.y);
float midX = (entity.position.x + other.position.x) / 2.0;
float midY = (entity.position.y + other.position.y) / 2.0;
float dx = entity.position.x - midX;
float dy = entity.position.y - midY;
float D = sqrt(dx * dx + dy * dy);
rEntity和rOther是对象的半径,midX和midY是它们的中心坐标。 dx和dy是实体到中心的距离。
然后做:
entity.position.x = midX + dx * rEntity / D;
entity.position.y = midY + dy * rEntity / D;
other.position.x = midX - dx * rOther / D;
other.position.y = midY - dy * rOther / D;
您应该检查D不是0,如果是,只需设置dx = 1,dy = 0,D = 1或类似的东西。
你还应该这样做:
velocity.x = 0;
velocity.y = 0;
如果你想要实体停止。
要获得更准确的建模,您还可以尝试以下方法:
float rEntity = sqrt(entity.size.x * entity.size.x + entity.size.y * entity.size.y);
float rOther = sqrt(other.size.x * other.size.x + other.size.y * other.size.y);
float midX = (entity.position.x * rOther + other.position.x * rEntity) / (rEntity + rOther);
float midY = (entity.position.y * rOther + other.position.y * rEntity) / (rEntity + rOther);
float dxEntity = entity.position.x - midX;
float dyEntity = entity.position.y - midY;
float dEntity = sqrt(dxEntity * dxEntity + dyEntity * dyEntity);
float dxOther = other.position.x - midX;
float dyOther = other.position.y - midY;
float dOther = sqrt(dxOther * dxOther + dyOther * dyOther);
entity.position.x = midX + dxEntity * rEntity / dEntity;
entity.position.y = midY + dyEntity * rEntity / dEntity;
other.position.x = midX + dxOther * rOther / dOther;
other.position.y = midY + dyOther * rOther / dOther;
在考虑半径时找到中点。但我不保证这有效。此外,最后添加的迹象很重要。
我希望这有助于(并且有效)。如果有什么不清楚,请告诉我。