p5.js Beginner Article 4

Arrays & Data

Store and iterate over collections of values to manage particles, trails, and collections of objects.

⏱ 18 min read arrays data objects particles forEach

What is an array?

An array is an ordered list of values, stored in a single variable:

let colours = ['red', 'green', 'blue'];
let sizes   = [10, 25, 40, 15, 30];
let points  = [];   // empty array

Access elements by index (starting at 0):

colours[0]  // 'red'
colours[1]  // 'green'
colours[2]  // 'blue'
colours.length  // 3

Adding and removing

let items = [];

items.push(42);         // add to end → [42]
items.push(17, 99);     // add multiple → [42, 17, 99]
items.pop();            // remove last → [42, 17]
items.unshift(0);       // add to front → [0, 42, 17]
items.shift();          // remove first → [42, 17]
items.splice(1, 1);     // remove 1 item at index 1 → [42]

Looping over arrays

for…of — the cleanest way to read every element:

let radii = [20, 40, 60, 80, 100];

for (let r of radii) {
  circle(width / 2, height / 2, r * 2);
}

forEach — array method with a callback:

radii.forEach(r => circle(width / 2, height / 2, r * 2));

Classic for loop — when you need the index:

for (let i = 0; i < radii.length; i++) {
  fill(map(i, 0, radii.length - 1, 50, 255), 100, 200);
  circle(width / 2, height / 2, radii[i] * 2);
}

Arrays of objects — particle system

The real power of arrays is storing objects (complex values with multiple properties):

let particles = [];

function setup() {
  createCanvas(700, 500);
}

function draw() {
  background(15, 15, 25);

  // Spawn new particles at mouse
  if (mouseIsPressed) {
    particles.push({
      x:    mouseX + random(-10, 10),
      y:    mouseY + random(-10, 10),
      vx:   random(-2, 2),
      vy:   random(-4, -0.5),
      life: 255,
      r:    random(4, 12)
    });
  }

  // Update and draw
  noStroke();
  for (let p of particles) {
    p.x    += p.vx;
    p.y    += p.vy;
    p.vy   += 0.05;   // gravity
    p.life -= 4;

    fill(255, 150, 50, p.life);
    circle(p.x, p.y, p.r * 2);
  }

  // Remove dead particles (filter returns a new array)
  particles = particles.filter(p => p.life > 0);
}

The filter() method is the right way to remove elements: it returns a new array containing only the elements that pass the test, and we reassign particles to that result.

Useful array methods

map() — transform every element

let angles  = [0, 0.5, 1, 1.5, 2];
let xCoords = angles.map(a => cos(a) * 100 + width / 2);

filter() — keep matching elements

let alive = particles.filter(p => p.life > 0);

find() — first matching element

let nearest = circles.find(c => dist(mouseX, mouseY, c.x, c.y) < c.r);

sort() — order elements

// Sort by y position (top to bottom)
particles.sort((a, b) => a.y - b.y);

reduce() — compute a single value from all elements

let totalSize = circles.reduce((sum, c) => sum + c.r, 0);
let avgSize   = totalSize / circles.length;

Mouse-trail with a fixed-length array

Limit the array size to create a trailing effect:

let trail = [];
const MAX_TRAIL = 40;

function setup() {
  createCanvas(700, 500);
}

function draw() {
  background(20);

  // Add current mouse position
  trail.push({ x: mouseX, y: mouseY });

  // Keep only the last MAX_TRAIL points
  if (trail.length > MAX_TRAIL) trail.shift();

  // Draw trail
  noFill();
  for (let i = 1; i < trail.length; i++) {
    let alpha = map(i, 0, trail.length, 0, 255);
    let w     = map(i, 0, trail.length, 0.5, 6);
    stroke(100, 200, 255, alpha);
    strokeWeight(w);
    line(trail[i - 1].x, trail[i - 1].y, trail[i].x, trail[i].y);
  }
}

2D arrays — grids of data

An array where each element is itself an array:

let grid = [];
let cols = 10, rows = 8;

function setup() {
  createCanvas(600, 400);

  // Initialise grid
  for (let c = 0; c < cols; c++) {
    grid[c] = [];
    for (let r = 0; r < rows; r++) {
      grid[c][r] = random(1);   // random value 0–1
    }
  }
}

function draw() {
  let cw = width / cols;
  let ch = height / rows;

  for (let c = 0; c < cols; c++) {
    for (let r = 0; r < rows; r++) {
      let val = grid[c][r];
      fill(val * 255, val * 100, 255 - val * 200);
      noStroke();
      rect(c * cw, r * ch, cw - 2, ch - 2, 4);
    }
  }
}

function mouseClicked() {
  let c = floor(map(mouseX, 0, width,  0, cols));
  let r = floor(map(mouseY, 0, height, 0, rows));
  grid[c][r] = random(1);  // randomise clicked cell
}

Key takeaways

  • Arrays store ordered collections; access elements by index starting at 0
  • push() / pop() add and remove from the end; shift() / unshift() from the front
  • for...of is the cleanest way to iterate; use for (let i = 0; i < arr.length; i++) when you need the index
  • filter() returns a new array of matching elements — use it to remove dead particles
  • map(), find(), sort(), reduce() are powerful functional tools
  • Arrays of objects (each with x, y, velocity, etc.) are the backbone of particle systems