setup()
setup() runs once at startup. Here it creates the canvas, loads assets, and generates the entire world. Procedural generation (using random placement rules) lets you create vast worlds—this 10,000×10,000 city with 500+ buildings would be tedious to hardcode, but a loop generates it in milliseconds.
🔬 This nested loop creates a grid of buildings. What happens if you change the outer loop's step from 400 to 800—do you expect twice as many or half as many buildings?
for(let x = -5000; x <= 5000; x += 400) {
for(let y = -5000; y <= 5000; y += 400) {
if(random() > 0.3) {
if(abs(x) < 200 && abs(y) < 200) continue;
function setup() {
createCanvas(windowWidth, windowHeight);
// Safely load the background image.
loadImage(bgImageUrl,
(img) => { bgImage = img; },
(err) => { console.warn("Background image failed to load (possibly blocked by CORS)."); }
);
// Generate Procedural City once
for(let x = -5000; x <= 5000; x += 400) {
for(let y = -5000; y <= 5000; y += 400) {
if(random() > 0.3) {
if(abs(x) < 200 && abs(y) < 200) continue;
buildings.push({
x: x + random(-15, 15),
y: y + random(-15, 15),
w: random(180, 260),
h: random(180, 260),
col: color(random(50, 100)),
roof: color(random(30, 50))
});
}
}
}
resetGame();
}
Line-by-line explanation (8 lines)
🔧 Subcomponents:
createCanvas(windowWidth, windowHeight);
Creates a fullscreen canvas that adapts to the window size
loadImage(bgImageUrl, (img) => { bgImage = img; }, (err) => { console.warn(...); });
Loads a background image with error handling so the game doesn't break if the image is blocked
for(let x = -5000; x <= 5000; x += 400) { for(let y = -5000; y <= 5000; y += 400) { ... } }
Creates a 50×50 grid of possible building locations and randomly populates them to generate a diverse city
createCanvas(windowWidth, windowHeight);- Creates the p5.js canvas at full window size so the game fills the screen on any device
loadImage(bgImageUrl, (img) => { bgImage = img; }, (err) => { console.warn(...); });- Asynchronously loads the background image from a URL; if it fails (CORS block), a warning is logged but the game still works
for(let x = -5000; x <= 5000; x += 400) {- Outer loop that steps through x-coordinates from -5000 to +5000 in increments of 400 pixels (the grid size)
for(let y = -5000; y <= 5000; y += 400) {- Inner loop that steps through y-coordinates, creating a 2D grid of potential building spots
if(random() > 0.3) {- 70% of grid cells will create a building (since random() returns 0–1, and 0.7–1.0 is > 0.3); this makes the city feel organic with gaps
if(abs(x) < 200 && abs(y) < 200) continue;- Skips any building generation near the origin (within 200 pixels), leaving open space for the player to start
buildings.push({ x: x + random(-15, 15), y: y + random(-15, 15), w: random(180, 260), h: random(180, 260), col: color(random(50, 100)), roof: color(random(30, 50)) });- Creates a building object with position (with ±15 pixel jitter to avoid a rigid grid), random width/height, and random gray colors for the walls and roof
resetGame();- Initializes the player, car, cops, and other game state once the city is fully generated