This is serious vote now you're going to pick me or the other guy it's only one answer who's winning

This sketch creates a full-screen voting interface with two large, colorful buttons representing competing game ideas. Click either button to cast your vote and watch the live vote counts update in real-time beneath each option.

🧪 Try This!

Experiment with the code by making these changes:

  1. Change button colors — The background-color hex codes control button appearance—swap them to make Speaker blue and Beanstalk green, instantly reversing their visual identity.
  2. Make votes count by 5 — Instead of gaining 1 vote per click, both counters will jump by 5 votes per click—useful for rapid testing or giving weight to votes.
  3. Spread buttons further apart
  4. Change button text — Customize the button labels to reflect new voting options—each button's text appears both on the button and in the vote count display below it.
  5. Move buttons higher on screen
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch builds an interactive voting system where visitors choose between two game concepts by clicking big, friendly buttons. The interface uses p5.js's DOM manipulation tools—createElement, createButton, and style methods—to create HTML elements directly from JavaScript, then positions them responsively on the canvas. The vote counts update instantly each time someone clicks, powered by simple event handlers and the continuous draw loop.

The code demonstrates how p5.js bridges the gap between canvas graphics and web page elements. You'll learn how to create buttons that trigger functions, update text displays every frame, and handle window resizing to keep elements centered no matter the screen size. This pattern is the foundation for building interactive web apps with p5.js.

