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
pairsToCheckwith all pairs of interlapping objects(ball, obj)whereobjcan be a ball or a wall. - While
pairsToCheckis not empty (and for a max ofTiterations):- Pop a pair
(x, y)frompairsToCheck. - Detect a collision if
xandyare getting nearer according to their velocity vector. - If a collision is detected:
- Resolve the collision:
- update
x.velocity - update
y.velocityifyis not a wall
- update
- (Propagation) (Re)add the following pairs to
pairsToCheck(if not present):- all pairs
(i_x, h)wherei_xis a ball interlapping withxandh != x - if
yis not a wall, all pairs(i_y, k)wherei_yis a ball interlapping withyandk != y
- all pairs
- Resolve the collision:
- Pop a pair