For my midterm, I had to create a game primarily focused on cats, driven by my love for them. The game’s objective is to reach a score of 20 by catching as many cats as possible within thirty seconds. Additionally, there is a power-up cat that boosts your score. I encountered two unsuccessful attempts in executing my ideas, leading me to start over, which I believe turned out quite well.
INITIAL IDEAS:
My initial idea was to create a game inspired by “My Talking Tom,” a game I enjoyed playing while growing up. I aimed to introduce a twist by replacing the cat with a camel. However, when it came time to execute the idea, I was unsure of how to begin and could not find any examples to follow.
My second idea involved creating an interactive game using PoseNet, modeled after the classic “I’ve got your nose” game. The core code functioned well; however, implementing the menu and other deliverables proved difficult, as they interfered with the rest of the code’s functionality. If you’re interested in trying it out, I recommend visiting the actual sketch, as you’ll need your webcam.
Moving on to the actual game, I aimed to create something simple and easy to play. However, I do wish it offered more of a challenge to players. Perhaps increasing the speed or adding another character that reduces the score instead of offering power-ups could enhance the difficulty. Additionally, feedback from one of my classmates highlighted the importance of clear instructions. Given the potential for confusion, providing explicit instructions regarding the timeframe, the scoring system, and the power-up cat would make it easier for users to understand and enjoy the game.
In terms of challenges, I faced issues similar to those of my classmates, particularly with the sketch not accepting images. I was advised to either work on the code locally or clear my cache to resolve this issue. However, my main challenges were related to the stylistic aspects of the game and deciphering the keyPressed(); function. Additionally, linking all parts of the game—from the menu to the game itself, and then to the win or lose screen—before looping it all back to the menu was probably the most time-consuming aspect of this entire project.
The most enjoyable aspect of this project for me was creating the graphics. I utilized Canva and Vecteezy to source all the elements needed to achieve the pixelated Mario aesthetic I desired.
Code + Notes:
// Midterm Project by Amal Almazrouei
// Credit:
// Sound: https://www.voicy.network/
// Font: Google Fonts
// Images: https://www.vecteezy.com/ ; pinterest.com
// Graphics: canva.com
// Example Code: https://editor.p5js.org/simontiger/sketches/Dj7GS2035
// Flags to control game state
let started = false;
let gameEnded = true; // Treat game as ended initially to present start menu
let showingEndScreen = false; // Indicates if end screen is currently displayed
// Game timing and positioning variables
let startTime;
let x = 200;
let y = 200;
let powerX = 100;
let powerY = 200;
// Score and game dynamics variables
let score = 0;
let r = 48; // Radius for interactive elements
let interval = 60; // Controls frequency of game events
let frames = interval; // Countdown to trigger game events
let powerIsThere = false; // Flag for power-up appearance
let increase = 1; // Score increment
let increased = 0;
// Assets and sound variables
let img, powerImg, startScreenBg; // Image variables for game elements
let myFont; // Custom font variable
let backgroundMusic, catSound, powerUpSound, winSound, loseSound; // Sound variables
function preload() {
// Preload all necessary media assets
img = loadImage('Media/cat1.png'); // Main character image
powerImg = loadImage('Media/cat2.png'); // Power-up image
startScreenBg = loadImage('Media/startScreenBg.png'); // Start screen background image
myFont = loadFont('assets/MyFont.ttf'); // Custom font
// Loading sound assets
backgroundMusic = loadSound('sounds/backgroundMusic.mp3');
catSound = loadSound('sounds/catSound.mp3');
powerUpSound = loadSound('sounds/powerUpSound.mp3');
winSound = loadSound('sounds/winSound.mp3');
loseSound = loadSound('sounds/loseSound.mp3');
}
function setup() {
createCanvas(400, 400);
textFont(myFont); // Set the custom font
backgroundMusic.loop(); // Play background music on loop
}
function keyPressed() {
// Handles key presses for restarting or transitioning from end screen
if (gameEnded && showingEndScreen) {
showingEndScreen = false; // Exit end screen to show start menu
} else if (!started && !showingEndScreen && gameEnded) {
resetGame(); // Reset and start game from menu
}
}
function resetGame() {
// Reinitialize game variables for a new session
started = true;
gameEnded = false;
showingEndScreen = false;
startTime = millis(); // Reset game timing and positioning
x = 200;
y = 200;
score = 0;
r = 48;
interval = 60;
frames = interval;
powerIsThere = false;
increase = 1;
increased = 0;
clear(); // Clear the screen before starting
}
function mousePressed() {
// Handle player interactions with game elements
if (started && !gameEnded && !showingEndScreen) {
if (dist(mouseX, mouseY, x, y) < r) {
catSound.play();
// Random chance for score increase
const rand = random(1);
if (rand < 0.02) {
increase = 50;
} else if (rand < 0.1) {
increase = 10;
} else {
increase = 1;
}
score += increase;
increased = 20;
interval--;
r--;
}
if (powerIsThere && dist(mouseX, mouseY, powerX, powerY) < r) {
powerUpSound.play();
score++;
interval = 60;
r = 48;
powerIsThere = false; // Remove power-up after clicking
}
}
}
function draw() {
// Main animation loop: Update game screen based on state
if (!started && !showingEndScreen) {
gameStartScreen(); // Show start screen if game hasn't started
} else if (started && !gameEnded) {
// Game play updates
let currentMillis = millis();
background(135, 206, 235); // Set background
// Display power-up image if present
if (powerIsThere) {
image(powerImg, powerX - r, powerY - r, r * 2, r * 2);
}
// Display main character image
image(img, x - r, y - r, r * 2, r * 2);
// Display score and time left
textAlign(LEFT, TOP);
textSize(30);
fill(255, 0, 255); // Set text color
text(score, 15, 15);
let timeLeft = 30 - Math.floor((currentMillis - startTime) / 1000);
text("Time: " + timeLeft, 15, 50);
// Update positions and check for game end conditions
frames--;
if (frames <= 0) {
frames = interval;
x = random(width);
y = random(height);
if (random(1) < 0.07) {
powerIsThere = true;
powerX = random(width);
powerY = random(height);
} else {
powerIsThere = false;
}
}
if (score >= 20) {
endGame(true); // Player won
} else if (currentMillis - startTime > 30000) {
endGame(false); // Time's up, player lost
}
}
}
function endGame(win) {
// Handle game end: Show win or lose screen
started = false;
gameEnded = true;
showingEndScreen = true;
background(135, 206, 235); // Optionally reset background
textAlign(CENTER, CENTER);
textSize(32);
// Display win or lose message
if (win) {
winSound.play();
fill(0, 0, 128); // Blue color for win
text("You Win!", width / 2, height / 2);
} else {
loseSound.play();
fill(0, 0, 128); // Blue color for lose
text("You Lose!", width / 2, height / 2);
}
fill(255, 0, 255); // Magenta color for subtitle
textSize(24); // Smaller font size for subtitle
text("Press any key to continue", width / 2, height / 2 + 20);
}
function gameStartScreen() {
// Display start screen at game launch
image(startScreenBg, 0, 0, 400, 400);
}
Credit + Resources:
Sound: https://www.voicy.network/
Font: Google Fonts
Images: https://www.vecteezy.com/ ; pinterest.com
Graphics: canva.com
Example Code: https://editor.p5js.org/simontiger/sketches/Dj7GS2035