【问题标题】:Collisions between rectangles矩形之间的碰撞
【发布时间】:2015-09-09 17:48:00
【问题描述】:

我已经尝试了几个小时来解决这个问题,而互联网在这个问题上却毫无成果。

我需要帮助检测和解决矩形之间的冲突,而不是只是检测,但请注意我也提到了解决问题。

这是两个框,具有 x/y 宽度/高度。我只需要检测它们何时重叠,然后将其中一个盒子顺利推出另一个盒子。

另外,请注意一个盒子是静止的 - 而另一个是移动的。

有没有人对此有任何了解(或者可以给我一个例子?)我真的很感激。

我还需要这些盒子能够彼此叠放。

谢谢!

【问题讨论】:

  • 具体是什么问题?您尝试过什么来检测重叠?这并不复杂。
  • 检测没有问题。问题是解决碰撞。我尝试了很多方法(比如在上一个工作位置和新位置之间进行插值以找到一个新的好位置,以及停止速度并强行将它们放在框外),但没有一个效果很好。
  • 布雷登,看看SAT(分离轴定理)
  • 什么构成“解决”碰撞?你使用什么工具?你的代码呢?
  • 成功地将碰撞的盒子移到彼此之外。我没有任何值得展示的工作代码。

标签: java physics collision


【解决方案1】:

我不确定这里的上下文是什么(这些框是移动的还是静止的?您是在寻找物理上准确的分辨率,还是只是几何上正确的分辨率?),但您似乎可以通过以下方式完成此操作方式:

1) 判断是否有框碰撞 2)确定两个盒子的交集,这将产生第三个盒子。盒子的宽度和高度就是你的穿透深度。 3)将其中一个盒子的中心移动穿透深度(x - 宽度,y - 高度)。

这应该会导致框变得不相交。

仅供参考:两个框的交集可以通过取两个框的最小值和最大值的最小值来计算。

这是我的引擎中用于方框交叉点的一些代码:

bool Bounds::IntersectsBounds(const Bounds &other) const
{
    return !(min.x > other.max.x || max.x < other.min.x
             || min.y > other.max.y || max.y < other.min.y);
}

bool Bounds::Intersection(const Bounds &other, Bounds &outBounds) const
{
    if (!this->IntersectsBounds(other)) {
        return false;
    }

    outBounds.min.x = std::max(min.x, other.min.x);
    outBounds.min.y = std::max(min.y, other.min.y);
    outBounds.max.x = std::min(max.x, other.max.x);
    outBounds.max.y = std::min(max.y, other.max.y);


    return true;
}

在这种情况下,“outBounds”变量是两个框的交集(在这种情况下是您的穿透深度)。您可以使用此框的宽度/高度来执行碰撞解决方案。

【讨论】:

  • 一个盒子是静止的,另一个不是。很抱歉没有澄清。我将修改问题并尝试您的解决方案。谢谢!
  • 你能详细说明一下交集计算吗?
  • 这行得通,但是非常不可靠并且导致了很多错误。实施可能是我的错 - 但是在设置了使用此方法解决冲突的不同方法一个小时后,我无法使任何工作正常进行。
  • 如果你发布一个带有代码的 github 或 pastebin,我可以看看。
【解决方案2】:

是的!这是一个很常见的问题!您可能想查看堆栈交换网络的gamedev 部分!

检测

bool collide(float x1,float y1,float sx1,float sy1, float x2, float y2, float sx2, float sy2){
 if (x1+sx1 <= x2)
        return false;
 if (x2+sx2 <= x1)
        return false;
 if (y1+sy1 <= y2)
        return false;
 if (y2+sy2 <= y1)
        return false;
 return true;
}

分辨率 至于答案,这取决于您要使用的应用程序类型。它是横向卷轴、自上而下、基于瓷砖的吗?答案取决于对这个问题的回答。我会假设一些动态的东西,比如横向卷轴或自上而下的动作游戏。

代码不难,但实现可以。如果屏幕上移动的物体很少,您可以使用类似的系统进行挖掘,如下所示:

  1. 获取当前正在碰撞的对象列表,按与当前对象的距离顺序排列。
  2. 遍历对象,并使用以下方法解决冲突
  3. 通过向对象发送消息并检查返回值来检查对象是否具有某种特殊的碰撞类型(传送器等)(传送器将负责解决冲突)
  4. 检查我们当前对象的先前底部位置(A)是否高于相关对象的顶部(B),如果是,则意味着您发生了底部碰撞。通过将A的y位置设置为B的y位置减去A的高度来解决
  5. (IF THE PREVIOUS FAILED) 检查A 之前的右侧是否在B 左侧的左侧,如果是,则表示您发生了右侧碰撞。通过将A的x位置设置为B的位置减去A的宽度来解决
  6. (IF THE PREVIOUS FAILED) 检查A 之前的左侧是否在B 右侧的右侧,如果是,则表示您发生了左侧碰撞。通过将A的x位置设置为B的x位置加上B的宽度来解决
  7. (IF THE PREVIOUS FAILED) 检查A 的前一个顶面是否低于B 的底面,如果是,则说明您发生了顶面碰撞。通过将A的y位置设置为B的y位置加上B的高度来解决

哇。根据距离对对象进行排序很重要,如果您检查与更远的对象的碰撞,它将捕捉到边缘!

我希望这是有道理的!

【讨论】:

  • 问题主要是关于如何解决它,如果可以,请比“检测碰撞,然后解决”更具体。谢谢!
  • 哈哈,你懂的,你是程序员!不要让我们为你做这一切:D 但我会为你更具体一点 - 我知道有时我们需要一些外部视角。
【解决方案3】:

编辑:显然在 Android 中不起作用。

https://stackoverflow.com/a/15515114/3492994

使用 2D 图形 API 中的可用类。

Rectangle r1 = new Rectangle(100, 100, 100, 100);
Line2D l1 = new Line2D.Float(0, 200, 200, 0);
System.out.println("l1.intsects(r1) = " + l1.intersects(r1));

这并没有告诉你,在哪里......

【讨论】:

  • 很遗憾,您无法在 Android 中使用它们。
猜你喜欢
  • 1970-01-01
  • 2023-04-01
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 2013-03-27
  • 2023-01-26
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多