Midterm Project – Feed No Face!

Here’s the link the the editor and to the full screen game
Concept

My midterm project concept is based on a Studio Ghibli film called Spirited Away. The movie is about a girl named Chihiro who enters an abandoned amusement park because she lost her parents in the midst of moving homes, only to find her parents turned into pigs. There was one particular scene in the movie where No Face, a spirit side character, is fed by the workers, so I decided to use this scene as inspiration for my game.

No Face feasting

The concept is a game where you, as the character No Face from Spirited Away, have to eat all the food that appears on the screen. The trick is that you can only eat it when it reaches the height of the character, so clicking above will not count. If one food reaches the bottom of the canvas and you fail to click it, the game will end. Below are the three states of the game: the start/instruction screen, the actual game, and the game over screen.

How it Works
class Food {
  constructor() {
    this.xPos = random(50, width - 80);
    this.yPos = -20;
    this.xSize = 95;
    this.ySize = 70;
    this.xCenter = this.xPos + (this.xSize/2); // Midpoint formula
    this.yCenter = this.yPos + (this.ySize/2); 
    this.food = random(foods);
    this.speed = random(2,4);
  }
  
  rainingFood() {
    this.yPos += this.speed;
    this.yCenter += this.speed; // Since the y-position is moving down the screen, the center position also has to move in order for the distance to be accurate
  }
  
  // Mouse Interactions with Objects (The Coding Train):
  // https://www.youtube.com/watch?v=TaN5At5RWH8
  checkFoodEatenAt(mousePosX, mousePosY) {
    
    // Finds the distance between the mouse position and center of the food
    let d = dist(mousePosX, mousePosY, this.xCenter, this.yCenter);
    d = round(d);
    
    if(this.yPos >= 440) { // Can only eat when the food reaches the height of the character
      if(d < this.xSize/2 || d < this.ySize/2) { 
        eatSound.play();
        return true;
      }
    } else {
      return false;
    }
  }
  
  missedFood() {
    if(this.yPos > height) { // If it goes off the screen it's game over
      gameState = "end";
    }
  }
  
  show() {
    image(this.food, this.xPos, this.yPos, this.xSize, this.ySize);
    
    // For debugging the food click
    // noFill();
    // stroke(255);
    // strokeWeight(2);
    // rect(this.xPos, this.yPos, 95, 70);
    // stroke("Red");
    // strokeWeight(10);
    // point(this.xCenter, this.yCenter);
  }
}

The main part of the game is clicking on the food, essentially eating it. The food appearing and disappearing is done in a class called Food, which is assigned to an array. A new food is pushed into the array based on the frameCount remainder. The falling effect is done simply by adding to the y-position of the food with a speed variable.

The tricky part was figuring out how to remove the food and check if the mouse clicked on the food. Professor Shiloh suggested that I use a method that is specifically made for removing elements in an array, which I had not thought of at first. That got me thinking, so I searched for the method, which wonderfully enough, The Coding Train had videos on how to remove items in an array as well as how to check if the mouse clicked on an object.

Before watching the video, I knew I had to use dist() to figure out if the cursor is within the object, but I struggled a lot with that. It also didn’t help that since I scaled the images, the x and y position was all scaled as well (I put it in push() and pop(), but the numbers were still in the thousands). The Coding Train example used a circle to figure out the distance, but for my code I used a rectangle.

To walk through the whole process of figuring out the distance, I first drew a rectangle that was roughly the same size as the foods. I tried using the sizes to get the center of the rectangle, and to get that point I needed to use the midpoint formula. If I know the size, I only need one x-y point for the formula. After getting the center point, I can use dist() and do the if condition.

The first issue was the scaling, which I mentioned earlier. This made the x-y position insanely large, because I was multiplying it to account for the scale. So I ended up removing the scale and hard coded the size of the food. While I was lucky that the image didn’t get distorted, I feel like this isn’t really the best approach, but it works better than scaling.

The next issue I encountered was that even though my code should technically work, when I clicked on the food it didn’t disappear. So I drew a point at the center of the food “rectangles” to get a clearer picture. Lo and behold, turns out the points were just being drawn at the top and they don’t move down. This seemed like such a silly error because of course I should have realized that if the y-position is changing then I need to change the y-position of the center point as well.

All the center points (red) just stay at the top because I’m not adding the speed variable to it as well.

After figuring out how to click and remove the food, completing the rest of my project was mostly smooth sailing. All that was left was fine tuning the instruction and game over screens and implementing sound. I did, however, have another laughable problem while creating my instruction screen: basically, I wanted to create random ellipses in the background so it didn’t seem as empty. Since random changes constantly, I put noLoop() in my for loop, but I also surround it with a push() and pop() thinking that it would only noLoop() the for loop. So after finishing the instruction screen, I tested out the game, but realized that it no longer goes to the play mode. I spent a while trying to figure out why it wouldn’t go to the next screen anymore even though it registered me pressing “Enter”. I did eventually have a eureka moment and realized it was the noLoop(), which was a very trivial error that could have been avoid.

The ellipses that ended my program and made me confused for 30 minutes
Conclusion – What I’m Proud of and Future Directions

On a brighter note, I am quite proud of how the game turned out. My biggest struggle is honestly what I’m most proud of because I managed to make it work. I also really like how the play mode and game over screens turned out in terms of design (the instruction screen could still use some work). I actually took the No Face image in the play mode from an image that had a background, so I had to Photoshop it. For the food images it was all one image with a white background, so I also had to remove the background for that and crop into each food image. As for the music choices, Studio Ghibli films always have great music, but honestly the soundtrack for Spirited Away weren’t “game” material. So I decided to go for 8bit sounding music, even though the game isn’t 8bit, but I feel like it makes it sound more like a game soundtrack. Also a side note: the sound effect when you click on a food is basically the only sound No Face makes in the movie.

I did a few user tests and the main issue I ran into was people not reading the instructions. One of them has never played games, so she was very confused with what to do. The other user tester thought it was catching the food by moving the character, not clicking on the food. These are a few things that I need to consider if I continue to work on this in the future. Additionally, other things I want to work on in the future are fixing the instruction screen and adding lives instead of ending it at just one food missed.

Overall, I really love how my project turned out and it was super fun to create. Print() everything and drawing every detail is your best friend when it comes to debugging (but it’ll cause the program to lag if you do too much)!  And finally, I highly recommend watching Spirited Away, if you haven’t already : ).

 

Leave a Reply