cookie clicker by:moon_noob (Remix)

This sketch creates a Cookie Clicker game where players click a giant cookie to earn points, then spend their cookies on animated upgrade buttons that boost their cookie production rate. The game state persists automatically using browser localStorage, and the score skyrockets exponentially as upgrades multiply income.

🧪 Try This!

Experiment with the code by making these changes:

  1. Triple the click damage — Each manual click will add 3 cookies instead of 1, making early game progression much faster
  2. Make upgrades cheaper — Reduce the cost scaling factor from 1.15 to 1.05 so upgrade prices grow more slowly and you can buy more frequently
  3. Double cookie production from upgrades — All upgrades will produce twice as many cookies per second, accelerating the late-game exponential growth dramatically
  4. Make the cookie golden — Changes the cookie from brown to a bright gold/yellow color for a premium look
  5. Add a second cookie upgrade tier — Inserts a new mid-tier upgrade between Farm and Mine that costs 5500 and produces 25 CPS
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch recreates the addictive Cookie Clicker game mechanic inside p5.js. Players click a large circular cookie to earn points, then buy upgrades that automatically generate cookies per second. The upgrades range from cheap Cursors to expensive Temples, each one accelerating progress exponentially. The sketch demonstrates core game design patterns: accumulating resources, purchasing upgrades with exponential cost scaling, and visual feedback through dynamic button states.

The code is organized into setup(), draw(), and several helper functions that handle upgrades, saving, and loading. By studying it, you'll learn how to manage game state across many objects, use localStorage to persist player progress between sessions, how the draw loop can accumulate resources over time, and how to dynamically style buttons based on game conditions. The sketch is an excellent template for any incremental or clicker-style game.

⚙️ How It Works

  1. When the sketch loads, setup() creates a full-screen canvas, initializes seven upgrades with names, base costs, and cookie production rates, creates interactive buttons for each upgrade, and loads any previously saved game progress from the browser's localStorage.
  2. Every frame, draw() adds cookies to the score based on totalCPS and the time elapsed since the last frame (deltaTime), creating smooth continuous income. It then displays the current score and CPS rate at the top of the canvas.
  3. The main cookie—a brown circle with chocolate chips—is drawn in the center. When clicked, mousePressed() increments the score by 1, allowing manual clicking.
  4. The draw loop continuously updates all seven upgrade buttons: each button shows its name, current count owned, cost, and production rate. Buttons turn green when affordable and grey when too expensive, encouraging the player to save up.
  5. When a player clicks an upgrade button, buyUpgrade() deducts the cost from the score, increments that upgrade's count, and adds its base production rate to totalCPS. The cost of the next copy increases exponentially by 15%.
  6. Every 5 seconds, saveGame() serializes the score and all upgrade states to localStorage. When the sketch reloads, loadGame() restores progress. The windowResized() function repositions buttons if the window changes size, and a beforeunload event listener ensures the game is saved even if the tab closes.

🎓 Concepts You'll Learn

Game state managementArray manipulation and object propertieslocalStorage persistenceEvent listeners and callbacksExponential scalingDynamic DOM stylingdeltaTime-based animationDistance-based collision detection

📝 Code Breakdown

setup()

setup() runs once when the sketch starts. It's where you initialize variables, create buttons, and set up game state. The loop that creates buttons shows a common pattern: for each item in a data array, create a UI element and store a reference to it for later updates.

🔬 This defines the cheapest upgrade. What happens if you change baseCPS from 0.1 to 1? How much faster does the game start? What if you change baseCost to 5?

  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:

calculation Canvas and text initialization createCanvas(windowWidth, windowHeight);

Creates a full-screen canvas that responds to the window size

for-loop Define seven upgrade objects upgrades.push({...});

Initializes the upgrades array with seven upgrade types, each with name, costs, and production rates

