Week 6 – Midterm Memory Box

Link to sketch: https://editor.p5js.org/ojmjunming/full/W-301y_lp 

Concept

I wanted to create an installation-type piece, something that you leave in a gallery or in some space and let users naturally interact with the piece. The idea behind my project is based off a thought I had a few weeks ago. I thought that despite all the new memories I make, I find myself forgetting things and people in my past who were once dear to me. This project is my take on trying to convey that feeling — the idea of losing memories for every new ones you gain.

How it Works

The screen prompts the user from a list of pre-determined questions and the viewer is encouraged to type a short response to it. When they press ‘Enter’, a photo will be taken of the viewer the viewer’s response and photograph will be inserted into the ‘Memory Box’, while an older memory is removed.

I also try to convey a feeling of fleetingness by making the title and question text look wobbly/jittery. The text doesn’t feel static and feels a little uncertain as they do not stay in one place, which I thought helps sell a feeling of dreamy-ness. The text input is also accentuated by the sounds of a typewriter, which I use to help create an atmosphere of retro-ness and nostalgia.

Technical Parts I’m Proud Of

class WobblyText {
  constructor(message, x, y, size = TEXT_SIZE) {
    this.letters = []
    this.size = size
    this.message = message
    this.x = x
    this.y = y
    
    let curString = '';
    for (let i = 0; i < message.length; i++) {
      let curLetter = message[i]
      this.letters.push(new Letter(curLetter, this.x + textWidth(curString) * 1.2, this.y, this.size))
      curString += curLetter
      
    }
  }
  
  render() {
    for (let letter of this.letters) {
      letter.render()
    }
  }
}
         
class Letter {
  constructor(letter, x, y, size = 16) {
    this.letter = letter
    this.size = size
    this.originX = x
    this.originY = y
    this.offsetX = 0
    this.offsetY = 0
    this.maxOffset = 2 + (size / 12)

    this.noiseX = random(10000)
    this.noiseY = random(10000)
  }
  
  render() {
    push()
    textSize(this.size)
    text(this.letter, this.originX + this.offsetX, this.originY + this.offsetY)
    pop()
    
    this.offsetX = (noise(this.noiseX) - 0.5) * 2 * this.maxOffset
    this.offsetY = (noise(this.noiseY) - 0.5) * 2 * this.maxOffset
    this.noiseX += 0.01;
    this.noiseY += 0.01;
  }
}

I’m really proud of the wobbly/jittery text as I feel that it helps add to the emotional feeling of the project. It was a little harder to achieve than I thought, as I had to manually create every letter of the text so I created two classes to help me achieve this effect without having to manually draw each of the letters. I maintain a separate state for each letter, so each letter moves independently of the other letters ( though within a certain bounds of it’s starting point ).

Things to improve

I left out the instructions for pressing ‘Enter’ as I assumed that it’s something that most viewers will know how to do, but I’m not sure if thats a good decision I’ve made and I wish I had more time to test my project with other people to see if there are any improvements I could’ve made on the UI/UX. I would’ve also liked to improve the animations for removing/creating a new memory, as right now there is only a simple fade out animation. A more dreamy animation for inserting the new memories would’ve been nice.

Midterm Project

Link to the Sketch: https://editor.p5js.org/be2143/full/wxUp4YLBf

Concept

“The Brain Game” is a game designed to challenge the user to complete 3 levels. Initially, my idea was to implement only “The 5 Hats to 3 Men Problem.” However, I later changed the concept to make it more engaging. One alternative idea I had was presenting the challenge in a storytelling format. Eventually, I drew inspiration from the “Brain Challenge” mobile game and developed the current game concept.

Key elements

Level 1: Reach the Exit

 

In level 1, the user’s task is to guide the character to the exit using arrow keys. To reach the exit, the player must first collect a key to clear the path. Once the player reaches the exit, the game proceeds to the next level.

 

Level 2: Odd One Out

The player is presented with an image and must identify what’s unusual. A cursor circle outlines the cursor, and the player must position it over the odd item and click. If the player makes two incorrect selections, a “hint” appears. Once the player correctly identifies the odd item, the game proceeds to the next level.

Level 3: Solve a Riddle

This level presents “The 5 Hats to 3 Men Problem,” challenging the player’s logical thinking skills. Three characters and five hats (three black and two white) are involved. The three hats are randomly assigned to each character. Given the ability to see the hats of the other two characters and the answer they have given, the player’s task is to guess the color of their own hat. An incorrect guess results in the level restarting, while a correct guess ends the game.

 

You can read more about the problem here: https://www.pumpfundamentals.com/The%205%20hats%20to%203%20men%20problem%20solution.pdf 

 

Design

I have intentionally provided instructions for each level before they begin to enhance player engagement and understanding.

Sound effects have been included throughout the game to enhance the user experience and provide feedback. For instance, an incorrect choice triggers a specific sound effect to signal that the player should try again.

A “home” button allows the player to restart the game without resetting the entire session.

I asked two of my friends to play my game to understand: what’s confusing for the user and to spot the areas to improve in the game. Based on their feedback, I added a hint feature for Level 2 to assist players in spotting the odd item. Additionally, in Level 3, I implemented a feature where the cursor touching a hat changes the background color around the image to clarify how to make a guess.

Problems I ran into

The most challenging part of this project was adapting “The 5 Hats to 3 Men Problem” into a playable game. To ensure solvability, I created specific hat combinations for the three characters, limiting the possibilities to wwb, wbb, and bwb (w = white; b = black). And it is not a random selection of combinations which limits the problem setting. I chose this combination based on the problem setting that the other two characters have already answered that they don’t know the color of their hat color. So that we should eliminate the combinations in which those two characters will be able to make the guess. 

let blackHatImg, whiteHatImg, greyHatImg;
let hats = [[1, 0, 1], [0, 1, 1], [0, 0, 1]]; // 1 for black, 0 for white
let randomHatSet;
let characters = 3;

// randomly choose hat set
  randomHatSet = floor(random(3));
