p5.js Particle Workshop 3/3
December 03, 2019
Add multiple particles. Make them bounce from each other, and from the mouse.
This post continues Part 2.
Here’s where we left off in the previous post.
Draw circles insead of squares.
Put the two particles in an array.
draw functions read the particles from the array, instead of from the
The two calls to
processParticle can be replaced by a call to
forEach(processParticle). This applies
processParticle to each of the items
in the array.
draw will work with an array of any length.
Give the particles a random initial position.
Math.random() returns a floating point number (basically, a real number or
decimal, although it is not exactly the same as either of these) between 0.0
(inclusive) and 1.0 (exclusive).
Multiplying such as number by
windowWidth yields a number between 0.0 and
The code that creates the initial value for
particle1 is now identical to the
code that creates the initial value for
Extract the code that computes an initial value for
particle1 into a new
makeParticle, and use this function to create the initial value for
Use this same function to create the initial value for
We’re only using the
particle2 variables to store the return
makeParticle long enough to put it in the
particles array. Put
these values directly into the array, instead. This allows us to remove the
(We’re gradually getting rid of the code that’s specific to their being exactly two particles.)
Here’s a trick for making an array of length 2, filled by calling
Array(2) makes an array with two elements. (They both have the special value
map calls its argument
makeParticle once for each element in
the array, and makes a new array that contains the return values from all these
makeParticle. That new array becomes the value of
The advantage of using this trick to create the array is that we can as easily make 100 particles instead of just two.
If we create the array inside of
setup, then we can use the p5.js
random(windowWidth) returns a floating-point number between 0.0 and
windowWidth. It’s simpler than the code we were using before.
The p5.js functions are only available inside the
functions (and the event handler functions such as
mouseClicked()), and the functions that they call. This is why we had to move
the initialization of
particles inside of
setup, in order to use p5.js’s
Give the particles a small initial random x and y velocity. They’ll each start out moving at a randomm speed (between 0 and 1.41 pixels per second), in a random direction.
The p5.js function
random(a, b), with two arguments, returns a value between a
a + (b - a) * Math.random().
Make the particles bounce them when they hit the “floor”.
Bounce them off the walls too. (But not — yet — the ceiling.)
I prefer separate functions for moving and drawing the particles.
The particles bounce when they get close to each other.
This is implemented by looping over each pair of particles
testing whether their centers are close enough, and, if they are, applying a
force that moves them away from each other.
forEach’s loop over pairs of particles. The outer
over each particle, the inner
forEach then loops over each particle, and the
if statement keeps the code beneath it from comparing a particle to itself.
This code actually examines each pair twice: At one point it sets
particles, and later
p1 == particles and
p2 == particles.
This is mostly
It means that the forces are applied twice, and it means that the
bounceParticles takes twice as long as it needs to. We’ll address this at the
end of this article.
Turn off gravity, so we can see the particle interactions more easily.
With gravity off, the particles should bounce off the ceiling as well.
Add viscosity (the particles slow down over time).
Bounce the particles off the mouse position as well as each other. This lets you move the mouse around the screen to scatter particles from the mouse path.
We handle this with minimal modifications considering the mouse to be just another object, and running the bounce code over all the objects including the mouse, instead of just the particles.
This updatees the mouse “object“‘s
dy properties, which we then
As promised, here’s the change to only consider each pair of particles once (to
objects, but not also to separately process
forEach call the supplied function with two arguments, the array
element and its index within the array. Use this to only consider pairs where
the p1 precedes p2.
Wouldn’t it be cool if there a function like
forEach, that called our function
on each pair of elements from the array, taking care not to call our function
(array, array) and
There can be! Now that we’ve written the logic that handles this, we can extract
it tto a new function
forEachPair. Now it’s easier to read what
bounceParticles is doing.