Week 7 means… MIDTERM! (╥ω╥)

You might need to open this on a different tab for the hand gestures and camera to work here! Aaaand this for phone (but some parts are a bit different.) The cursor still works on this though.

Preface…? (And Concept)

Before I actually get into my project, I’ll tell you about how terrible my process was, for the sake of transparency. I started off with making a visual novel: think if you combined Doki Doki Literature Club, Butterfly Soup, and Persona… or something (but not a shoujo one. That definitely did pop up in my head, though.) I had my laptop out and thumbnails ready to go…

Ryuji (Persona 5): "I'm an esteemed scholar (Just opened my laptop.)"

…and then I ended up moving between 5 houses, 2 countries and five states in the span of 3 weeks. Yippee! The weekend the crisis started was the weekend I was expected to cram my project, and so, the cramming did NOT happen.

Ryuji (P5): "Bad news about my academic career Guys (Just closed my laptop)"

During these three weeks, while jumping from one house to another, I was also jumping from idea to idea: 14-year-old me was geeking out because I had the time to actually make a video game… except now not in great circumstances and constant power cutouts. I gave up on the visual novel idea (despite having some sprites ready </3) and tried to make a rhythm game, and then the issue of (one) copyright and (two) not having my keyboard with me resulted in a bigger headache figuring out the music than the coding itself. I tried to make a pixel game, and then realized that it would take me a long time to translate my ideas into pixel art and be satisfied with the amount of time I had.

One thing I really did want to include in my project was my artwork, and I realized very late, that why don’t I make a dress-up game? I used to play those games religiously on my dad’s Dell laptop while he would sleep in the afternoons when I was a kid, and now, I could make my own! I love fashion and since I’ve been holed up in each of the houses I’m staying in (Indian families are huge), I’ve missed dressing up a lot. In some way, I might be projecting onto this project. So… my concept is:

Short version: Hand-made Picrew with my own drawings and my own website code.

Long version: The short version explains it pretty well. I wanted the interface to be sketchy, as if I hand-drew it, and I wanted it to look very simplistic so that users would pay more attention to the character they were making. Then, you can also download your own version of the character! This would be a prototype for me to figure out how I could create this, and if it went well, I would reuse my code in the future to make a more extensive page (maybe even with backgrounds…).

Process

Firstly, I thumb-nailed. The first is before I started drawing the characters, and the second is after I finished all the elements for the characters. As you can see, I didn’t follow this exact layout, but it did help.

To make sure I didn’t end up spending too much time on this (since I didn’t have much time to begin with), I forced myself to set a fixed time restriction when drawing each element out on Procreate. I gave myself 3 hours, and here’s the results. You can see the elements much better on the game:

To make sure that when I layered each element over each other, you wouldn’t see the layers below, I made sure to color the lines with white in case. (Hence the lack of color… if I had more time I would have variations in color). To also make some cuter elements, I drew some more things out. .

Title! I tried to be consistent with my drawing style when I drew this.

I just layered the elements I drew to make two characters. Easy Peasy.

I started by putting (and renaming) my elements into folders on p5.js for each category, and then establishing each category and the layer order they would be stacked in (since all images are .pngs).

const LAYER_ORDER = ["base", "socks", "shoes", "pants", "tops", 
                     "accessories", "eyebrows", "eyes", "noses", 
                     "mouths", "hair", "hands"];

From there, I started building the sidebar and the overall layout of the game.

While I struggled with the hand tracking interaction, I was somewhat happy with the outcome. Using ml5’s handPose, I tracked only the tip of the index finger and mapped it to the canvas.

let indexFinger = hands[0].keypoints[8];
let tx = map(indexFinger.x, 0, 640, 0, CW);
let ty = map(indexFinger.y, 0, 480, 0, CH);
fingerX = lerp(fingerX, tx, 0.3); 
fingerY = lerp(fingerY, ty, 0.3);

However, I struggled with how to “click” without a mouse, and so I used a hover timer system. If I held my finger over a box for long enough, it would trigger the action:

let foundID = getHoverID();
if (foundID !== null) {
  if (foundID !== currentHoverID) { 
    currentHoverID = foundID; 
    hoverTimer = 0; 
    isLocked = false; 
  }
  if (!isLocked) {
    hoverTimer++;
    if (hoverTimer >= clickDelay) { 
      triggerAction(); 
      isLocked = true; 
    }
  }
}

// the arc cursor:
if (hoverTimer > 0 && !isLocked) {
  let arcEnd = map(hoverTimer, 0, clickDelay, 0, TWO_PI);
  strokeWeight(4); 
  arc(fingerX, fingerY, 35, 35, -HALF_PI, arcEnd - HALF_PI);
}

I turned it to 55 frames: not too long or short. I also added a circle that fills around the cursor to see the timer count down, which made it easier for the user to understand.

For the sketchy feeling of the boxes, I drew it so the buttons redraw with slightly different lines every frame, and it made it look much more fun.

render() {
  push(); stroke(0); strokeWeight(this.isMain ? 4 : 2); 
  fill(this.isOver() ? 240 : 255);
  
  randomSeed(this.x + this.y + floor(millis()/150));
  beginShape();
  vertex(this.x + random(-3,3), this.y + random(-3,3));
  vertex(this.x + this.w + random(-3,3), this.y + random(-3,3));
  vertex(this.x + this.w + random(-3,3), this.y + this.h + random(-3,3));
  vertex(this.x + random(-3,3), this.y + this.h + random(-3,3));
  endShape(CLOSE);
  
  noStroke(); fill(0); textAlign(CENTER, CENTER);
  if(customFont) textFont(customFont);
  textSize(this.isMain ? 32 : 18);
  text(this.label, this.x + this.w/2, this.y + this.h/2 + (this.isMain ? 5 : 2));
  pop();
}

For sounds, I had different sounds loaded for different actions. I had background music, and three different click sounds (for buttons in the sidebar, anything other buttons, and any of the items individually):

bgMusic = loadSound("song1.mp3", () => {
  bgMusic.setVolume(0.6);
  assetLoaded();
});
sfxItem = loadSound("click_item.mp3", assetLoaded);
sfxUI = loadSound("click_ui.mp3", assetLoaded);
sfxSidebar = loadSound("click_sidebar.mp3", assetLoaded);

if (aid === "start_btn") { 
  sfxUI.play(); 
  appState = "HELP"; 
  if (bgMusic && !bgMusic.isPlaying()) bgMusic.loop(); 
}

To make sure that when I reset the game, it would ask me for confirmation (in case I accidentally put my hand on the reset button), I used this code:

