努力与碰撞检测。如何正确检测碰撞?

时间:2019-08-21 14:17:51

标签: c++ sfml collision shapes

class ShapePlanet
{
public:
    sf::CircleShape shape;
    sf::Vector2f planetposition;
    int radius = 45;
    ShapePlanet()
    {
        float x = rand() % 1020; //invece che 1280
        float y = rand() % 650; //invece che 720
        this->shape.setFillColor(sf::Color::Green);
        this->planetposition.x = x;
        this->planetposition.y = y;
        this->shape.setPosition(x, y);
    }
};

struct Node_Planet
{
    ShapePlanet Planet;
    Node_Planet* next;
};
typedef Node_Planet* ptr_list;

class Planet
{
private:
    ptr_list head;
public:
    ptr_list create(int n)
    {
        ptr_list tmp = NULL;
        for (int i = 0; i < n; i = i + 1)
        {
            {
                tmp = new Node_Planet;
                tmp->Planet = ShapePlanet();
                tmp->next = head;
                head = tmp;
            }
            return this->head;
        }


        void draw(sf::RenderWindow& window)
        {
            ptr_list p = this->head;
            while (p != NULL)
            {
                window.draw(p->Planet.shape);
                p = p->next;
            }
        }

        void IsItOverLapped()
        {
            ptr_list p1 = this->head;
            ptr_list p2 = this->head;
            // bool collision = false;
            sf::FloatRect shape1;
            sf::FloatRect shape2;
            float distance;
            float dx;
            float dy;
            //float distance = std::sqrt((dx * dx) + (dy * dy));

            while ((p1 != NULL))
            {
                //float distance = std::sqrt((dx * dx) + (dy * dy));
                while (p2 != NULL)
                {
                    shape1 = p1->Planet.shape.getGlobalBounds();
                    shape2 = p2->Planet.shape.getLocalBounds();
                    dx = (p1->Planet.shape.getPosition().x + (shape1.width / 2)) - (p2->Planet.shape.getPosition().x + (shape2.width / 2));
                    dy = (p1->Planet.shape.getPosition().y + (shape1.height / 2)) - (p2->Planet.shape.getPosition().y + (shape2.height / 2));
                    distance = std::sqrt((dx * dx) + (dy * dy));
                    if (distance <= (shape1.width / 2) + (shape2.width / 2))
                    //if (p2->Planet.shape.getGlobalBounds().intersects(p1->Planet.shape.getLocalBounds()))
                    {
                        std::cout << "Collision Detected" << std::endl;
                        //p2 = p2->next;
                        //collision = true;
                    }
                    else
                    {
                        std::cout << "No Collision Detected" << std::endl;
                        //collision = false;
                    }
                    /*if (p2->Planet.shape.getLocalBounds().intersects(p1->Planet.shape.getLocalBounds()))
                        std::cout << "collision";
                        std::cout <<'\n'; */
                    p2 = p2->next;
                }
                p1 = p1->next;
            }
            //return collision;
        }
    }
};

因此,我希望能够在屏幕上绘制形状。问题是我难以检测形状的碰撞。如果能够检测到碰撞,则可以更改重叠形状的位置。但是我为此付出了很多努力。 我有一个对象列表。并且它们在形状,位置等方面具有一些特征。 我也尝试过使用if(object1.getLocalBounds.intersects(object2.getLocalbounds()){然后做点事},但似乎代码不在if方面。我已经尝试了很多次,但我确实不这样做再也不知道该如何处理了。

2 个答案:

答案 0 :(得分:3)

首先,除非有充分的理由(或者,如果要明确地编写代码以了解指针和数据结构),否则不要构建自己的数据结构(例如ptr_list),但是那么也许不要将其与碰撞混合使用)。相反,请使用STL-已经不必担心的一件事了。还有avoid new and delete

接下来,请确保您了解所使用的SFML函数。 getLocalRect()getGlobalRect()会在两个不同的坐标系中返回矩形,您不能只是将它们相加/相减并得到有意义的结果。请查阅SFML文档以获得更清晰的信息。另外,您应该直接使用sf::Rect::intersects()而不是自己构建。

您需要考虑的是,SFML将对与轴对齐的边界框进行相交检查,而检查实际矩形是否相交。这比正确的矩形检查更为简单和快捷,但是准确性较低。我将从对齐轴的矩形开始,然后从那里开始。

可能还有帮助的是,将检查重叠的代码(碰撞检测)和对其进行反应的代码(碰撞响应)分开。第一个是简单的布尔函数,它不会修改任何状态,第二个然后执行必要的操作。

答案 1 :(得分:0)

p1 = head;
p2 = head;

while (p1)
{
    while (p2)
    {
        // ...
        p2 = p2->next;
    }
    (*)
    p1 = p1->next;
}

当代码第一次到达(*)时,在内循环中将p2设置为nullptr;但由于您无需在内部循环中将其重置,因此它将在所有其他循环运行中保持不变,从而将列表中的第二个行星与其他任何一个都不再进行比较。

另外,当您最初将两个指针都设置为head时,您将比较第一个行星与其自身,这自然会导致碰撞。

两个问题的解决方法:

p1 = head;
while (p1)
{
    p2 = p1->next;
    //       ^ avoid self-comparison
    while (p2)
    {
        // ...
        p2 = p2->next;
    }
    p1 = p1->next;
}