0
votes

I'm a complete beginner to OOP and I'm trying to figure out the best way to write a program for 2D collision of circles of equal mass in SFML C++. I want to generate two or more circles in a box with set starting velocity, but random starting position and direction, then have them interact. I'm having a lot of difficulty with the pseudocode for the mechanics since my physics is very rusty. I found this equation for 2D elastic collisions on wiki:

enter image description here

Does this mean that I should use this for both the x and y coordinates for each ball? I was thinking of doing something like this for the balls and velocities:

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

and I wrote a collision function like this:

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;

The detection sometimes works and sometimes gets stuck, I'm not sure if it's a problem with the logic or if the performance is bad and I need to do bounding-box collision first.

Does how I'm going about this make any sense? Is there something I'm overlooking or a more standard way that people usually code this?

1
There are tutorials everywhere on the internet on how to implement sphere/circle collisions (since it's the simplest to implement). The old Pool Hall Lessons: Fast, Accurate Collision Detection Between Circles or Spheres is one such example.DanielKO

1 Answers

0
votes

For rectangles there are sf::Rect<typename T> with the intersects()-method but nothing like sf::Circle<typename T> and such a method. This is because SFML needs a rectangle-class in for example the management of textures. The problem with no support for circles facing other SFML-developers too. So one of them created an SFML "extension" wich add a sf::Circle<typename T> Here are his code:

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

You can use it exactly like the rectangles. The author also provided an example:

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

I hope this can help you a bit.