๐ŸŽ Interactive modelling with p5.js

I worked a lot with particle models (molecular dynamics, agent-based models). In all those cases plotting is at times even more tedious than writing the simulation itself.

A nice tool to circumvent this issue in the prototyping stage is the javascript library p5js! Let's dive straight into it.

First steps first: the model

Every simulation starts (hopefully) with a rough model in mind. Let's simulate an apple ๐ŸŽ falling down. The corresponding model is of course Newton's second law

mxยจ=โˆ’mgx. m \ddot x = -m g x.

Example simulation with p5js

Below you can see a simple example for this model using p5js.

Click into the white area to add more apples ๐Ÿ˜‰. [1]

How does it work?

For simplicity, we just simulate one apple ๐Ÿ‘. How many lines do we need for that, including the simulation and plotting?

With p5js, we need only 32 lines![2]

First we define the objects we need.

let pv = p5.Vector;  // shortcut for using p5.Vector functions

let X, V, gravity;      // position, velocity and gravity
const R = 20;        // radius in pixel

For p5js we only need to define two functions: setup and draw. The setup function is called once in the beginning and the draw for each time-step. Easy ๐Ÿ™‚!

The setup function in our case just initiated the initial position, velocity and a vector pointing downwards.

function setup() {
  createCanvas(240, 320);
  frameRate(30);
  
  X = createVector(width/2, height/4);
  V = createVector(0.0, 0.0);
  gravity = createVector(0.0, 0.001);
}

Finally, the draw function will draw the canvas white and iterate the symplectic Euler method [3]

vn+1=vn+ฮ”tf(xn),xn+1=xn+ฮ”tvn+1. v_{n+1} = v_n + \Delta t f(x_n), \\ x_{n+1} = x_n + \Delta t v_{n+1}.

Then we ensure that the apple stays within the canvas[4] and draw it.

function draw() {
  background(255,255,255);
  
  // symplectic Euler method
  V.add( pv.mult( gravity, deltaTime ) );
  X.add( pv.mult( V, deltaTime) );
  
  // keep apple above the ground
  if( X.y + R > height){
    X.y = height - R;
    V.y = 0.0;
  }

  // draw apple
  fill(200,50,50);
  noStroke();
  circle(X.x, X.y, 2*R);
}

Voila. That's it! From here you could start to experiment with the simulation. For example using the online p5js-editor ๐Ÿš€ !

Challenge: Can you modify the example such that there are two falling apples?

You can find all available functions of p5js in the reference. For adding two apples you might want to use the p5.Vector.dist function.

โ†ช๏ธ If you want to read more on the numerical method, check out my project description about position-based dynamics.


  1. For the curious reader, to add more objects we need to deal with collisions. I used the Position-based dynamics method, you can read more about this method here and in the cited references therein. โ†ฉ๏ธŽ

  2. In case you are wondering: The full simulation shown above, with restart button and arbitray many apples, just needs 111 lines! โ†ฉ๏ธŽ

  3. The symplectic Euler method is preferable to the explicit or implicit Euler method here, as it will almost conserve the total energy of the system. โ†ฉ๏ธŽ

  4. The only small complication is that the point (0,0)(0,0) is on the top right of the image canvas, which means that the ground is at (0,h)(0,h) when hh is the height of the canvas. โ†ฉ๏ธŽ