function playPuzzle() {
  if (puzzleImgIndex < puzzleImg.length) {
    image(puzzleImg[puzzleImgIndex], 0, 0, width, height);
  }

  // Calculate the available width for the rectangles (canvas width minus margins)
  let availableWidth = width - 60; // 30 pixels from the left and 30 pixels from the right

  // Calculate the width of each section for three hats
  let sectionWidth = availableWidth / 3;

  // Draw the hats
  for (let i = 0; i < characters; i++) {
    // Calculate the x-coordinate for each hat based on the section
    let x = 30 + (i * sectionWidth) + sectionWidth / 2;
    let y = height / 4;

    // Draw the assigned hat images
    if (hats[randomHatSet][i] === 1) {
      image(blackHatImg, x - 45, y + 30, 90, 45);
    } else if (hats[randomHatSet][i] === 0) {
      image(whiteHatImg, x - 45, y + 30, 90, 45);
    }
  }
  // Draw a mystery hat on top of the hat of the user
  image(greyHatImg, (30 + (2 * sectionWidth) + sectionWidth / 2) - 45, (height / 4) + 30, 90, 45);
  
  // Choose from the black or white hat
  
  if (puzzleImgIndex === 1) {
    if (mouseX > blackHatGuess.x && mouseX < blackHatGuess.x + blackHatGuess.w && mouseY > blackHatGuess.y && mouseY < blackHatGuess.y + blackHatGuess.h) {
      // Change the color when the cursor is inside
      noStroke();
      fill('#FFB8CD');
      rect(blackHatGuess.x - 2, blackHatGuess.y - 2, blackHatGuess.w + 4, blackHatGuess.h + 4);
    } else if (mouseX > whiteHatGuess.x && mouseX < whiteHatGuess.x + whiteHatGuess.w && mouseY > whiteHatGuess.y && mouseY < whiteHatGuess.y + whiteHatGuess.h) {
      // Change the color when the cursor is inside
      noStroke();
      fill('#FFB8CD');
      rect(whiteHatGuess.x - 2, whiteHatGuess.y - 2, whiteHatGuess.w + 4, whiteHatGuess.h + 4);
    }
    // Draw a rect around the hat choices
    image(blackHatImg, blackHatGuess.x, blackHatGuess.y, blackHatGuess.w, blackHatGuess.h);
    image(whiteHatImg, whiteHatGuess.x, whiteHatGuess.y, whiteHatGuess.w, whiteHatGuess.h);
  }
}

function makeGuess(mouseX, mouseY) {
  if (mouseX > blackHatGuess.x && mouseX < blackHatGuess.x + blackHatGuess.w &&
      mouseY > blackHatGuess.y && mouseY < blackHatGuess.y + blackHatGuess.h) {
    pauseAndResumeDraw();
    levelCompleteSound.play();
    gameState = 'end';
  } else {
    pauseAndResumeDraw();
    // restart level 3
    wrongChoiceSound.play();
    restartPuzzle();
  }
}

Areas for improvement

If I had more time, I would implement additional features, such as allowing players to skip levels or revisit previous levels. I also observed that players tend to forget the challenge scenario in Level 3 thus it  would be better to enable players to revisit instructions for clarification.

Despite my overall satisfaction with the game, I could have enhanced the game’s visual appeal by investing in more attractive graphics, animations, and a user-friendly interface design. For my future projects, I will certainly prioritize the overall graphic design, its aesthetics, and user coherence.

Week 6 – Midterm Project

DiDesign – create your room design

Link to my sketchhttps://editor.p5js.org/Diannella/full/BCjYoXQdw

My Concept: “DiDesign” is a realization of my childhood dreams. As a child, I wanted to become an interior designer and was always interested in choosing and drawing the pieces of furniture and allocating them inside the room. Being inspired by the “coffee shop” game shown during the class, I also wanted to produce a calming experience with aesthetic images and pleasing sounds. The users have a chance to feel themselves as interior designers and even get imaginary payment for that. 

The explanation of how the project works: The rules of the game are simple. The game starts with the instructions section, where the character asks the user to design the room for the client and gives instructions on how to play the game. The users click on the “PLAY” button, which leads them to the room with the default most simple design. The users should click on each of the pieces of furniture and choose their favorite one from the array of six options. The users can change the sofa, the decors on the left and right sides of the sofa, and the lamp. In addition to that, the users can click on the character on the left side, who will give comments about the design process. When the users are done with the design, they can click on the button “SELL” to sell their designs to the client. This would lead to the last section, which shows the payment amount for the project. This amount is randomly chosen from the range of $2000 to $20000. If the users want to create another design, they can click on the button “RESTART” which would restart the game with the instructions section, followed by the default furniture.

The examples of the each image of sofa created by me on Canva

The areas I am proud of: Overall, I am proud of the project because the reality met my expectations of the project by around 90% and, most importantly, I have seen a huge development since the beginning of the semester. Firstly, I am very proud of the aesthetics of the game because I believe that the colors, shapes, allocation, the chosen pieces of furniture, and the sound effects are chosen great so that the users have an enjoyable experience of playing this game. Secondly, I am proud of the process of creating this game. Specifically, other than coding, the project includes the work on the design of each of the pieces of furniture. I selected each piece of an image and constructed the whole image of the room in the canvas to make sure that they looked great with each other resized every image to match the dimensions and downloaded every piece separately. Last but not least, I am most proud of the code with the mouseClicked function. It includes every conditional of the game, operating the change of each furniture and dialogue box, as well as the change over the stages with the resetting of the game and random payment. 

function mouseClicked() {
  clicking.play (); //every click is accompanied with clicking sound
// everything inside this conditional happens only in the playing state, which is the state inside the room
  if (gameState == 'playing') {
//if the mouse is clicked inside the area of piece of furniture, the next image is shown from the array of that piece of furniture
    if (mouseX >= width / 2 - sofas[0].width / 2 &&
        mouseX <= width / 2 - sofas[0].width / 2 + sofas[0].width &&
        mouseY >= height * 0.5 &&
        mouseY <= height * 0.5 + sofas[0].height) {
      currentSofa++;
      if (currentSofa >= sofas.length) {
        currentSofa = 0;
      }
}
//there are four more similar conditionals to manipulate the array of the left decor, right decor, lamp and the dialogue bubbles
  }
//one button is responsible for changing the game states. Every time the rectangle is clicked, the state of the game changes.
   if (mouseX >= width * 0.8 &&
      mouseX <= width * 0.9  &&
      mouseY >= height * 0.8 &&
      mouseY <= height * 0.9) {
    if (gameState == 'start') {
    gameState = 'playing';
    stopPayment() ; //random payment amount is generated every time the game starts
    } else if (gameState == 'playing') {
    gameState = 'end';
  } else if (gameState == 'end') {
//the design is returned back to default design of interior, which is the image in the first position of each array of images.
    currentSofa = 0;
    currentLeftDecor = 0;
    currentRightDecor = 0;
    currentLamp = 0;
    currentBubble = 0;
    restartGame();
  } 
}
    return false;
}

Areas for improvement: 

