Midterm Project – The Cookie Game!

For my midterm project, I decided to channel my love for baking and code a game for baking cookies!

Link to the full screen sketch: https://editor.p5js.org/lr3258/full/e-z5Ur1g3

Concept :

This is a simple game to bake chocolate chip cookies, very direct and fun! The player drags ingredients into a bowl to create the dough, which then bakes into delicious chocolate chip cookies! I wanted it to have a very comfy and cozy vibe, so I chose a colour palette of baby blues and browns. To make the entire game more aesthetically cohesive, I drew the ingredients on Autodesk Sketchbook and made the layouts on Canva. I also drew the egg –> dough sprite sheet since I couldn’t find any suitable ones online.

How it works:

The game isn’t meant to be challenging or competitive, it is more inclined to the process and joy of baking the cookies than being a “game” itself.

First, the user has to click on any key to start the game:

Next, the player has to drag the ingredients into the bowl. Here, when the egg is clicked on, it triggers the animation to display the dough. We can then press the Next button.

After this, we have to wait for 5 seconds, while the cookies “bake” in the oven. After 5 seconds, the screen automatically shifts with a Ding! sound.

Then, the final screen shows the baked cookies! We can then restart the game.

highlights of the code i’m proud of

A part of the game I’m pretty proud of is the sprite sheet animation. It took a lot of time to draw, create and then animate the sprite sheet. It was also the hardest part, and there was a LOT of debugging involved, but in the end I’m happy with how it turned out, even with the ingredients being dragged into the bowl. I’m also very happy with the aesthetic of the game, which really feels like home to me.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Ingredient {
constructor(name, x, y, img, isEgg) {
this.name = name;
this.x = x;
this.y = y;
this.img = img;
this.isEgg = isEgg;
this.isDragging = false;
this.offsetX = 0;
this.offsetY = 0;
this.isDropped = false;
this.currentFrame = 0;
this.numFrames = 5;
this.frameWidth = 150;
this.frameHeight = 150;
this.isCracked = false;
this.frameTimer = 0;
this.frameSpeed = 6;
this.originalX = x;
this.originalY = y;
}
display() {
if (!this.isDropped && !this.isEgg && bowl.isIngredientInBowl(this)) {
this.isDropped = true;
this.x = bowl.x;
this.y = bowl.y;
}
if (this.isEgg) {
let sx = this.currentFrame * this.frameWidth;
image(this.img, this.x, this.y, this.frameWidth, this.frameHeight, sx, 0, this.frameWidth, this.frameHeight);
} else if (!this.isDropped) {
image(this.img, this.x, this.y);
}
}
update() {
if (this.isDragging) {
this.x = mouseX + this.offsetX;
this.y = mouseY + this.offsetY;
}
//dropping ingredient into bowl
if (!this.isDropped && !this.isEgg && bowl.isIngredientInBowl(this)) {
this.isDropped = true;
this.x = bowl.x;
this.y = bowl.y;
}
// animate the egg spritesheet if it's clicked
if (this.isEgg && this.isCracked) {
this.frameTimer++;
if (this.frameTimer >= this.frameSpeed) {
this.frameTimer = 0; // to reset timer
if (this.currentFrame < this.numFrames - 1) {
this.currentFrame++;
}
}
}
}
checkDragging() {
if (
mouseX > this.x &&
mouseX < this.x + this.img.width &&
mouseY > this.y &&
mouseY < this.y + this.img.height &&
!this.isDropped
) {
this.isDragging = true;
this.offsetX = this.x - mouseX;
this.offsetY = this.y - mouseY;
}
}
checkClicked() {
if (
mouseX > this.x &&
mouseX < this.x + this.img.width &&
mouseY > this.y &&
mouseY < this.y + this.img.height &&
!this.isCracked
) {
this.isCracked = true; //start the animation of egg cracking
this.currentFrame = 0;
}
}
class Ingredient { constructor(name, x, y, img, isEgg) { this.name = name; this.x = x; this.y = y; this.img = img; this.isEgg = isEgg; this.isDragging = false; this.offsetX = 0; this.offsetY = 0; this.isDropped = false; this.currentFrame = 0; this.numFrames = 5; this.frameWidth = 150; this.frameHeight = 150; this.isCracked = false; this.frameTimer = 0; this.frameSpeed = 6; this.originalX = x; this.originalY = y; } display() { if (!this.isDropped && !this.isEgg && bowl.isIngredientInBowl(this)) { this.isDropped = true; this.x = bowl.x; this.y = bowl.y; } if (this.isEgg) { let sx = this.currentFrame * this.frameWidth; image(this.img, this.x, this.y, this.frameWidth, this.frameHeight, sx, 0, this.frameWidth, this.frameHeight); } else if (!this.isDropped) { image(this.img, this.x, this.y); } } update() { if (this.isDragging) { this.x = mouseX + this.offsetX; this.y = mouseY + this.offsetY; } //dropping ingredient into bowl if (!this.isDropped && !this.isEgg && bowl.isIngredientInBowl(this)) { this.isDropped = true; this.x = bowl.x; this.y = bowl.y; } // animate the egg spritesheet if it's clicked if (this.isEgg && this.isCracked) { this.frameTimer++; if (this.frameTimer >= this.frameSpeed) { this.frameTimer = 0; // to reset timer if (this.currentFrame < this.numFrames - 1) { this.currentFrame++; } } } } checkDragging() { if ( mouseX > this.x && mouseX < this.x + this.img.width && mouseY > this.y && mouseY < this.y + this.img.height && !this.isDropped ) { this.isDragging = true; this.offsetX = this.x - mouseX; this.offsetY = this.y - mouseY; } } checkClicked() { if ( mouseX > this.x && mouseX < this.x + this.img.width && mouseY > this.y && mouseY < this.y + this.img.height && !this.isCracked ) { this.isCracked = true; //start the animation of egg cracking this.currentFrame = 0; } }
class Ingredient {
constructor(name, x, y, img, isEgg) {
    this.name = name;
    this.x = x;
    this.y = y;
    this.img = img;
    this.isEgg = isEgg;
    this.isDragging = false;
    this.offsetX = 0;
    this.offsetY = 0;
    this.isDropped = false;
    this.currentFrame = 0; 
    this.numFrames = 5; 
    this.frameWidth = 150;
    this.frameHeight = 150;
    this.isCracked = false;
    this.frameTimer = 0;
    this.frameSpeed = 6;  
    this.originalX = x;  
    this.originalY = y;  
  }
  
  display() {
    
    if (!this.isDropped && !this.isEgg && bowl.isIngredientInBowl(this)) {
  this.isDropped = true;
  this.x = bowl.x;
  this.y = bowl.y;
}
    
    if (this.isEgg) {
      let sx = this.currentFrame * this.frameWidth;
      image(this.img, this.x, this.y, this.frameWidth, this.frameHeight, sx, 0, this.frameWidth, this.frameHeight);
    } else if (!this.isDropped) {
      image(this.img, this.x, this.y);
    }
  }

  update() {
    if (this.isDragging) {
      this.x = mouseX + this.offsetX;
      this.y = mouseY + this.offsetY;
    }
    
    //dropping ingredient into bowl
    if (!this.isDropped && !this.isEgg && bowl.isIngredientInBowl(this)) {
      this.isDropped = true;
      this.x = bowl.x; 
      this.y = bowl.y;
    }

    // animate the egg spritesheet if it's clicked
    if (this.isEgg && this.isCracked) {
      this.frameTimer++;
      if (this.frameTimer >= this.frameSpeed) {
        this.frameTimer = 0;  // to reset timer
      if (this.currentFrame < this.numFrames - 1) {
          this.currentFrame++;  
        }
      }
    }
  }

  checkDragging() {
    if (
      mouseX > this.x &&
      mouseX < this.x + this.img.width &&
      mouseY > this.y &&
      mouseY < this.y + this.img.height &&
      !this.isDropped
    ) {
      this.isDragging = true;
      this.offsetX = this.x - mouseX;
      this.offsetY = this.y - mouseY;
    }
  }

  checkClicked() {
    if (
      mouseX > this.x &&
      mouseX < this.x + this.img.width &&
      mouseY > this.y &&
      mouseY < this.y + this.img.height &&
      !this.isCracked
    ) {
      this.isCracked = true; //start the animation of egg cracking
      this.currentFrame = 0;
    }
  }

 

challenges and improvements:

When it came to challenges, the main concern was the sprite sheet itself. It was also hard to transition from different states smoothly, but I implemented the concept of state machine we discussed in class, and it went pretty well. In the end, the final problem I had was the autoplay of the background audio, which wasn’t working in the full screen version. For this, I used the p5js built in code, userStartAudio(), which starts the audio on click. Implementing the restart button at the end was also a bit tricky, but overall, I’m pleased with the final result.

If I could make some improvements, I’d add some extra elements, like a timer, or maybe animations for the baking time. I would also like to change the design of the buttons, which are currently very basic in contrast to the rest of the game.

Embedded sketch :

Leave a Reply