xxxxxxxxxx
874
// ~ D E C L A R E D V A R I A B L E S ~ //
let help = "Press f (possibly twice) to toggle fullscreen";
let fenceImg;
let horseSpriteSheet;
let manSpriteSheet;
let rockImg;
let standingFrames = [];
let runningFrames = [];
let currentFrame = 0;
let frameWidth, frameHeight;
let animationSpeed = 8;
let scaleFactor = 3;
let horseX;
let horseY;
let horseSpeed = 3.5;
let isHorseVisible = true;
let isRunning = false;
let startButton;
let isBackgroundMoving = false;
let movingBackground;
let man;
let isManVisible = false;
let fenceScaleFactor;
let fenceX;
let fenceY;
let fenceSpeed = 2;
let isFenceLeaving = false;
let rocks = []; // Array to hold all rock objects
let totalRocksGenerated = 0; // Track total rocks generated
let canGenerateRock = true; // Cooldown flag for rock generation
let rockTimestamp = 0; // Timestamp of the last rock generation
let gameState = "playing";
let serialInput = ""; // Variable to store serial data
let birdSpriteSheet;
let birds = []; // Array to hold all bird objects
let totalBirdsGenerated = 0; // Track total birds generated
let canGenerateBird = true; // Cooldown flag for bird generation
let sensorActive = false; // Flag to track ultrasonic sensor
let diceGame;
let dice;
let flippedRunningFrames = []; // To store flipped horse frames
let flippedHorseX; // X position of the flipped horse in gameWon state
let flippedHorseY; // Y position of the flipped horse in gameWon state
let horseStopX = 400;
let flippedStandingFrame;
let backgroundStartTime = null; // To track when the background started moving
let maxTimeToWin = 90; // Timer starts at 90 seconds
let timeRemaining = maxTimeToWin; // Track the current remaining time
let lastTimeUpdated = 0; // Track the last time the timer was updated
let meterImg; // To store meter.png
let meterStartTime = null; // To track when the game meter state starts
let arrowAngle = -90; // Start angle for the arrow
let arrowDirection = 1; // Direction of movement (1 for clockwise, -1 for counterclockwise)
let arrowSpeed; // Speed of the arrow (set by skill or luck)
let choiceScreenStartTime = null; // Track when to start the choice screen
let skillButton, luckButton; // Buttons for the choice screen
let isArrowRotating = true; // Flag to control arrow rotation
let tryAgainAllowed = true;
let tryAgainButton = null;
let choiceCooldownStart = 0;
let restartButton = null;
let playAgainButton = null;
let ninjaSound;
let ninjaSoundPlaying = false;
let horseSoundPlaying = false;
// ~ I M A G E S ~ //
function preload() {
horseSpriteSheet = loadImage("Images/horse.png");
manSpriteSheet = loadImage("Images/man.png");
bgImg = loadImage("Images/background.png");
fenceImg = loadImage("Images/fence.png");
rockImg = loadImage("Images/rock.png");
birdSpriteSheet = loadImage("Images/bird.png");
meterImg = loadImage("Images/meter.png");
// Load the ninja.mp3 sound file
ninjaSound = loadSound("ninja.mp3");
horseSound = loadSound("horse.mp3");
}
function setup() {
createCanvas(windowWidth, windowHeight);
print(help);
// Initialize moving background
movingBackground = new MovingBackground(bgImg, 2, width, height);
// Calculate the width and height of each sprite
frameWidth = horseSpriteSheet.width / 7;
frameHeight = horseSpriteSheet.height / 3;
// Extract the frames for the standing animation
for (let i = 0; i < 7; i++) {
let x = i * frameWidth;
let y = frameHeight;
standingFrames.push(horseSpriteSheet.get(x, y, frameWidth, frameHeight));
}
// Extract the frames for the running animation
for (let i = 0; i < 7; i++) {
let x = i * frameWidth;
let y = 0;
runningFrames.push(horseSpriteSheet.get(x, y, frameWidth, frameHeight));
}
// Create flipped running frames
for (let i = 0; i < runningFrames.length; i++) {
flippedRunningFrames.push(flipImage(runningFrames[i]));
}
horseX = 1200;
horseY = 700 - frameHeight * scaleFactor;
flippedHorseX = -frameWidth * scaleFactor; // Start off-screen for the gameWon state
flippedHorseY = horseY;
flippedStandingFrame = flipImage(standingFrames[0]);
startButton = createButton("Start");
startButton.position(width / 2 - 50, height / 2);
startButton.size(100, 50);
startButton.mousePressed(startRunning);
// Initialize Man object
man = new Man(manSpriteSheet, 1400, height - 260, width, height);
// Initialize fence properties
fenceScaleFactor = scaleFactor * 0.8;
fenceX = 1525 - frameWidth * fenceScaleFactor;
fenceY = 700 - frameHeight * fenceScaleFactor;
dice = new Dice();
// Setup serial communication
setUpSerial();
}
function draw() {
if (gameState === "gameWon") {
if (!horseSoundPlaying) { // Check if the sound is already playing
horseSound.play(); // Play the horse sound once
horseSoundPlaying = true; // Set the flag to true
console.log("Playing horse.mp3");
}
} else {
if (horseSoundPlaying) { // Stop the horse sound if leaving the "gameWon" state
horseSound.stop();
horseSoundPlaying = false; // Reset the flag
console.log("Stopping horse.mp3");
}
}
if (gameState === "playing") {
if (!ninjaSoundPlaying) { // Check if the sound is already playing
ninjaSound.loop(); // Loop the sound
ninjaSoundPlaying = true; // Set the flag to true
console.log("Playing ninja.mp3");
}
} else {
if (ninjaSoundPlaying) { // Stop the sound if leaving the "playing" state
ninjaSound.stop();
ninjaSoundPlaying = false; // Reset the flag
console.log("Stopping ninja.mp3");
}
}
if (gameState === "diceGame") {
dice.update();
dice.draw();
if (!dice.rolling) {
if (!dice.rollStoppedTime) {
// Record the time when the rolling stopped
dice.rollStoppedTime = millis();
}
// Wait for 4 seconds after displaying the roll result
if (millis() - dice.rollStoppedTime > 4000) {
dice.rollStoppedTime = null; // Reset the timer for the next roll
if (dice.rollValue === 5 || dice.rollValue === 6) {
isBackgroundMoving = false; // Stop the background
man.setStanding(); // Switch the man to standing mode
sendCommandToArduino("stop_motor"); // Send command to stop the motor
gameState = "gameWon"; // Switch to gameWon state
} else {
backgroundStartTime = millis();
gameState = "playing"; // Return to playing state for other rolls
}
}
}
return;
}
if (gameState === "gameWon") {
drawGameWonScreen();
return;
}
if (gameState === "gameOver") {
drawGameOverScreen();
return;
}
if (gameState === "choiceScreen") {
drawChoiceScreen();
return; // Stop further drawing
}
if (gameState === "gameMeter") {
drawGameMeterScreen();
return;
}
if (gameState === "playing") {
if (isBackgroundMoving) {
// Track the start time of the background moving
if (!backgroundStartTime) backgroundStartTime = millis();
// Continue the countdown timer logic
let currentTime = millis();
if (currentTime - lastTimeUpdated >= 1000) {
lastTimeUpdated = currentTime;
timeRemaining--;
if (timeRemaining <= 0) {
gameState = "gameOver"; // Trigger game over if the timer runs out
return;
}
}
// Draw the countdown number
textSize(32);
textAlign(RIGHT, TOP);
textStyle(BOLD); // Make the text bold
if (timeRemaining <= 5) {
fill(255, 0, 0); // Red for the last 5 seconds
} else {
fill(255); // White for normal countdown
}
text(`${timeRemaining}`, width - 20, 20); // Display the timer at the top-right
}
}
background(0); // Clear background
// Only move the background if `isBackgroundMoving` is true
if (isBackgroundMoving) {
movingBackground.update(); // Update the background position
movingBackground.draw(); // Draw the moving background
if (!isFenceLeaving) {
isFenceLeaving = true; // Start moving the fence
}
let currentTime = millis();
if (currentTime - lastTimeUpdated >= 1000) {
lastTimeUpdated = currentTime;
timeRemaining--;
if (timeRemaining <= 0) {
gameState = "gameOver"; // Trigger game over if timer runs out
return;
}
}
// Draw the countdown timer in the top-right corner
textSize(32);
textAlign(RIGHT, TOP);
if (timeRemaining <= 5) {
fill(255, 0, 0); // Red for the last 5 seconds
} else {
fill(255); // White for normal countdown
}
text(`${timeRemaining}`, width - 20, 20); // Display the timer
} else {
image(bgImg, 0, 0, width, height); // Draw static background
}
if (isManVisible) {
// Check if the man has reached the stopX position
if (man.manX === man.stopX && !isBackgroundMoving) {
isBackgroundMoving = true; // Start the background scrolling
}
}
if (isHorseVisible) {
if (isRunning) {
image(
runningFrames[currentFrame],
horseX,
horseY,
frameWidth * scaleFactor,
frameHeight * scaleFactor
);
horseX -= horseSpeed;
if (horseX + frameWidth * scaleFactor < 0) {
isHorseVisible = false;
isManVisible = true;
sendCommandToArduino("start_motor");
}
} else {
image(
standingFrames[currentFrame],
horseX,
horseY,
frameWidth * scaleFactor,
frameHeight * scaleFactor
);
}
if (frameCount % animationSpeed === 0) {
currentFrame = (currentFrame + 1) % 7;
}
}
// Update and draw the fence
if (!isFenceLeaving) {
image(
fenceImg,
fenceX,
fenceY,
frameWidth * fenceScaleFactor,
frameHeight * fenceScaleFactor
);
} else {
fenceX += fenceSpeed; // Move fence to the right
if (fenceX > width) {
// Once the fence leaves the screen, stop drawing it
isFenceLeaving = false;
} else {
image(
fenceImg,
fenceX,
fenceY,
frameWidth * fenceScaleFactor,
frameHeight * fenceScaleFactor
);
}
}
// Update and draw all rocks (before the man is drawn, to appear behind)
for (let i = rocks.length - 1; i >= 0; i--) {
let rock = rocks[i];
rock.update();
rock.draw();
if (rock.x > width) {
rocks.splice(i, 1); // Remove rock if it leaves the canvas
}
}
// Update and draw all birds
for (let i = birds.length - 1; i >= 0; i--) {
let bird = birds[i];
bird.update();
bird.draw();
// Check if the bird is at the specified position and the sensor is active
if (
bird.x >= width / 2 - 2 &&
bird.x <= width / 2 + 2 &&
sensorActive
) {
console.log("Bird triggered sensor-based game over");
gameState = "gameOver"; // Trigger game-over state
break; // Exit the loop to avoid multiple triggers
}
if (bird.isOutOfCanvas()) {
birds.splice(i, 1); // Remove bird if it leaves the canvas
}
}
if (isManVisible) {
man.draw(); // Draw the man after the rocks, to appear in front
}
if (!serialActive && !isHorseVisible) {
text("Press Space Bar to select Serial Port", 20, 30);
}
// Check for game over condition
let currentTime = millis();
if (
currentTime - rockTimestamp > 4800 && // After the valid jump window
totalRocksGenerated > 0 && // A rock has been generated
!isSafe // Player didn't jump during the valid time window
) {
gameState = "gameOver";
}
}
let isSafe = false; // Track if the player successfully jumped
function drawGameOverScreen() {
background(0); // Black background
textAlign(CENTER, CENTER); // Center align text
textSize(64); // Large font size
fill(255, 0, 0); // Red color for "Game Over"
text("Horse Escaped", width / 2, height / 2 - 50); // Display "Game Over" message
// Create a Restart button
if (!restartButton) {
restartButton = createButton("Restart");
restartButton.position(width / 2 - 60, height / 2 + 100); // Position below the text
restartButton.size(120, 40);
restartButton.mousePressed(restartGame); // Attach the restartGame function
}
}
function startRunning() {
isRunning = true;
startButton.remove();
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
horseX = 1200;
horseY = 700 - frameHeight * scaleFactor;
if (!isRunning) {
startButton.position(width / 2 - 50, height / 2);
}
movingBackground.resize(width, height);
}
function keyTyped() {
if (key === "f") {
toggleFullscreen();
}
}
function keyPressed() {
if (gameState === "diceGame") {
dice.update();
return; // Do not process other keys during dice game
}
if (gameState === "gameMeter") {
if (key === "s" || key === "S") {
isArrowRotating = false; // Stop the arrow's rotation
console.log("Arrow stopped at angle:", arrowAngle); // Log the angle when stopped
}
return; // Prevent other keys from being processed during the game meter state
}
if (key === " ") {
console.log("spacebar key pressed");
setUpSerial();
}
if (key.toLowerCase() === "c" && isBackgroundMoving) {
// Check cooldown and trigger choice screen
let currentTime = millis();
if (currentTime - choiceCooldownStart >= 30000) { // 30-second cooldown
gameState = "choiceScreen";
choiceCooldownStart = currentTime; // Reset cooldown timer
console.log("Choice screen triggered by 'C'");
} else {
console.log("Choice screen is on cooldown.");
}
return;
}
if (key.toLowerCase() === "b" && isBackgroundMoving) {
if (canGenerateBird && totalBirdsGenerated < 10) {
console.log("B key pressed: Generating bird");
birds.push(new Bird(birdSpriteSheet, -50, height / 2 - 50, 4));
totalBirdsGenerated++;
canGenerateBird = false;
// Set a timeout to re-enable bird generation after 10 seconds
setTimeout(() => {
canGenerateBird = true;
}, 10000);
} else if (!canGenerateBird) {
console.log("Bird generation is on cooldown.");
} else {
console.log("Maximum number of birds generated.");
}
}
if (key.toLowerCase() === "j") {
console.log("Jump key pressed"); // Log the key press
// Check if jump is pressed between 4.2 and 4.8 seconds after rock generation
let currentTime = millis();
if (currentTime - rockTimestamp >= 4200 && currentTime - rockTimestamp <= 4800) {
console.log("safe");
isSafe = true; // Mark as safe
}
man.jump(); // Trigger jump
}
if (key.toLowerCase() === "r" && isBackgroundMoving) {
if (canGenerateRock && totalRocksGenerated < 10) { // Limit the total number of rocks to 10 with cooldown
console.log("R key pressed: Generating rock");
rocks.push(new Rock(-50, 585, 2));
totalRocksGenerated++;
canGenerateRock = false; // Start cooldown
rockTimestamp = millis(); // Record the time of rock generation
isSafe = false; // Reset the safe status
// Set a timeout to re-enable rock generation after 10 seconds
setTimeout(() => {
canGenerateRock = true;
}, 10000);
} else if (!canGenerateRock) {
console.log("Rock generation is on cooldown.");
} else {
console.log("Maximum number of rocks generated.");
}
}
if (key.toLowerCase() === "d" && isBackgroundMoving) {
dice.startRolling();
gameState = "diceGame";
return;
}
}
function readSerial(data) {
console.log(`Received from Arduino: ${data}`);
serialInput = data.trim();
if (serialInput === "jump") {
man.jump(); // Trigger jump regardless of timing
// Check if the jump happens within the safe window
let currentTime = millis();
if (currentTime - rockTimestamp >= 4200 && currentTime - rockTimestamp <= 4800) {
console.log("Button triggered jump (safe)");
isSafe = true; // Mark as safe if within the correct time window
} else {
console.log("Button jump outside the safe window");
}
}
if (serialInput === "rock") {
// Perform the same logic as the "R" key press
if (isBackgroundMoving && canGenerateRock && totalRocksGenerated < 10) {
console.log("Button triggered rock generation");
rocks.push(new Rock(-50, 585, 2));
totalRocksGenerated++;
canGenerateRock = false; // Start cooldown
rockTimestamp = millis(); // Record the time of rock generation
isSafe = false; // Reset the safe status
// Set a timeout to re-enable rock generation after 10 seconds
setTimeout(() => {
canGenerateRock = true;
}, 7000);
} else if (!canGenerateRock) {
console.log("Rock generation is on cooldown.");
} else {
console.log("Maximum number of rocks generated.");
}
}
if (serialInput === "choice") {
// Handle the button connected to pin 5
if (gameState === "gameMeter") {
// Simulate S key press: Stop the arrow rotation in the meter game
isArrowRotating = false;
console.log("Arrow stopped via choice button");
} else if (gameState === "playing" && isBackgroundMoving) {
// Simulate C key press: Trigger the choice screen
let currentTime = millis();
if (currentTime - choiceCooldownStart >= 30000) { // 30-second cooldown
gameState = "choiceScreen";
choiceCooldownStart = currentTime; // Reset cooldown timer
console.log("Choice screen triggered via choice button");
} else {
console.log("Choice screen is on cooldown.");
}
}
}
if (serialInput === "sensor_detect") {
sensorActive = true; // Sensor is detecting something
console.log("(detecting)");
} else {
sensorActive = false; // Reset sensor flag if no detection
}
if (serialInput === "bird") {
// Perform the same logic as the "B" key press
if (isBackgroundMoving && canGenerateBird && totalBirdsGenerated < 10) {
console.log("Button triggered bird generation");
birds.push(new Bird(birdSpriteSheet, -50, height / 2 -50, 4));
totalBirdsGenerated++;
canGenerateBird = false; // Start cooldown
// Set a timeout to re-enable bird generation after 10 seconds
setTimeout(() => {
canGenerateBird = true;
}, 3000);
} else if (!canGenerateBird) {
console.log("Bird generation is on cooldown.");
} else {
console.log("Maximum number of birds generated.");
}
}
serialInput = ""; // Clear serial input after processing
}
async function sendCommandToArduino(command) {
if (serialActive && writer) {
await writer.write(`${command}\n`);
console.log(`Sent to Arduino: ${command}`);
}
}
function toggleFullscreen() {
let fs = fullscreen();
fullscreen(!fs);
}
function flipImage(img) {
let flipped = createGraphics(img.width, img.height);
flipped.scale(-1, 1); // Flip horizontally
flipped.image(img, -img.width, 0); // Draw the flipped image at negative x
return flipped.get(); // Return the flipped image
}
function drawChoiceScreen() {
background(249, 179, 167); // Set the background color
textAlign(CENTER, CENTER);
textSize(32);
fill(0); // Black text
text("Choose Your Path", width / 2, height / 3);
// Ensure buttons are re-initialized every time the choice screen is shown
if (!skillButton && !luckButton) {
skillButton = createButton("Skill");
skillButton.position(width / 2 - 100, height / 2 - 20);
skillButton.size(120, 40);
skillButton.mousePressed(() => startMeterGame(9)); // Skill speed: 3
luckButton = createButton("Luck");
luckButton.position(width / 2 + 20, height / 2 - 20);
luckButton.size(120, 40);
luckButton.mousePressed(() => startMeterGame(6)); // Luck speed: 6
}
}
function startMeterGame(speed) {
arrowSpeed = speed; // Set the arrow speed based on the choice
if (skillButton) {
skillButton.remove(); // Remove the skill button
skillButton = null; // Reset the variable
}
if (luckButton) {
luckButton.remove(); // Remove the luck button
luckButton = null; // Reset the variable
}
gameState = "gameMeter"; // Transition to the meter game
}
function drawGameMeterScreen() {
background(249, 179, 167); // Black background
image(meterImg, width / 2 - meterImg.width / 2, height / 2 - meterImg.height / 2); // Draw the meter image
// Define arrow properties
let pivotX = width / 2; // Center horizontally
let pivotY = height / 2 + 100; // Adjust this value to move the arrow higher or lower
push();
translate(pivotX, pivotY); // Set new pivot point
rotate(radians(arrowAngle)); // Rotate the arrow
stroke(0); // Black color
strokeWeight(7); // Thin line
line(0, 0, 0, -150); // Arrow shaft
line(0, -150, -5, -140); // Left wing of the arrowhead
line(0, -150, 5, -140); // Right wing of the arrowhead
pop();
// Update the arrow rotation
if (isArrowRotating) {
arrowAngle += arrowDirection * arrowSpeed;
if (arrowAngle >= 90 || arrowAngle <= -90) {
arrowDirection *= -1; // Reverse direction at boundaries
}
}
// Check if the arrow is stopped and determine actions
if (!isArrowRotating) {
if (arrowSpeed === 6 && arrowAngle >= -90 && arrowAngle <= -50) {
dice.startRolling(); // Trigger dice roll logic
gameState = "diceGame"; // Transition to dice game if Luck and angle in range
} else if (arrowSpeed === 9 && arrowAngle >= -90 && arrowAngle <= -50) {
sendCommandToArduino("stop_motor"); // Stop the motor
gameState = "gameWon"; // Transition to game won if Skill and angle in range
} else if (arrowAngle > -50 && arrowAngle <= 0) {
// Check if no more Try Again is allowed
if (!tryAgainAllowed) {
setTimeout(() => {
arrowAngle = -90; // Reset the arrow for the next game
arrowDirection = 1; // Reset the direction
isArrowRotating = true; // Enable rotation for the next game
gameState = "playing"; // Transition back to playing
backgroundStartTime = millis(); // Reset the background timer
}, 2000); // Wait for 2 seconds
} else {
// Show the Try Again button if within the range and allowed
if (tryAgainAllowed) {
showTryAgainButton();
} else {
console.log("No more tries allowed.");
}
}
} else if (arrowAngle > 0 && arrowAngle <= 90) {
// Wait 2 seconds and then transition back to the playing state
setTimeout(() => {
arrowAngle = -90; // Reset the arrow for the next game
arrowDirection = 1; // Reset the direction
isArrowRotating = true; // Enable rotation for the next game
gameState = "playing"; // Transition back to playing
backgroundStartTime = millis(); // Reset the background timer
}, 2000);
}
}
}
// Function to show the Try Again button
function showTryAgainButton() {
if (!tryAgainButton) {
tryAgainButton = createButton("Try Again");
tryAgainButton.position(width / 2 - 50, height / 2 + 200); // Position below the meter
tryAgainButton.size(120, 40);
tryAgainButton.mousePressed(restartMeterGame);
}
}
// Function to restart the meter game
function restartMeterGame() {
tryAgainAllowed = false; // Disable further retries
tryAgainButton.remove(); // Remove the Try Again button
tryAgainButton = null; // Reset the button variable
arrowAngle = -90; // Reset the arrow angle
arrowDirection = 1; // Reset the direction
isArrowRotating = true; // Restart the arrow rotation
gameState = "gameMeter"; // Stay in the meter game
}
function drawGameWonScreen() {
background(bgImg); // Static background
man.drawStanding(); // Draw the man's standing frame
if (flippedHorseX < horseStopX) {
// Animate the flipped horse running
image(
flippedRunningFrames[currentFrame],
flippedHorseX,
flippedHorseY,
frameWidth * scaleFactor,
frameHeight * scaleFactor
);
// Update flipped horse position
flippedHorseX += horseSpeed;
// Update animation frame
if (frameCount % animationSpeed === 0) {
currentFrame = (currentFrame + 1) % flippedRunningFrames.length;
}
} else {
// Draw the flipped standing frame when horse reaches stop position
image(
flippedStandingFrame,
flippedHorseX,
flippedHorseY,
frameWidth * scaleFactor,
frameHeight * scaleFactor
);
}
// Create the Play Again button if it doesn't exist
if (!playAgainButton) {
playAgainButton = createButton("Play Again");
playAgainButton.position(width / 2 - 60, height - 100); // Position at the center, near the bottom
playAgainButton.size(120, 40);
playAgainButton.mousePressed(() => {
restartGame(); // Restart the game when clicked
if (playAgainButton) {
playAgainButton.remove(); // Remove the button after clicking
playAgainButton = null;
}
});
}
}
function restartGame() {
// Stop the motor
sendCommandToArduino("stop_motor");
// Stop the ninja sound if playing
if (ninjaSoundPlaying) {
ninjaSound.stop();
ninjaSoundPlaying = false;
}
if (horseSoundPlaying) {
horseSound.stop();
horseSoundPlaying = false;
}
// Reset all game variables to their initial states
gameState = "playing";
timeRemaining = maxTimeToWin; // Reset the countdown timer
lastTimeUpdated = 0;
isBackgroundMoving = false;
isHorseVisible = true;
isRunning = false;
isManVisible = false;
isFenceLeaving = false;
fenceX = 1525 - frameWidth * fenceScaleFactor; // Reset fence position
rocks = [];
totalRocksGenerated = 0;
canGenerateRock = true;
birds = [];
totalBirdsGenerated = 0;
canGenerateBird = true;
tryAgainAllowed = true;
tryAgainButton = null;
skillButton = null;
luckButton = null;
horseX = 1200;
flippedHorseX = -frameWidth * scaleFactor;
movingBackground.reset(); // Reset the background movement
// Reset the man's position and state
man = new Man(manSpriteSheet, 1400, height - 580, width, height);
// Reset jump timing variables
rockTimestamp = 0; // Ensure no stale rock timing remains
isSafe = false;
// Remove the restart button
if (restartButton) {
restartButton.remove();
restartButton = null;
}
// Recreate the start button
if (startButton) {
startButton.remove(); // Remove any existing button
}
startButton = createButton("Start");
startButton.position(width / 2 - 50, height / 2);
startButton.size(100, 50);
startButton.mousePressed(startRunning);
}