Initially, I also had an additional idea of adding the character from the sprite sheet, which could be controlled by the user. By pressing the arrow buttons, it would be possible to move that character inside the room. However, the issue was that I simply couldn’t find the sprite sheets of the character, which would match the vibe of the game. Most of the characters are made for arcade games with the jumping and falling images of little cartoon-looking characters. As there was no image that would match the style, I was thinking of drawing that character. Because of the time restrictions, the image of the girl was inserted, which talks when gets clicked by the user, but doesn’t move. As it doesn’t fully replace the initial idea, the drawing of own sprite sheet of the character would be a good improvement of the game for the future. 

Furthermore, the array of images I found might not be enough as well as the number of pieces that can be changed. In the future, room decor can be developed into house decor, so the users would have a chance to decorate every room in the house such as the bathroom, bedroom, kitchen, and living room. Each of the rooms would have at least ten changeable pieces of furniture with at least 10 options in each. This would expand the project and make it more interesting for older people because for now, only children would be engaged with the game. 

The resolved problem:

  1. I had an issue with the change of the pieces of furniture because the new image was added on top of the previous image, instead of replacing that. It was solved by adding the background image and the current image of the piece of furniture in every frame, so the old pieces of furniture would be covered by the background image and the new piece of furniture. I was not using this way initially because I thought that would lead to the freezing issues of p5.js, but everything works well with this strategy. 
  2. I had an issue that the game doesn’t go to the default design every time I restart the game, but stays in the last chosen images of the furniture. The solution was very obvious and was solved by explaining the steps of refreshing the game. I simply forgot to specify in the conditional that each element in the arrays should be in the first position, which is the default image. 

The unresolved problem: 

  1. I had a huge issue with the hover of the images, so when the mouse is on top of the image, that image would be colored white. This actually worked with single images, but couldn’t be applied to each of the images as a class. Just a hover for one image took almost 100 lines and just copy-pasting that code to each image wouldn’t be effective. The idea of using that in the class was not very successful. Because of this, I still should work on this and find a better solution. 

Reference List:

The website used for the images: canva

Sound used: 

Modern technology select. Source: https://mixkit.co/free-sound-effects/click/?page=2 

Simple Piano Melody by Daddy_s_Music. Source: https://pixabay.com/music/search/?order=ec&pagi=6 

Week 6 – Midterm Project!

Concept

As we approach the festive months of the year, all I can think about is winter break, my favorite holiday. The warmth, comfort, excitement, and simple joys that this season brings are what I eagerly anticipate for months. When considering ideas for this open-ended and creative project, I wondered if there were others like me who simply can’t wait for the Christmas season and New Year. Thus, I decided to create an Early Christmas Experience as an ode to one of my favorite festivals. The candy canes from school, the joy of exchanging gifts during Secret Santa, and the delight of decorating the Christmas tree are just a few things that make this season special, and I aimed to incorporate them into my project. From the reading ‘Making Art is like setting a trap’, my takeaways were to focus on and convey the simpler things and the feelings behind it

My project aimed to encapsulate the essence of Christmas, focusing on two central elements: decorating a Christmas tree and the excitement of hunting for hidden presents around a cozy house—both cherished traditions in my family. Having spent my entire life in a region where snowfalls are rare, I yearn for snowy vacations. For this project, I wanted to create a visually captivating experience, making it heavily reliant on graphics rather than physical and mechanical elements.

How It Works:

The experience begins with a screen featuring a play button. Upon clicking this button, users are transported to the experience screen—the screen of magic. Santa himself makes an appearance, offering brief instructions on how to navigate the experience. Users can click on the Christmas tree and decorate it by dragging and dropping ornaments. These decorations are saved for later viewing. Clicking on the house triggers a mini Christmas-themed hidden object game. The objective is to find a minimum of 5 presents to win. Throughout the experience, a snowy backdrop adds to the festive atmosphere, and users can navigate through the various parts of the experience using marked buttons in the form of presents with a carol playing in the background and end with a real – time countdown to Christmas.

 View directly in the editor for sound , re run and let Santa guide you further! https://editor.p5js.org/keyaa/full/lvw7KccaA 

Technical Parts I’m Proud Of

The Christmas tree was a major highlight of my project. While the drag-and-drop functionality for ornaments was easy with the reference shared in class, a significant challenge was saving the positions of these ornaments and placing them exactly on the experience screen tree as the user had arranged them on the tree screen. After multiple experiments with vectors in p5.js and other coordinate system functions, I chose to calculate the relative positions of X and Y coordinates of the ornaments and confirm if they were correctly placed on the tree. To add a more realistic touch, I included a layer of snow with gradually decreasing velocity, simulating the accumulation of snow on the tree. This was a personal favorite effect that enhanced the overall experience.

if (decorated == true) {
   for (let draggableObject of draggableObjects) {
     if (draggableObject.onTree) {
       draggableObject.x = draggableObject.relativeX + treeX;
       draggableObject.y = draggableObject.relativeY + treeY;
       draggableObject.show();
     }
   }
 }

 // Check if snowflakes2 touch the tree
 for (let snowflake of snowflakes2) {
   const distanceToTreeCenter = dist(snowflake.x, snowflake.y, treeX + christmasTree.width / 2, treeY + christmasTree.height / 2);
   if (distanceToTreeCenter < 70) {
     snowflake.speed = 0;
   }
   snowflake.update();
   snowflake.display();
 }

The typewriter effect for Santa’s words:

typewriterEffect() {
  if (this.index < this.message.length) {
    this.displayedMessage += this.message[this.index];
    this.index++;
  }
}

The usage of OOP and arrays is at the core of this project. It simplified tasks and made the project more organized. Creating Santa’s movement using sprites was a more significant challenge than anticipated. To enhance the visual appeal, I incorporated images from Shutterstock and designed some of my own using PicMonkey and Canva, opting for efficiency over drawing everything directly in p5.js.

Areas for Improvement

While I’m pleased with the project’s overall outcome, there are many other areas that I can improve and add to. Adding more challenging elements to the hidden objects game, such as a timer, or refining Santa’s movement for smoother animation, could make the project better.

In conclusion, creating this Christmas-themed interactive project for my midterm assignment was a delightful experience. I tried to work more on my creative skills instead of just coding like I would for other classes. I tried to incorporate most of the concepts learnt over the past few weeks and am already excited to see what the second half of the semester in this class holds for me to learn!

References

https://www.shutterstock.com/image-vector/bright-new-year-santa-claus-2d-1563199690, https://www.youtube.com/watch?v=bKEaK7WNLzM, https://www.youtube.com/watch?v=3noMeuufLZY, https://editor.p5js.org/codingtrain/sketches/U0R5B6Z88 