⚙️ How It Works

  1. When the sketch loads, setup() creates a full-screen canvas and places a centered instruction heading at the top of the page.
  2. Two voting buttons are created side-by-side (one green for 'Don't go hard on the speaker bro', one blue for 'Beanstalk Growing Game'), positioned with offsets to keep them separated.
  3. Below each button, a text display shows the current vote count for that option, initially set to 0.
  4. Every frame, the draw() function updates both vote displays by reading the voteSpeakerBro and voteBeanstalk counters and inserting them into the HTML text.
  5. When a visitor clicks either button, its mousePressed event fires the corresponding increment function (incrementSpeakerBroVote or incrementBeanstalkVote), adding 1 to that option's vote count.
  6. If the window is resized, windowResized() fires automatically to reposition all buttons and displays so they stay centered and properly spaced.

🎓 Concepts You'll Learn

DOM element creationEvent handling (mousePressed)Responsive positioningState management (vote counters)Real-time display updatesHTML styling via p5.js

📝 Code Breakdown

setup()

setup() runs once when the sketch starts. It's the perfect place to create DOM elements (buttons, text, images) and configure them with styles and event handlers. Everything positioned here will be responsive when windowResized() runs.

🔬 Notice how the first button uses -150 and the second uses +150 to spread them apart. What happens if you change both -150 values to 0 so the Speaker button sits at center instead of left?

  buttonSpeakerBro.position(width / 2 - buttonSpeakerBro.width / 2 - 150, height * 0.4);
  displaySpeakerBro.position(width / 2 - displaySpeakerBro.width / 2 - 150, height * 0.5);
  buttonBeanstalk.position(width / 2 - buttonBeanstalk.width / 2 + 150, height * 0.4);
  displayBeanstalk.position(width / 2 - displayBeanstalk.width / 2 + 150, height * 0.5);
function setup() {
  createCanvas(windowWidth, windowHeight);
  background(220); // Initial background color

  // Create instructions text
  instructions = createElement('h2', 'Vote for your favorite game!');
  instructions.style('text-align', 'center');
  instructions.style('color', '#333');
  instructions.position(0, height * 0.1);
  instructions.style('width', '100%');

  // Create button for "Don't go hard on the speaker bro🫠"
  buttonSpeakerBro = createButton("Vote for Don't go hard on the speaker bro🫠"); // Updated button text
  buttonSpeakerBro.style('font-size', '24px');
  buttonSpeakerBro.style('padding', '15px 30px');
  buttonSpeakerBro.style('background-color', '#4CAF50'); // Green
  buttonSpeakerBro.style('color', 'white');
  buttonSpeakerBro.style('border', 'none');
  buttonSpeakerBro.style('border-radius', '8px');
  buttonSpeakerBro.style('cursor', 'pointer');
  buttonSpeakerBro.style('margin', '10px');
  // Adjust position for potentially longer text
  buttonSpeakerBro.position(width / 2 - buttonSpeakerBro.width / 2 - 150, height * 0.4);
  buttonSpeakerBro.mousePressed(incrementSpeakerBroVote); // Attach event handler

  // Create display for "Don't go hard on the speaker bro🫠" votes
  displaySpeakerBro = createElement('p', "Don't go hard on the speaker bro🫠 Likes: 0"); // Updated display text
  displaySpeakerBro.style('font-size', '20px');
  displaySpeakerBro.style('text-align', 'center');
  displaySpeakerBro.style('color', '#555');
  displaySpeakerBro.position(width / 2 - displaySpeakerBro.width / 2 - 150, height * 0.5);
  displaySpeakerBro.style('width', 'auto'); // Let width adjust to content

  // Create button for "Beanstalk Growing Game"
  buttonBeanstalk = createButton('Vote for Beanstalk Growing Game');
  buttonBeanstalk.style('font-size', '24px');
  buttonBeanstalk.style('padding', '15px 30px');
  buttonBeanstalk.style('background-color', '#008CBA'); // Blue
  buttonBeanstalk.style('color', 'white');
  buttonBeanstalk.style('border', 'none');
  buttonBeanstalk.style('border-radius', '8px');
  buttonBeanstalk.style('cursor', 'pointer');
  buttonBeanstalk.style('margin', '10px');
  buttonBeanstalk.position(width / 2 - buttonBeanstalk.width / 2 + 150, height * 0.4);
  buttonBeanstalk.mousePressed(incrementBeanstalkVote); // Attach event handler

  // Create display for "Beanstalk Growing Game" votes
  displayBeanstalk = createElement('p', 'Beanstalk Growing Game Likes: 0');
  displayBeanstalk.style('font-size', '20px');
  displayBeanstalk.style('text-align', 'center');
  displayBeanstalk.style('color', '#555');
  displayBeanstalk.position(width / 2 - displayBeanstalk.width / 2 + 150, height * 0.5);
  displayBeanstalk.style('width', 'auto'); // Let width adjust to content

  // You can also add some visual elements on the canvas if you like
  // For now, the canvas is just a background for the DOM elements.
}
Line-by-line explanation (11 lines)

🔧 Subcomponents:

function-call Canvas Setup createCanvas(windowWidth, windowHeight);

Creates a full-screen canvas that fills the entire browser window

function-call Instructions Heading instructions = createElement('h2', 'Vote for your favorite game!');

Creates an HTML h2 element with voting instructions

function-call First Vote Button buttonSpeakerBro = createButton("Vote for Don't go hard on the speaker bro🫠");

Creates the first voting button with custom text

loop Button Styling Loop buttonSpeakerBro.style('font-size', '24px');

Repeatedly applies CSS styles to customize the button appearance

function-call Event Listener Binding buttonSpeakerBro.mousePressed(incrementSpeakerBroVote);

Connects the button to a function that fires when clicked

createCanvas(windowWidth, windowHeight);
Creates a p5.js canvas that fills the entire browser window. windowWidth and windowHeight are built-in p5.js variables that track screen dimensions.
background(220);
Fills the canvas with a light gray color (220 on a 0-255 brightness scale). This is mostly visual since the buttons and text sit on top.
instructions = createElement('h2', 'Vote for your favorite game!');
Creates a new HTML heading element displaying voting instructions. This is NOT drawn on the canvas—it's a real web page element.
instructions.style('text-align', 'center');
Applies CSS styling to center-align the heading text horizontally.
instructions.position(0, height * 0.1);
Places the heading at x=0 (left edge), y=10% down from the top. Uses p5.js height variable for responsive positioning.
buttonSpeakerBro = createButton("Vote for Don't go hard on the speaker bro🫠");
Creates a clickable button with the first game option label. This returns a p5.Renderer object stored in the variable.
buttonSpeakerBro.style('background-color', '#4CAF50');
Sets the button's background color to green (#4CAF50). This makes it visually distinctive.
buttonSpeakerBro.mousePressed(incrementSpeakerBroVote);
Registers incrementSpeakerBroVote as a callback function that runs whenever the button is clicked.
buttonSpeakerBro.position(width / 2 - buttonSpeakerBro.width / 2 - 150, height * 0.4);
Positions the button 150 pixels to the LEFT of center, and 40% down from the top. The subtraction by half-width centers it first, then -150 pushes it left.
displaySpeakerBro = createElement('p', "Don't go hard on the speaker bro🫠 Likes: 0");
Creates a paragraph element below the button to show the current vote count, starting at 0.
displaySpeakerBro.position(width / 2 - displaySpeakerBro.width / 2 - 150, height * 0.5);
Positions the vote count display directly below the button (50% down). Uses same left-offset math as the button.

draw()

draw() runs continuously at 60 frames per second. Here it reads the vote counters and pushes their values into the HTML displays, creating the real-time update effect. This is the heartbeat of any interactive p5.js app.

🔬 These two lines update the text every frame using .html(). What happens if you add a multiplier like * 2 to voteSpeakerBro—would the display show double the actual votes?

function draw() {
  // Update the text displays with current vote counts
  displaySpeakerBro.html("Don't go hard on the speaker bro🫠 Likes: " + voteSpeakerBro);
  displayBeanstalk.html('Beanstalk Growing Game Likes: ' + voteBeanstalk);
}
function draw() {
  // Update the text displays with current vote counts
  displaySpeakerBro.html("Don't go hard on the speaker bro🫠 Likes: " + voteSpeakerBro);
  displayBeanstalk.html('Beanstalk Growing Game Likes: ' + voteBeanstalk);
}
Line-by-line explanation (2 lines)

🔧 Subcomponents:

function-call Update Speaker Vote Display displaySpeakerBro.html("Don't go hard on the speaker bro🫠 Likes: " + voteSpeakerBro);

Inserts the current voteSpeakerBro count into the HTML element every frame

function-call Update Beanstalk Vote Display displayBeanstalk.html('Beanstalk Growing Game Likes: ' + voteBeanstalk);

Inserts the current voteBeanstalk count into the HTML element every frame

displaySpeakerBro.html("Don't go hard on the speaker bro🫠 Likes: " + voteSpeakerBro);
The .html() method replaces the text inside the displaySpeakerBro element with a string that includes the current vote count. This runs 60 times per second, so votes update instantly.
displayBeanstalk.html('Beanstalk Growing Game Likes: ' + voteBeanstalk);
Same as above but for the Beanstalk button's display. Both happen every frame, keeping counts synchronized.

incrementSpeakerBroVote()

This is an event handler—a function that p5.js calls automatically when its button is clicked (via .mousePressed() in setup). Every event handler you write follows this pattern: receive the event, update your state variables, and let draw() handle the visual updates.

🔬 This function runs every time the green button is clicked. What happens if you change voteSpeakerBro++ to voteBeanstalk++ instead—which button's count would go up?

function incrementSpeakerBroVote() { // Renamed function
  voteSpeakerBro++;
  console.log("Don't go hard on the speaker bro🫠 votes:", voteSpeakerBro);
}
// Function to increment vote for "Don't go hard on the speaker bro🫠"
function incrementSpeakerBroVote() { // Renamed function
  voteSpeakerBro++;
  console.log("Don't go hard on the speaker bro🫠 votes:", voteSpeakerBro);
}
Line-by-line explanation (2 lines)

🔧 Subcomponents:

calculation Vote Counter Increment voteSpeakerBro++;

Adds 1 to the vote count each time this function runs

function-call Debug Output console.log("Don't go hard on the speaker bro🫠 votes:", voteSpeakerBro);

Prints the updated vote count to the browser console for debugging

voteSpeakerBro++;
Increments the voteSpeakerBro counter by 1. This is shorthand for voteSpeakerBro = voteSpeakerBro + 1. Called every time the green button is clicked.
console.log("Don't go hard on the speaker bro🫠 votes:", voteSpeakerBro);
Prints a debug message to the browser console (open with F12) showing the updated vote count. Helpful for troubleshooting.

incrementBeanstalkVote()

This function mirrors incrementSpeakerBroVote but increments the Beanstalk counter instead. It's attached to the blue button via buttonBeanstalk.mousePressed() in setup(), so it fires on every blue button click.

// Function to increment vote for Beanstalk Growing Game
function incrementBeanstalkVote() {
  voteBeanstalk++;
  console.log("Beanstalk Growing Game votes:", voteBeanstalk);
}
Line-by-line explanation (2 lines)

🔧 Subcomponents:

calculation Beanstalk Vote Counter Increment voteBeanstalk++;

Adds 1 to the Beanstalk vote count each time the blue button is clicked

function-call Beanstalk Debug Output console.log("Beanstalk Growing Game votes:", voteBeanstalk);

Prints the updated Beanstalk vote count to the browser console

voteBeanstalk++;
Increments the voteBeanstalk counter by 1, fired every time the blue 'Beanstalk' button is clicked.
console.log("Beanstalk Growing Game votes:", voteBeanstalk);
Outputs the updated vote count to the browser console for debugging purposes.

windowResized()

windowResized() is a special p5.js function that fires automatically whenever the browser window changes size. It's essential for making responsive sketches that work on phones, tablets, and desktops. Always call resizeCanvas() first, then update all element positions using the fresh width and height values.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  // Re-position elements when the window is resized
  buttonSpeakerBro.position(width / 2 - buttonSpeakerBro.width / 2 - 150, height * 0.4);
  displaySpeakerBro.position(width / 2 - displaySpeakerBro.width / 2 - 150, height * 0.5);
  buttonBeanstalk.position(width / 2 - buttonBeanstalk.width / 2 + 150, height * 0.4);
  displayBeanstalk.position(width / 2 - displayBeanstalk.width / 2 + 150, height * 0.5);
  instructions.position(0, height * 0.1);
}
Line-by-line explanation (6 lines)

