I'm trying to calculate new velocities for 2 colliding balls, but can't really do that before I solve another problem.
Since in digital world a real collision almost never happens, we will always have a situation where the "colliding" balls overlap.
Imagine there is a 100 balls moving randomly so, if I understand it correctly, the procedure should be as follows:
x += vx
; y+= vy
;)If the above is correct, then, how could I move the balls "back in time" to the point of first collision? Known data:
b[i].x
, b[i].y
)X
and Y
velocities (b[i].vx
, b[i].vy
)dist
)Should I just calculate how many percent the dist
is of the perfect distance to the collision and then simply move back x
and y
coordinates by the same amount of percent of vx
and vy?
Determining whether or not two circles intersect or overlap is the most basic way of determining whether or not two circles have collided. This is done by comparing the distance squared between the two circles to the radius squared between the two circles.
One of the simpler forms of collision detection is between two rectangles that are axis aligned — meaning no rotation. The algorithm works by ensuring there is no gap between any of the 4 sides of the rectangles. Any gap means a collision does not exist.
Whether your strategy of move-then-collide makes sense depends on what kind of thing you are trying to simulate, and on the trade-off between accuracy and speed. If you are, say, writing a snooker simulator, or Super Monkey Ball, then move-then-collide is probably not good enough, for three reasons.
First, the balls will have the wrong velocities after collision. The differences will be subtle, but will feel wrong to players:
On the left, velocities at the end of a time-step when balls are allowed to intersect before collision is detected. On the right: velocities immediately after a collision at the correct time and place.
Second, objects moving fast enough may pass through each other without colliding. Or even if you detect the collision, you may eject the objects in the wrong way, causing some kind of illegal motion. (See tasvideos.org for a collection of collision bugs in the Super Mario Bros games that are caused by this move-then-eject strategy.)
Third, objects may end up intersecting at the end of your time step, with no room to move them apart (because other objects get in the way). So you end up having to draw the objects in intersecting position, which looks wrong.
In applications where these issues matter, then it's better to determine the point of collision before moving the balls. See this article of mine for a basic introduction to this collide-then-move approach.
For collisions like these, it's usually easiest to look at it from the reference frame of one of the balls.
Let's say you have ball1
and ball2
. These balls have positions p1
and p2
respectively, and velocities v1
and v2
. Let the relative velocity of ball1
with respect to ball2
be v1-v2=v
.
We want to know when ||p1-p2||
is less than ||r1||+||r2||
, where r1
is the vector with a length of the radius of the first ball in the direction towards the second ball, and r2
is vice-versa.
From ball2
's perspective, ball1
is moving with velocity v1+v2
. At time t
, ball2
is at position p2+(v1+v2)*t
.
The balls collide when:
(p1-(p2+vt)) = (r1+r2)
-(p2+vt) = (r1+r2)-p1
-p2-vt = (r1+r2)-p1
-vt = (r1+r2)-p1+p2
vt = (p1-p2)-(r1+r2)
Now since ||a|| = ||b||+||c||
when a = b+c
, we know that
||v||t = ||p1-p2|| - ||r1+r2||
t = (||p1-p2|| - ||r1+r2||)/||v||
For example: p1 = (7,5)
and p2=(4,1)
, ||r1||=1
and ||r1||=2
, and v1=(1,2)
and v2=(-2,-2)
then v=(3,4)
. The collision happens at:
t = (||(3,4)|| - 3)/||(3,4)||
t = (5-3)/(5) = 2/5 = 0.4
Now that you have the time of the collision, figuring out where the balls are is easy :-)
edit to put the vectormath into pseudocode:
p = p1-p2
v = v1-v2
t = (sqrt(p.x*p.x + p.y*p.y) - (r1+r2)) / sqrt(v.x*v.x + v.y*v.y)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With