cookie clicker by:moon_noob

This is a Cookie Clicker game where players click a central cookie to earn points, then purchase upgrades that generate cookies automatically. The game features persistent save/load functionality using localStorage, responsive button positioning, and real-time score updates displaying cookies per second (CPS).

🧪 Try This!

Experiment with the code by making these changes:

  1. Make the cookie red — Change the fill color RGB values to make the cookie visually distinct—a red cookie feels more playful
  2. Earn 10 cookies per click — Change the click reward from 1 to 10, making manual clicking feel more powerful early in the game
  3. Slow down upgrade price scaling — Reduce the cost multiplier from 1.15 to 1.08, making upgrades stay affordable longer and progression feel faster
  4. Add more chocolate chips — Increase numChips to make the cookie look more detailed and visually interesting
  5. Save every second instead of every 5 — Make the game save more frequently so you lose less progress if the browser crashes
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch recreates the addictive incremental game mechanic of Cookie Clicker in p5.js. Players click a large cookie circle to earn points, then spend those points on upgrades that automatically generate cookies over time. The game combines p5.js canvas drawing with HTML buttons, localStorage for persistence, and real-time score calculation—making it a practical project that teaches game loops, state management, object arrays, and DOM manipulation together.

The code is structured around a game state (score, totalCPS, upgrades array) that persists across browser sessions. Setup creates the canvas, defines seven upgrade tiers, and generates buttons for each. The draw() loop continuously adds cookies based on CPS, updates button labels and colors, and renders the animated cookie with chocolate chips. By studying it, you will learn how to build games with progression systems, save game data, and coordinate p5.js graphics with interactive HTML buttons.

⚙️ How It Works

  1. When the sketch loads, setup() creates a full-window canvas, defines seven upgrade types (Cursor through Temple) with escalating costs and CPS values, creates clickable buttons for each upgrade on the right side, and loads any previously saved game state from localStorage.
  2. Every frame, draw() adds cookies to the score based on totalCPS and elapsed time (deltaTime), displays the current score and CPS at the top, draws a large brown cookie circle in the center with randomly positioned chocolate chips, and updates all upgrade button labels and colors based on whether the player can afford them.
  3. When the player clicks the cookie, mousePressed() checks the distance from the click to the cookie center and increments the score by 1 if the click was inside the cookie's radius.
  4. When the player clicks an upgrade button, buyUpgrade() checks if the player has enough cookies, deducts the cost, increments the upgrade count, adds its base CPS to totalCPS, and increases the upgrade's cost by 15% exponentially for the next purchase.
  5. Every 5 seconds, saveGame() converts the current score and upgrade data to JSON and stores it in localStorage; when the sketch restarts, loadGame() retrieves and restores that data.
  6. When the window resizes, windowResized() scales the canvas and repositions all buttons to stay aligned on the right side; when the browser tab closes, a beforeunload event listener saves the game one final time.

🎓 Concepts You'll Learn

Game loops and state managementdeltaTime-based animationObject arrays and upgrade progressionlocalStorage persistenceDOM manipulation with p5.buttonsDistance-based collision detectionExponential cost scaling

📝 Code Breakdown

setup()

setup() runs once when the sketch starts. It initializes your game state (the upgrades array), creates all interactive elements (buttons), and loads any saved progress. Notice how each upgrade is an object containing multiple properties—this is a common pattern for managing game data.

🔬 This code defines the Cursor upgrade with baseCost: 15 and baseCPS: 0.1. What happens if you change baseCPS to 0.5 or 1? How does that change how fast you can earn cookies?

  upgrades.push({
    name: "Cursor",
    baseCost: 15,
    cost: 15,
    baseCPS: 0.1,
    cps: 0.1,
    count: 0,
    button: null
  });