function drawModal() {
  fill(255, 230); noStroke(); rect(0, 0, CW, CH); // translucent overlay
  drawStaticBox(CW/2-150, CH/2-100, 300, 200);
  fill(0); textAlign(CENTER, CENTER); textSize(26);
  
  if (modalState === "RESET_CONFIRM") {
    text("Are you sure?", CW/2, CH/2 - 40);
    new SketchButton(CW/2-110, CH/2+20, 100, 40, "YES").render();
    new SketchButton(CW/2+10, CH/2+20, 100, 40, "NO").render();
  }
}

// in triggerAction():
if (modalState === "RESET_CONFIRM") {
  if (aid === "mod_yes") { avatar.reset(); sfxUI.play(); modalState = "NONE"; }
  else if (aid === "mod_no") { sfxUI.play(); modalState = "NONE"; }
  return; // early return stops anything else from firing
}

To save the image of the avatar, I used p5’s get() to screenshot the avatar preview region of the canvas and save it as a .jpg.

else if (aid === "save_btn") { 
  sfxUI.play(); 
  get(382, TOP_H+2, 366, CH-TOP_H-BOT_H-4).save('doodle','jpg'); 
  modalState = "SAVE_DONE"; 
}

I calculated the coordinates to make sure this crops cleanly no matter what the avatar is wearing. However, I think I messed this up on the mobile version (⇀‸↼‶).

