A micro codebase that plays around with some mathematically dubious riffs on Newton's law of universal gravitation, in order to produce some pretty (though unrealistic) animations:
Note: actual animation is smoother than what's shown in this screencap.
Clone the repo, then run:
$ clj -i init.clj -r
Look for the Java GUI window and bring it into focus; an initial random simulation will be running in it. Press the 'q' key to close the window, or use the OS controls.
To run another random simulation, with between 50 and 200 randomly located objects:
(gg/simulate width height (gu/gen-random-objs 50 200 width height))
The code is divided into 2 primary namespaces: gravity.core
and gravity.gui
, and one supplementary namespace: gravity.util
.
This ns contains pure logic for calculating the pseudo-gravitational effects a sequence of 'objects' has on one another. Objects are simple maps with these keys (all of which are unitless numerical values):
:x
- x location:y
- y location:x-vel
- velocity in the horizontal dimension (optional, defaults to 0):y-vel
- velocity in the vertical dimension (optional, defaults to 0):mass
- mass of the object (optional, defaults to 1)
To step the objects, based on the (fudged) forces they exert on one another, the function gravity.core/step-simul
may be called. The first, mandatory, parameter is the sequence of objects to use as input, and it returns an equivalent sequence with all of the objects' positions and velocities updated.
The remaining, optional, parameters allow the caller to specify that the objects "bounce" at the edge of a given bounding box. These parameters are:
merge-collided-objects?
- boolean indicating whether to merge objects that have collided or notbounce-at-edge?
- boolean indicating whether edge bouncing is enabled or notmin-x
- the minimum value of the horizontal dimension of the bounding boxmin-y
- the minimum value of the vertical dimension of the bounding boxmax-x
- the maximum value of the horizontal dimension of the bounding boxmax-y
- the maximum value of the vertical dimension of the bounding box
This ns contains the logic related to displaying a simulation in a GUI window, currently via the clojure2d
library. The primary function here is gravity.gui/simulate
, which takes these parameters:
width
- the width of the window, in pixelsheight
- the height of the window, in pixelsobjs
- the sequence of objects to use in the simulation:trails true/false
- an optional flag that indicates whether the visualisation should have object trails or not (defaults tofalse
)
The window runs independently of the calling thread, and terminates when the window is closed via OS mechanisms, or when the 'q' key is pressed while the window has focus.
Note that this also means you can have any number of independent simulation windows open concurrently.
Includes a gen-random-objs
fn that will create a random number of randomly located objects, with random velocities.
It takes four mandatory parameters:
mini
- the minimum number of objects to create (inclusive)maxi
- the maximum number of objects to create (inclusive)width
- the maximum x coordinate to generateheight
- the maximum y coordinate to generate
Copyright © 2019 Peter Monks
This work is licensed under the GNU Affero General Public License v3.0 or later.
SPDX-License-Identifier: AGPL-3.0-or-later