setup()
setup() runs once when the sketch starts. It's where you create textures (reusable images) and initialize variables. Using p5.Graphics to pre-render shapes is much faster than redrawing them every frame—you draw once, then reuse the result thousands of times. This is how real games optimize performance.
🔬 The first parameter of fill() is red, second is green, third is blue—each from 0 to 255. What happens if you change (0, 0, 255) to (255, 0, 255)? To (100, 100, 100)?
let maxPlayerSize = 60; // Max size player could grow to (if upgrades affected size)
playerTexture = createGraphics(maxPlayerSize, maxPlayerSize);
playerTexture.fill(0, 0, 255); // Blue
function setup() {
createCanvas(windowWidth, windowHeight);
// Create simulated textures (p5.Graphics objects)
// These are created once and then scaled when drawn.
let maxPlayerSize = 60; // Max size player could grow to (if upgrades affected size)
playerTexture = createGraphics(maxPlayerSize, maxPlayerSize);
playerTexture.fill(0, 0, 255); // Blue
playerTexture.noStroke();
playerTexture.beginShape();
playerTexture.vertex(maxPlayerSize / 2, 0);
playerTexture.vertex(maxPlayerSize, maxPlayerSize);
playerTexture.vertex(maxPlayerSize / 2, maxPlayerSize * 0.75);
playerTexture.vertex(0, maxPlayerSize);
playerTexture.endShape(CLOSE);
playerTexture.fill(255); // White "eye" or indicator
playerTexture.ellipse(maxPlayerSize / 2, maxPlayerSize * 0.4, maxPlayerSize * 0.2);
let maxEnemySize = 70; // Max size enemy could grow to
enemyTexture = createGraphics(maxEnemySize, maxEnemySize);
enemyTexture.fill(255, 0, 0); // Red
enemyTexture.noStroke();
enemyTexture.beginShape();
enemyTexture.vertex(maxEnemySize / 2, 0);
enemyTexture.vertex(maxEnemySize, maxEnemySize / 3);
enemyTexture.vertex(maxEnemySize * 0.75, maxEnemySize);
enemyTexture.vertex(maxEnemySize / 4, maxEnemySize);
enemyTexture.vertex(0, maxEnemySize / 3);
enemyTexture.endShape(CLOSE);
enemyTexture.fill(255); // White "eye" or indicator
enemyTexture.ellipse(maxEnemySize / 2, maxEnemySize * 0.3, maxEnemySize * 0.2);
let maxItemSize = 30;
itemTexture = createGraphics(maxItemSize, maxItemSize);
itemTexture.fill(255, 255, 0); // Yellow
itemTexture.noStroke();
itemTexture.beginShape();
for (let i = 0; i < 5; i++) {
let angle = TWO_PI / 5 * i - HALF_PI;
let x = maxItemSize / 2 + cos(angle) * maxItemSize * 0.4;
let y = maxItemSize / 2 + sin(angle) * maxItemSize * 0.4;
itemTexture.vertex(x, y);
angle += TWO_PI / 10;
x = maxItemSize / 2 + cos(angle) * maxItemSize * 0.15; // Inner point
y = maxItemSize / 2 + sin(angle) * maxItemSize * 0.15;
itemTexture.vertex(x, y);
}
itemTexture.endShape(CLOSE);
// --- Weapon Textures (new) ---
pistolTexture = createGraphics(30, 20);
pistolTexture.fill(100); // Gray
pistolTexture.noStroke();
pistolTexture.rect(0, 5, 25, 10);
pistolTexture.rect(5, 15, 10, 5); // Handle
pistolProjectileTexture = createGraphics(15, 5); // Green rectangle (NOW GLOBAL)
pistolProjectileTexture.fill(0, 255, 0);
pistolProjectileTexture.noStroke();
pistolProjectileTexture.rect(0, 0, 15, 5);
shotgunTexture = createGraphics(40, 25);
shotgunTexture.fill(150, 75, 0); // Brown
shotgunTexture.noStroke();
shotgunTexture.rect(0, 5, 35, 15);
shotgunTexture.rect(30, 8, 10, 9); // Barrel tip
shotgunProjectileTexture = createGraphics(10, 10); // Red circle (pellet) (NOW GLOBAL)
shotgunProjectileTexture.fill(255, 0, 0);
shotgunProjectileTexture.noStroke();
shotgunProjectileTexture.ellipse(5, 5, 10, 10);
machineGunTexture = createGraphics(35, 20);
machineGunTexture.fill(50); // Dark Gray
machineGunTexture.noStroke();
machineGunTexture.rect(0, 5, 30, 10);
machineGunTexture.rect(25, 8, 10, 4); // Barrel tip
machineGunTexture.rect(5, 15, 15, 5); // Handle
machineGunProjectileTexture = createGraphics(8, 3); // Small, fast, light blue rectangle
machineGunProjectileTexture.fill(100, 100, 255);
machineGunProjectileTexture.noStroke();
machineGunProjectileTexture.rect(0, 0, 8, 3);
rocketLauncherTexture = createGraphics(50, 25);
rocketLauncherTexture.fill(75); // Dark Greenish Gray
rocketLauncherTexture.noStroke();
rocketLauncherTexture.rect(0, 8, 45, 9);
rocketLauncherTexture.ellipse(45, 12, 10, 10); // Barrel opening
rocketLauncherTexture.rect(10, 17, 20, 5); // Handle
rocketLauncherProjectileTexture = createGraphics(20, 10); // Large, slow, orange rocket
rocketLauncherProjectileTexture.fill(255, 150, 0);
rocketLauncherProjectileTexture.noStroke();
rocketLauncherProjectileTexture.rect(0, 0, 15, 10);
rocketLauncherProjectileTexture.triangle(15, 0, 15, 10, 20, 5); // Rocket tip
// Create the background texture
backgroundTexture = createGraphics(width, height);
generateBackgroundTexture(); // Initial generation
// Initialize player character (or load from localStorage)
loadProgress();
// Start the first wave
// If loading progress, start next wave directly, otherwise start wave 1
if (waveNumber === 0) {
startNextWave();
} else {
// If progress was loaded, ensure game state is set for the next wave
gameState = "WAVE_START";
waveStartTime = millis(); // Reset wave start time for countdown
setTimeout(() => gameState = "PLAYING", 3000); // 3-second countdown
}
}
Line-by-line explanation (8 lines)
🔧 Subcomponents:
playerTexture = createGraphics(maxPlayerSize, maxPlayerSize);
Creates a 60x60 pixel canvas object to pre-render the blue triangle player shape once, reused throughout the game
pistolTexture = createGraphics(30, 20);
Pre-renders all four weapon types (pistol, shotgun, machine gun, rocket launcher) as p5.Graphics objects for fast drawing
loadProgress();
Loads saved game data from localStorage if it exists, otherwise initializes a fresh player
createCanvas(windowWidth, windowHeight);- Creates a full-screen canvas that adapts to the window size
playerTexture = createGraphics(maxPlayerSize, maxPlayerSize);- Creates a 60x60 pixel off-screen canvas (p5.Graphics) where the player shape will be drawn once
playerTexture.fill(0, 0, 255); // Blue- Sets the fill color to blue for the player shape
playerTexture.beginShape(); ... playerTexture.endShape(CLOSE);- Draws a four-pointed triangle shape (like a spaceship) using vertices
playerTexture.ellipse(maxPlayerSize / 2, maxPlayerSize * 0.4, maxPlayerSize * 0.2);- Adds a white circle at the top of the player to represent an eye or indicator
backgroundTexture = createGraphics(width, height);- Creates a full-size off-screen canvas where the animated noise background will be rendered
loadProgress();- Attempts to load saved game data from the browser's localStorage, or initializes a new player if none exists
if (waveNumber === 0) { startNextWave(); }- If no game was loaded (fresh start), begin wave 1; otherwise resume from the saved wave