circle collision

Hello everybody

Right now i am coding on a circle collision programm. It detects the collision but somehow it wont move the second circle "Ball".

Here is the code:

The interesting part starts at line 96.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream.h>

int main() {
    sf::RenderWindow App(sf::VideoMode(400, 400, 32), "SFML Events");
    //sf::RenderWindow App(sf::VideoMode::GetMode(0), "SFML Window", sf::Style::Fullscreen);

    sf::Image iCircle;
    if (!iCircle.LoadFromFile("perfect.png")) {
        // Error...
    }
    sf::Sprite CircleP1;
    CircleP1.SetImage(iCircle);
    CircleP1.SetColor(sf::Color(255, 255, 255, 255));
    CircleP1.SetX(100.f);
    CircleP1.SetY(100.f);
    CircleP1.SetPosition(0.f, 0.f);
    CircleP1.SetRotation(0.f);
    CircleP1.SetCenter(0, 0);

    sf::Sprite Ball;
    Ball.SetImage(iCircle);
    Ball.SetColor(sf::Color(0, 255, 0, 255));
    Ball.SetX(100.f);
    Ball.SetY(100.f);
    Ball.SetPosition(150.f, 150.f);
    Ball.SetRotation(0.f);
    Ball.SetCenter(0, 0);

    int resX = 1280;
    int resY = 800;

    double PI = 3.14159;
    double rad = CircleP1.GetSize().x / 2;
    double fric = 0.98;
    double xSpeedBall = 0;
    double ySpeedBall = 0;
    double xSpeedP1 = 0;
    double ySpeedP1 = 0;
    double massP1 = 1;
    double massBall = 1;
    bool left = false;
    bool right = false;
    bool up = false;
    bool down = false;


    while (App.IsOpened()) {
        App.UseVerticalSync(true);
        double ElapsedTime = App.GetFrameTime();
        sf::Event Event;
        while (App.GetEvent(Event)) {
            if (Event.Type == sf::Event::Closed)
                App.Close();
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
                App.Close();
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Left))
                left = true;
            if ((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Key::Left)) {
                left = false;
                xSpeedP1 = 0;
            }
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Right))
                right = true;
            if ((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Key::Right)) {
                right = false;
                xSpeedP1 = 0;
            }
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Up))
                up = true;
            if ((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Key::Up)) {
                up = false;
                ySpeedP1 = 0;
            }
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Down))
                down = true;
            if ((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Key::Down)) {
                down = false;
                ySpeedP1 = 0;
            }
        }

        // CONTROL of P1
        if (left)
            xSpeedP1 = -100 * ElapsedTime;
        if (right)
            xSpeedP1 = 100 * ElapsedTime;
        if (up)
            ySpeedP1 = -100 * ElapsedTime;
        if (down)
            ySpeedP1 = 100 * ElapsedTime;


        // COLLISION
        if (pow(CircleP1.GetPosition().x - Ball.GetPosition().x, 2)
                + pow(CircleP1.GetPosition().y - Ball.GetPosition().y, 2)
                < pow(rad * 2, 2)) {
            Ball.SetColor(sf::Color(255, 0, 0, 255));
            // arc angel of collision
            double atan = atan2(CircleP1.GetPosition().y - Ball.GetPosition().y,
                    CircleP1.GetPosition().x - Ball.GetPosition().x);
            // velocity and direction in normal coordinate system
            double magP1 = sqrt(pow(xSpeedP1, 2) + pow(ySpeedP1, 2));
            double magBall = sqrt(pow(xSpeedBall, 2) + pow(ySpeedBall, 2));
            double dirP1 = atan2(ySpeedP1, xSpeedP1);
            double dirBall = atan2(ySpeedBall, xSpeedBall);
            //cout << dirBall;
            // convert velocity to temp coordinate system
            double xVelP1TempPre = xSpeedP1 * cos(magP1 - atan);
            double yVelP1TempPre = ySpeedP1 * sin(magP1 - atan);
            double xVelBallTempPre = xSpeedBall * cos(magBall - atan);
            double yVelBallTempPre = ySpeedBall * sin(magBall - atan);
            //cout << xVelBallTempPre;
            // collision in temp coordinate system
            // (only xSpeed due to 1 dimensional collision)
            double xVelP1TempPost = ((massP1 - massBall) * xVelP1TempPre + (massBall * 2) * xVelBallTempPre) / (massP1 + massBall);
            double yVelP1TempPost = yVelBallTempPre;
            double xVelBallTempPost = ((massP1 - massBall) * xVelBallTempPre + (massBall * 2) * xVelP1TempPre) / (massP1 + massBall);
            double yVelBallTempPost = yVelBallTempPre;
            //cout << xVelBallTempPost;
            // convert collision to normal coordinate system
            double xSpeedBallTemp = cos(atan * xVelBallTempPost) + cos(atan + PI / 2) * yVelBallTempPost;
            double ySpeedBallTemp = sin(atan * xVelBallTempPost) + sin(atan + PI / 2) * yVelBallTempPost;
            double xSpeedBall = xSpeedBallTemp;
            double ySpeedBall = ySpeedBallTemp;
            cout << xSpeedBall;

        }

        if (pow(CircleP1.GetPosition().x - Ball.GetPosition().x, 2)
                + pow(CircleP1.GetPosition().y - Ball.GetPosition().y, 2)
                > pow(rad * 2, 2)) {
            Ball.SetColor(sf::Color(0, 255, 0, 255));
        }
        

        // MOTION
        CircleP1.Move(xSpeedP1, ySpeedP1);
        Ball.Move(xSpeedBall, ySpeedBall);

        App.Draw(Ball);
        App.Draw(CircleP1);
        App.Display();
        App.Clear();
    }
    return EXIT_SUCCESS;
}

