【问题标题】:2D Elastic Collision with SFML使用 SFML 的 2D 弹性碰撞
【发布时间】:2015-07-24 22:28:18
【问题描述】:

我是 OOP 的完全初学者,我正在尝试找出在 SFML C++ 中为等质量圆的 2D 碰撞编写程序的最佳方法。我想在一个具有设定起始速度但随机起始位置和方向的框中生成两个或多个圆圈,然后让它们交互。由于我的物理学非常生疏,因此我对力学的伪代码有很多困难。我在wiki 上找到了这个二维弹性碰撞方程:

这是否意味着我应该将它用于每个球的 x 和 y 坐标?我正在考虑为球和速度做这样的事情:

std::vector<sf::CircleShape> balls;
std::vector<sf::Vector2f> Xvelocities; // (magnitudes, directions)
std::vector<sf::Vector2f> Yvelocities; // (magnitudes, directions)

我写了一个这样的碰撞函数:

bool Collision_Detection(sf::CircleShape &ball1, sf::CircleShape &ball2)
{
    bool collision = false;
    float distance = sqrt(pow(ball2.getPosition().x - ball1.getPosition().x, 2) +
        pow(ball2.getPosition().y - ball1.getPosition().y, 2));
    if (distance <= ball1.getRadius() + ball2.getRadius() + 4)
        collision = true;
    return collision;

检测有时会起作用,有时会卡住,我不确定这是逻辑问题还是性能不好,我需要先进行边界框碰撞。

我如何处理这件事有意义吗?有没有我忽略的东西或者人们通常编码的更标准的方式?

【问题讨论】:

标签: c++11 2d collision-detection velocity sfml


【解决方案1】:

对于矩形,有sf::Rect&lt;typename T&gt; 和intersects()-方法,但没有像sf::Circle&lt;typename T&gt; 这样的方法。这是因为 SFML 在纹理管理等方面需要一个矩形类。不支持其他 SFML 开发人员所面临的圈子的问题。所以one of them 创建了一个SFML“扩展”,添加了一个sf::Circle&lt;typename T&gt; 这是他的代码:

namespace sf
{
    template <typename T> 
    class Circle
    {
    public:
        T x, y;
        T radius;

        Circle<T>()
        {
            this->x      = T(0);
            this->y      = T(0);
            this->radius = T(0);
        }

        Circle<T>(T _x, T _y, T _radius)
        {
            this->x      = _x + _radius;
            this->y      = _y + _radius;
            this->radius = _radius;
        }

        Circle<T>(sf::CircleShape cShape)
        {
            this->x      = T(cShape.getRadius() + cShape.getPosition().x);
            this->y      = T(cShape.getRadius() + cShape.getPosition().y);
            this->radius = T(cShape.getRadius());
        }

        bool intersects(sf::Circle<T> circle)
        {
            return (sqrt(pow(this->x - circle.x, 2) + pow(this->y - circle.y, 2)) >= this->radius + circle.radius)
        }

        bool contains(sf::Vector2<T> vecT)
        {
            return (sqrt(float(pow(float(this->x - vecT.x), (float)2) + pow(float(this->y - vecT.y), (float)2))) <= this->radius)
        }
    };

    typedef sf::Circle<int> IntCircle;
    typedef sf::Circle<double> DoubleCircle;
    typedef sf::Circle<float> FloatCircle;
    typedef sf::Circle<unsigned int> UintCircle;
}

您可以像使用矩形一样使用它。作者还举了一个例子:

sf::CircleShape sfCircle(20);
sfCircle.setPosition(100, 100);
sf::FloatCircle myCircle(sfCircle); 
// or:
// sf::FloatCircle myCircle(100, 100, 20);
// ---------------------------------------
// or:
// sf::FloatCircle myCircle;
// myCircle.radius = 20;
// myCircle.x = 100 + myCircle.radius;
// myCircle.y = 100 + myCircle.radius;

if (myCircle.contains((sf::Vector2f)sf::Mouse::getPosition(window)))
{
     //Collision.
}

希望对你有所帮助。

【讨论】:

    猜你喜欢
    • 2018-09-18
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2021-09-26
    • 2014-02-27
    • 1970-01-01
    相关资源
    最近更新 更多