function setup() {
  createCanvas(windowWidth, windowHeight);
  textAlign(CENTER, CENTER);
  textSize(24);

  upgrades.push({
    name: "Cursor",
    baseCost: 15,
    cost: 15,
    baseCPS: 0.1,
    cps: 0.1,
    count: 0,
    button: null
  });
  upgrades.push({
    name: "Grandma",
    baseCost: 100,
    cost: 100,
    baseCPS: 1,
    cps: 1,
    count: 0,
    button: null
  });
  upgrades.push({
    name: "Farm",
    baseCost: 1100,
    cost: 1100,
    baseCPS: 8,
    cps: 8,
    count: 0,
    button: null
  });
  upgrades.push({
    name: "Mine",
    baseCost: 12000,
    cost: 12000,
    baseCPS: 47,
    cps: 47,
    count: 0,
    button: null
  });
  upgrades.push({
    name: "Factory",
    baseCost: 130000,
    cost: 130000,
    baseCPS: 260,
    cps: 260,
    count: 0,
    button: null
  });
  upgrades.push({
    name: "Bank",
    baseCost: 1400000,
    cost: 1400000,
    baseCPS: 1400,
    cps: 1400,
    count: 0,
    button: null
  });
  upgrades.push({
    name: "Temple",
    baseCost: 20000000,
    cost: 20000000,
    baseCPS: 7800,
    cps: 7800,
    count: 0,
    button: null
  });

  let buttonY = 50;
  for (let i = 0; i < upgrades.length; i++) {
    let upgrade = upgrades[i];
    let btn = createButton('');
    btn.addClass('upgrade-button');
    btn.position(width - 200, buttonY);
    btn.mouseClicked(() => buyUpgrade(i));
    upgrade.button = btn;
    buttonY += 70;
  }

  let resetButton = createButton('Reset Game');
  resetButton.addClass('reset-button');
  resetButton.position(width - 200, height - 50);
  resetButton.mouseClicked(resetGame);

  loadGame();

  autoSaveInterval = setInterval(saveGame, 5000);
}
Line-by-line explanation (8 lines)

🔧 Subcomponents:

for-loop Upgrade Array Initialization upgrades.push({name: "Cursor", baseCost: 15, ...})

Defines all seven upgrade types with their base cost and CPS, which scale as the player purchases them

for-loop Button Creation Loop for (let i = 0; i < upgrades.length; i++) { let btn = createButton(''); ... }

Creates a clickable p5.Button for each upgrade, positions it on the right side, and stores a reference to it in the upgrade object

createCanvas(windowWidth, windowHeight);
Creates a canvas that fills the entire browser window, making the game responsive to screen size
textAlign(CENTER, CENTER);
Centers all text horizontally and vertically, so text draws from its center point rather than its top-left corner
upgrades.push({name: "Cursor", baseCost: 15, cost: 15, baseCPS: 0.1, cps: 0.1, count: 0, button: null});
Adds the first upgrade object to the upgrades array with its name, base cost, CPS value, count (initially 0), and a button placeholder
let btn = createButton('');
Creates an empty button—its text will be updated in draw() every frame with current cost and count
btn.mouseClicked(() => buyUpgrade(i));
Assigns a click handler that calls buyUpgrade with the index i, so each button knows which upgrade to purchase
upgrade.button = btn;
Stores the button object reference in the upgrade's 'button' property so draw() can update it later
loadGame();
Restores the player's previous score, upgrade counts, and costs from localStorage if they exist
autoSaveInterval = setInterval(saveGame, 5000);
Starts an automatic save timer that calls saveGame() every 5000 milliseconds (5 seconds)

draw()

draw() runs 60 times per second, updating the game world and redrawing everything. The key innovation here is using deltaTime to scale cookie generation—this ensures the game progresses at the same speed whether it's running at 30 FPS or 60 FPS. Notice the DOM optimization: button properties only update if they actually changed, reducing lag during gameplay.

function draw() {
  background(240);

  score += totalCPS * deltaTime / 1000;

  fill(0);
  textSize(48);
  text(floor(score), width / 2, 50);
  textSize(18);
  text(`Cookies per second: ${totalCPS.toFixed(1)}`, width / 2, 90);

  fill(139, 69, 19);
  noStroke();
  ellipse(width / 2, height / 2, cookieSize, cookieSize);

  fill(60, 30, 0);
  let numChips = 20;
  for (let i = 0; i < numChips; i++) {
    let angle = map(i, 0, numChips, 0, TWO_PI);
    let r = cookieSize * 0.4 * random(0.8, 1.2);
    let x = width / 2 + r * cos(angle);
    let y = height / 2 + r * sin(angle);
    ellipse(x, y, 10, 10);
  }

  for (let i = 0; i < upgrades.length; i++) {
    let upgrade = upgrades[i];

    let newButtonText = `${upgrade.name} (x${upgrade.count})\nCost: ${floor(upgrade.cost)}\nCPS: ${upgrade.cps.toFixed(1)}`;

    let newBgColor = score >= upgrade.cost ? '#4CAF50' : '#cccccc';
    let newTextColor = score >= upgrade.cost ? 'white' : '#666666';
    let isDisabled = score < upgrade.cost;

    if (upgrade.button.html() !== newButtonText) {
      upgrade.button.html(newButtonText);
    }
    if (upgrade.button.style('background-color') !== newBgColor) {
      upgrade.button.style('background-color', newBgColor);
    }
    if (upgrade.button.style('color') !== newTextColor) {
      upgrade.button.style('color', newTextColor);
    }
    if (upgrade.button.attribute('disabled') !== (isDisabled ? 'disabled' : null)) {
      if (isDisabled) {
        upgrade.button.attribute('disabled', 'disabled');
      } else {
        upgrade.button.removeAttribute('disabled');
      }
    }
  }
}
Line-by-line explanation (13 lines)

