繁体   English   中英

如何在2D碰撞检测中正确解决碰撞的位置?

[英]How do I resolve a collision's position properly in 2D collision detection?

我当前的实现如下所示:

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);

rEntityrOther是对象的半径,并且midXmidY是它们的中心坐标。 dxdy是从实体到中心的距离。

然后做:

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;

在考虑半径时找到中点。 但我不能保证那行得通。 同样,最后添加的符号也很重要。

我希望这会有所帮助(并能奏效)。 让我知道是否有不清楚的地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM