This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.
When walking around London one day, I found a science museum and decided to drop by and take a look inside. Inside, I found this cool machine that has everything to do with what this article is going to be about, elastic collisions. Anyway, I decided to take a recording of it and you can see it below:
[ a real-life simulation of an elastic collision ]
When I saw that crazy machine, properly known as Energy Ring by soda.co.uk, the first thing that came to my mind was trying to emulate it in code. This article will provide an overview of elastic collisions and examples of code where you can see it in action.
With that said, this isn't a traditional article where I provide some code and explain it line-by-line. Instead, the goal is to provide increasingly complicated examples and the associated source files so that you can explore how elastic collisions can be used and implemented.
As you can guess, there is some level of physics knowledge required to fully understand elastic collisions. While you are not required to read the following articles, doing so will bring some clarity to the madness that you are about to be subjected to for the next two pages:
If you opted to not read the above articles, don't worry. I will provide a very brief overview of the important concepts that you need to know.
You probably know what a collision is. It is when objects collide with each other. There are two parts to a collision. The first part is the actual impact when two or more objects hit each other. The second part is what happens after they collide with each other. A collision where the total momentum of all objects before the first part is equal after the total momentum in the second part is called an elastic collision.
Notice that I am emphasizing momentum instead of energy. The reason is that momentum only cares about speed because the mass of the colliding objects isn't changing. When you talk about energy, in reality with a collision, you will lose some energy to heat, sound, and other things that will subtract from the total energy left over for dealing with movement.
Here is a very simple example of elastic collision at work where you have blocks of varying weight colliding with each other:
[ download source file (Flex / AS3) ]
Notice the reaction after the collision between the blocks. Some blocks bounce back faster than when they initially collided. Some other blocks bounce back slower.
To reiterate, the main concept of elastic collisions is quite simple. An elastic collision is a collision between two objects (bodies which have mass) where the total momentum of the objects colliding is preserved. In other words, none of the energy involved in the collision is lost. It is distributed between the objects depending on their mass and speed they had when the collision happened.
Let's say you have two objects of different masses moving towards each other:

They each have a certain speed before the collision. To put another way, they have a certain momentum going into the collision. After the collision, the speed they have as they bounce back will be something else:

How is that speed calculated? One thing we know is that the total momentum the objects have before the collision needs to be the same as the total momentum the objects have after the collision. This is an ideal case where energy isn't wasted on heat, sound, etc. Everything is purely transferred into movement.
Well...this is where some math comes into play. In the above diagram, I labeled the mass and velocity (speed) of each block. The formula for calculating the speed after a 2D collision is:

...and...

