与SFML的2D弹性碰撞

时间:2015-07-24 22:28:19

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

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

enter image description here

这是否意味着我应该将它用于每个球的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;

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

我对此的看法是否有意义?是否有一些我忽略的东西或者人们通常编码的更标准的方式?

1 个答案:

答案 0 :(得分:0)

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

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

我希望这可以帮到你一点。