繁体   English   中英

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

[英]Struggling with collision detection. How do I detect the collision correctly?

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()){然后做点事},但是似乎代码没有我已经尝试了很多次,但我真的不知道该怎么处理了。

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

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

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

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

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

暂无
暂无

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

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