🔧 Subcomponents:

function-call Canvas Resizing resizeCanvas(windowWidth, windowHeight);

Adjusts the canvas size to match the new window dimensions

loop Element Repositioning Loop buttonSpeakerBro.position(width / 2 - buttonSpeakerBro.width / 2 - 150, height * 0.4);

Recalculates and applies positions for all buttons and displays based on new canvas size

resizeCanvas(windowWidth, windowHeight);
Built-in p5.js function that stretches or shrinks the canvas to fit the new window size. Must run first so width and height variables update.
buttonSpeakerBro.position(width / 2 - buttonSpeakerBro.width / 2 - 150, height * 0.4);
Recalculates the green button's position based on the new canvas width and height. Keeps it centered with a 150-pixel left offset.
displaySpeakerBro.position(width / 2 - displaySpeakerBro.width / 2 - 150, height * 0.5);
Reposition the vote count display below the green button using the updated height variable.
buttonBeanstalk.position(width / 2 - buttonBeanstalk.width / 2 + 150, height * 0.4);
Recalculates the blue button's position using +150 offset (right side) so it stays opposite the green button.
displayBeanstalk.position(width / 2 - displayBeanstalk.width / 2 + 150, height * 0.5);
Reposition the Beanstalk vote count display below the blue button.
instructions.position(0, height * 0.1);
Reposition the heading using the new height so it stays 10% down from the top.

