The Creative Coder’s Field Guide
Everything You Need to Survive and Thrive with p5.js
Creative Coding · Week 1
Everything the first week of p5.js stands on: the canvas, the grid it draws on, functions, draw() running again and again, and how color works. Keep it next to the editor.
Three things are in play, and it helps to keep them straight.
So the full picture: you write JavaScript, you lean on p5's commands, and the result shows up on the canvas.
Find these under the gear icon / Preferences. Set them once and forget about them.
| Setting | Set it to | Why |
|---|---|---|
| Autosave | On | Saves periodically in the background, but it only kicks in after you've saved the sketch manually once, and it isn't perfect. Keep hitting Save yourself too. |
| Theme | Dark | The editor only offers Dark while you're logged in. Set it once, and if the editor ever looks light again, that's your sign you got logged out. |
| Auto-Refresh | Off | Otherwise the sketch reruns on every keystroke, restarting your animation mid-thought. Refresh manually when you want to see the change. |
Every position on the canvas is a pair of numbers, (x, y), that maps to a horizontal and vertical spot.
x: how many pixels from the left edge. Bigger x moves right.y: how many pixels from the top edge. Bigger y moves down. (Not like math class, because the plane is flipped vertically.)width: the total number of pixels across.height: the total number of pixels from top to bottom.The origin (0, 0) is the top-left corner.
y runs the opposite direction from the graphs you've seen before.width and height| Point | Coordinate |
|---|---|
| Top-left (origin) | (0, 0) |
| Top-right | (width, 0) |
| Bottom-left | (0, height) |
| Bottom-right | (width, height) |
| Center | (width / 2, height / 2) |
For a canvas created with createCanvas(400, 300): the corners are (0,0), (400,0), (0,300), (400,300), and the center is (200, 150). Practice this until it's instant for any width and height.
A function is a command: a named bundle of instructions. Two different things happen with functions, and mixing them up is the classic first-week confusion:
function setup() { … } means “here is what setup means.” Nothing runs yet.createCanvas(400, 400) is a call.This week you only call functions. Writing your own from scratch comes in Week 5. The one thing that looks like defining, function setup() and function draw(), is really you filling in a body that p5 already asked for (see section 06).
The values inside the parentheses are parameters (also called arguments): the specifics a function needs to do its job. circle(x, y, d) can't draw anything until it knows where and how big. Parameters are what let one function handle every case instead of just one.
createCanvas() with nothing in the parentheses is still a valid call, because the parentheses are non-negotiable.p5 ships with a long list of prefab functions, including createCanvas, background, fill, stroke, circle, ellipse, rect, line, and text, plus a few prefab values like width and height. Two special functions, setup and draw, are ones p5 expects you to write the body of.
A variable is a labeled container that holds a piece of data: a number, some text, a color. The data might change over time, or it might not.
p5 keeps a handful of these filled in for you automatically, so you can use them right away without ever writing one yourself:
| Variable | Holds |
|---|---|
width | The canvas's width, in pixels |
height | The canvas's height, in pixels |
mouseX | The mouse's current x position |
mouseY | The mouse's current y position |
Notice you never had to set any of these: p5 updates them for you, every frame. Making your own variables, and using them to move things around, is next week.
setup() and draw()These are the two functions whose bodies you write and p5 calls. You never call them yourself: you fill them in, and p5 runs them on a schedule. (Writing functions of your own, from nothing, is Week 5.)
setup() runs once, first. It's for one-time jobs, above all createCanvas().draw() runs right after, then again and again, about 60 times per second, forever.draw() is one frame.setup() and draw(); p5 owns the clock. That's why the starting state goes in setup() and anything that should update goes in draw().Within one draw(), lines run top to bottom, and two habits matter.
background() wipes the canvasbackground(...) paints over the entire canvas in one color. Put it at the top of draw() to erase the previous frame before drawing the new one. It takes a color in the same formats as fill(), e.g. background(220) for light grey.
fill() and stroke() are not attached to shapesThey set the “current” fill and outline color, like picking up a colored pen. Every shape drawn after uses that color until you pick up a different one.
fill() was last called. Change the pen once and it stays changed.Rule of thumb: set fill() / stroke() before the shape you want them to affect, not after.
Each shape is a function call. The parameters are coordinates and sizes, in pixels, so knowing the coordinate plane (section 03) is what makes these usable.
| Call | What it draws |
|---|---|
point(x, y) | A single pixel: set strokeWeight(4) or more first, or it's almost invisible |
line(x1, y1, x2, y2) | A straight segment between two points |
rect(x, y, w, h) | A rectangle, anchored at its top-left corner |
square(x, y, s) | A square, also from the top-left corner |
ellipse(x, y, w, h) | An ellipse, anchored at its center |
circle(x, y, d) | A circle from its center; d is the diameter |
triangle(x1, y1, x2, y2, x3, y3) | A triangle through three points |
quad(x1, y1, … x4, y4) | A four-sided shape through four points |
rect measures from a corner, but ellipse and circle measure from the middle. rectMode(CENTER) switches the rectangle to center-anchored if you want them to match.rectMode() and ellipseMode() both take the same four modes as their setting; they just start from different defaults, which is why the two shapes disagree by default.
| Mode | x, y is | w, h is | Default for |
|---|---|---|---|
CORNER | a corner | width, height | rect() |
CENTER | the center | width, height | ellipse(), circle() |
RADIUS | the center | half-width, half-height | n/a |
CORNERS | one corner | the opposite corner (a point, not a size) | n/a |
Call rectMode(CENTER) or ellipseMode(RADIUS) once, near the top of setup(), and every call to that shape uses the new mode from then on: it's state, same as fill().
strokeWeight(n): outline thickness in pixels. It also sets how big a point() draws, so keep it above 2 when you're plotting points.noFill(): draw the outline only.noStroke(): draw the fill only, no outline.Like fill() and stroke(), these are all state (section 07), so set them before the shapes they should affect.
arc(x, y, w, h, start, stop) draws a slice of an ellipse. Start and stop angles are in radians (0 to TWO_PI), or call angleMode(DEGREES) first to use 0–360.
w, h) is invisible: only the wedge from start to stop actually gets drawn.bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2) draws a smooth curve between two endpoints, bent by two control points.
beginShape() … vertex(x, y) … endShape() connect a list of points into a freeform outline.
vertex() adds one point, joined to the point before it. The dashed edge back to point 1 only appears if you finish with endShape(CLOSE) instead of a plain endShape().A color is a parameter like any other: you hand one to fill(), stroke(), or background(), and the command uses it. Before the code, though, it helps to know how a screen makes color at all.
Every pixel on your screen is really three tiny lights packed side by side: one red, one green, one blue. They're far too small to see separately, so their glow blends into a single color. Turn all three up to full power and the pixel looks white; turn them all off and it's black; every other color is some in-between recipe of the three.
Notice that this is the opposite of mixing paint: paint gets darker the more you add, light gets brighter. And it means every color format below is secretly writing down the same one thing: how strong each of the three lights should be.
All three formats describe the same colors, so pick whichever is easiest to think in. p5 assumes RGB unless you tell it otherwise.
Three numbers, always in the same order: red, green, blue. Each one is a light's strength, from 0 (off) to 255 (as bright as it goes). So fill(230, 60, 90) says “red almost full, only a little green, some blue,” which blends into the raspberry pink above.
Shortcut: give just one number and p5 sets all three lights to it. Equal amounts of red, green, and blue always make a grey, so fill(0) is black, fill(255) is white, and fill(120) is a middle grey.
The same three numbers in disguise, squeezed into one code borrowed from the web. After the #, each pair of characters is one channel: red, green, blue, same order as always. Letters show up because hex counts past 9 with A–F, so 00 is 0 and FF is 255.
Nobody converts these in their head. You copy them out of a color picker and paste them in quotes: fill('#E63C5A'). Color names in quotes work too: fill('tomato'), background('white').
0–3600 washed-out grey → 100 full strength0 black → 100 fully litRGB is how the machine thinks; HSB is closer to how you'd describe a color out loud: pick the color, then say how vivid and how bright. Tell p5 to switch with colorMode(HSB), then fill(340, 78, 90).
Its superpower: the three sliders match how you think, so “same color but darker” or “sweep through the rainbow” means nudging just one number.
Syntax is a language's grammar: the rules for how words, symbols, and punctuation have to be arranged before it counts as valid. It's different from vocabulary: p5 function names like circle() or fill() are vocabulary, specific to p5. The parentheses around their parameters, the semicolon that ends the line, and the braces that wrap a block are JavaScript's syntax, and it's the same no matter which functions you're calling.
Unlike English, this grammar isn't a suggestion. A person can untangle a sentence missing a comma; the computer can't guess what a missing brace or parenthesis was supposed to mean, so it just stops. That's also why syntax is worth learning to recognize early: most of your first error messages will be some flavor of “your syntax is broken here,” and being able to name what you're looking at makes them far less mysterious.
You don't need to have mastered these yet; you need to know what they're called and roughly what they're for.
| Category | What you'll see |
|---|---|
| Keywords | let, function, if, else if, else, for |
| Operators | = + - * / ++ -- += -= *= /=: just know these are operators; the details come later |
Parentheses ( ) | Hold a function's parameters, and group conditions |
Braces { } | Wrap the block of statements that belong to a function, loop, or if |
Semicolon ; | Ends a statement. Technically optional, but use them anyway |
Comments // | Everything after // on a line is ignored. Toggle with Cmd/Ctrl - / |
| Indentation | Optional for the computer, essential for humans. Keep it consistent |
Given any width and height, name the coordinates of all four corners and the center, without hesitating.
You are defining setup() and draw(). Inside them, you are calling createCanvas(), background(), fill(), and the shape functions.
setup() or draw()?“It starts at the center, (width/2, height/2)” or a corner, or 50 pixels in from the left edge. That decision is a setup() job, because it happens once.
Sketch a simple house or face on graph paper, read off the coordinates, then reproduce it with rect, ellipse, triangle, and line, remembering that rect starts at a corner and ellipse at the center. Going further: add a smile with arc() or a curved roofline with bezier().
p5 keeps mouseX and mouseY filled with the cursor's current position. Reading them belongs in draw(), so the sketch checks where the mouse is on every frame, e.g. “draw the circle at (mouseX, mouseY) so it follows the pointer.”