Code Steps

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.

export function setup() {}
export function draw() {}
export function setup() {}
export function setup() {}
export function setup() {}
export function setup() {}
createCanvas(1000, 1000)
export function setup() {}
createCanvas(1000, 1000)
createCanvas(windowWidth, windowHeight)
createCanvas(1000, 1000)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)
createCanvas(windowWidth, windowHeight)

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.


  1. p5.js looks for functions named setup and draw in your sketch, and calls them if they are present.
  2. In this sketch, since we made the canvas the same width and height as the page, width and height have the same same value as windowWidth and windowHeight, we could have used rect(0, 0, windowWidth, windowHeight) instead of rect(0, 0, width, height). I chose to use width and height 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.
  3. “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”.
  4. 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-/.