for-loop Create and position upgrade buttons for (let i = 0; i < upgrades.length; i++) {

Creates a p5.Button for each upgrade, assigns a click handler, and positions them vertically on the right side

calculation Create reset button let resetButton = createButton('Reset Game');

Creates a red button at the bottom right to reset all game progress

calculation Load game and set auto-save autoSaveInterval = setInterval(saveGame, 5000);

Restores previous progress and sets up automatic saving every 5 seconds

createCanvas(windowWidth, windowHeight);
Creates a canvas that fills the entire browser window, allowing the game to be responsive
textAlign(CENTER, CENTER);
Centers all text both horizontally and vertically, so text() commands will be centered at their coordinates
upgrades.push({...});
Each push() adds a new upgrade object to the upgrades array. The object stores the upgrade's name, base cost, current cost, production rate, and count owned
let btn = createButton('');
Creates a p5.Button element with empty text (text will be updated each frame in draw())
btn.mouseClicked(() => buyUpgrade(i));
Assigns a click handler using an arrow function that calls buyUpgrade() with the upgrade's index when clicked
upgrade.button = btn;
Stores a reference to the button object inside the upgrade data, so it can be updated later in draw()
loadGame();
Restores the player's score and upgrade progress from localStorage if a previous game was saved
autoSaveInterval = setInterval(saveGame, 5000);
Sets up automatic saving every 5000 milliseconds (5 seconds) to prevent progress loss

draw()

draw() is called 60 times per second. The key insight here is the deltaTime calculation: by multiplying CPS by the actual time elapsed (not frame count), income stays smooth regardless of frame rate. The button-update loop shows a critical optimization pattern: only change DOM properties that actually changed, not every frame. This keeps the browser responsive.

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 (11 lines)

🔧 Subcomponents:

calculation Auto-income from totalCPS score += totalCPS * deltaTime / 1000;

Adds cookies every frame based on cookies-per-second and time elapsed since last frame, creating smooth continuous income

calculation Display score and CPS text(floor(score), width / 2, 50);

Shows the current score as a whole number and the production rate below it

for-loop Draw chocolate chips for (let i = 0; i < numChips; i++) {

Places 20 small circles around the cookie in a circle pattern to look like chocolate chips

for-loop Update all upgrade buttons for (let i = 0; i < upgrades.length; i++) {

Each frame, refreshes button text, colors, and disabled state based on whether the player can afford each upgrade

background(240);
Fills the canvas with light grey color, erasing the previous frame's drawings so they don't stack
score += totalCPS * deltaTime / 1000;
deltaTime is the milliseconds since the last frame. Dividing by 1000 converts it to seconds. Multiply by CPS to add the correct amount of cookies based on time, not frame count
text(floor(score), width / 2, 50);
floor() rounds down to a whole number for display. The score appears cleaner without decimals
text(`Cookies per second: ${totalCPS.toFixed(1)}`, width / 2, 90);
Template string with interpolation: toFixed(1) shows CPS with exactly one decimal place, like '47.3'
fill(139, 69, 19);
Sets fill color to brown (RGB values) for the cookie
ellipse(width / 2, height / 2, cookieSize, cookieSize);
Draws a circle at the canvas center. The size is controlled by the cookieSize variable
let angle = map(i, 0, numChips, 0, TWO_PI);
map() remaps the loop counter from 0-20 to 0-360 degrees (TWO_PI radians), spreading chips evenly around the cookie
let r = cookieSize * 0.4 * random(0.8, 1.2);
Calculates distance from center. Multiplying by random(0.8, 1.2) adds natural variation so chips aren't in a perfect circle
let newButtonText = `${upgrade.name} (x${upgrade.count})\nCost: ${floor(upgrade.cost)}\nCPS: ${upgrade.cps.toFixed(1)}`;
Constructs the button's label showing name, count owned, cost, and production rate. \n creates line breaks
let newBgColor = score >= upgrade.cost ? '#4CAF50' : '#cccccc';
Ternary operator: if the player can afford the upgrade, button is green; otherwise grey
if (upgrade.button.html() !== newButtonText) {
Only updates the button text if it has changed. This optimization reduces DOM reflows and performance warnings

mousePressed()

mousePressed() is called automatically whenever the player clicks. The distance-based collision check teaches a fundamental game programming concept: detecting when a point (the mouse) is inside a circle (the cookie). This pattern works for any shape with a simple geometry.

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

🔧 Subcomponents:

conditional Check if cookie was clicked if (d < cookieSize / 2) {

Uses distance to determine if the mouse click landed inside the circular cookie

let d = dist(mouseX, mouseY, width / 2, height / 2);
dist() calculates the Euclidean distance from the mouse position to the cookie's center. This allows circular collision detection
if (d < cookieSize / 2) {
If the distance is less than the radius (cookieSize / 2), the mouse clicked inside the cookie circle
score++;
Increments the score by 1 when the cookie is clicked, rewarding manual clicking

buyUpgrade(index)

buyUpgrade() is the economic engine of the game. Every mechanic inside this function—deducting cost, incrementing count, adding production, scaling price—directly affects how players experience progression. The exponential cost scaling is what makes clicker games addictive: you're always just one or two purchases away from the next big milestone.

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 Check if player can afford upgrade if (score >= upgrade.cost) {

Only processes the purchase if the player has enough cookies

calculation Exponential cost scaling upgrade.cost = floor(upgrade.cost * 1.15);

Increases the next purchase cost by 15%, creating exponential difficulty that encourages buying a variety of upgrades

let upgrade = upgrades[index];
Retrieves the upgrade object from the array using the passed index
if (score >= upgrade.cost) {
Guards the entire transaction: only allows purchase if the player has enough cookies
score -= upgrade.cost;
Deducts the cost from the player's score, spending the cookies
upgrade.count++;
Increments the count of this upgrade owned, used to display 'x1', 'x2', etc. on the button
totalCPS += upgrade.baseCPS;
Adds the upgrade's base production rate to the total CPS pool, immediately increasing income
upgrade.cost = floor(upgrade.cost * 1.15);
Multiplies the cost by 1.15 (15% increase) and rounds down. Each copy gets more expensive, slowing power scaling

saveGame()

saveGame() introduces localStorage, a browser API that persists data even after the tab closes. The key pattern here is map(): transforming one array into another by applying a function to each element. We can't save the button objects (they can't be converted to JSON), so map() filters to only the essential data. This function is called every 5 seconds automatically, and also on beforeunload when the user closes the tab.

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 (8 lines)

🔧 Subcomponents:

conditional Check localStorage availability if (typeof localStorage !== 'undefined') {

Ensures localStorage is available before attempting to use it (some browsers disable it)

calculation Build game state object const gameState = {

Creates a clean object containing only the data needed to restore progress, excluding the button objects

for-loop Map upgrades to saveable format upgrades: upgrades.map(u => ({

Uses map() to transform the full upgrade objects into a simpler format with only name, cost, and count

calculation Serialize and store localStorage.setItem('cookieClickerGame', JSON.stringify(gameState));

Converts the JavaScript object to JSON and saves it to the browser's persistent storage

if (typeof localStorage !== 'undefined') {
Checks if localStorage exists in this browser. Some environments don't support it, so this prevents errors
const gameState = {
Creates a new object that will hold only the essential data needed to restore the game
upgrades: upgrades.map(u => ({
map() transforms each upgrade object into a simpler version. It iterates through upgrades and returns a new array of simplified objects
name: u.name,
Copies the upgrade name so we can match it during load
cost: u.cost,
Saves the current cost (including all multiplier increases) so the next session's prices match
count: u.count
Saves how many of each upgrade the player owns
localStorage.setItem('cookieClickerGame', JSON.stringify(gameState));
JSON.stringify() converts the JavaScript object to a text string. setItem() stores it with key 'cookieClickerGame'
} catch (e) {
If any error occurs during saving (e.g., localStorage quota exceeded), it logs the error instead of crashing

loadGame()

loadGame() is the mirror of saveGame(). It retrieves the data and reconstructs the game state. The key challenge here is matching saved upgrades to current upgrades using find(). If you later rename an upgrade, that saved data becomes orphaned. In production games, developers use upgrade IDs instead of names to avoid this fragility. The recalculation of totalCPS is essential: we can't just restore it directly because counts might have changed in code updates.

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 (10 lines)

🔧 Subcomponents:

conditional Check if localStorage is available if (typeof localStorage !== 'undefined') {

Safely checks for localStorage before attempting to use it

calculation Retrieve and parse saved data const gameState = JSON.parse(savedGame);

Converts the stored JSON string back into a JavaScript object

for-loop Restore each upgrade's state gameState.upgrades.forEach(savedUpgrade => {

Iterates through saved upgrades and restores their counts, costs, and recalculates total CPS

calculation Recalculate total CPS from upgrades totalCPS += currentUpgrade.baseCPS * currentUpgrade.count;

Rebuilds totalCPS by summing the production of all owned upgrades

const savedGame = localStorage.getItem('cookieClickerGame');
Retrieves the stored game data from localStorage. If nothing was saved, savedGame will be null
if (savedGame) {
Only proceeds if a saved game exists—prevents errors if this is the player's first session
const gameState = JSON.parse(savedGame);
JSON.parse() converts the stored text string back into a JavaScript object we can work with
score = gameState.score;
Restores the player's cookie count to the value saved last time
totalCPS = 0;
Resets totalCPS to zero before recalculating, so we don't double-count
gameState.upgrades.forEach(savedUpgrade => {
forEach() iterates through each saved upgrade. Similar to a for-loop but cleaner syntax
let currentUpgrade = upgrades.find(u => u.name === savedUpgrade.name);
find() searches the upgrades array for an upgrade matching the saved name. This matches saved data with current upgrade definitions
currentUpgrade.count = savedUpgrade.count;
Restores the count of this upgrade owned
currentUpgrade.cost = savedUpgrade.cost;
Restores the escalated cost (so prices don't reset to base costs)
totalCPS += currentUpgrade.baseCPS * currentUpgrade.count;
Adds this upgrade's production to totalCPS: if you own 3 Grandmas (baseCPS 1 each), add 3 to totalCPS

resetGame()

resetGame() completely wipes the game state and saved data. It's called when the player clicks the Reset Game button. This function demonstrates the importance of cleaning up both in-memory state (the variables) and persistent storage (localStorage). A good reset is thorough and leaves nothing behind.

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 (6 lines)

🔧 Subcomponents:

calculation Clear score and CPS score = 0;

Resets both score and totalCPS to zero

for-loop Reset all upgrades upgrades.forEach(upgrade => {

Iterates through all upgrades, resetting counts to 0 and costs back to base values

calculation Delete saved game from localStorage localStorage.removeItem('cookieClickerGame');

Removes the stored save file so loadGame() won't restore old data

score = 0;
Sets the cookie count back to zero
totalCPS = 0;
Resets cookies per second to zero (no upgrades, no income)
upgrades.forEach(upgrade => {
Iterates through every upgrade object in the upgrades array
upgrade.count = 0;
Resets how many of this upgrade the player owns
upgrade.cost = upgrade.baseCost;
Resets the cost back to its original base cost, undoing all multipliers
localStorage.removeItem('cookieClickerGame');
Deletes the saved game from the browser's storage, ensuring a clean slate

windowResized()

windowResized() is called automatically whenever the browser window is resized. Without this function, buttons would stay in their original positions and could go off-screen. The function demonstrates responsive design in p5.js: always consider how your layout adapts to different screen sizes. The select() method is p5.js's way of finding HTML elements—similar to document.querySelector() in vanilla JavaScript.

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:

calculation Resize canvas to fit window resizeCanvas(windowWidth, windowHeight);

Stretches the canvas to match the new window dimensions

for-loop Reposition all upgrade buttons for (let i = 0; i < upgrades.length; i++) {

Moves each button to the correct vertical position based on new window height

calculation Reposition reset button select('.reset-button').position(width - 200, height - 50);

Moves the reset button to the bottom-right corner of the resized window

resizeCanvas(windowWidth, windowHeight);
p5.js detects window size changes and calls windowResized() automatically. This function resizes the canvas to match
let buttonY = 50;
Resets the Y position for button layout to start at 50 pixels from the top
upgrades[i].button.position(width - 200, buttonY);
Repositions each upgrade button on the right side at the new window width
select('.reset-button').position(width - 200, height - 50);
select() finds the reset button by its CSS class and repositions it to the bottom-right of the resized window

📦 Key Variables

score number

Tracks the total cookies earned, displayed at the top and checked to determine which upgrades are affordable

let score = 0;
totalCPS number

Stores the total cookies per second generated by all owned upgrades; used to calculate automatic income in draw()

let totalCPS = 0;
upgrades array

Array of upgrade objects, each with name, costs, production rates, count, and button reference; defines all purchaseable items

let upgrades = [];
cookieSize number

Diameter of the main clickable cookie circle in pixels; affects both its appearance and click detection area

let cookieSize = 250;
autoSaveInterval number/object

Stores the interval ID returned by setInterval(); used to reference the auto-save loop for potential cancellation

let autoSaveInterval;

🔧 Potential Improvements (5)

Here are some ways this code could be enhanced:

BUG loadGame() and find()

If an upgrade's name in setup() is changed, saved games won't load that upgrade. The find() method uses name matching, which breaks on any name change

💡 Add a unique ID property to each upgrade (e.g., 'id: 1') and match by ID instead of name. Store IDs in localStorage. This makes the save format robust to future code changes

PERFORMANCE draw() button update loop

The button text is reconstructed every frame even if nothing changed, causing unnecessary string allocations

💡 The code already optimizes this by checking if newButtonText !== upgrade.button.html() before updating. This is good! However, consider caching the previous buttonText in the upgrade object to avoid comparing large strings

FEATURE buyUpgrade()

Players cannot 'sell' upgrades or undo a purchase, and the game has no soft reset option

💡 Add a 'refund' function that returns 90% of the cost and decrements count/totalCPS. This gives players strategic flexibility and helps new players who make early mistakes

STYLE setup() upgrade definitions

Seven nearly identical upgrade objects are defined with repetitive push() calls, making the code verbose and hard to maintain

💡 Define upgrades as an array of objects with just the unique properties, then loop to push them: const upgradeData = [{name: 'Cursor', baseCost: 15, baseCPS: 0.1}, ...]; upgradeData.forEach(u => upgrades.push({...u, cost: u.baseCost, cps: u.baseCPS, count: 0, button: null}))

FEATURE draw() and display

The game doesn't show visual feedback when upgrades are purchased—buttons only change color, no animation or toast notification

💡 Create a visual effect (e.g., floating '+100 cookies!' text at the upgrade button, or a brief color flash) to celebrate upgrades and make the game feel more rewarding

🔄 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 --> canvas-setup[canvas-setup] draw --> auto-click-logic[auto-click-logic] draw --> score-display[score-display] draw --> cookie-drawing[cookie-drawing] draw --> chips-loop[chips-loop] draw --> button-update-loop[button-update-loop] button-update-loop --> button-update-loop button-update-loop --> affordability-check[affordability-check] button-update-loop --> cost-escalation[cost-escalation] button-update-loop --> button-update-loop click setup href "#fn-setup" click draw href "#fn-draw" click canvas-setup href "#sub-canvas-setup" click auto-click-logic href "#sub-auto-click-logic" click score-display href "#sub-score-display" click cookie-drawing href "#sub-cookie-drawing" click chips-loop href "#sub-chips-loop" click button-update-loop href "#sub-button-update-loop" setup --> upgrade-definitions[upgrade-definitions] setup --> button-creation-loop[button-creation-loop] setup --> reset-button[reset-button] setup --> load-save-init[load-save-init] click upgrade-definitions href "#sub-upgrade-definitions" click button-creation-loop href "#sub-button-creation-loop" click reset-button href "#sub-reset-button" click load-save-init href "#sub-load-save-init" mousepressed[mousepressed] --> click-detection[click-detection] click-detection --> affordability-check affordability-check --> buyupgrade[buyupgrade] click buyupgrade href "#fn-buyupgrade" buyupgrade --> cost-escalation buyupgrade --> cps-recalculation[cps-recalculation] savegame[savegame] --> storage-check[storage-check] storage-check --> gamestate-creation[gamestate-creation] gamestate-creation --> upgrades-map[upgrades-map] upgrades-map --> json-storage[json-storage] click savegame href "#fn-savegame" click storage-check href "#sub-storage-check" click gamestate-creation href "#sub-gamestate-creation" click upgrades-map href "#sub-upgrades-map" click json-storage href "#sub-json-storage" loadgame[loadgame] --> local-storage-check[local-storage-check] local-storage-check --> retrieve-data[retrieve-data] retrieve-data --> restore-upgrades-loop[restore-upgrades-loop] restore-upgrades-loop --> cps-recalculation click loadgame href "#fn-loadgame" click local-storage-check href "#sub-local-storage-check" click retrieve-data href "#sub-retrieve-data" click restore-upgrades-loop href "#sub-restore-upgrades-loop" resetgame[resetgame] --> reset-variables[reset-variables] reset-variables --> reset-upgrades-loop[reset-upgrades-loop] reset-upgrades-loop --> clear-storage[clear-storage] click resetgame href "#fn-resetgame" click reset-variables href "#sub-reset-variables" click reset-upgrades-loop href "#sub-reset-upgrades-loop" click clear-storage href "#sub-clear-storage" windowresized[windowresized] --> canvas-resize[canvas-resize] canvas-resize --> button-reposition-loop[button-reposition-loop] button-reposition-loop --> reset-button-reposition[reset-button-reposition] click windowresized href "#fn-windowresized" click canvas-resize href "#sub-canvas-resize" click button-reposition-loop href "#sub-button-reposition-loop" click reset-button-reposition href "#sub-reset-button-reposition"

❓ Frequently Asked Questions

What visual elements can users expect to see in the Cookie Clicker sketch?

Users will see a giant clickable cookie and various animated upgrade buttons that represent different ways to increase cookies-per-second as the cookie empire grows.

How can players interact with the Cookie Clicker game?

Players interact by clicking the giant cookie to earn points and spending those points on upgrades that enhance their cookie production.

What creative coding techniques are showcased in this Cookie Clicker sketch?

The sketch demonstrates the use of object-oriented programming to manage game upgrades and real-time score tracking to enhance user engagement and interactivity.

Preview

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