Week 6: Midterm Project

For my midterm project, I decided to change  my initial idea and created a unique card matching game “Paws and Puzzles”. The game revolves around Simba (named after my own dog<3), a lovable dog who has scattered his toys in the park and needs players’ assistance to match these toys through a card game. The objective is to pair up cards that represent Simba’s toys, including items like balls, a rubber duck, a squeaky chicken and more. The twist is that players must complete the matching within 30 attempts; otherwise, Simba becomes sad, leading to a game over scenario. Paws and Puzzles is not just about matching; it’s wrapped in a delightful storyline, making it engaging and fun.

Here are a few images of the cards I designed:

Card 1
Card 2
Card 3

 

How It Works:

In “Paws and Puzzles,” the game’s core mechanics involve flipping and matching cards. It starts with a visually appealing menu page, and players can choose between starting the game or viewing instructions. There’s also a win condition, and the restart functionality is in place, enhancing the overall user experience. Additionally, the integration of audio elements specific to each scene complements the game, making it more engaging for players.

What I’m particularly proud of is the game’s visual design, which includes amusing captions for the cards, adding an enjoyable element to the gameplay. I’m especially happy with the mousePressed function and the card-matching logic in my code. It did take some time, but I got them working just the way I wanted.

function mousePressed() {
   if (!gameStarted) {
    if (instructionMode) {
      // Clicked on "Start Game" button on instructions page
      const startGameButtonX = 31;  
      const startGameButtonY = 598; 
      const buttonWidth = 150;
      const buttonHeight = 50;
      
      if (mouseX > startGameButtonX && mouseX < startGameButtonX + buttonWidth && mouseY > startGameButtonY && mouseY < startGameButtonY + buttonHeight) {
        gameStarted = true;
        initializeCards();
      }
    }else {
      const startButtonX = 222;
      const startButtonY = 235;
      const buttonWidth = 150;
      const buttonHeight = 50;

      if (mouseX > startButtonX && mouseX < startButtonX + buttonWidth && mouseY > startButtonY && mouseY < startButtonY + buttonHeight) {
        //clicked on start game button
        gameStarted = true;
        initializeCards();
      } else if (mouseX > startButtonX && mouseX < startButtonX + buttonWidth && mouseY > startButtonY + buttonHeight + 20 && mouseY < startButtonY + buttonHeight + 20 + buttonHeight) {
        //clicked on instructions button
        instructionMode = !instructionMode;
      }
    }
  } else {
    for (let card of cards) {
      if (card.contains(mouseX, mouseY) && !card.isFlipped() && flippedCards.length < 2) {
        card.setFlipped(true);
        flippedCards.push(card);
        audioCard.play();

        if (flippedCards.length === 2) {
          tries++; //increment the tries
          if (millis() - startTime >= flipDelay) {
            checkMatch();
            startTime = millis(); //reset the timer
          }
        }
      }
    }

    //restart button click on game win
     if (gameWon && mouseX >= 210 && mouseX <= 420 && mouseY >= 297 && mouseY <= 347) {
      restartGame();
    }

    //restart button click on the loss
    if (tries > 30 && mouseX >= width / 2 - 75 && mouseX <= width / 2 + 75 && mouseY >= height - 100 && mouseY <= height - 50) {
      restartGame();
    }
  }
}




function checkMatch() {
  //check if flipped cards match
  if (flippedCards.length === 2) {
    if (flippedCards[0].getValue() === flippedCards[1].getValue()) {
      score++;
      flippedCards = [];
    } else {
      //not a match, unflip the cards after a delay
      setTimeout(function () {
        flippedCards[0].setFlipped(false);
        flippedCards[1].setFlipped(false);
        flippedCards = [];
      }, flipDelay);
    }

    //checking win condition
    if (score === cards.length / 2) {
      gameWon = true;
      audioGame.stop(); 
      audioWin.play();
     
      //lose game if more than 30 tries
    } else if (tries > 30) {
      
      gameWon = false;
      audioGame.stop();
      audioLose.loop();
     
    }
  }
}

 

Challenges Faced and Areas for Improvement:

I encountered some challenges, notably a performance issue on the Safari browser. Although I tried various online solutions, none seemed to work, and I eventually opted to playing the game on Chrome for better performance. An area for improvement is adding more levels to the game to increase the difficulty and provide players with a sense of progression. And, of course, there were a couple of bugs that I had to wrestle with – but that’s all part of the coding “fun”, right? Creating this game was a lot of fun, and I hope that people enjoy playing it just as much:)

Week 6: Midterm Project

Concept:

Anyone who knows me knows that I love baking and cooking. Being in the kitchen and creating something from scratch is such an amazing experience for me. Even though some people may argue that being in the kitchen is actually stressful, I don’t see it that way. It disconnects me from all the stress and anxiety of the outside world for a while and leaves me feeling relaxed. So for my midterm project, I wanted to create a kitchen simulation to let others feel a semblance of the calmness and joy I get when in the kitchen. 

My program is so easy to navigate. At first, the user is prompted to choose one of three recipes, Chocolate Cupcakes, Spaghetti and Meatballs or Avocado salad. After clicking on a recipe, the program takes the user through a few steps to prepare the recipe they chose. The user has to follow all the instructions to successfully deliver the recipe or else they fail and have to start over. After completing a recipe, the user is given two options, to follow a link with the actual recipe, if they want to try it in real life, or to go back to the homepage to start a new recipe. The program also allows users to return to the home page at any given time by pressing esc on the keyboard. I tried to make the program as fun and as engaging as possible. Additionally, I chose a calm music track for the background to add an extra level of tranquility as well as a soft palette of colors to maintain the overall theme of the program which is calming and relaxing.

*open in a new window to hear the music

How it works:

I created my program by creating a function for each screen and calling these functions at the necessary time. I created a list to store the ingredients that are being displayed on the screen and used OOP to define an ingredient class that handles the display and hide-when-clicked methods. I used clip art images for all the icons and pictures included in the program and sized them as necessary to fit the way I want them to. Additionally, I linked a font file to define the font I wanted to use. I chose this font because it looks cute and cartoon-ish even, which makes the program look more fun and gives it an element of style that my program would lack if I had used a standard font.

I included dynamic features where possible and tried to make the motion randomized instead of defined (the dressing drops, the home page animation and the smoke). I handled all the transitions using the mouseClicked() function to determine which screens are displayed when and after which conditions are met. I tried to make my code as modifiable as possible, that is making it easy to add more screens, more ingredients, more functionalities, even more recipes if needed, by using encapsulation and modularity. I found that compressing the functions in p5js made it easier and clearer for me to navigate through the code. 