The variables u specify the speed of the object before the collision. The variables v specify the speed of the object after the collision.
Plugging in some values and converting the above formula into code, you simply have:
mass1 = 3 //mass of object A
vel1 = -1 //speed of object A (negative because of collision, opposite direction against object B)
mass2 = 1 //mass of object B
vel2 = 2 //speed of object B
bothmass = mass1 + mass2
newvel1 = (vel1 * (mass1 - mass2) + (2 * mass2 * vel2)) / bothmass
newvel2 = (vel2 * (mass2 - mass1) + (2 * mass1 * vel1)) / bothmass
//result...
//newvel1 = 0.5
//newvel2 = 2.5
Ok, now seems like a good place to take a short breather and look at more involved examples in the next section!
In the previous section, you learned a bit about elastic collisions and how they fit in with the physical laws that we are subjected to! In this page, let's look at two quick examples of Flash applications that implement elastic collisions.
If you saw the video in the previous section, you saw a circular ring with colorful blocks colliding with other blocks and bouncing back and forth. What is unique about the collision is that the path all objects move in is constrained by a circular, ring shape.
Below, you will find an example of the energy ring created in Flash:
You can download the source code for the above example here:
First of all, as you can tell from my version, I focused only on the movement and the collision. Some of the nice artistic touches like the small flying particles cannot be found in this. I'll leave it as an exercise to you, the fair reader, the add those nice finishing touches!
If you saw the source code for the bouncing blocks in the
previous section, you'll see a lot of similarities in this
version. What you may find useful is how to look at elastic
collision from not just the horizontal/x-axis collisions but
also taking the vertical/y-axis as well. Add in a bit of
gravity and simulating the loop using a sine curve, and
hopefully you find the source code valuable to look into.
The final example I am going to show is a pure 2D implementation of elastic collisions involving the typical billiards/pool scenario:
Move your mouse around the white ball to adjust the angle you are interested in hitting the ball with the pool stick. Click on the pool stick and move it back to adjust the force with which you want to hit the ball.
As you can tell by playing with this for a few minutes, this is something that I haven't fully finished! If you pocket the white ball, the ball simply just appears behind the line haha. It is really more of a technical demo than a game...for now. I will provide the full source file for this shortly once I have finished it as well.
To make up for not providing the source file, I will share how I am specifying the elastic collision. In this example, I am optimizing for performance because I want the response from a collision to be nearly instantaneous:
static public function doElasticCollision(b1:Ball,b2:Ball){
// Compute unit normal and unit tangent vectors
// v_n = normal vec. - a vector normal to the collision surface
var v_n:Point = new Point(b2.x-b1.x, b2.y-b1.y);
var hyp:Number = getHypotenuse(v_n.x,v_n.y); //distance between dots
var v_un:Point = new Point(v_n.x/hyp, v_n.y/hyp); // unit normal vector
var v_ut:Point = new Point(-v_un.y, v_un.x); // unit tangent vector
// Compute scalar projections of velocities onto v_un and v_ut
var v1n:Number = v_un.x * b1.vx + v_un.y * b1.vy;
var v1tPrime:Number = v_ut.x * b1.vx + v_ut.y * b1.vy;
var v2n:Number = v_un.x * b2.vx + v_un.y * b2.vy;
var v2tPrime:Number = v_ut.x * b2.vx + v_ut.y * b2.vy;
// Compute new velocities using one-dimensional elastic collision equations in the normal direction
// Division by zero avoided. See early return above.
var v1nPrime:Number = (v1n * (b1.m - b2.m) + 2. * b2.m * v2n) / (b1.m + b2.m);
var v2nPrime:Number = (v2n * (b2.m - b1.m) + 2. * b1.m * v1n) / (b1.m + b2.m);
// Compute new normal and tangential velocity vectors
var v_v1nPrime:Point = new Point(v_un.x*v1nPrime, v_un.y*v1nPrime);
var v_v1tPrime:Point = new Point(v_ut.x*v1tPrime, v_ut.y*v1tPrime);
var v_v2nPrime:Point = new Point(v_un.x*v2nPrime, v_un.y*v2nPrime);
var v_v2tPrime:Point = new Point(v_ut.x*v2tPrime, v_ut.y*v2tPrime);
//update velocities.
b1.vx = v_v1nPrime.x + v_v1tPrime.x;
b1.vy = v_v1nPrime.y + v_v1tPrime.y;
b2.vx = v_v2nPrime.x + v_v2tPrime.x;
b2.vy = v_v2nPrime.y + v_v2tPrime.y;
}
One way I am able to get better performance is because I am not using the Cosine and Sine functions. The downside is that some of the rotational tricks you can perform on a real game of billiards or pool aren't possible, but the upside is blink-of-an-eye collision detection and reaction!
I hope this article helped get you started with elastic collisions and how to implement them in your applications.
One thing I want to emphasize is that you are free to choose whatever approach you want for collision detection independently of what approach you want to take for the reaction to the collision. Kirupa has a few articles on Collision Detection already written, so check them out by clicking here. This article provides you with some examples of how to react to the collision. A clean reaction to the collision where momentum is preserved is...an elastic collision!
If you have any questions or want to learn more, visit yoambulante.com or post on the forums here.
|
|
|
|
Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence, ads, and algorithm-driven doodads. A huge thank you to all of you who buy kirupa's books, became a paid subscriber, watch the videos, and/or interact on the forums.
Your support keeps this site going! 😇
:: Copyright KIRUPA 2026 //--