📦 Key Variables

voteSpeakerBro number

Stores the current vote count for the 'Don't go hard on the speaker bro' game option, incremented by 1 each time the green button is clicked.

let voteSpeakerBro = 0;
voteBeanstalk number

Stores the current vote count for the 'Beanstalk Growing Game' option, incremented by 1 each time the blue button is clicked.

let voteBeanstalk = 0;
buttonSpeakerBro object

Holds a reference to the clickable button element for voting on the speaker game. Used to apply styles, position it, and attach the click event handler.

let buttonSpeakerBro;
buttonBeanstalk object

Holds a reference to the clickable button element for voting on the beanstalk game. Used to apply styles, position it, and attach the click event handler.

let buttonBeanstalk;
displaySpeakerBro object

Holds a reference to the text display element showing the speaker game's vote count. Updated every frame by draw().

let displaySpeakerBro;
displayBeanstalk object

Holds a reference to the text display element showing the beanstalk game's vote count. Updated every frame by draw().

let displayBeanstalk;
instructions object

Holds a reference to the heading element displaying 'Vote for your favorite game!' at the top of the page.

let instructions;

🔧 Potential Improvements (5)

Here are some ways this code could be enhanced:

BUG setup() and windowResized()

Display elements are repositioned using width/height calculations based on their own width property, which may not be fully calculated when createElement() is called. This can cause misalignment on page load.

💡 Use fixed pixel offsets instead: buttonSpeakerBro.position(50, height * 0.4) and buttonBeanstalk.position(width - 250, height * 0.4). This is simpler and avoids the width-calculation trap.