For the smoke screens, I included an internal timer in my code that records the start time and the current time and compares them till the required time has elapsed and then if no action was taken then the smoke screen is displayed. I tried severaltimesto create it with a different logic but it did not work and I found this to be the most appropriate to use in my code.

if (screen === 3) { //screen is the cupcake oven screen
   CupcakeOven();
   currentTime = millis();
   if (currentTime - startTime > cupcakeinterval) { //count the seconds elapsed and //compare it to the allowed interval, if it is greater than the time allowed, //cupcakes burnt so go to smoke screen
      screen = 5; //go to the cupcake smoke screen
   }
}

 

Problems faced:

The main problem I faced in the beginning was the transitions. I had all the screens defined and working perfectly, but I could not get them to link together properly without facing so many bugs. I tried so many different ways to get them to call each other from within the functions itself, but I would get stuck on one single screen forever. I tried to link them using mouseButton, it worked partially but I faced so many problems with the ingredients when I implemented it. When I finally decided to use mouseClicked(), I tried to call the functions from within and use if functions to identify when and which screen is needed to be called, but I also faced errors 🙁  It was after a lot of trial and error that I realized having a screen variable that is controlled through the mouseClicked() and then having draw() call the screen functions is the way to go. 

Another major problem I faced was implementing the ingredients objects and how to make them disappear when clicked and how to link the screen transitions with the ingredients. At first it was mostly trial and error, but then I decided to take a step back and understand every little detail related to how I am implementing them and come up with a solution that works on paper and then implement it step by step. I am proud of the way I got it to work in the end because it just makes sense to me and makes the whole process smooth and straightforward as well as easy to add/remove/modify the ingredients as needed. It is also worth noting that I originally wanted to implement a drag and drop feature for the ingredients but it was too complicated to use within my program especially that I wanted to use resized images for the ingredients so I settled on mouse clicks instead.

Last but not least, I faced problems with implementing the smoke screens and how to make them appear automatically after the time elapses. It was a bit confusing for me at first to implement it, it never worked at all to the point where I decided to completely disregard the idea of smoke screens, but I managed to get it working in the end. I wanted to add a timer functionality where it displayed the timer on screen so that the user can visually see how much time they have left, but it created so many bugs and did not work effectively, even though it is a straight forward feature, it clashed with my other functionalities, so i decided that the users can count to 5 or 7 themselves.

Future improvements and reflection:

I would love to add more features to make the program more advanced like adding mixing and frosting stages for the cupcakes and adding a stirring stage for the spaghetti as well as some steam while it is cooking. I would also love to add more choices within the recipes so that users can choose what dressing they want for the salad for example. I am overall satisfied with what I have now and I am proud that I got my program to look like what I had initially planned for it.

References:

images:

https://www.clipartmax.com/

https://www.freepik.com/

https://www.vecteezy.com/vector-art/11234689-cocoa-sack-with-seeds

recipes:

https://sallysbakingaddiction.com/super-moist-chocolate-cupcakes/

https://www.onceuponachef.com/recipes/spaghetti-and-meatballs.html

https://www.onceuponachef.com/recipes/summer-avocado-salad.html

music:

https://www.ashamaluevmusic.com/cooking-music

Font:

https://textfonts.net/one-little-font.html#google_vignette

midterm project

Introduction

For my midterm project, I created a spooky juggling game called Morbid Juggler. I thought of the concept in week 2, and for the project involving arrays and classes I made a simple game that lets users add balls using the keyboard and juggle them using the cursor. Morbid Juggler version 2 is built on top of the same motion logic, but instead of using standard input (mouse and keyboard), players have to use their webcam and their hands to interact with the game. To add a new ball, the user makes the “🤘” gesture with their left hand. The balls automatically move in a parabolic trajectory, and the goal of the game is to not drop the balls, i.e. catch them before they leave the screen. To catch a ball, users can use any hand and pinch their fingers and drag a ball across the screen. To throw the ball again, they just have to release the pinch.

How it works

The following explains the balls’ motion and is from my documentation for my week 2 project:

I save the initial time when an (eye)ball is created, and measure the time that has passed since. This allows me to use values of elapsedTime as a set of x values, which, when plugged into a quadratic equation, give a parabola. Changing the coefficients in the equation allows me to modify the shape of the parabola and thus the trajectory of the (eye)ball, such as how wide the arc created by its motion is. I played around with the coefficients and decided to use (0.4x)(2-x), which works nicely for a canvas of this size.

A more detailed explanation of how the balls are stored in memory and moved with each frame update can be found here.

For tracking hands using the webcam, I used a Javascript library called Handsfree.js. I was initially going to use PoseNet, but I realized it wasn’t the best for this use case. PoseNet’s landmark model tracks 17 points on the human body, but for my game, I didn’t need all that. I just needed to track the user’s fingers, and PoseNet only returns one keypoint for the user’s wrist. So, I looked up other libraries and found Handsfree.js, which is built on the same framework, Google’s Mediapipe, as PoseNet, but it is more geared towards hand tracking. It tracks all fingers and knuckles and even has built in gesture recognition to detect pinches, which is what my users would need to do to drag balls around the screen. Furthermore, it was very easy to train the model to recognize new gestures using the website. It lets you collect your own data and create a gesture model to plug into your code. For example, this is the code for recognizing the “🤘” gesture.

handsfree.useGesture({
    name: "addBall",
    algorithm: "fingerpose",
    models: "hands",
    confidence: "9",
    description: [
      ["addCurl", "Thumb", "HalfCurl", 1],
      ["addDirection", "Thumb", "DiagonalUpRight", 1],
      ["addDirection", "Thumb", "VerticalUp", 0.19047619047619047],
      ["addCurl", "Index", "NoCurl", 1],
      ["addDirection", "Index", "VerticalUp", 0.3888888888888889],
      ["addDirection", "Index", "DiagonalUpLeft", 1],
      ["addCurl", "Middle", "FullCurl", 1],
      ["addDirection", "Middle", "VerticalUp", 1],
      ["addDirection", "Middle", "DiagonalUpLeft", 0.47058823529411764],
      ["addCurl", "Ring", "FullCurl", 1],
      ["addDirection", "Ring", "VerticalUp", 1],
      ["addDirection", "Ring", "DiagonalUpRight", 0.041666666666666664],
      ["addCurl", "Pinky", "NoCurl", 1],
      ["addDirection", "Pinky", "DiagonalUpRight", 1],
      ["addDirection", "Pinky", "VerticalUp", 0.9230769230769231],
    ],
  });

