C++ 碰撞检测的改进

C++ 碰撞检测的改进,c++,collision-detection,game-engine,collision,game-physics,C++,Collision Detection,Game Engine,Collision,Game Physics,我有两个函数,我将使用它们来检查屏幕上对象之间的冲突,因为这些函数将要执行很多次,我想确保它们以最高效率运行,而且因为它们目前看起来相当混乱,我想知道是否可以得到您的帮助 我的职能如下: 这是在对象上实际调用的函数: bool ScreenObject::intersects(ScreenObject & a,ScreenObject & b) { if(inter(a,b)) return true; else return in

我有两个函数,我将使用它们来检查屏幕上对象之间的冲突,因为这些函数将要执行很多次,我想确保它们以最高效率运行,而且因为它们目前看起来相当混乱,我想知道是否可以得到您的帮助

我的职能如下: 这是在对象上实际调用的函数:

bool ScreenObject::intersects(ScreenObject & a,ScreenObject & b) {
    if(inter(a,b))
        return true;
    else
        return inter(b,a);
}
这是inter:

bool inter(ScreenObject & a,ScreenObject & b) {
    if(a->getsx()>b->getsx()) {
        if(a->getsx()<b->getSxmax()) {
            if(a->getsy()>b->getsy())) {
                if(a->getsy<b->getSymax()) {
                    return true;
                }
            } else {
                if(b->getsy()>a->getsy())) {
                    if(b->getsy<a->getSymax()) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
bool inter(屏幕对象&a、屏幕对象&b){
如果(a->getsx()>b->getsx()){
如果(a->getsx()getSxmax()){
如果(a->getsy()>b->getsy()){
如果(a->GetSymax()){
返回true;
}
}否则{
如果(b->getsy()>a->getsy()){
如果(b->getsymax()){
返回true;
}
}
}
}
}
返回false;
}

getsx/getsy返回x/y的最小值(即对象的左下角),而getSxmax/getSymax返回最大值。我的问题是,有没有办法使这段代码更好,因为目前这段代码的执行情况似乎相当糟糕。

你说得对。这太乱了。要跟踪每个对象的矩形范围:

typedef struct range { int min, max; } RANGE;
typedef struct bb { RANGE x, y; } BOUNDING_BOX;
关键操作是通过确定对象A必须位于B的任一侧来发现一维中没有重叠。这就是不相交:

bool disjoint(RANGE *a, RANGE *b) { return b->max < a->min || b->min > a->max; }
当然,碰撞是不相交的逻辑补充,至少对于矩形对象是如此

对于其他形状,仍然可以使用矩形范围来消除碰撞测试的大部分成本。如果范围是不相交的,则可以确定没有碰撞。如果多边形不是不相交的,则必须对一般多边形的碰撞执行更昂贵的测试。这里有一些基本信息。但是有几本关于这个话题的大书

对于@DanielKO来说,他不喜欢C约定,尽管它们在这个问题上比OO更简洁地表达了计算;还省略了构造函数和其他样板文件:

class Extent { 
  public:
    bool isDisjointWithRespectTo(Extent &other) {
      return max < other.min || other.min > max; 
    }
  private:
    int min, max;
}

class BoundingBox {
  public:
    bool isDisjointWithRespectTo(BoundingBox &other) {
       return x.isDisjointWithRespectTo(other.x) || y.isDisjointWithRespectTo(other.y);
    }
    bool intersectsWith(BoundingBox &other) { return !isDisjointWithRespectTo(other); }
  private:
    Extent x, y;
}
类范围{
公众:
bool IsJointWithTo(范围和其他){
返回maxmax;
}
私人:
最小整数,最大整数;
}
类边界框{
公众:
bool IsIsJointWithTo(边界框和其他){
返回x.isdisjointwithreserveto(other.x)| | y.isdisjointwithreserveto(other.y);
}
bool intersectsWith(BoundingBox&other){return!isdisjointwithreserveto(other);}
私人:
范围x,y;
}

构造器需要确保
min
max
在两个版本中的顺序正确。

对象的形状是什么?例如,如果一个对象是凸的,而另一个对象是凹的,则仅检查最小值或最大值可能会返回假阳性结果。在这种情况下,大多数对象将是矩形的,但也会有其他对象不是矩形的,您能否解释如何对照该结果进行检查,我在想,我必须检查与对象曲线对齐的坐标,但是如果有更好的方法,请解释一下这个gamedev.se主题:看在上帝的份上,像其他人一样,编写一个轴对齐的边界框类,并进行适当的相交测试。OOP的存在正是为了把简单的概念变成简单易读的代码。@DanielKO我很抱歉这给你带来了如此大的压力,以至于你觉得需要调用你的神。OP询问如何安排测试,所以我的目的是给出一个代码片段,它显示了不一致性测试,而不是编写完整的类。关于OOP,问题是标记C++,所以如果语言可用的话,使用该工具是合适的。边界框是一个相当直观的概念(请不要在C版本中将其称为
范围
,然后再次使用它来表示间隔,名称很重要),显式表示它是有意义的。一个<代码>屏幕对象< /代码>将有一个边框,而不是一对间隔(这是合理的实现细节)。@丹尼尔科,我确信我的代码将编译为C++,虽然我没有尝试过。啊,但是术语“范围”比“包围盒”早了好几年。我在1984年从布莱恩·巴斯基那里学的。我相信,由于Adobe的缘故,它被精度较低的边界框所取代,这是令人遗憾的。最小边界框会更好。尽管如此,让这些例子保持一致仍然是合理的,所以我会这么做。根据维基百科的说法,“计算机”一词最早是由理查德·布雷斯韦(Richard Braithwait)在1613年使用的:“我指的是一个进行计算的人,这个词的含义一直保持到20世纪中叶。”词语的演变是为了表达相关的含义。“范围”的含义在很大程度上取决于上下文,而“边界框”(谁说它必须是最小的?即使是一个填充得很宽的边界框也可以,只要它包含相关对象)是非常明确的(它的形状像一个框,并且它限制了某些内容),并且没有含糊不清的含义。
class Extent { 
  public:
    bool isDisjointWithRespectTo(Extent &other) {
      return max < other.min || other.min > max; 
    }
  private:
    int min, max;
}

class BoundingBox {
  public:
    bool isDisjointWithRespectTo(BoundingBox &other) {
       return x.isDisjointWithRespectTo(other.x) || y.isDisjointWithRespectTo(other.y);
    }
    bool intersectsWith(BoundingBox &other) { return !isDisjointWithRespectTo(other); }
  private:
    Extent x, y;
}