Implementation in JavaScript (ES6) of an engine for elastic collisions' resolution between balls.
Additional behavior can be injected by passing EnginePlugin's
to the Engine
.
Several plugins are implemented in plugins.js. In general, they can be used for drawing additional elements, performing simple animations, sanity checking,
measuring performances...
Try it at https://janluke.github.io/colliding-balls/
Command | Key(s) |
---|---|
Restart/refresh | r |
Pause/resume | p |
Next frame (while paused) | → |
Increase/decrease speed | ↑ / ↓ |
You need npm
. To install all dependencies:
npm install
To start webpack-dev-server:
npm start
To build a production release in the dist
folder:
npm run build
Collision detection follows the Periodic Interference Test (PIT) approach: when a new frame must be drawn (e.g. each 16ms), balls are checked for interlaps; if two balls interlap and are approaching, a collision is detected. Thus, the collisions are detected with delay, meaning that the simulation is not totally accurate and, in some circumstances, a collision may not be detected at all; see this document for a comparison between PIT and the more precise (but more computationally expensive) PIC methods.
The algorithm is meant to (decently) handle complex cases in which the effect of a collision must be propagated to obtain an accurate resolution. This is done through a kind of "sequential collision resolution" procedure. It doesn't work perfectly in all circumstances (e.g. try the "Two hit one (45°)" initialization) but it works well most of the times. I didn't take the algorithm from a book so it's probably not the best way to do it. Here is the gist of it (the actual implementation is slightly different):
- For each ball, find the list of balls and walls interlapping to it.
- Initialize a set
pairsToCheck
with all pairs of interlapping objects(ball, obj)
whereobj
can be a ball or a wall. - While
pairsToCheck
is not empty (and for a max ofT
iterations):- Pop a pair
(x, y)
frompairsToCheck
. - Detect a collision if
x
andy
are getting nearer according to their velocity vector. - If a collision is detected:
- Resolve the collision:
- update
x.velocity
- update
y.velocity
ify
is not a wall
- update
- (Propagation) (Re)add the following pairs to
pairsToCheck
(if not present):- all pairs
(i_x, h)
wherei_x
is a ball interlapping withx
andh != x
- if
y
is not a wall, all pairs(i_y, k)
wherei_y
is a ball interlapping withy
andk != y
- all pairs
- Resolve the collision:
- Pop a pair