Last edited on
What is the actual behavior on collision? Are the balls just passing through each other, or are they sticking to each other?
do you mean the balls should not overlap, instead they should repel?
1
2
3
4
5
if (pow(CircleP1.GetPosition().x - Ball.GetPosition().x, 2)
                + pow(CircleP1.GetPosition().y - Ball.GetPosition().y, 2)
                > pow(rad * 2, 2)) {
            Ball.SetColor(sf::Color(0, 255, 0, 255));
        }


ugh. Why does everybody want to use pow to square stuff? pow is dreadfully slow because it's meant to handle obscure (floating point) powers. Straight multiplication is much simpler and faster than calling pow.

Just do the multiplication yourself:

1
2
3
4
5
6
double x = CircleP1.GetPosition().x - Ball.GetPosition().x;
double y = CircleP1.GetPosition().y - Ball.GetPosition().y;
if( (x*x) + (y*y) > (rad*rad) )  // MUCH better
{
  //...
}



EDIT:
Is there any reason you are squaring rad*2 in your original post? You only should be squaring rad. (assuming the coords you have here are the center points)
Last edited on
EDIT:
Is there any reason you are squaring rad*2 in your original post? You only should be squaring rad. (assuming the coords you have here are the center points)


Yes, there is.

As I'm sure you're aware, Pythagorean theorem is a2 + b2 = c2
a = x dimension distance between the two circles
b = y dimension distance between the two circles
c = sum of radii of the two circles.

Assuming the two circles have the same radius (and I'm taking a slight leap of faith there, since the code is a bit ambiguous about that), then c = rad*2 is also valid, as opposed to using c = rad1+rad2.

So, it is the sum of radii that need to be squared, not just an individual radius, which would only be the case if you were determining a point to circle intersection, as opposed to a circle to circle intersection.
oh okay. I just assumed 'rad' was the sum of the radiuses like 'x' was the difference of the coords.

My mistake!
Thanks for your suggestions up to this point. But my problem is still unsolved.

The prgramm detects the the collision properly but when "CircleP1" (which is controlled by the keyboard) and "Ball" overlap "Ball" doesnt move at all.

I tried to cout some values but couldnt figure out the reason.
"Ball" doesnt move at all.


Line 141 moves it by xSpeedBall,ySpeedBall. The problem is both of those vars are always zero because you never set them to any other value.

It looks like you're trying to set them on lines 126,127.... but you're declaring different variables with the same names instead of assigning your existing variables.

So I guess the solution would be to remove the doubles from lines 126,127
Topic archived. No new replies allowed.