Then I can use this information like so:

function addBall() {
  const hands = handsfree.data?.hands;
  if (hands?.gesture) {
    if (hands.gesture[0]?.name == "addBall") {
      let x = sketch.width - hands.landmarks[0][9].x * sketch.width;
      let y = hands.landmarks[0][9].y * sketch.height;
      console.log(x, y);
      balls.push(new Ball(x, y));
      canAddBall = false;
      // go to sleep for a second
      setTimeout(() => {
        canAddBall = true;
      }, 1000);
    }
  }
}

The hardest part of this project was working with Handsfree.js. There is criminally limited documentation available on the website, and I had to teach myself how to use it by looking at the few demo projects the author of the library had created. For hand tracking, there was a piece of code that closely approximated what I wanted to do. It loops through the hands in the object returned by handsfree.data, and for each hand, it loops through all the fingers. Each finger can be identified using its landmark, and its location and other information can be used elsewhere in the program. For example, in handsfree.data.landmarks[handIndex][fingertips[finger]], handIndex=0 and finger=8 represents the tip of the left index finger. In Morbid Juggler, when handsfree.data.pinchState for any hand or finger becomes held near a ball, the ball sticks to the tip of the pointer finger. When it becomes released, the ball restarts its parabolic motion.

To see the full code for the project, refer to the p5 web editor.

Playing the game

The game can be played here. When the project has loaded, click on ‘start game’. It takes a second for Handsfree to load. You can check if the game is fully loaded by waving your hands in front of your webcam. You should see the skeleton for your hand mapped on the canvas.

Make a “🤘” sign with your left hand (tuck in your thumb, and make your index and pinky straight!). You’ll see a new ball pop from between your fingers. Add a few more balls like this, but be quick! Don’t let them leave the screen, or the counter in the corner of the screen will tell you how badly you’re losing even after death. To keep the balls from falling off, pinch your fingers like you would pick up a real juggling ball, drag the ball you’re holding across the screen, and release your fingers somewhere near the bottom left corner of the screen, so the ball can travel again. You can add as many balls as you like — at your own risk.

Final thoughts

I think there’s still room to fine tune the hand tracking. If I were to upgrade the game, I would probably use a different library than Handsfree.js. The tracking information isn’t the most accurate, and neither is it consistent. For example, even when a hand is being held up still, the keypoints on screen are seen to jitter. Since during dragging, the balls stick to the tip of the pointer finger, the balls were jittering badly too. I later added some smoothing using the lerp() function to fix that. I also had to do a lot of trial and error when picking a gesture that would trigger the function to add a new ball. The model wasn’t very confident about a lot of the other gestures, and kept adding balls erroneously. The “🤘” sign was the final choice because it was explicit enough and did not resemble other gestures a user might inadvertently make while playing the game.

One thing worth special mention is the background music used in the game, which was produced by my friend by sampling my other friend’s vocals. I heard the track and liked the spooky yet playful feel to it and asked if I could use it in my project. My friend agreed, and now I have a bespoke, perfectly fitting music to accompany my project.

Week 5 – Midterm

Concept

“Remy the Rat” is a dark visual novel about a comical and relatable experience related to pets. It tells the story of a teenager that forgets to feed his brother’s rat, and his attempt in solving the issue.

Elements

All of the background drawings were made by me on Paint. They are extremely minimalistic, almost like they could have been made by a five year old, but truthly that was the aesthetic that I was trying to achieve. This rough look is also enhanced by the doodled dialogue boxes of the library p5.scribble. The background music was also done by me, being the recording of boiling meat tweaked on Audacity.

Below are some pictures:


Future Improvements

Unfortunately, I was not able to add some of the game mechanics that I wanted to, such as controlling the sprites of a character, or choosing your own paths, which could have improved the concept and the replayability of the game. Nonetheless, I am satisfied with the final product, and I believe that taking a more minimalistic approach was more effective.

CATSAWAY- Midterm Project

  • some images:

  • concept of my project

As a student at NYUAD, I really love our campus cat, Caramel. She makes being here even better. I enjoy graphic design, and it’s fun for me to draw. I’m also getting into coding, and I want to learn more about it. So, I had this idea for a project I call “Catsaway.” It’s a game inspired by Caramel. In the game, she can fly around the campus without crashing into the pointy palm tree corners. Instead, she gracefully glides through the soft palm leaves. To make her fly, you just press the spacebar. It’s a way to enjoy a little adventure through our campus. This project lets me combine my love for art and my interest in coding, turning my fondness for Caramel into a fun game.

My Game starts with my landing page that have 2 options either to start the game directly or taking you into the instructions page.

  • how my project works and what parts you’re proud of (e.g. good technical decisions, good game design)

I’m happy with how I brought Caramel to life in the game. Players get to control Caramel as she gracefully flies around our campus, avoiding obstacles like pointy palm trees. I’ve also made sure the game feels like NYUAD by adding familiar buildings and fluffy clouds.

I’m proud of the technical choices I made. The game has different parts, like the start page and instructions, to make it easy to play. I even added sound effects, like a cheerful jump sound when Caramel takes off. Players can restart the game or go back to the start page with simple key presses.

  • Some areas for improvement and problems that you ran into (resolved or otherwise)

During the development of my project, I encountered a few challenges and areas for improvement. One major issue I faced was optimizing the game’s performance. As the game got more complex with added elements, like the buildings and clouds, I noticed some slowdowns. I had to spend time fine-tuning the code to make sure the game runs smoothly, especially on lower-end devices. This was a valuable lesson in optimizing game design.

I had to work on enhancing the game’s instructions. I realized that players might need clearer guidance on how to play, so I made improvements to ensure that the instructions are more user-friendly.

Another challenge was making sure that the game’s look and feel truly capture the essence of NYUAD and Caramel. It required some iterations to get the graphics just right and create that immersive atmosphere.

While these challenges arose during development, I’m happy to say that I addressed them, resulting in a game I’m proud to share. The process of tackling these issues taught me valuable lessons in game development and design.

  • Future plans:
  • Play on Phones: Right now, you can play the game on a computer P5.js, but it would be great to play it on your phone or tablet. I need to make sure it works well on all kinds of devices.
  • High Score List: Having a list that shows who has the highest scores can make the game competitive. People will want to beat each other’s scores and share their achievements.
  • Listening to Players: I’ll pay attention to what players say and try to make the game better based on their ideas. They’re the ones playing it, so their feedback is important.
  • Making Money: If I want to earn money from the game, I can think about ways like letting people buy things in the game or showing ads. But I’ll be careful not to make the game annoying with too many ads 🙂

