C ++矩形到矩形碰撞

时间:2013-04-26 04:49:07

标签: c++ c++11 collision-detection

我在这里寻找代码中的错误非常糟糕。

即使我在Google搜索的算法,我的碰撞检测也不起作用。

void PollEvents()
{

for (int i = 0;i < NUMBER_OF_BLOCKS; ++i)
{

    Rectangle& a = blocks[i];

    if (mouse.state == GLFW_PRESS)
    {   
        //look for any block to grab
        if (mouse.leftClick && !blocks[selectedBlock].Grab() &&
            a.Hover(mouse.pos.x, mouse.pos.y))
        {
            //prevent grabbing another block
            if (i != selectedBlock) {
                selectedBlock = i;
            }

            a.Grab() = true;

            if (a.IsTypeHorizontal()) {
                diff = mouse.pos.x - a.Left();
            } else {
                diff = mouse.pos.y - a.Top();
            }
        }

        if (a.Grab())
        {   

            for (int j = 0;j < NUMBER_OF_BLOCKS; ++j)
            {
                //skip for any self-checking
                if (i == j) continue;

                Rectangle& b = blocks[j];

                //check for rectangle collision
                if (!a.Collide(b) || b.Collide(a)) {
                    //j++;
                    //how does this block will move.

                    if (a.IsTypeVertical()) {
                        a.SetY(mouse.pos.y - diff);
                    } else {
                        a.SetX(mouse.pos.x - diff);
                    }

                } else {

                    switch (a.sideHit)
                    {
                    case UP:
                        //a.SetY(b.Bottom());
                        printf("UP\n");
                        break;
                    case DOWN:
                        //a.SetY(b.Top() + a.GetHeight());
                        printf("DOWN\n");
                        break;
                    case LEFT:
                        //a.SetX(b.Right());
                        printf("LEFT\n");
                        break;
                    case RIGHT:
                        //a.SetX(b.Left() - a.GetWidth());
                        printf("RIGHT\n");
                        break;
                    }
                }

                //check for bound collision
                a.BoundCheck(1.f);
            }

        }

    } else {
        a.Grab() = false;
    }
}
}

碰撞检测:

bool Rectangle::Collide(const Rectangle& r) {

if (IsTypeHorizontal()) {
    if (r.Hover(Left(), Top()) && r.Hover(Right(), Top())) {
        sideHit = UP;
        return true;
    } else if (r.Hover(Right(), Bottom()) && r.Hover(Left(), Bottom())) {
        sideHit = DOWN;
        return true;
    }
    // } else if (r.Hover(Left(), Top())) {
        // sideHit = UP;
        // return true;
    // } else if (r.Hover(Right(), Top())) {
        // sideHit = UP;
        // return true;
    // } else if (r.Hover(Right(), Bottom())) {
        // sideHit = DOWN;
        // return true;
    // } else if (r.Hover(Left(), Bottom())) {
        // sideHit = DOWN;
        // return true;
    // }
} else {
    if (r.Hover(Left(), Top()) && r.Hover(Left(), Bottom())) {
        sideHit = LEFT;
        return true;
    } else if (r.Hover(Right(), Top()) && r.Hover(Right(), Bottom())) {
        sideHit = RIGHT;
        return true;
    }
    // } else if (r.Hover(Left(), Top())) {
        // sideHit = LEFT;
        // return true;
    // } else if (r.Hover(Left(), Bottom())) {
        // sideHit = LEFT;
        // return true;
    // } else if (r.Hover(Right(), Top())) {
        // sideHit = RIGHT;
        // return true;
    // } else if (r.Hover(Right(), Bottom())) {
        // sideHit = RIGHT;
        // return true;
    // }
}

return false;

}

Hover的代码:

inline float Hover(float X, float Y) const {
    return  X >= Left() &&
            X <= Right() &&
            Y >= Bottom() &&
            Y <= Top();
}

我正在尝试制作自己的unblockme

请帮我解决碰撞问题。自从我遇到这个问题以来已经有3天了。

更新

我发现了为什么所有直肠碰撞检测在我的程序中都不起作用的问题。

错误:

if (!a.Collide(b)) {

    //Move()

} else {

    //Resolve collision
}

这个应该是

if (!Rectangle::Collide(a, b)) {

    //Move()

} else {

    //Resolve collision

}

Collide()成为static Rectangle成员,因为正如您在Collide()的实施中所看到的那样,它的决定基于其自己的成员a.Hover(b.x, b.y) {{1}} 1}}没有任何意义。

希望这会对像我这样的所有新手有所帮助。

1 个答案:

答案 0 :(得分:3)

要做直肠/直接碰撞检测,如果其中一个(与x和y轴平行的边)矩形的四个点在另一个矩形内,我们就会发生碰撞。

比检查四个点中的每一个更简单的方法是检查一个X边缘是否在其他矩形的X边缘之间,并且如果一个Y边缘位于其他矩形的Y边缘之间 - 如果两者都是真的,我们发生碰撞(因为两条边必须在另一条直线内的一点处相遇)。所以我们只是在两个方向检查:

bool isclamped(float mid, float A, float B)
{
    if (A > B)
    {
        return mid >= B && mid <= A;
    }
    return mid >= A && mid <= B;
}

bool checkcollisiononeway(rect rectA, rect rectB)
{
    if (isclamped(rectA.left, rectB.left, rectB.right)
    || isclamped(rectA.right, rectB.left, rectB.right))
    && (isclamped(rectA.bottom, rectB.bottom, rectB.top)
    || isclamped(rectA.top, rectB.bottom, rectB.top))
    {
        return true;
    }
    return false;
}

bool checkcollisionbothways(rect rectA, rect rectB)
{
    return checkcollisiononeway(rectA, rectB) || checkcollisiononeway(rectB, rectA);
}

要确定碰撞后的碰撞角度,请使用atan2(rectA.y - rectB.y, rectA.x - rectB.x)找到两个中心之间的角度(角度以弧度返回,而不是以度为单位)