PERFORMANCE draw()

The draw() function calls .html() every single frame (60 times per second) even when the vote counts haven't changed. Unnecessary DOM manipulation is expensive.

💡 Store the previous vote counts and only update the display when they change: if (prevVoteSpeakerBro !== voteSpeakerBro) { displaySpeakerBro.html(...); prevVoteSpeakerBro = voteSpeakerBro; }

STYLE incrementSpeakerBroVote() and incrementBeanstalkVote()

Two nearly identical functions with different variable names violate the DRY (Don't Repeat Yourself) principle. If you need to change vote increment logic, you must edit both functions.

💡 Create a single function that takes a parameter: function incrementVote(voteCounter) { eval('vote' + voteCounter + '++'); } or better yet, refactor to use an object: let votes = {speakerBro: 0, beanstalk: 0}; then one function can increment votes[key].

FEATURE Global scope

Votes are not persisted—they reset to 0 if the page is refreshed. For a real voting system, votes should be stored somewhere permanent.

💡 Use localStorage to save votes: localStorage.setItem('votes', JSON.stringify({speakerBro, beanstalk})); and restore them in setup(): let saved = localStorage.getItem('votes'); if (saved) { let data = JSON.parse(saved); voteSpeakerBro = data.speakerBro; ... }

FEATURE setup()

No visual feedback when buttons are hovered or clicked—they feel unresponsive compared to modern web interfaces.

💡 Add hover and active states via CSS in style.css: button:hover { opacity: 0.8; } and button:active { transform: scale(0.98); }. Or add feedback in the increment functions like a temporary color flash.

🔄 Code Flow

Code flow showing setup, draw, incrementspeakerbrVote, incrementbeanstalkVote, windowResized

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

graph TD start[Start] --> setup[setup] setup --> canvas-creation[Canvas Setup] setup --> heading-creation[Instructions Heading] setup --> button-speaker-creation[First Vote Button] setup --> button-styling[Button Styling Loop] setup --> event-handler-attachment[Event Listener Binding] setup --> draw[draw loop] draw --> update-speaker-display[Update Speaker Vote Display] draw --> update-beanstalk-display[Update Beanstalk Vote Display] update-speaker-display --> vote-increment[Vote Counter Increment] vote-increment --> console-log[Debug Output] update-beanstalk-display --> beanstalk-vote-increment[Beanstalk Vote Counter Increment] beanstalk-vote-increment --> beanstalk-console-log[Beanstalk Debug Output] draw --> draw setup --> windowResized[windowResized] windowResized --> canvas-resize[Canvas Resizing] canvas-resize --> element-repositioning[Element Repositioning Loop] element-repositioning --> windowResized click setup href "#fn-setup" click canvas-creation href "#sub-canvas-creation" click heading-creation href "#sub-heading-creation" click button-speaker-creation href "#sub-button-speaker-creation" click button-styling href "#sub-button-styling" click event-handler-attachment href "#sub-event-handler-attachment" click draw href "#fn-draw" click update-speaker-display href "#sub-update-speaker-display" click update-beanstalk-display href "#sub-update-beanstalk-display" click vote-increment href "#sub-vote-increment" click console-log href "#sub-console-log" click beanstalk-vote-increment href "#sub-beanstalk-vote-increment" click beanstalk-console-log href "#sub-beanstalk-console-log" click windowResized href "#fn-windowResized" click canvas-resize href "#sub-canvas-resize" click element-repositioning href "#sub-element-repositioning"

❓ Frequently Asked Questions

What visual experience does the p5.js voting sketch provide?

This sketch creates a vibrant, full-screen voting interface featuring large, colorful buttons for users to choose between two game ideas, accompanied by live vote counts.

How can users participate in the voting process within the sketch?

Users can interact with the sketch by clicking on one of the two colorful buttons to cast their vote, which updates the like counts displayed beneath each option in real-time.

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

The sketch demonstrates interactive programming and dynamic UI updates by using buttons and live text displays to engage users in a voting experience.

Preview

This is serious vote now you're going to pick me or the other guy it's only one answer who's winning - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of This is serious vote now you're going to pick me or the other guy it's only one answer who's winning - Code flow showing setup, draw, incrementspeakerbrVote, incrementbeanstalkVote, windowResized
Code Flow Diagram