p5.js Particle Workshop 1/3
November 22, 2019
A series of code snapshots from day one of the p5.js Particle
Workshop.
To run a snapshots, copy and paste the code into the sketch.js
file in your
own p5.js project, such as one created by cloning the
https://github.com/osteele/p5-particle-workshop repository.
This is the code boilerplate for a p5.js sketch.
The setup
function is run once, when the sketch is started.
The code in the draw
function is run once per animation frame.1
Since the draw
function is empty, so is the drawing.
The draw
function now draws a rectangle. The rectangle is 100 pixels wide, and
50 pixels high.
Since the draw
function draws the same thing each time, this sketch appears as
a still image — it is not animated.
p5.js maintains graphics state — what color should rectangles (and other shapes) be drawn, should be colored along their edges (“stroke”), interior (“fill”), or both? A function that changes the graphics state, affects the behavior of subsequent drawing functions.
The call to fill
affects the behavior of rect
on the following line.
Changing the fourth rect
argument from 50
to 100
makes the rectangle twice
as tall (as it was before). Now it has the same width and height.
Changing the third rect
argument from 100
to 200
ought to make the
rectangle twice as wide. But it doesn’t. What’s going on?
All drawing happens on a “canvas”. The default canvas is only 100 pixels wide by 100 pixels high. If we try to draw a larger rectangle, we’re only seeing the left 100 pixels.
The rectangle didn’t appear any larger, becuase the (default) canvas was too
small. Add a function call to the setup
, to make the canvas bigger.
createCanvas
directs p5.js to create a canvas of the specified size, instead
of the 100 x 100 canvas that it creates if we don’t specify anything more
specific.
createCanvas
is inside the setup
function, because it only takes place once
(when the sketch is created). We don’t want a new canvas for each animation
frame; we want to keep drawing on the existing one.
Change the background to dark blue, and make the rectangle large enough to fill the entire canvas.
Colors can be specified as JavaScript Strings (inside single quotes 'blue'
or
double quotes "blue"
), or as mixtures of red, green, and blue light.
p5.js provides variables windowWidth
and windowHeight
, whose values are the
width and height of the browser page. If we use these in setup
, the canvas
will be exactly large enough to fill the browser page.
p5.js also provides width
and height
. These are width and height of the
canvas. By changing the rect
in draw
to use these, we’ll insure that the
rectangle is exactly large enough to fill the canvas (and, therefore, the page)2.
Draw a smaller rectangle, in white. This will be our first particle.
Once we’ve used let
to define a variable named particleX
whose value is 150,
we can use particleX
instead of 150
.
Similarly for particleY
.
The introduction of these variables changes the source code of the program, but we haven’t changed its behavior.
Now that the particle’s y position is specified by a variable, we can vary it.
This new line increases the value of particleY
by one, each animation frame.
For the first time, draw
has a different behavior each time it runs. (Its
behavior depends on the value of particleY
, and particleY
has a different
value each time it runs — because draw
changes it.)
Our sketch is now an animation.
Since particleY
represents the particle’s (vertical) position, the change to
its position is the particle’s velocity. The particle now has a constant
downwards velocity — it is moving towards (and past) the “ground”.
Hoist the 1
from particleY = particleY + 1
into a new variable, and give it
a name (dy
).
dy
represents the difference in particleY
’s value between one frame and
the next3. This is a common naming pattern for variables whose values are the
difference between other values.
The rectangle disappears when it passes the bottom of the window. Later, we’ll fix this. For now, you can reload the browser page in order to restart the animation.
increase dy
by a constant amount each time. dy
is the velocity: the rate
at which the value of particleY
increases. 0.01
is the rate at which this
velocity increases; it’s the acceleration. In this sketch, the particle has a
constant acceleration, as though it were subject to a constant force. This is
just like objects in the real world, that are subject to gravity.
Increasing a variable’s value by a number is a common operation.
particleX += dx
is a shortcut for particleX = particleX + dx
. It is exactly
equivalent, but (1) easier to type, and (2) avoids the risk of a certain typo
(particleY = particleX + dy
).
This step also demonstrates the practice of commenting out code4. The code that is
being replaced (particleX = particleX + dx
) is disabled by prefixing it with
//
, in order to turn it into a comment, that isn’t executed. This allows it
to be used as a visual reference while writing or debugging the new code. Where
it’s not too messy, I like to see the new code working before I completely
delete the code that it replaced.
Now remove the unused code.
(In coding, as with cooking and various other crafts, it is useful to alternate between making messes and cleaning them up, as you go along.)
Part 2 continues these notes.
- p5.js looks for functions named
setup
anddraw
in your sketch, and calls them if they are present.↩ - In this sketch, since we made the canvas the same width and height as the
page,
width
andheight
have the same same value aswindowWidth
andwindowHeight
, we could have usedrect(0, 0, windowWidth, windowHeight)
instead ofrect(0, 0, width, height)
. I chose to usewidth
andheight
because (1) they’re shorter, and (2) this way of doing it is less fragile: it will continue to work if we change our mind later about how large the canvas should be in relation to the browser page.↩ - “d” also stands for “delta”. In math and physics, the Greek letters ẟ and Δ — delta — are used for difference. But this is just because delta is the Greek letter that’s closed to “d”, and “difference” begins with “d”.↩
- Every modern code editor has a keyboard shortcut that comments out the
selected lines of code by adding
//
to the beginning of each line — or, removes the initial//
s if all the lines already begin with them, in order to un-comment-out the code. On macOS, this short cut is command-/. On Windows, it’s control-/.↩