Basic Usage
Hello, world
- Setting the stage
The foundation for all physics simulations is a world
object. You must create a world,
add objects and behaviors, and then advance the simulation.
There are several ways to create a world object, all of which involve calling Physics
as a function. The following three world
s are equivalent:
The return value, the function argument, and the “this” variable all refer to the same world. The benefit of using the last two methods is that it encourages a coding style that does not polute the global scope. Many worlds can be created this way which will be properly scoped and modular.
Example:
Configure your world
Several configuration options are settable when constructing a world. To set
any options, pass in a configuration object as the first argument to Physics
.
Example:
Making things “go” - Advancing the simulation
In order to advance the simulation by one frame, simply call the .step()
method
with the current time as a parameter. This can be done in any way you like,
but usually this will be called inside an animation loop, using
window.requestAnimationFrame
or similar.
A helper is provided with PhysicsJS to facilitate animation loops:
Physics.util.ticker
. The ticker methods will use requestAnimationFrame
so
you will need to polyfill it if necessary. To use the ticker,
just call .on()
to subscribe to the event, and call the start()
method.
Example:
Add things to the world
The “Swiss Army Knife” method of the world, is world.add()
. This method
will accept several types of “things” that can be added or replaced in the
world: bodies (objects), behaviors, renderers, and integrators.
Any number of bodies and behaviors may be added to the world, but only one renderer and one integrator can be added to any one world at any one time.
Bodies
Read more about Bodies on the wiki.
Bodies are the “what” of a physics simulation. They represent physical objects that can be rendered as DOM Elements, or drawn on canvas, or however you’d like to display them. They are not by default tied to any particular “view” or visual representation.
Bodies, like points, circles, or convex polygons, are available as extensions.
Creating a body is done using the Physics.body()
factory function.
Example:
Custom bodies can also be created and bodies can be extended. Read the wiki entry on bodies to learn more.
Behaviors (or Behaviours)
Read more about Behaviors on the wiki.
Behaviors (or Behaviours) are the “how” of a physics simulation. They are rules applied to the world that act on bodies during every timestep to simulate specific physical laws. A world without any behaviors will act as an infinite, frictionless vacuum. (No behaviors are included in the core library)
The most familiar example of a behavior is adding “gravity” to a simulation. What is most often meant by “gravity” is a constant acceleration in the downward (positive “y”) direction. Because of the frequent need for this, a “constant-acceleration” behavior is available as an extra.
Example:
Some behaviors act as “detectors”, which don’t modify bodies directly. Instead they detect specific events and announce them to the world’s pubsub system so other behaviors can take appropriate actions. One example of this is collision detection and response. There are separate behaviors for collision detection, collision response, and even so-called “sweep and prune” optimization algorithms.
Custom behaviors can also be created and behaviors can be extended. Read the wiki entry on behaviors to learn more.
Renderers
Read more about Renderers on the wiki.
Renderers are the user’s viewport into the simulation. At this stage, renderers are primitive and their capabilities limited. Simple renderers exist for DOM and HTML Canvas rendering. It is likely that for any involved simulations or animations, you will have to write your own renderer… but never fear, it’s not all that bad.
Adding an HTML Canvas renderer to the world is simple.
In order to render the state of the world to the canvas, you
will have to call the world.render()
method on every step.
Custom renderers can be created and renderers can be extended. Read the wiki entry on renderers to learn more.
Integrators
Read more about Integrators on the wiki.
An integrator is the mathematical workhorse of a simulation. An integrator will numerically integrate the physical properties of the bodies. In other words, it will move them to their next positions and velocities every “tick”.
Different integrators have different benefits and drawbacks. Currently the default integrator is the verlet integrator because of its benefits for rigid constraints. An “improved euler” integrator exists and community contributions are welcome (wishlist: RK4).
The integrator for the world can be set when the world is created, or afterwards.
Custom integrators can be created and integrators can be extended. Read the wiki entry on integrators to learn more.
Full Example
The example code snippets from these basic instructions can be found in this little example simulation:
Physics(function(world){ var viewWidth = 500; var viewHeight = 300; var renderer = Physics.renderer('canvas', { el: 'viewport', width: viewWidth, height: viewHeight, meta: false, // don't display meta data styles: { // set colors for the circle bodies 'circle' : { strokeStyle: '#351024', lineWidth: 1, fillStyle: '#d33682', angleIndicator: '#351024' } } }); // add the renderer world.add( renderer ); // render on each step world.on('step', function(){ world.render(); }); // bounds of the window var viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight); // constrain objects to these bounds world.add(Physics.behavior('edge-collision-detection', { aabb: viewportBounds, restitution: 0.99, cof: 0.99 })); // add a circle world.add( Physics.body('circle', { x: 50, // x-coordinate y: 30, // y-coordinate vx: 0.2, // velocity in x-direction vy: 0.01, // velocity in y-direction radius: 20 }) ); // ensure objects bounce when edge collision is detected world.add( Physics.behavior('body-impulse-response') ); // add some gravity world.add( Physics.behavior('constant-acceleration') ); // subscribe to ticker to advance the simulation Physics.util.ticker.on(function( time, dt ){ world.step( time ); }); // start the ticker Physics.util.ticker.start(); });