I was really proud of the UI and how everything looked (somewhat) cohesive with each other, even though I drew some parts and coded other parts. And… even though this isn’t a coding part… I’m also really proud of my drawings. I’ve been in art block for a bit, so this forced me to draw (which helped somehow). ( ⸝⸝´꒳`⸝⸝)

Improvements (and our favorite thing… problems):
  • Originally when making the cursor, I struggled because I thought I should use a pinch action to select each box. That did NOT work due to the size of each box. So, I changed it to an (as others referred to it) x-box loading cursor with the circle to show how long you’re holding it before it selects. Worked pretty well!
  • There’s no color… which I really did want to put but I didn’t have time. While I do like the sketchiness of this, it would have been cooler to have more options and colors.
  • Also I have a lack of body diversity (race, body shapes, even gender) so I am SOAnyone else have this problem? : r/picrew SORRY! This was not intentional at all… I probably can’t even make myself on this, to be honest. This IS a prototype so I promise if I make a proper version, it’ll be very diverse.
  • On the mobile version, I can’t do computer vision. It also took me an hour to figure out why my code (which I altered for mobile)  wasn’t working on itch.io, so I would say the mobile version is worse than the desktop version.
  • I struggled with computer vision for an embarrassingly long amount of time. I still think it’s wonky, because I have to move my hands in really absurd distances and places to hit just a few buttons. The mouse is so much easier to use.
  • One thing I DID resolve was that while I was arranging images in the sidebar, due to the canvas size of each image being 1000×1000, it ended up looking tiny in each box. To fix this, I sorted the categories based on where on the canvas they were located (face were top right, feet were bottom right, etc.):
let zone = ["eyes", "eyebrows", "noses", "mouths", "hair"].includes(catKey) ? FACE_ZONE : (["shoes", "socks"].includes(catKey) ? FEET_ZONE : BODY_ZONE);

…and used this code to individually zoom in:

const FACE_ZONE = { x: 700, y: 120, w: 70, h: 70 }, FEET_ZONE = { x: 600, y: 670, w: 200, h: 200 }, BODY_ZONE = { x: 600, y: 200, w: 300, h: 300 };

I have more I want to say but I think this may turn into an essay, so I’ll leave it at that.

I hope that, at least, you all enjoy this! (੭˃ᴗ˂)੭
Credits

The Sanderling Brush on Procreate | This instrumental for background music | This cute font | The JJK S3 OST (good work music) | MixKit for sound effects

Midterm Project – Rooftop Rush

Concept

Rooftop Rush is a fast rooftop runner where every second feels like a chase scene. You play as a street runner jumping across city rooftops, dodging obstacles, and grabbing coins while the world keeps speeding up. Since each run is slightly different, you never know exactly what is coming next.

The main idea is simple: the more points you earn, the farther you can jump. At first, your jumps are short and careful. As your score rises, your movement starts to feel powerful and confident. But there is a catch: the city also gets faster. That push and pull is what makes the game exciting.

To keep every run exciting, I added extra moves and features:

  • Double Jump: Jump once more in the air for extra control.
  • Grapple Hook: Swing across very wide gaps using crane points.
  • Wall-Run and Wall-Jump: Use building walls to climb and launch back into the air.
  • Dash: A quick burst forward to escape danger.
  • Slide Kick: Slide into some obstacles to break them and gain points.
  • Tricks: Do flips and spins in the air for bonus points.
  • Near-Miss Bonus: Get rewarded for narrowly avoiding obstacles.
  • Power-ups: Temporary boosts like speed, shield, and coin magnet.
  • Upgrade Shop: Unlock permanent upgrades by playing well over many runs.
  • Day/Night Cycle: The background slowly changes from sunset to night.

Code I Am Proud Of

getJumpForce() {
  let base = CFG.BASE_JUMP * this.jumpMult;
  let bonus = CFG.JUMP_SCORE_K * Math.log(1 + this._score);
  return max(base - bonus, CFG.MAX_JUMP);
}

This is the code I am most proud of because it controls the feeling of the whole game. It decides jump strength each time the player jumps.

In simple terms, the game checks your score and makes your jump stronger as you improve. It also has a safe limit, so the jumps never become wild or unfair. Players can clearly feel their progress, but they still need timing and focus to survive.

How It Was Made

I built Rooftop Rush in p5.js and kept the project organized by splitting it into small parts. One part handles the player, others handle buildings, obstacles, effects, sound, and the game screens.

The hardest part was balancing the jump feel. I wanted players to feel stronger as they scored more points, but I also wanted the game to stay fair. I tested many versions until the movement felt fun, smooth, and controllable.

Another challenge was making movement feel responsive. Wall-running, dashing, grappling, and trick moves all had to work together without glitches. I used AI tools to help with some tricky parts, then tuned and tested everything by hand.

I also made sure random level generation stays fair. Gap sizes and building heights are controlled so the game does not create impossible situations.

The visual style was drawn directly in p5.js, including the runner, skyline, and effects. Sound effects were generated directly in code using p5.js sound tools.

Reflection

This project taught me a lot about game design and creative problem-solving. Keeping the game organized helped me test faster, fix bugs faster, and stay motivated.

I am most proud that the main mechanic works in real playtests. Players could feel their jump getting stronger as they scored more points, which was exactly the feeling I wanted to create.

In the future, I want to add more power-ups, a second playable character, and a mobile version with touch controls. I also want to improve character animation so tricks and wall-runs look even more dynamic.

Play Rooftop Rush

You can play the game directly below:

Live Project URL: https://enockmagara.github.io/Rooftop-Rush/


p5.js v1.9.0 · March 2026 · Intro to IM, NYUAD

Midterm project : Bakkar Ramadan Game

Concept:

Oy, “Hello” in the Nubian language , My concept is my favorite Ramadan series teaching students new lessons everyday in the holy month of Ramadan offering wisdom and importance of community as well ass offering awareness to children and adults since it the series was a great success in Egypt and The Arab World. It is also the first 100% created Egyptian cartoon series started in 1998. It also introduces the Nubian culture which on of the rich, unique, and strongly continuing cultures in Egypt.

Bakkar (TV Series 1998– ) - IMDb

So how does it work and what am I proud of:

Initializing all images and assets

let startImg, homeImg, bakkarImg, hassonaImg, mapImg, mapSceneImg;
let teacherImg, rashidaImg, friend1Img, shalabiImg, friend2Img, shalabi2Img;
let storeShelfImg, storeAsset1Img, storeAsset2Img, bagImg, shopSignImg;
let button;
let homeMapStartTime = 0;

 

Hassona is Bakkar friend guiding him through the game. I added Typetext message. HassonaStoreIdx and hassonaMapIdx starts at 0 and counts up to the full length of the map and home  scene text, making it appear letter-by-letter.

let homeTypeText = "حسونه: يا بكار يلا نجمع فلوس الزينة رمضان\nHassona: Yalla Bakar Lets collect the money for the Ramadan decorations";
let homeTypeIdx = 0;

const hassonaMapText = "حسونة: اضغط Space للتكلم مع أصحابنا والجيران!\nHassona: Press Space to Talk to our Friends and Neighbors!";
const hassonaStoreText = "حسونة: اسحب الأغراض للشنطة عشان تشتري!\nHassona: Click & Drag objects to the Bag to Buy!";
let hassonaMapIdx = 0;
let hassonaStoreIdx = 0;

 

 

This is the pinned message at the top giving instruction. I added a white speech box to make it more clear to see the message.

fullText.substring(0, idx) slices the full string to only show characters up to idx, creating the typewriter effect.

function drawHassonaBanner(fullText, idx) {
noStroke();

// Dark semi-transparent backing strip
fill(0, 150);
rect(0, 0, width, BANNER_H);

// Hassona avatar
image(hassonaImg, ICON_PAD, ICON_PAD, ICON_SIZE, ICON_SIZE);

// White speech box
fill(255);
rect(BOX_X, ICON_PAD, BOX_W, BANNER_H - ICON_PAD * 2, 8);

// Typewriter text inside box
fill(0);
textAlign(LEFT);
textSize(14);
text(fullText.substring(0, idx), BOX_X + 12, ICON_PAD + 18, BOX_W - 22, BANNER_H - ICON_PAD * 2 - 10);
}

 

This function draws the Hassona intro banner on the home screen. It waits 2 seconds after the scene starts. I used Chatgbt to learn more about how to use time countdown before it shows an image or an object as well as typer style of text banner. Also there is a debugMode to help with seeing where the collision boxes are I got it form Claude because I struggle to envision where everything goes.

function drawHomeTypewriter() {
if (millis() - homeMapStartTime < 2000) return;
image(hassonaImg, 10, 10, 100, 100);
fill(255); rect(120, 20, 650, 100, 10);
fill(0); textAlign(LEFT);
text(homeTypeText.substring(0, homeTypeIdx), 140, 50, 600);
if (frameCount % 2 === 0 && homeTypeIdx < homeTypeText.length) homeTypeIdx++;
}

 

Every frame, updateRashidaTrail saves Bakkar’s current position to a history array, trims it to TRAIL_DELAY frames long, then positions Rashida at the oldest saved position — making her follow Bakkar with a slight delay. drawRashida simply draws her sprite at that calculated position.

function updateRashidaTrail() {
posHistory.push({ x: x, y: y });
if (posHistory.length > TRAIL_DELAY + 1) posHistory.shift();
if (posHistory.length > 0) {
rashidaX = posHistory[0].x - RASHIDA_W * 0.5;
rashidaY = posHistory[0].y + (charH - RASHIDA_H) * 0.5;
}
}

function drawRashida() {
image(rashidaImg, rashidaX, rashidaY, RASHIDA_W, RASHIDA_H);
}

 

 

For the collision I used a fixed hitboxoffset  so when my character collides with an object it gets detected, and the it either stops the object from going through the object or transitions to the next scene

The moveCharacter function moves using arrows and it minus the amount of steps towards a specific direction like x or y in negative which the left side or positive side which to the right side. If moving horizontally doesn’t cause a collision, it applies the new X; if moving vertically doesn’t cause a collision, it applies the new Y. This way the player can slide along a wall instead of getting completely stuck when hitting it diagonally.

function checkCollision(cx, cy, ox, oy, ow, oh) {
return (
cx + hitboxOffsetX < ox + ow &&
cx + hitboxOffsetX + hitboxW > ox &&
cy + hitboxOffsetY < oy + oh &&
cy + hitboxOffsetY + hitboxH > oy
);
}

function collidesWithList(nx, ny, list) {
for (let obs of list) {
if (checkCollision(nx, ny, obs.x, obs.y, obs.w, obs.h)) return true;
}
return false;
}

function moveCharacter(obstacles) {
let nx = x, ny = y;
if (keyIsDown(LEFT_ARROW)) nx -= step;
if (keyIsDown(RIGHT_ARROW)) nx += step;
if (keyIsDown(UP_ARROW)) ny -= step;
if (keyIsDown(DOWN_ARROW)) ny += step;
nx = constrain(nx, 0, width - charW);
ny = constrain(ny, 0, height - charH);
if (!collidesWithList(nx, y, obstacles)) x = nx;
if (!collidesWithList(x, ny, obstacles)) y = ny;
}

 

In the store scene it shows the amount of money collected in the variable  moneyTotal and then we have an object bag with a specific x,y,w, and h to drop object in the bag.

function drawStoreScene() {
image(storeShelfImg, 0, 0, width, height);

image(bagImg, bagZone.x, bagZone.y, bagZone.w, bagZone.h);
fill(255); textAlign(CENTER); textSize(14);
text("Drop to Buy", bagZone.x + 90, bagZone.y + 30);

// Money HUD sits below the banner
fill(0, 180); rect(0, BANNER_H, width, 48);
fill(255, 215, 0); textSize(20); textAlign(CENTER);
text("Money: " + moneyTotal + " EGP", width / 2, BANNER_H + 33);

 

It loops through storeItems and draws each one that hasn’t been bought or placed yet, then if the player is currently dragging an item it draws it following the mouse. Finally it handles the error message, dialogue, back button, and draws the Hassona banner last so it always appears on top of everything else.

for (let itm of storeItems) {
if (!itm.inBag && !itm.placedOnMap) {
image(itm.img, itm.px, itm.py, 100, 100);
fill(255); textSize(18); text(itm.name, itm.px + 50, itm.py - 10);
}
}
if (dragging && scene === 'store_scene') {
image(storeItems[dragging.idx].img, mouseX - 50, mouseY - 50, 100, 100);
}
if (millis() < statusTimer) { fill(255, 0, 0); text(statusMessage, width / 2, height / 2); }

drawDialogueUI();

fill(255); textSize(18); text("Press 'B' to Return to Map", width / 2, height - 30);

// Hassona banner drawn last — always on top
drawHassonaBanner(hassonaStoreText, hassonaStoreIdx);
if (frameCount % 2 === 0 && hassonaStoreIdx < hassonaStoreText.length) hassonaStoreIdx++;
}

 

drawBakar draws the player , drawDoor draws a brown rectangle for the home door, drawStoreEntrance draws the shop sign image, and startGame switches to the home scene, hides the start button, records the start time, and resets Rashida’s position and trail history.

function drawBakar() { image(bakkarImg, x, y, charW, charH); }
function drawDoor() { fill(101, 67, 33); rect(doorX, doorY, doorW, doorH, 5); }
function drawStoreEntrance() {
image(shopSignImg, storeDoor.x, storeDoor.y, storeDoor.w, storeDoor.h);
}
function startGame() {
scene = "home_map";
button.hide();
homeMapStartTime = millis();
rashidaX = x - RASHIDA_W - 10;
rashidaY = y;
posHistory = [];
}

 

Draws a small semi-transparent dark badge in the top-right corner just below the Hassona banner, displaying the player’s current cash total in gold text.

function drawMoneyHUD() {
// In map_scene, cash badge sits just below the Hassona banner
fill(0, 180); rect(width - 190, BANNER_H + 8, 170, 40, 10);
fill(255, 215, 0); textSize(16); textAlign(CENTER);
text("Cash: " + moneyTotal, width - 105, BANNER_H + 30);
}

 

with each interaction with each store asset and their x,y positions, name, and image that was initialized in the beginning of the code.

function initStoreItems() {
storeItems = [
{ name: "Lantern", img: storeAsset1Img, cost: 10, shelfX: 100, shelfY: 300, px: 100, py: 300, inBag: false, placedOnMap: false, mapX: 0, mapY: 0 },
{ name: "Decor", img: storeAsset2Img, cost: 15, shelfX: 300, shelfY: 300, px: 300, py: 300, inBag: false, placedOnMap: false, mapX: 0, mapY: 0 }
];
}

 

I wrote the dialogue  with each interaction with each character  and their x,y positions, name, and image that was initialized in the beginning of the code.

function initNPCs() {
npcs = [
{ name: "Teacher", img: teacherImg, x: 100, y: 200, completed: false,
greet: "Bakar! Help with Ramadan decorations?",
opts: [{ text: "Yes! (Collect 10 EGP)", reward: 10, reply: "Good luck!" }] },

{ name: "Friend", img: friend1Img, x: 200, y: 600, completed: false,
greet: "Bakar! I saved some money for the decorations!",
opts: [{ text: "Thanks! (Collect 15 EGP)", reward: 15, reply: "Yalla habibi!" }] },

{ name: "Friend2", img: friend2Img, x: 380, y: 600, completed: false,
greet: "Hey Bakar! I have some money for decorations!",
opts: [{ text: "Thanks! (Collect 15 EGP)", reward: 15, reply: "Happy Ramadan!" }] },

{ name: "Shalabi", img: shalabi2Img, x: 560, y: 200, completed: false,
greet: "Bakar ya basha! Khawd el floos!",
opts: [{ text: "Shukran! (Collect 25 EGP)", reward: 25, reply: "Ramadan Kareem!" }] }
];
}

Sketch:

Areas I would like to improve:

I would to improve a lot of things like the quality of the pixelated, adding more assets to ramadan decoration, more interaction between Bakkar and the NPCs. I honestly, had an idea in mind to make an interactive immersive game, but due to circumstance it was a bit difficult to create it. There so much more things I think I could have added it to my project to make it more unique. I feel the most unique part of it is a simple introduction to Egyptian community and culture. I could also add the music effects from the music series. I also did not end the game because I want to work on improving it and make it into a true RBG game similar to starview valley and add different quests and games. Therefore, I would like to add more dialogues between the character to learn about them and there role and stories in the series.

 

“you have no idea how ALONE you are” : Midterm Project

We know.
We know music can alter the state of the human mind. When you’re happy, a sad song can sway your happiness. When you’re sad, a joyful song can sway the latter. Music can make you feel alone, it brings out parts of your personality that may otherwise be hidden.

Music can shape us, but what if it could shape the environment around us?

“you have no idea how ALONE you are” is the title of my midterm project.

 *Graphics & Memory intensive. 4GB RAM is advised.

Space is so unfathomably vast, that we are but like atoms to mountains amid it. Thus, it is only natural for feelings of solitude and loneliness to be invoked in this alien world beyond our blue horizons. This is exactly the emotion the project targets: to invoke feelings of this loneliness, one that we all have felt at some point in our lives.

And what could accentuate that feeling, or perhaps evoke it from slumber to wake? One avenue is certainly music. The music I have chosen for this project is aligned with the genres of science fiction, of terror and upbeat, and of solace and emotion.

I was inspired by the timelessness of the Temple of Karnak (Egypt), with towering pillars making us feel small and very much alone.

Favorite Code Snippet:

let half = {
  x: boxSize.x / 2,
  y: boxSize.y / 2,
  z: boxSize.z / 2
};
let closest = {
  x: constrain(spherePos.x, boxPos.x - half.x, boxPos.x + half.x),
  y: constrain(spherePos.y, boxPos.y - half.y, boxPos.y + half.y),
  z: constrain(spherePos.z, boxPos.z - half.z, boxPos.z + half.z)
};

let dx = spherePos.x - closest.x;
let dy = spherePos.y - closest.y;
let dz = spherePos.z - closest.z;

let distanceSq = dx*dx + dy*dy + dz*dz;

return distanceSq <= radius * radius;

As the game is 3D, I decided to implement collision detection (wouldn’t be much of a game otherwise).

This uses Axis Aligned Bounding Boxes (AABB) as extended upon in the book Real Time Collision Detection.

I really loved how simple yet effective this part of the logic was. It really helped save resources (as compared to my other, independent and failed attempts).

The Toughest Part:

I had absolutely no idea how the final project would look like until 3 days before submission. The reason: I had to script in my own game engine and graphics rendering pipeline, shaders, etc. before attempting to even build anything in the map. That was a significant amount of trust I had to place inside of my own capabilities, and I’m glad I trusted myself. The final result wasn’t what I initially planned for, but it looks awesome!

Known problems:

Unfortunately, with this project came a lot of problems. Firstly, any graphics, interfaces, etc. that I attempted to implement continued to fail. Thus, I was unable to implement any interfaces to tutorials.

Furthermore, the collision detection works properly, but I use a dumbed down version of collision handling. This was so as to prevent the browser consuming egregious amounts of memory, and to reduce lag spikes. There are some points where stuff glitches, but those are few and far between.

Development Process:

The development process entailed me working on the entirety of the project (unless otherwise stated). I wrote the code, sourced PBR textures from PolyHaven (free textures!) and audio from PixaBay (free with credit!) I used google to search for collision detection algos, and came across the book on collision detection on google. AI was used for only sourcing out textures and audio files. I didn’t fancy it too much beyond that.

Week 7: Midterm Project

Concept

Ella’s Panaderya is an interactive experience set inside a Filipino bakery, also called a panaderya. The piece invites users to explore the space, click on pastries to learn about them, control the music playing on the radio, and interact with a pot of champurado. My goal was to create something that felt warm and nostalgic to Filipino while informative for those  who aren’t.

Final Sketch!

How This Was Made

The sketch was built in p5.js using a game state system to manage which scene is displayed at any given time. Each state has its own draw function that renders the appropriate graphics. The bakery scene uses a photo background with clickable regions mapped onto the pastries and interactive objects in the image. To find the correct coordinates for each pastry, I used a temporary debug line was added inside drawBakery() that displayed live mouse x and Y values on the canvas as the mouse moved. It was easier to pinpoint the top-left and bottom-right corners of each item and calculate the width and height of each clickable zone. I just removed debug line  once all coordinates were set.

Temporary DeBug line:

fill(255, 0, 0);
textSize(10);
text(mouseX + ", " + mouseY, mouseX, mouseY);

Each pastry is a class that has its position, dimensions, name, and description. I made it so when you click a pastry, a popup displays that information. The champurado pot has its own layer with a top-down bowl drawn using shapes, a stirring animation, and a milk interaction that lightens the color of the champurado. The radio buttons are mapped to coordinates on the bakery image  (same as the pastries) and control three songs using the song functions learned from the class.

Reflection & Future Improvements

This project came together under a time crunch, so there are a few things I would have liked to develop further. The biggest one is the fan: the original plan was to make it interactive, cycling through speed settings with a sprite-based spinning animation to show the blades actually turning. Given more time, that would have added another layer of life to the bakery scene. I also would have liked to refine the popup sizing and positioning across all pastries, and possibly add a zoomed-in image for each one rather than just text. Overall though, I think the piece  succeeded in creating a small, explorable slice of a Filipino bakery that feels interactive and grounded in real cultural context.

Midterm – Mohamed Sunkar

Overall Concept

links:

https://editor.p5js.org/mss9452/sketches/OTs6tFggnA

https://editor.p5js.org/mss9452/full/OTs6tFggnA

For my project, I redesigned the classic Snake game, with more focus on the atmosphere and visual experience rather than just the gameplay. For the design I added geometric patterns for the background with music playing as well. The game also changes themes by pressing the t button to either light or dark. Instead of the usual blocky snake I made it with a glowing circular shape to represent light movement through an environment.

I wanted the experience to feel somewhere between calm and intense. The background slowly shifts between geometric patterns, creating subtle motion without distracting from the game itself. At the same time, the gameplay remains simple and familiar, allowing the user to focus on both playing and experiencing the visuals. Overall, my goal was to take a very well-known game and transform it into something more immersive while still keeping it intuitive.

How the Project Works / What I’m Proud Of

The game is built using p5.js and uses object-oriented programming to organize the main elements. I created separate classes for the Snake and the Fruit, which made the code easier to manage and extend. The snake moves across a grid system, updating its position each frame, while collision detection checks for walls, self-collision, and fruit collection. When the snake eats the fruit, it grows, the score increases, and a sound effect plays to give feedback to the player.

One part I am particularly proud of is the visual design. I replaced the traditional square snake with glowing circular segments that create a layered light effect. This connects back to my concept of light moving through darkness. I also added two background images that slowly fade into each other, which gives the game a more dynamic and atmospheric feel without interfering with gameplay. The dark/light mode toggle was another feature I liked, since it allows the user to switch between two different moods.

Another aspect I think works well is the overall structure of the program. I used a game state system (start, playing, and game over), which made it easier to control what is displayed at different times. I also added background music and sound effects, which made the game feel more complete and interactive rather than just a basic version of Snake.

Code Snippets

Fruit interaction + sound

if (snake.getHead().equals(fruit.position)) {
  score += 1;
  snake.grow();
  fruit.relocate();

  eatSound.play();
}

Snake movement

move() {
  this.segments.pop();

  let head = this.segments[0].copy();
  this.segments.unshift(head);
}

Areas for Improvement / Challenges

One of the biggest challenges I had to deal with was the interaction between the different parts of the program, especially when incorporating new features such as the use of sound, images, and different game states. There was also the time when some of the functions were not recognized, as well as the issue with the game over screen not displaying as desired. This was easily solved by organizing the code in such a way that the state system is utilized.

Another challenge I encountered was dealing with the images and the sound files with the p5.js library. There was some difficulty with the formats as well as ensuring that the sounds do not overlap. This made me think more critically about the use of the sounds.

If I had more time, I would definitely consider incorporating some new features such as the difficulty level as well as the level. This would definitely make the gameplay experience more interesting. In addition to this, I would consider further improving the looks as well as incorporating some interactive elements. While the atmosphere is good, there is still room for improvement with regard to the gameplay experience.

Week 8 – Midterm Project

Sketch link!

Describe the overall concept of your project (1-2 paragraphs)

My project is a puzzle solving game with an “Ancient Egypt” theme. I wanted to have theme that related to me and since I’m Egyptian, this theme only made sense. Initially, I planned to use cartoon-like images of landmarks in Egypt, but I couldn’t find any images online of what I wanted or there wasn’t enough variety. I also can’t draw so I ended up just using realistic images instead (which I think I found through a website called freepik, but it was so long ago that I don’t even remember anymore). I had a rough plan of how I wanted the different screens within the game to look like in Canva (included in my midterm progress documentation), most things stayed the same in my final project. I found a font online called “khamenet,” which I decided to use throughout. I feel that this really added to the vibe of my project. 

As for the game aspect, I settled on having each piece just be a square, rather than actual puzzle shaped since that would’ve been too difficult to code. The user can move the pieces around using their mouse. I didn’t add any instructions for my game as I felt it was self-explanatory, I tested it with my siblings and they both were able to play the game without any instructions. The only thing that I needed to point out was the ‘peek’ button. The peek button allows the user to see a preview of what the image they’re putting together looks like on the board itself. Initially, I was planning to just have a small reference image at the bottom of the screen, however, the peek overlay option ended up being more helpful and looks more seamless than having something in the corner. While the user plays, there’s background music and a ‘ding’ whenever a piece is placed correctly, if the user turns of the sound, both of these audio elements are muted/stopped. In addition, while the user plays, the game keeps track of the time taken, number of pieces placed, and number of moves taken. Finally, at any point, if the user gives up, they can press the menu button at top right to go back to the main menu. If they do not give up and complete the puzzle successfully, there’s a victory cheer (called a zaghrouta) that plays as well as an ending screen with their time taken. They can press anywhere to restart.

Describe how your project works and what parts you’re proud of (e.g. good technical decisions, good game design) 2-3 paragraphs

For the start screen, the main interactions are choosing the image and the difficulty level. The user can select each of these elements by clicking on them using the mouse. If the user presses within the coordinates of the element, their choice is recorded and the game proceeds accordingly. By default, if the user does not click on anything, the first image is selected and the difficulty is easy. The user can see which option is selected as the selected image has a border around it and selected difficulty is darker in color. Finally, the user starts the game by pressing within the boundaries of the lines around the work “START”. As long as the user is on the start screen, there is some music in the background.

I’m really proud of the aesthetic and the look of my start screen, since I wasn’t sure how closely I would be able to match the idea I had put together on Canva. However, luckily everything came together really nicely. I was really happy with the visual feedback to the user selecting the image and difficulty.

On the game screen, there’s a puzzle board on the left where the user puts the pieces together, a piece tray on the right where all the pieces start out scattered, and a few buttons at the top to control different things. First, top left, there’s the peek button. This button (as described earlier) allows the users to see a light preview of the full image overlaid on the puzzle board. I’m really proud of this element since I didn’t really have a plan of how I wanted to display the preview, so the fact that in the end, it ended up being something so simple is really nice.

// shows a preview of the image being solved, as a background 
function drawPeekOverlay() {
  let img = getSelectedImage();
  if (img) {
    push();
    tint(255, 70);
    imageMode(CORNER);
    image(img, 10, 120, 600, 600);
    pop();
  }
}

Next to the peek button is the volume button which simply either toggles all the sound on or off, which includes the correct ding sound and the background music. A possible improvement is keeping the ding sound audible even when the user silences the music since I feel like that audible feedback can be more helpful.

In the middle at the top there’s an info bar that tracks the time elapsed, how many pieces have been placed out of the total, and the number of moves taken. The time elapsed is tracked by calculating the difference between millis() and the startTime that was recorded when the puzzle began, and counts placed pieces by looping through the pieces array each frame. Finally, on the top right, there’s a menu button which simply takes the user back to the start screen at any point.

As for the actual puzzle, when buildPuzzle() is called it creates a PuzzlePiece  object for every cell in the grid and scatters each one at a random position inside the tray using random(). Each piece stores which row and column it belongs to, so it knows its exact target position on the board. The drag and drop system uses three separate p5.js mouse functions working together: mousePressed() picks up the topmost unplaced piece the user clicked on by looping backwards through the array, mouseDragged() updates the piece’s position to follow the mouse every frame, and mouseReleased() drops it and calls trySnap() which checks if the piece landed within 30 pixels of its correct target — if it did, it locks into place exactly and the border around it turns green. The dragged piece is always moved to the end of the pieces array so it draws on top of everything else. When all pieces are placed, the background music stops, the zaghrouta audio plays, and the state switches to WIN which triggers the win screen on the next frame.

class PuzzlePiece {

  constructor(id, col, row, cols, img) {
    this.id = id;
    this.col = col;
    this.row = row;
    this.cols = cols;
    this.img = img;
    
    // calculate piece size based on the no. of cols and board size
    this.w = 600 / cols;
    this.h = 600 / cols;

    // current position, updated in buildPuzzle
    this.x = 0;
    this.y = 0;
    
    // target position (where the piece actually belongs on the board)
    this.targetX = 10 + col*this.w;
    this.targetY = 120 + row*this.h
    this.isPlaced = false;
}
draw() {
    push();
    // draw the actual image slice
    if (this.img) {
      let sliceW = this.img.width / this.cols;
      let sliceH = this.img.height / this.cols;
      let sliceX = this.col * sliceW;
      let sliceY = this.row * sliceH;

      imageMode(CORNER);
      // draw slice at current this.x and this.y
      image(this.img, this.x, this.y, this.w, this.h, sliceX, sliceY, sliceW, sliceH);
    }
    // draw border based on 'state'
      noFill();
      if (this.isPlaced) {
      stroke("#2a7a2a"); // green, if correct
      strokeWeight(3);
    } else if (this === dragging) {
      stroke("#e59828"); // orange, if being moved
      strokeWeight(3);
    } else {
      stroke("#6b2705");
      strokeWeight(1);
    }
      rect(this.x, this.y, this.w, this.h);
      pop();
    }

    // check if the mouse is touching this specific piece
   contains(mx, my) {
    return mx > this.x && mx < this.x + this.w && my > this.y && my < this.y + this.h;
  }
// snap logic
  trySnap() {
    let d = dist(this.x, this.y, this.targetX, this.targetY);
    if (d < 30) {
      this.x = this.targetX;
      this.y = this.targetY;
      this.isPlaced = true;
      return true;
    }
    return false;
  }
}
Describe some areas for improvement and problems that you ran into (resolved or otherwise) (1-2 paragraphs)

I think one main area for improvement is having actual puzzle shaped pieces rather than just squares. I think that would’ve definitely my idea across more, however, considering my skill set and based on tutorials and p5.js reference page, square seemed more feasible. I think adding instructions to clarify what the peek button does would’ve also been helpful, but my hope was that the user would just play around with the buttons and eventually discover it themselves (or ask me how to view a preview and I would guide them to use the button). I also would’ve loved to add some visual animations associated with the background music and also have different music/audio for each picture, but I completely forgot about the sound requirement till the last minute so there was a bit of a time constraint there.

I ran into a few problems throughout writing the code for this project, however, at this point, most of the problems have slipped my mind. One thing that I do remember since it was added last minute is that when I added audio files, my code was stuck in an endless loading loop. I was stuck on that for around 10 minutes, thinking maybe the files are just taking longer than usual to load, before I checked back through our class notes and realized I needed to add the sound library to my index.html file. Luckily, that wasn’t too big of an issue. Whenever I did run into any problems with my code (debugging) or was stuck with how to begin or how to proceed with specific features, I did get some help from Gemini as it would guide me on what topics to cover, give me links to videos to refer to, and what pages would helpful from the p5.js reference so I felt that I learnt a lot more that way.

Midterm – Zere Kystaubayeva

View only link: https://editor.p5js.org/lunaland/full/lguzYiIJr

1. Concept of the game: I decided to create an interactive piece called “Day in the Life of a Cat”, where the user gets to experience normal cat stuff that cats get to do throughout their days.

  • I have a hairless cat, Luna. I miss her a lot since she lives with my grandparents, and I decided to remind myself of her by creating this interactive experience. Everything that the game includes is pretty much all she does every day – eat, play with random things, terrorize insects outside, and poop.
  • What and how: The user gets to experience morning, day, and night as a cat, clicking on different items and discovering what they can do with them. I decided to keep the interface very simple, since overcomplicating things would make it hard for me personally to produce a good interactive experience. Each part of the day has its own mini-game to complete in order to transition into the next part of the day. The user collects points for completing the mini games. You get 30 points in total. You can play the game again after finishing it.
  • Additional stuff: Initially, I wanted to draw all of the backdrops myself or create them using code, using simple shapes and colors. Then I remembered a game I always wanted to play called Animal Crossing, and wanted to create a similar atmosphere – cute and simple background decor. I wanted to use images from the internet, but none were “flat” enough for a backdrop, and I couldn’t insert my own images in there due to a lack of space. In the end, I decided to generate Animal Crossing and other cute mini-games-inspired backdrops, as well as all of the items that are needed to complete the game. I generated everything through ChatGPT image generation.

2. Code that I’m proud of and why

The part of my code that I am most proud of is the scene system and the way the game moves from one part of the day to another. I used different game states like the instruction screen, morning scene, day scene, night scene, and ending scene. This made the project feel real and interactive, as if it’s truly a cat that goes about its day. I am proud of this because it helped me organize the game clearly and made it easier to control what the user sees at each moment.

3. What I found challenging

The most challenging part for me was making the different scenes connect smoothly. At first, I struggled with where the player should go after each interaction. I had to think carefully about how to move from the instruction screen to the morning scene, then to mini-game scenes, then back again, and finally to the ending, without making it confusing for the user and me. This taught me that you need to have both the idea and the execution planned to detail before starting the process, because I had to redo a lot of stuff to create mini-game scenes in between the bigger scenes.

Midterm “Nebula Chase” Game – Kamila Dautkhan

Sketch

The Concept

I wanted to make something that felt exciting and had that arcade game tension where you’re always on edge. The idea came from thinking about those old falling-object games, but I wanted to add my own twist, for example, what if the game itself reacted to how much time you have left? What if it got harder as you played? And what if the music changed when things got intense? So Nebula Chase became this space game where you’re flying through a nebula collecting stars while dodging bombs. Simple concept, but I put a lot of work into making it feel engaging.

The Game in Action

Start Screen: 

When you first load the game, you see the title with this “CLICK TO START” button. I made the title bounce a little using a sine wave. And in order to make it easier for the user to understand the instructions of the game, they can press ‘I’ to see them. 

Gameplay:

Once you’re playing, the screen gets busy very fast. Yellow stars fall down, those are the good ones, and red bombs come at you too. Your ship follows your mouse, and you will have only 60 seconds to grab as many stars as possible without hitting bombs. The UI at the top shows your score, timer, and lives. I made the timer turn red and the whole screen flash when you’re under 10 seconds. 

Object-Oriented Design

I used three classes to organize everything:

  1. Star Class 
  2. class Star {
      constructor() {
        this.x = random(width);
        this.y = random(-600, -50);
        this.speed = random(2, 4) * difficulty;
        this.wobble = random(TWO_PI);
      }
      
      move() {
        this.y += this.speed;
        this.wobble += 0.05;
        if (this.y > height + 50) {
          this.y = -50;
          this.x = random(width);
        }
      }
      
      display() {
        push();
        translate(this.x + sin(this.wobble) * 10, this.y);
        tint(255, tintAmount, tintAmount);
        image(starImg, -20, -20);
        pop();
      }
    }
    

    Each star wobbles side to side as it falls which makes them really hard to catch. The speed multiplies by the difficulty variable, so as the game goes on, everything gets faster and it makes everything harder for the user. 

    1. Bomb Class – The obstacles
    class Bomb {
      constructor() {
        this.x = random(width);
        this.y = random(-600, -50);
        this.speed = random(3, 5) * difficulty;
        this.rotation = 0;
        this.pulsePhase = random(TWO_PI);
      }
      
      move() {
        this.y += this.speed;
        this.rotation += 0.05;
        this.pulsePhase += 0.1;
        if (this.y > height + 50) {
          this.y = -50;
          this.x = random(width);
        }
      }
      
      display() {
        push();
        translate(this.x, this.y);
        rotate(this.rotation);
        let pulseSize = 1 + sin(this.pulsePhase) * 0.15;
        scale(pulseSize);
        image(bombImg, -22, -22);
        pop();
      }
    }

    I made the bombs rotate and pulse to make them feel dangerous. They also move slightly faster than stars on average, which created the pressure for the player. 

  3. Particle Class
class Particle {
  constructor(x, y, col) {
    this.x = x;
    this.y = y;
    this.vx = random(-3, 3);
    this.vy = random(-3, 3);
    this.life = 255;
    this.col = col;
  }
  
  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.vy += 0.1;  // Gravity
    this.life -= 5;
  }
  
  display() {
    fill(red(this.col), green(this.col), blue(this.col), this.life);
    ellipse(this.x, this.y, this.size);
  }
}

Whenever you collect a star or hit a bomb, it creates approx 15 particles that spray out in random directions. They fade out over time and fall slightly from gravity. I made this just to make the interactions feel way more satisfying. 

The Spaceship:

I didn’t want to use basic shapes for everything, so I made custom graphics using p5’s createGraphics():

playerImg = createGraphics(60, 60);
// Outer glow
playerImg.fill(0, 255, 200, 100);
playerImg.triangle(30, 5, 10, 50, 50, 50);
// Main body
playerImg.fill(0, 255, 150);
playerImg.triangle(30, 10, 15, 45, 45, 45);
// Cockpit detail
playerImg.fill(100, 200, 255);
playerImg.ellipse(30, 25, 8, 12);

Since to come up with this code was very challenging for me, I used these resources to help me navigate:

https://www.deconbatch.com/2022/01/blendmode-add.html

https://www.youtube.com/watch?v=pNDc8KXWp9E

As you can see the stars and bombs have this glowing effects  because I drew multiple overlapping circles with decreasing opacity to create that glow. The stars are yellow or white and the bombs are red with a darker center that kind of looks like a skull.

The code I’m proud of:

It is definitely the sound system since I didn’t want to just upload the mp3 because I didn’t find the suitable one. So, I decided to generate it myself , that’s the reason why I spent a lot of time on it.

function updateBackgroundMusic() {
  if (timer > 10) {
    // Calm ambient music
    bgMusic.amp(0.15, 0.5);
    bgMusic.freq(220 + sin(frameCount * 0.02) * 20);
    bassLine.amp(0.1, 0.5);
    urgentMusic.amp(0, 0.5);
  } else {
    // DRAMATIC URGENT MUSIC FOR FINAL 10 SECONDS
    bgMusic.amp(0.05, 0.3);
    urgentMusic.amp(0.25, 0.3);
    urgentMusic.freq(110 + sin(frameCount * 0.1) * 30);
    bassLine.amp(0.2, 0.3);
  }
}

For most of the game you hear this calm wave that wavers slightly (that’s the sin(frameCount * 0.02) * 20 part, it creates a slow sound in pitch). There’s also a quiet bass line. But when you hit 10 seconds left the music completely changes.  The bass gets louder and the calm music fades. I just wanted to make feel the pressure for the user.

Reflection

I’m really happy with how this game turned out. The music transition at 10 seconds is probably my favorite part because it genuinely makes the game feel more intense and interesting. The particle effects were also surprisingly easy to implement but it added so much to the feel of the game. The biggest thing I learned was about game balance. It’s one thing to make mechanics work, but making them feel good for the user is way harder. I probably spent as much time tweaking numbers like how fast things fall and etc. as I did writing the actual code.

 



Midterm Project – SignSprint

Sign Sprint

Concept

SignSprint is a game based on computer vision that recognizes 7 different hand gestures which are Thumbs up, Thumbs down, Victory, Pointing Up, Victory, Closed Fist, I love you and Open Palm. The game works on a gesture recognition machine learning model by Google AI for Developers through MediaPipe Studio. The model can be tried out here.

The whole concept of the game is to make as many signs within a specified time period. An array of the possible hand gestures is created and one is randomly displayed at a time and the user is meant to make the hand gesture corresponding to the gesture being displayed. The score of the user is recorded and displayed at the end of the designated time period. The ML model uses measurements to accurately estimate a hand gesture and detect it. A validation condition is used to check if the detected gesture is exactly as the the target gesture and only then will the target gesture change. The model has also been set to detect one hand at a time so using multiple hands will cause the gesture not to be detected.

The main function sets up the machine learning model, detects gesture and randomly selects a target gesture

 

 

 

Code I am proud of

function drawGame() {
  background(0);
  image(video, 0, 0, width, height);
  
  // Timing game
  let elapsed = (millis() - startTime)/1000;
  if (elapsed >= gameTime) {
    gamestate = "end";
    }
  
  // Gesture detected & scoring
  let detectedName;
  let detectedEmoji;
  
  if (results && results.gestures && results.gestures.length > 0) {
    detectedName = results.gestures[0][0].categoryName;
    detectedEmoji = gestureMap[detectedName];
    
    if (targetGesture.name == detectedName && !matchCooldown) {
      score++;
      // sound for feedback
      matchCooldown = true;
      correct.play();
      pickNewTarget();
      }
    }
  
  // Target Emoji
  if (targetGesture) {
    textFont("OpenSans");
    textAlign(CENTER, TOP);
    textSize(70);
    text(targetGesture.emoji, width/2, 30);
  }
  
  // Score
  textFont(font);
  fill(255);
  textAlign(RIGHT, TOP);
  textSize(30);
  textFont("OpenSans")
  text("⭐", width-55, height-45);
  textFont(font);
  text(score, width-20, height-45);
  
  // Time remaining
  textSize(40);
  text(ceil(gameTime-elapsed), width-20, 20)  
}

The code I am proud of is the drawGame function. This is the function that contains the bulk of the game mechanism. It first shows the camera output of the the program, shows the target gesture as an emoji, detects the gesture of the player through the camera and checks if it is the same as the required gesture. If the detected and target emojis are the same, it increases the score and creates a new target. The function also displays the time left and the current score on the screen. Finally the function has a condition that automatically switches the game to the end screen when the specified time is elapsed.

How it was made

The game mainly runs on the the hand gesture machine learning model which was stated above. The biggest challenge in making this game was importing the gesture recognition model in p5js. I used cluade AI to help in this process. With the help of AI, I was able to modify the html file and create functions in order to import the right model into the p5js file which enables us to run the game. Claude AI was also used in the making of the setupMediaPipe and detectGesture() function to enable the game run the scoring system.

The game code was mostly composed of if conditions and booleans for the game logic. The start and end screen background was fully generated by Gemini AI and the sounds for the game, which are the theme sound and the correct matching sound were obtained from Freesound.

Reflection

This was a really fun game to create. I got to explore all the concepts deal with class and I got a greater understanding of decisions structures and also learn how import models into p5js. A possible improvement in the increasing the number of hands that can be in the game and the hand gesture can be further developed to remotely control other computer devices to generate art and just express creativity. I see this project as stepping stone to explore my interest in computer vision and its possible application in interactive media and I am excited to see how I can blend this knowledge and skill with physical computing.