My own checklist of the requirements:

  • At least one shape

The background was coded the exact same way as the first-ever assignment, The NYUAD building, clouds, highline, and trees. I’ve used plenty of shapes  

  • At least one image

The Cat is an imported image sketched by Hand using Procreate.  as well as the NYUAD logo 

  • At least one sound

When the cat is flying the moment you hit on the Up Arrow you will hear a jumping sound

  • At least one on-screen text

The Score and the final score is a screen on text 

  • Object Oriented Programming

The game is entirely made using OOP

  • The experience must start with a screen giving instructions and wait for user input (button / key / mouse / etc.) before starting

The landing page has 2 options either wait for the user input to click on the space bar to start playing immediately or press on the letter “i” (stands for instructions) to access the instructions page.

  • After the experience is completed, there must be a way to start a new session (without restarting the sketch)

Again there are 2 options either to press on the space bar to replay or press on the letter B (stands for begin) to take you to the landing page again

Code:

let pipes = []; // An array to store information about the pipes in the game.
let score = 0; // Keep track of the player's score.
let gameOver = false; // A flag to check if the game is over.
let backgroundImage; // Not used in the code, possibly intended for a background image.
let backgroundX = 0; // The horizontal position of the background image.
let gameStarted = false; // Indicates whether the game has started.
let speed = 10; // The speed of the game elements, adjustable.
let gameState = 'landing'; // Tracks the current state of the game.

function preload() {
  // Loading images and sounds used in the game.
  // backgroundImage = loadImage('11.png');
  landing = loadImage('Catsaway(1).png');
  instruction = loadImage('instructions.png');
  caramel = loadImage("caramel.PNG");
  palm1 = loadImage("palm2-1.PNG");
  palm2 = loadImage("palm2 -2.PNG");
  ending = loadImage("score2.png");
  NYUAD = loadImage("NYUAD.png");
  
  // Load the jump sound
  jumpSound = loadSound('sfx_point.mp3');
  // hitSound = loadSound('sfx_hit.mp3');
}

function setup() {
// Set up the initial canvas for the game and create a bird object.
  createCanvas(800, 450);
  bird = new Bird(); 
}

function draw() {

  if (gameState === 'game') {
    // Code for the game state
    // Drawing buildings, clouds, and other elements on the canvas
    // Pipes are also created, and the game logic is implemented
    background(156,207,216,255);
    fill(207,207,207,255);
    rect(150,150, 500, 300);
    ellipse(400,150, 490, 100)
    
    // strokes for the building 
   fill(169, 169, 169)
    rect(150, 220, 500, 10);
    rect(150, 235, 500, 10);
    rect(150, 250, 500, 10);
    rect(150, 265, 500, 10);
    rect(150, 280, 500, 10);
    rect(150, 295, 500, 10);
    // rect(200, 220, 10, 100);
    rect(260, 220, 10, 100);
    rect(320, 220, 10, 100);
    rect(380, 220, 10, 100);
    rect(440, 220, 10, 100);
    rect(500, 220, 10, 100);

    
    image(NYUAD, 55, 0);
    fill(171,109,51,255);
    rect(150, 300, 510, 100);
    
    
    fill(121,68,19,255);
    rect(150, 310, 500, 5);
    rect(150, 317, 500, 5);
    rect(150, 324, 500, 5);
    rect(150, 331, 500, 5);
    
    rect(150, 390, 500, 20);
    

    
    // the 2 buildings
    fill(115,115,115,255);
    noStroke();
    square(0, 250, 200);
    square(600, 250, 200);
    
    // windows 
    fill(207,207,207,255);
    rect(20,260, 40, 50)
    rect(70,260, 40, 50)
    rect(120, 260, 40, 50)
    rect(640, 260, 40, 50)
    rect(690, 260, 40, 50)
    rect(740, 260, 40, 50)
  
        noStroke();
    fill(255);
    // First Cloud
    ellipse(200, 100, 80, 60);
    ellipse(240, 100, 100, 80);
    ellipse(290, 100, 80, 60);
    ellipse(220, 80, 70, 50);
    ellipse(260, 80, 90, 70);

    // Second Cloud
    ellipse(400, 80, 60, 40);
    ellipse(440, 80, 80, 60);
    ellipse(490, 80, 60, 40);
    ellipse(420, 60, 50, 30);
    ellipse(460, 60, 70, 50);

    // Third Cloud
    ellipse(600, 120, 90, 70);
    ellipse(640, 120, 110, 90);
    ellipse(690, 120, 90, 70);
    ellipse(630, 100, 80, 60);
    ellipse(670, 100, 100, 80);
    
    ellipse(0, 80, 60, 40);
    ellipse(40, 80, 80, 60);
    ellipse(90, 100, 60, 40);
    ellipse(140, 150, 50, 30);
    
    fill(15,138,70,255);
    ellipse(100, 420, 90, 70);
    ellipse(60, 450, 90, 70);
    ellipse(140, 420, 110, 90);
    ellipse(190, 420, 90, 70);
    ellipse(130, 500, 80, 60);
    ellipse(170, 500, 100, 80);
    
    ellipse(600, 420, 90, 70);
    ellipse(640, 420, 110, 90);
    ellipse(690, 420, 90, 70);
    ellipse(630, 500, 80, 60);
    ellipse(670, 500, 100, 80);
    
    
    fill(0,166,81,255);
    ellipse(0, 420, 90, 70);
    ellipse(40, 420, 110, 90);
    ellipse(90, 420, 90, 70);
    ellipse(30, 500, 80, 60);
    ellipse(70, 500, 100, 80);
    ellipse(670, 420, 90, 70);
    ellipse(700, 420, 110, 90);
    ellipse(740, 420, 90, 70);
    ellipse(750, 500, 80, 60);
    ellipse(760, 500, 100, 80);
    
    if (!gameOver) {
      bird.update();
      bird.show();
      for (let i = pipes.length - 1; i >= 0; i--) {
        pipes[i].show();
        pipes[i].update();
        if (pipes[i].hits(bird)) {
          gameOver = true;
        }
        if (pipes[i].offscreen()) {
          pipes.splice(i, 1);
        }
      }
      if (frameCount % 15 === 0) {
        pipes.push(new Pipe());
      }
      textSize(32);
      fill(255);
      text(score, 100, 30);
      for (let i = pipes.length - 1; i >= 0; i--) {
        if (pipes[i].pass(bird)) {
          score++;
        }
      }
    } else {
      image(ending, 0, 0, width, height);
      textSize(64);
      fill(255, 0, 0);
      text("", 200, height / 2 - 32);
      textSize(50);
      fill(0);
      text("" + score, 450, height / 2);
      // Provide a restart option

      // Check for restart key press
      if (keyIsDown(32)) { // SPACE key
        restart();
      } else if (keyIsDown(66)) { // 'B' key
        gameState = 'landing';
      }
    }
  } else if (gameState === 'landing') {
    
    // Code for the landing screen state
    // Displays the landing image and checks for keypress to start the game
    background(0);
    image(landing, 0, 0, width, height);
    textSize(32);
    fill(255);
    textAlign(CENTER, CENTER);
    text("", width / 2, height / 2);
    // Check for start key press (SPACE key) or 'i' key press for instructions
    if (keyIsDown(32)) { // SPACE key
      startGame();
    } else if (keyIsDown(73)) { // 'i' key
      gameState = 'instruction';
    }
  } else if (gameState === 'instruction') {
    // Code for the instruction screen state
    // Displays instructions and checks for keypress to start the game
    background(0);
    image(instruction, 0, 0, width, height);
    textSize(32);
    fill(255);
    textAlign(CENTER, CENTER);
    if (keyIsDown(32)) { // Check for SPACE key press
      startGame();
    }
  }
}

