setup()
setup() runs once when the sketch starts. It initializes the canvas, color mode, HTML overlay elements, and the rings array that powers the entire tunnel. The map() function is essential here—it transforms a sequence (0, 1, 2...69) into evenly spaced positions and colors across the tunnel.
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
colorMode(HSB, 360, 100, 100, 1);
// Create an overlay instruction text
inst = createDiv('CLICK / TAP & HOLD TO DIVE FASTER');
inst.style('position', 'absolute');
inst.style('bottom', '30px');
inst.style('width', '100%');
inst.style('text-align', 'center');
inst.style('color', 'rgba(255, 255, 255, 0.7)');
inst.style('font-family', 'sans-serif');
inst.style('font-size', '14px');
inst.style('letter-spacing', '3px');
inst.style('pointer-events', 'none');
// Create the squares counter text in the top left corner
counterDiv = createDiv('');
counterDiv.style('position', 'absolute');
counterDiv.style('top', '20px');
counterDiv.style('left', '20px');
counterDiv.style('color', 'rgba(255, 255, 255, 0.6)');
counterDiv.style('font-family', 'sans-serif');
counterDiv.style('font-size', '12px');
counterDiv.style('letter-spacing', '2px');
counterDiv.style('pointer-events', 'none');
// Initialize the rings
for (let i = 0; i < numRings; i++) {
rings.push({
z: map(i, 0, numRings, 0, -totalDepth),
hue: map(i, 0, numRings, 0, 360),
active: true // Tracks if the ring is still rendering
});
}
}
Line-by-line explanation (12 lines)
🔧 Subcomponents:
createCanvas(windowWidth, windowHeight, WEBGL);
Creates a fullscreen 3D canvas using WEBGL renderer, making 3D transforms and depth possible
inst = createDiv('CLICK / TAP & HOLD TO DIVE FASTER');
Creates an HTML text element positioned at the bottom of the screen to guide the player
counterDiv = createDiv('');
Creates an HTML element in the top-left to display the remaining squares counter
for (let i = 0; i < numRings; i++) {
rings.push({
z: map(i, 0, numRings, 0, -totalDepth),
hue: map(i, 0, numRings, 0, 360),
active: true
});
}
Populates the rings array with initial objects spaced evenly down the tunnel depth, each with a z-position and hue that cycles through the color spectrum
createCanvas(windowWidth, windowHeight, WEBGL);- Creates a fullscreen 3D canvas. WEBGL is the renderer that enables 3D transforms like translate() and rotateZ()
colorMode(HSB, 360, 100, 100, 1);- Switches color mode to HSB (Hue, Saturation, Brightness) with hue 0-360, saturation 0-100, brightness 0-100, and alpha 0-1. This makes smooth color cycling easy
inst = createDiv('CLICK / TAP & HOLD TO DIVE FASTER');- Creates an HTML div element for instructions that sits on top of the canvas
inst.style('position', 'absolute');- Positions the div absolutely so it floats over the canvas rather than affecting the page layout
inst.style('bottom', '30px');- Places the instruction text 30 pixels from the bottom of the screen
counterDiv = createDiv('');- Creates an empty HTML div that will hold the counter text, updated every frame in draw()
counterDiv.style('top', '20px');- Places the counter 20 pixels from the top of the screen
counterDiv.style('left', '20px');- Places the counter 20 pixels from the left edge of the screen
for (let i = 0; i < numRings; i++) {- Loops once for each ring (70 times by default), creating an initial array of ring objects
z: map(i, 0, numRings, 0, -totalDepth),- Uses map() to spread rings from z=0 (nearest camera) to z=-5000 (farthest), creating initial depth spacing
hue: map(i, 0, numRings, 0, 360),- Assigns each ring a hue from 0 (red) to 360 (red again), cycling through the full color spectrum as you move down
active: true // Tracks if the ring is still rendering- Marks each ring as active so draw() knows to render it; becomes false when remainingRings hits zero