Elastic Collision Ball Physics

Hi everyone, I just thought I’d share something I’ve been working on. Aside from game developers I doubt many will have much of a use for it.

So for one of my upcomming games I needed to be able to handle collisions between two circular sprites, which was umm… harder than I hoped. In the end though I was able to get it going and I have a working sample channel if anyone is interested.
https://github.com/Romans-I-XVI/Roku-El … on-Physics

If you just want to see what the channel does without installing you can see here…
https://www.youtube.com/watch?v=httCGL_XwLA

So in this sample we are essentially spawning 20 balls with random sizes that also correlate to their mass, tell them to start moving at a random speed, and then let the ManageBounce() function do its magic :face_with_tongue:

If you look at my commit history on github you might see I’ve been banging my head on the desk trying to make the code perfect. Because, although everything works great, there are special circumstances where occassionally a ball will pass through another ball. I know what the cause is, but I don’t know the solution. Once two balls have collided I have to mark that the collision has happened because if I don’t, and the collision is still occuring in the next frame even though speeds have already been altered, the collision will be processed again and the balls get stuck together. The problem that creates though is that if say another ball comes and hits the ball, while it is still registering that previous collision, it won’t register it another time (again because it doesn’t want to get stuck together) and will pass right through the ball it originally had a collision with. I’ve tried getting really crazy with it from about every angle I can think of, handling multiple collisions at a time, disabling the first collision if a second collision occurs ( this just leads back to the problem of balls getting stuck together sometimes ), manually altering speeds. In the end I reverted to the code I had originally that seemed to work just as good ( it’s hard to tell for sure since it’s so random ) and is a lot less complicated.

So if anyone has any thoughts on getting this to work 100% with balls never passing through each other, even if there were say 40+ on the screen, let me know. Otherwise enjoy the code. Hopefully somebody can use this in a game or something.

That’s pretty impressive really. It makes you appreciate a little bit what has been accomplished in general gaming and physics programming in 3D.

Thanks, and yeah I totally agree. So much math just to make two balls bounce against each other, modern physics engines really are a marvel.

I did it!!!

I fixed the problem of balls passing through each other! Here’s a video with a very crowded space, and yet are collisions working properly :sunglasses: .
https://youtu.be/2YFNhNFcnkM

Essentially I added an entire new function that checks if the total distance between two balls is less than it should be ( i.e. One is inside of the other, even just slightly ). If so I simply adjust the x and y positions ( without touching the speeds at all, since that is what the other function does ) so that it is at the point where the edges are just barely touching, essentially where it would be in a real world collision where balls passing through each other is physically impossible lol.

The solution wasn’t necessarily easy, but it was much easier than some of the other madness I was trying, and it is also a much more elegant solution.

:mrgreen:

What Roku model are you running that on? Looks like you’re achieving an impressive framerate for having so many sprites on screen at once.

Roku 3, if I do that on Roku 1 it’s very laggy.

“Romans_I_XVI” wrote:
I did it!!!

The solution wasn’t necessarily easy, but it was much easier than some of the other madness I was trying, and it is also a much more elegant solution.

:mrgreen:

Congrats - I love little breakthroughs, always make me feel so smart and satisfied and extra-nerdy! :sunglasses: :oops:

Thanks for sharing. Good example of Sprite collision
Couldn’t believe it - :shock: you even got the desk to shake when they collided

Lol, and thanks :slightly_smiling_face:

Thanks for sharing!

-JT

“Romans_I_XVI” wrote:
Roku 3, if I do that on Roku 1 it’s very laggy.
How many FPS on #42xx vs #3xxx vs 27xx?

Doing the elastic collision of round particles should be simple - admittedly i haven’t done it in years but https://en.wikipedia.org/wiki/Elastic_c … _Newtonian

The “pass trought” and “drag along” are interesting issues of simulation discretization to frames which i seem to vaguely remember. Your method of “back off” correction - does it work well when there is bunch of objects touching at the same time? For example line of balls like in Newton’s craddle (no need of wires, end balls may bounce back from the room walls).

Alternatively, how about counting collision between two bodies only when they are touching (or overlapping) AND their speed vectors are colliding? (I.e. when they are pulling apart that’s not collision or both are moving same direction and frontmost is faster, that’s also not)

Hey EnTerr, the “back off” method is working very well. I even added gravity and friction and the balls all eventually settled with no issues. :grinning_face_with_smiling_eyes:

Well if you add enough friction, all issues will be settled sooner than later :grinning_face_with_smiling_eyes:
Looks quite neat, i share your enthusiasm!
W/o friction/gravity - it’s a screen saver. With - it made me think of those sand picture frames - where you flip and watch sand grains settle down in water.

Don’t you have something to track frames-per-second? I find it quite useful, but doing it right can be tricky. Here is what i do now (sorry for copying Lua, don’t have my B/S handy but is trivial to adapt):

FPS_label = director:createLabel {
  vAlignment = "top", hAlignment="right",   textXScale = 2,     textYScale = 2,
  textBorderTop = 30, textBorderRight = 70,  color = FONT_COLOR, zOrder = 100,
  text = ''
}
scene:addChild(FPS_label)
avg_deltaTime = 0.03  -- start value, unimportant
time_to_next_report = 0
function update_fps()
  avg_deltaTime = (19 * avg_deltaTime + system.deltaTime) / 20    -- keep running average
  time_to_next_report = time_to_next_report - system.deltaTime    
  if time_to_next_report <= 0  then
    time_to_next_report = 1 -- every 1 second
    local fps = string.format(avg_deltaTime > 0.101 and '%.1f' or '%.0f', 1/avg_deltaTime)
    FPS_label.text = fps
  end    
end

The interesting parts are keeping (exponential) moving average to stabilize the value - and updating the displayed text less often than every frame (for humane reasons)