function startGame() {
  // Function to start the game
  // Resets game variables and sets the game state to 'game'
  gameState = 'game';
  gameStarted = true;
  bird = new Bird();
  pipes = [];
  score = 0;
  gameOver = false;
}

function restart() {
  // Function to restart the game
  // Calls the startGame function to reset the game
  startGame();
}

function keyPressed() {
    // When the UP_ARROW key is pressed, the bird jumps (if the game is not over)
    // Plays a jump sound when the bird jumps
  if (keyIsDown(UP_ARROW) && !gameOver && gameState === 'game') {
    bird.jump();
    jumpSound.play();
  }
}

function restartGame() {
  bird = new Bird();
  pipes = [];
  score = 0;
  gameOver = false;
}

class Bird {
  // Bird class to handle bird-related functionality
  constructor() {
    this.y = height / 2;
    this.x = 64;
    this.gravity = 0.6;
    this.lift = -15;
    this.velocity = 0;
  }

  show() {
    noFill();
    ellipse(this.x, this.y, 32, 32);
    image(caramel, this.x - 70, this.y - 30, 150, 90);
  }

  update() {
    this.velocity += this.gravity;
    this.velocity *= 0.9;
    this.y += this.velocity;
    if (this.y > height) {
      this.y = height;
      this.velocity = 0;
    }
    if (this.y < 0) {
      this.y = 0;
      this.velocity = 0;
    }
  }

  jump() {
    this.velocity += this.lift;
  }
}

class Pipe {
  // Pipe class to handle pipe-related functionality
  constructor() {
    this.top = random(height / 2.5);
    this.bottom = random(height / 2);
    this.x = width;
    this.w = 20;
    this.speed = speed; // Adjust the speed here as well
    this.highlight = false;
  }

  show() {
    fill(106, 69, 46, 255);
    if (this.highlight) {
      fill(106, 69, 46, 255);
      noStroke();
    }
    rect(this.x - 8, 0, this.w + 6, this.top);
    rect(this.x, height - this.bottom, this.w + 2, this.bottom);
    const palmX = this.x - 82;
    const palmYTop = this.top - 250;
    const palmYBottom = height - this.bottom - 120;
    image(palm2, palmX - 20, palmYTop + 195, 200, 200);
    image(palm1, palmX, palmYBottom, 200, 200);
  }

  update() {
    this.x -= this.speed;
  }

  offscreen() {
    return this.x < -this.w;
  }

  hits(bird) {
    if (bird.y < this.top || bird.y > height - this.bottom) {
      if (bird.x > this.x && bird.x < this.x + this.w) {
        this.highlight = true;
        return true;
      }
    }
    this.highlight = false;
    return false;
  }

  pass(bird) {
    if (bird.x > this.x && !this.highlight) {
      return true;
    }
    return false;
  }
}

 

Week 6 | Midterm Project

The Concept:
In this engaging “Chromamood” game, players take control of a catching hand, moving it through the game screen width. The objective is to collect words falling from the top of the screen. These words encapsulate various human moods, such as “happy,” “calm,” and “excited.” But the interesting part of the game lies in its categorization system. These words are neatly organized into distinct categories, with each category intimately linked to a unique display color and an associated score. As players adeptly gather these words, they trigger a series of cascading effects. The real magic happens as the words are seamlessly woven into the live video feed, enhancing the text display in the most visually enthralling way possible. The text dynamically updates, with its color shifting harmoniously, reflecting the precise word that the player has successfully captured.

Why “ChromaMood”?
The name “ChromaMood” is a fusion of two essential elements in the game. “Chroma” relates to color and represents the dynamic background shifts triggered by the words collected, where each mood category is associated with a distinct color. “Mood” encapsulates the central theme of the game, which revolves around collecting words that express various human emotions and moods

How the project works:
The game starts on a welcoming screen with the title “ChromaMood” and two options: “start” and “help.” Clicking “start” leads you to the main game screen. Here, you’ll see a hand-shaped object set against a black background, with words falling from the top. The game’s twist is in the words you catch. Each word represents a different mood, like “happy” or “angry,” and it impacts the background and your score. For example, catching words associated with anger turns the background red and gives you a score of 2. The words on the background change too. The goal is to get the highest score by collecting words that reflect positive moods within a limited time.

Welcoming Screen
Chromamood In-game Screenshot

Code Highlight I am proud of:
The part of the game I am proud of is developing the video display background as I had no idea of how to do it. It required somehow intricate coding to seamlessly integrate dynamic text updates with the live video feed, ensuring a cohesive and engaging user experience. The idea is that I am dealing with the sketch as pixels. So, I update the pixels with every character of the words the player catches. Honestly, it was challenging for me to do it but I watched some tutorials and managed to figure it out.

Sketch:
The video and sound effects are not working in the embedded iframe below. Open it on P5JS editor for better experience.

Soma areas of improvement:
A potential enhancement to consider is shifting the way we control the hand object. Instead of relying on traditional keyboard controls, we could explore the possibility of tracking the player’s movements in the live video feed. By doing so, we could introduce a new level of interactivity, allowing players to physically interact with the game. This change not only simplifies the game’s control mechanics but also aligns perfectly with its fundamental concept. It would create a more immersive experience, where players can use their own motions to catch the falling words, making the game even more engaging and unique.