🔧 Subcomponents:

calculation Auto-click Score Addition score += totalCPS * deltaTime / 1000;

Adds cookies automatically each frame based on CPS and time elapsed, converting milliseconds to seconds

for-loop Chocolate Chips Loop for (let i = 0; i < numChips; i++) { let angle = map(...); ... }

Distributes chocolate chips evenly around the cookie using polar coordinates (angle and radius)

for-loop Upgrade Button Update Loop for (let i = 0; i < upgrades.length; i++) { ... }

Updates each upgrade button's text, color, and disabled state based on the player's current score

background(240);
Clears the canvas with light grey color (RGB 240), erasing everything from the previous frame
score += totalCPS * deltaTime / 1000;
Adds cookies passively each frame: totalCPS is cookies per second, deltaTime is milliseconds since last frame, so dividing by 1000 converts to seconds
text(floor(score), width / 2, 50);
Displays the score rounded down to a whole number at the top center of the canvas
text(`Cookies per second: ${totalCPS.toFixed(1)}`, width / 2, 90);
Shows the total CPS with one decimal place using toFixed(1) and template literal syntax
fill(139, 69, 19);
Sets the fill color to brown (RGB 139, 69, 19) for the cookie
ellipse(width / 2, height / 2, cookieSize, cookieSize);
Draws a circle at the canvas center with diameter equal to cookieSize, creating the main clickable cookie
let angle = map(i, 0, numChips, 0, TWO_PI);
Maps loop counter i from 0 to numChips onto an angle from 0 to 2π, evenly spacing chips around the circle
let r = cookieSize * 0.4 * random(0.8, 1.2);
Calculates a random radius for each chip so they don't form a perfect ring—adds natural variation
let x = width / 2 + r * cos(angle);
Converts polar coordinates (angle, radius) to cartesian x using cosine
let y = height / 2 + r * sin(angle);
Converts polar coordinates (angle, radius) to cartesian y using sine
let newButtonText = `${upgrade.name} (x${upgrade.count})\nCost: ${floor(upgrade.cost)}\nCPS: ${upgrade.cps.toFixed(1)}`;
Constructs the button's display text showing upgrade name, how many owned, cost, and CPS per unit—\n adds line breaks
let newBgColor = score >= upgrade.cost ? '#4CAF50' : '#cccccc';
Sets button color to green (#4CAF50) if affordable, grey (#cccccc) if not—quick visual feedback
if (upgrade.button.html() !== newButtonText) { upgrade.button.html(newButtonText); }
Only updates button text if it changed—this optimization prevents unnecessary DOM reflows that can cause lag

mousePressed()

mousePressed() is a p5.js event function that runs whenever the player clicks the mouse. By using the distance formula, we create a circular hitbox—a common technique in games. This is more satisfying than a square button because the clickable area matches the visual cookie shape.

function mousePressed() {
  let d = dist(mouseX, mouseY, width / 2, height / 2);
  if (d < cookieSize / 2) {
    score++;
  }
}
Line-by-line explanation (3 lines)

🔧 Subcomponents:

conditional Click Detection Condition if (d < cookieSize / 2)

Checks whether the click was inside the cookie's radius using distance formula

let d = dist(mouseX, mouseY, width / 2, height / 2);
Calculates the distance from the click position (mouseX, mouseY) to the cookie center using p5.js's dist() function
if (d < cookieSize / 2) {
Checks if the distance is less than the cookie's radius (half its diameter), meaning the click was inside the cookie
score++;
Increments the score by 1 when a valid click is detected

buyUpgrade(index)

buyUpgrade() implements the core economic loop: spend resources to unlock passive generation. The exponential cost scaling (multiply by 1.15) is key to incremental game design—it creates progression tiers where early upgrades feel fast, but higher tiers require patience or active clicking. This teaches players to plan ahead.

function buyUpgrade(index) {
  let upgrade = upgrades[index];
  if (score >= upgrade.cost) {
    score -= upgrade.cost;
    upgrade.count++;
    totalCPS += upgrade.baseCPS;
    upgrade.cost = floor(upgrade.cost * 1.15);
  }
}
Line-by-line explanation (6 lines)

🔧 Subcomponents:

conditional Affordability Check if (score >= upgrade.cost)

Prevents purchase if the player lacks enough cookies

let upgrade = upgrades[index];
Retrieves the upgrade object from the upgrades array at the given index
if (score >= upgrade.cost) {
Only proceeds if the player's score is at least as high as the upgrade's current cost
score -= upgrade.cost;
Deducts the upgrade cost from the player's score
upgrade.count++;
Increments the count property, tracking how many of this upgrade the player owns
totalCPS += upgrade.baseCPS;
Adds the upgrade's base CPS to the global totalCPS, so auto-clicking increases immediately
upgrade.cost = floor(upgrade.cost * 1.15);
Multiplies the current cost by 1.15 (15% increase) and rounds down, making each subsequent upgrade more expensive

saveGame()

saveGame() uses localStorage to persist game state across browser sessions. The key innovation is using map() to extract only the saveable properties from each upgrade object—the button reference can't be stringified to JSON, so it's excluded. The try-catch ensures the game continues running even if saving fails.

function saveGame() {
  if (typeof localStorage !== 'undefined') {
    try {
      const gameState = {
        score: score,
        upgrades: upgrades.map(u => ({
          name: u.name,
          cost: u.cost,
          count: u.count
        }))
      };
      localStorage.setItem('cookieClickerGame', JSON.stringify(gameState));
    } catch (e) {
      console.error("Error saving game:", e);
    }
  }
}
Line-by-line explanation (5 lines)

🔧 Subcomponents:

conditional localStorage Availability Check if (typeof localStorage !== 'undefined')

Ensures localStorage is supported before attempting to save

calculation Game State Object Creation const gameState = { score: score, upgrades: upgrades.map(...) }

Constructs a serializable object containing only essential game data, excluding p5.Button objects

if (typeof localStorage !== 'undefined') {
Checks if the browser supports localStorage—some browsers or modes (like private browsing) don't have it
const gameState = {
Creates an object to hold all game data that needs to be saved
upgrades: upgrades.map(u => ({ name: u.name, cost: u.cost, count: u.count }))
Uses map() to transform the full upgrades array into a smaller one with only saveable properties (excludes the p5.Button object which can't be JSON stringified)
localStorage.setItem('cookieClickerGame', JSON.stringify(gameState));
Converts the gameState object to a JSON string and stores it in localStorage under the key 'cookieClickerGame'
} catch (e) { console.error("Error saving game:", e); }
Catches any save errors (e.g., localStorage full) and logs them without crashing the game

loadGame()

loadGame() is the inverse of saveGame()—it retrieves JSON from localStorage, parses it back into an object, and restores both player score and upgrade state. Notice it recalculates totalCPS from the saved upgrade counts rather than trying to save totalCPS directly; this makes the code more robust to future changes. The try-catch ensures corrupted data doesn't break the game.

function loadGame() {
  if (typeof localStorage !== 'undefined') {
    try {
      const savedGame = localStorage.getItem('cookieClickerGame');
      if (savedGame) {
        const gameState = JSON.parse(savedGame);
        score = gameState.score;
        totalCPS = 0;

        gameState.upgrades.forEach(savedUpgrade => {
          let currentUpgrade = upgrades.find(u => u.name === savedUpgrade.name);
          if (currentUpgrade) {
            currentUpgrade.count = savedUpgrade.count;
            currentUpgrade.cost = savedUpgrade.cost;
            totalCPS += currentUpgrade.baseCPS * currentUpgrade.count;
          }
        });
      }
    } catch (e) {
      console.error("Error loading game:", e);
      resetGame();
    }
  }
}
Line-by-line explanation (8 lines)

🔧 Subcomponents:

conditional Saved Game Retrieval const savedGame = localStorage.getItem('cookieClickerGame');

Attempts to retrieve previously saved game data from localStorage

for-loop Upgrade Restoration Loop gameState.upgrades.forEach(savedUpgrade => { ... })

Iterates through saved upgrades and restores their count, cost, and recalculates totalCPS

const savedGame = localStorage.getItem('cookieClickerGame');
Retrieves the JSON string from localStorage, or null if no save exists
if (savedGame) {
Only proceeds if a save was found—prevents errors from trying to parse null
const gameState = JSON.parse(savedGame);
Converts the JSON string back into a JavaScript object
score = gameState.score;
Restores the saved score
totalCPS = 0;
Resets totalCPS to 0 so it can be recalculated from the loaded upgrades
gameState.upgrades.forEach(savedUpgrade => {
Iterates through each saved upgrade using forEach
let currentUpgrade = upgrades.find(u => u.name === savedUpgrade.name);
Uses find() to locate the matching upgrade object in the current upgrades array by name
totalCPS += currentUpgrade.baseCPS * currentUpgrade.count;
Recalculates totalCPS by multiplying each upgrade's base CPS by how many the player owns

resetGame()

resetGame() is called when the player clicks the Reset button or when saveGame() fails due to corruption. It wipes all progress and clears localStorage, creating a clean slate. This is essential for testing and allows players to restart if they want a fresh challenge.

function resetGame() {
  score = 0;
  totalCPS = 0;
  upgrades.forEach(upgrade => {
    upgrade.count = 0;
    upgrade.cost = upgrade.baseCost;
  });
  if (typeof localStorage !== 'undefined') {
    localStorage.removeItem('cookieClickerGame');
  }
}
Line-by-line explanation (4 lines)

🔧 Subcomponents:

for-loop Upgrade Reset Loop upgrades.forEach(upgrade => { upgrade.count = 0; upgrade.cost = upgrade.baseCost; })

Resets all upgrade counts to 0 and restores costs to their base values

score = 0;
Sets the score back to 0
totalCPS = 0;
Resets the cookies-per-second to 0
upgrades.forEach(upgrade => { upgrade.count = 0; upgrade.cost = upgrade.baseCost; })
Iterates through all upgrades, setting count to 0 (player owns none) and cost back to baseCost (undoing all price increases)
localStorage.removeItem('cookieClickerGame');
Deletes the saved game data from localStorage so a fresh start isn't contaminated by old data

windowResized()

windowResized() is a p5.js event function that fires whenever the browser window is resized. It ensures the canvas scales responsively and buttons stay in proper positions. This is essential for full-screen games that need to work on phones, tablets, and desktops.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  let buttonY = 50;
  for (let i = 0; i < upgrades.length; i++) {
    upgrades[i].button.position(width - 200, buttonY);
    buttonY += 70;
  }
  select('.reset-button').position(width - 200, height - 50);
}
Line-by-line explanation (4 lines)

🔧 Subcomponents:

for-loop Button Repositioning Loop for (let i = 0; i < upgrades.length; i++) { upgrades[i].button.position(width - 200, buttonY); buttonY += 70; }

Re-positions all upgrade buttons to the right side of the resized canvas

resizeCanvas(windowWidth, windowHeight);
Resizes the p5.js canvas to match the new window dimensions
let buttonY = 50;
Resets the starting Y position for button repositioning
upgrades[i].button.position(width - 200, buttonY);
Repositions each upgrade button 200 pixels from the right edge (width - 200) and adjusts vertical position
select('.reset-button').position(width - 200, height - 50);
Repositions the reset button to stay at the bottom right even after resizing

📦 Key Variables

score number

Stores the total cookies earned by the player through clicking and passive generation

let score = 0;
totalCPS number

Tracks the combined cookies-per-second from all owned upgrades, used to calculate automatic cookie generation in draw()

let totalCPS = 0;
upgrades array

An array of upgrade objects, each containing name, cost, CPS value, count owned, and a button reference

let upgrades = [];
cookieSize number

The diameter of the main clickable cookie circle in pixels

let cookieSize = 250;
autoSaveInterval object

Stores the interval ID returned by setInterval(), used to track the auto-save timer

let autoSaveInterval;

🔧 Potential Improvements (5)

Here are some ways this code could be enhanced:

PERFORMANCE draw() - chocolate chips loop

The chocolate chips are recalculated with new random positions every frame using random(0.8, 1.2), causing them to jitter instead of stay fixed on the cookie

💡 Pre-calculate chip positions once in setup() and store them, then draw from those fixed positions in draw(). This improves performance and makes the cookie look more like a real object.

BUG draw() - button update loop

Comparing button styles with .style() returns computed values that may include spaces or alternate formatting, leading to false negatives and unnecessary DOM updates

💡 Store the previous text, color, and disabled state as properties on the upgrade object, then only update when state actually changes. This is more reliable than comparing CSS strings.

FEATURE buyUpgrade()

Players can only buy one upgrade at a time; there's no way to bulk-buy multiple copies of the same upgrade

💡 Add a shift-click or right-click handler to buy 10 of an upgrade at once, or add an input field to specify quantity. This is a common feature in incremental games and speeds up late-game progression.

STYLE setup() - upgrade definitions

The seven upgrades are defined with repetitive syntax using multiple .push() calls, making the code verbose and hard to modify

💡 Use an array of objects and loop through them to call .push() once per upgrade, or define them as a constant array outside setup(). This reduces code duplication and makes balancing values easier.

FEATURE draw() - score display

Large numbers become hard to read (e.g., 1234567890 is easier to read as 1.23B). The display doesn't use number formatting for readability

💡 Implement a formatting function that converts large numbers to abbreviated notation (K, M, B, T) so players can instantly understand their progress at a glance.

🔄 Code Flow

Code flow showing setup, draw, mousepressed, buyupgrade, savegame, loadgame, resetgame, windowresized

💡 Click on function names in the diagram to jump to their code

graph TD start[Start] --> setup[setup] setup --> draw[draw loop] draw --> auto-click-calculation[Auto-click Score Addition] draw --> cookie-drawing[Cookie and Chips Drawing] draw --> chips-loop[Chocolate Chips Loop] draw --> button-update-loop[Upgrade Button Update Loop] draw --> distance-check[Click Detection Condition] click setup href "#fn-setup" click draw href "#fn-draw" click auto-click-calculation href "#sub-auto-click-calculation" click cookie-drawing href "#sub-cookie-drawing" click chips-loop href "#sub-chips-loop" click button-update-loop href "#sub-button-update-loop" click distance-check href "#sub-distance-check" distance-check -->|Click Inside| mousepressed[mousePressed] distance-check -->|Click Outside| draw mousepressed --> affordability-check[Affordability Check] affordability-check -->|Affordable| buyupgrade[buyUpgrade] affordability-check -->|Not Affordable| draw click mousepressed href "#fn-mousepressed" click buyupgrade href "#fn-buyupgrade" click affordability-check href "#sub-affordability-check" buyupgrade --> upgrade-definitions[Upgrade Array Initialization] click upgrade-definitions href "#sub-upgrade-definitions" setup --> button-creation-loop[Button Creation Loop] click button-creation-loop href "#sub-button-creation-loop" setup --> loadgame[loadGame] loadgame --> save-retrieval[Saved Game Retrieval] save-retrieval -->|Data Found| upgrade-restoration-loop[Upgrade Restoration Loop] save-retrieval -->|No Data| draw click loadgame href "#fn-loadgame" click upgrade-restoration-loop href "#sub-upgrade-restoration-loop" setup --> localstorage-check[localStorage Availability Check] localstorage-check -->|Supported| savegame[saveGame] localstorage-check -->|Not Supported| draw click savegame href "#fn-savegame" click localstorage-check href "#sub-localstorage-check" savegame --> state-serialization[Game State Object Creation] click state-serialization href "#sub-state-serialization" resetgame --> upgrade-reset-loop[Upgrade Reset Loop] click resetgame href "#fn-resetgame" click upgrade-reset-loop href "#sub-upgrade-reset-loop" windowresized --> button-repositioning-loop[Button Repositioning Loop] click windowresized href "#fn-windowresized" click button-repositioning-loop href "#sub-button-repositioning-loop"

❓ Frequently Asked Questions

What visual elements does the cookie clicker sketch display?

The sketch features a large clickable cookie and various upgrade options displayed on the canvas, creating an engaging game interface.

How can users interact with the cookie clicker game?

Users can click on the cookie to earn points and purchase upgrades to increase their cookie production over time.

What creative coding concepts are showcased in this p5.js sketch?

The sketch demonstrates game state management, dynamic user interface updates, and the use of arrays to handle multiple upgrade options.

Preview

cookie clicker by:moon_noob - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of cookie clicker by:moon_noob - Code flow showing setup, draw, mousepressed, buyupgrade, savegame, loadgame, resetgame, windowresized
Code Flow Diagram