midterm project: a life odyssey

link to sketch: https://editor.p5js.org/parchinkos/full/6Wh1hDMjG

link to p5.js web editor: https://editor.p5js.org/parchinkos/sketches/6Wh1hDMjG

(for some reason the initial start screen music doesn’t play on full-screen)

concept:

I knew from the beginning that I wanted to make a game. The aesthetics I had in mind for my project were always there, too – I’m a huge fan of 16-bit and 8-bit pixel art, and I knew I wanted to incorporate that art style into my work. I was also torn between the type of game I wanted to make; I could make it a complex story told through an RPG game format, or I could lean towards something more simple but with more gameplay. In the end, I ended up doing the latter, because it held one’s focus on the project for much longer. The gameplay for my project was inspired by simple platform games like Google’s T-Rex runner game or even Flappy Bird. Essentially, the player stays in one position throughout the game but has to avoid obstacles and/or hurdles throughout the way. My game has collectibles, which the player gathers for points, and obstacles which the user has to jump/avoid or else they lose points.

The main thing that I thought about was what I wanted the setting of the game to be. This semester, I’m taking a core class called Hindsight which focuses a lot on autobiographical story. So naturally, my mind went towards something similar: different life phases for different levels. Initially I was making it my own, but then I realized it would be infinitely more interesting if I loosely based the levels around my father’s life. He’s lived through much more different ‘settings’ (I’ve been in a city for my entire life). The game isn’t super focused on his life story, but the general inspiration for each level can be seen below.

chapter 1: the simple life

My dad grew up in a village, and on a farm, so the setting of this level is inspired by that! You also collect mangoes because that’s his favorite fruit.

 

 

chapter 2: the concrete jungle

In his late teens/early twenties, he moved from his village to Karachi, a large metropolitan city. It was his first time being in such an environment, so the level is based on the novelty of that. Cars, crows and rats are things one often finds in big cities like this which is why they’re the obstacles.

chapter 3: setting sail

After completing training at his cadet college (which was why he moved in the first place), my dad officially joined the Navy. He spent a lot of time at sea in his early years, which is why the last level he’s on a boat. At first I wanted there to be fish or something, but that seemed a bit difficult so I just settled on making the obstacles birds.

how it works

The functionality is relatively straightforward. There is a player object, which actually stays in place the entire game. The only movement from the user is that it can jump (and double-jump!) using the spacebar. The player object is given the illusion of moving because everything else – the obstacles, the collectibles, the background – move towards the player. The collectables and obstacles essentially have speeds at which they move towards the user, and if the player collides with a collectible points are added and deducted for obstacles. The placement of the obstacles and the collectables are random. Once the user has passed all obstacles in the game, the game advances to the next level.

My player class can be seen below.

class Player {
  constructor(spritesheet, spritesAcross, spritesDown, x, y, speed) {
    this.w = int(spritesheet.width / spritesAcross);
    this.h = int(spritesheet.height / spritesDown);
    this.across = spritesAcross;
    this.down = spritesDown;
    this.direction = 2;
    this.sprites = [];
    for (let y = 0; y < spritesDown; y++) {
      this.sprites[y] = [];
      for (let x = 0; x < spritesAcross; x++) {
        this.sprites[y][x] = spritesheet.get(
          x * this.w,
          y * this.h,
          this.w,
          this.h
        );
      }
    }
    this.x = this.w + 15;
    this.y = y;
    this.ground = y;
    this.speed = speed;
    this.step = 0;
    this.jump = 15;
    this.vy = 0;
    this.canDoubleJump = true;
    this.g = 1;
    this.isMoving = true;
    // this.score = 0;
  }

  setGround(newY) {
    this.ground = newY;
  }

  updatePosition() {
    this.y += this.vy;
    // gx -= obstacleSpeed;

    if (this.y < this.ground) {
      this.vy += g;
    } else {
      this.vy = 0;
      this.y = this.ground;
      this.canDoubleJump = true;
    }

    if (this.isMoving) {
      if (frameCount % this.speed == 0) {
        this.step = (this.step + 1) % this.across;
      }
    }
    // print(isMoving);

    image(this.sprites[this.direction][this.step], this.x, this.y);
  }

  doAJump() {
    if (this.y >= this.ground) {
      this.vy = -this.jump;
      this.canDoubleJump = true;
    } else if (this.canDoubleJump) {
      this.vy = -this.jump;
      this.canDoubleJump = false; // Consume double jump
    }
  }

 

things i’m proud of

One of my favorite things to do when I’m working on a technical creative project is figuring out the ambiance/aesthetics of the piece. Sometimes, I spend more time on that than the actual code. So needless to say, I’m the most proud of the aesthetics of this project. Not only does it it looks very in line with my initial vision of a retro game project, but I’m proud of how I was able to create the atmosphere for every setting. The background graphics, the obstacles, the collectibles, and the music. I think it all ties together very well and makes the game super immersive.

improvements

While I’m happy with how my project turned out, there is definitely room for improvements, or small changes that could completely elevate the level of my work.

  • Canvas size! I think because I was thinking of platform games on small screens, I kept the canvas size small. But I now wish it was bigger – unfortunately my code wasn’t typed in the most adaptable way, so it became a bit difficult to change the size towards the end.
  • Small features like being able to turn off the music would help a lot as well as I know the game is a bit heavy on the sound, which can be a bit disruptive.
  • Making the scoring system much more refined, i.e. adding points based on how elevated the collectable object is.

These changes seem relatively straightforward to implement, but I couldn’t mostly because of time restrictions.

 

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 progress

Concept

For my midterm project, I decided not to make a game, and rather focus on creating a program for an emotional experience. I think that midterms are always associated with stress and people need to find a way to balance these emotions and have time to focus on their well-being. Therefore, I decided to create a meditation program that will allow its users to calm themselves and enjoy self-care exercises.

Design

I started off by visualizing my project. Below you can see the developed design.

 

Here is a more detailed look at the three exercises I’m planning to create:

Frightening moments

The most frightening part for me is to understand how to create several pages that can be manipulated with buttons. I tried to look at the students’ codes, however, they were very complicated and I could not understand them. Therefore, with the help of the professor, I decided to use a switch statement to manipulate different cases (scenes) within the program.

Another complexity was regarding the buttons. For my program, I wanted to have a button as an image. So, a built-in function of creating a button was not appropriate. After doing some search, I eliminated this issue by finding a code that could help me to create and program my own buttons that are images. You can view the code here.

Also, I felt overwhelmed with doing everything within one code as it is very easy to find and analyze the bug when you run a long code. Therefore, I decided to test my exercises in a separate and much shorter code, which I can later implement in the main long code. Thus, I designed two separate codes for the breathing and journaling exercises.

Breathing exercise

For now, I’m still working on debugging the code that causes issues with the switch statement and buttons. Nevertheless, I am proud that the code functions more or less. As I am finished with debugging, I am going to add two last parameters that I need: shapes and sounds.

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 

Midterm Project

Pride Dragon Generator 🏮🐲🌈

Link to fullscreen: https://editor.p5js.org/eggangie/full/RdxIGV1n8 

Concept:
“Pride Dragon Generator” is essentially a very simplified version of a Picrew avatar maker, in which users can select a LGBTQ+ identity and receive a dragon with spike colors of the corresponding pride flag. They can then press “s” to save the image to their device.

Image of “Bi” dragon saved to device

This project was inspired by my identity as a queer Chinese-American  who has been immersed in queer culture for years, but did not know the terms in Chinese until very recently. These terms are not taught in language classes, and the queerness is oftentimes not spoken about in Chinese or Chinese diasporic families. Additionally, queer narratives in popular culture are overwhelmingly western-centric. Thus, I wanted to combine Chinese imagery (the color red, the lantern images, guqin music, dragons) with queer imagery to represent this intersection of identities. I hope this program makes the process of learning queer Chinese terms a little more cute and memorable than by just typing them into Google Translate.

Parts I’m Proud Of:
The thing I am most proud of in creating this project is not necessarily any single bit of code, since the code is quite basic (to those well versed in p5js —aka not me), but rather stringing it all together to form a functional work of art. In each week’s assignment, I gained individual skills such as drawing with shapes, making classes, and using the mouseClicked and keyPressed functions. The challenge was combining all of these into one project, and at first it kind of felt like starting off on a marathon when you had just learned how to walk. What helped was breaking the project down into chunks, and first establishing the “structure” of the code before actually drawing the details. Here are the steps I followed, roughly in order:

  1. Figuring out how to toggle between two screens with true/false & if statements
  2. Programming the “S” key and back arrow to save image & return to homepage
  3. Creating a Button class and adding functionality (hover and click) to it
  4. Drawing the unchanging elements of the homepage and the dragon page
  5. Creating a Dragon class
  6. Figuring out how to make the scales change color depending on which button was pressed (if I were to do this project again, I would perhaps move step 6 to the beginning and try to figure out the 6 buttons + 6 color schemes while my code was still minimal).

As for the design of the project, I like its minimalistic, cute feel, which I tried to emanate with round rectangle corners, bold Futura font, and pastel colors. I also believe it was a good decision to have the “back” and “save image” functions be keyboard commands, because it decluttered the area under the canvas and foregrounded the LGBTQ+ identity terms that I wanted to highlight.

I also think it was a good idea to have the toggling between scenes controlled by a boolean variable + functions to draw each scene, as it made it very clear which scene was being drawn currently. I had to restructure my program in the middle of my working process, as I realized that it made much more sense to have a dragon class and then call different dragons within one scene than to have different scenes with one dragon each, and call the scenes. Also, originally, the buttons were all on the homepage with only the Chinese terms, which was a bit confusing for the user.

Old version of sketch with buttons on homepage and 5 different scenes: https://editor.p5js.org/eggangie/sketches/Idyuc-bto

After revising, there was a start button on the homescreen and a “canvas” on the second screen, which brings to mind the universal design of familiar drawing programs, creating a more intuitive experience. I also added English to the buttons, because although my original intent was to omit English and have the user learn the terms by associating them with the pride flag colors, I realized this was not explicit enough and also many people may not know or remember which pride flag colors correspond with which identities.

Problems:

I encountered four main bugs in this code, two are resolved and two are still remaining.

The first bug was with the “press ‘s’ to save image” functionality. The bug was that every key being pressed was triggering the program to save the image, not just the “s” key. The issue was that I had written keyCode === "s" instead of keyCode === 83, as keyCode is only intended to work in natural language with special keys such as LEFT_ARROW, whereas for letter keys you need to find its numerical code. Below is the working code:

function keyPressed() {
  // To find keyCode of letter keys:
  // console.log(keyCode);
  if (keyCode === LEFT_ARROW && homePageVisible === false) {
    homePageVisible = true;
    scene1Visible = false;
  }

  if (keyCode === 83 && homePageVisible === false) {
    savedImg = myCanvas.get(0, 0, width, height - 115);
    savedImg.save("my-pride-dragon", "png");
  }
}

The second bug was that the buttons were triggering different scale colors to show up when the user was merely hovering over them, but not clicking them. This was because I was writing code for clicking specific buttons inside the class, which I later learned is unideal because classes are not supposed to know the specifics of each button, they should be as general as possible. Here is the code before, with this section repeated for each button 1-6:

  click(clickX, clickY) {
    if (
      clickX > button1.x - button1.buttonWidth / 2 &&
      clickX < button1.x + button1.buttonWidth / 2 && clickY > button1.y - button1.buttonHeight / 2 &&
      clickY < button1.y + button1.buttonHeight / 2
    ) {
      dragon1Scales();
    } else {
      mainDragonDisplay();
    }
  

And after I corrected the issue within the Button class:

click(clickX, clickY) {
    if (
      clickX > this.x - this.buttonWidth / 2 &&
      clickX < this.x + this.buttonWidth / 2 &&
      clickY > this.y - this.buttonHeight / 2 &&
      clickY < this.y + this.buttonHeight / 2
    ) {
      return true;
    } else {
      return false;
    }

In office hours, I learned that the click within the Button class can be used to make a boolean variable either true or false, and then that true or false can be used in the mouseClicked function to actually detect clicks on different buttons and call each button’s associated actions.

//code for detecting click on buttons to trigger
  //different scale colors
  if (scene1Visible) {
    if (button1.click(mouseX, mouseY)) {
      dragon1Visible = true;
      dragon2Visible = false;
      dragon3Visible = false;
      dragon4Visible = false;
      dragon5Visible = false;
      dragon6Visible = false;
      mainDragonVisible = false;
    }

The third bug, which I have not resolved yet, is one in which the “bi” dragon (dragon3) sometimes shows up as the “default”, what the user sees when entering sceneOne before clicking on any buttons. By putting print statements in every function where dragon3 is called, I was able to see that that something is happening between the moment the user goes back to the homepage and the moment they returns to sceneOne to call dragon3. All the code for the bi dragon is the same as for the other dragons, so I have not been able to figure out what is causing it, in particular, to be called.

Finally, the background audio does not play when the sketch is embedded into this blog post or in fullscreen mode, but it plays fine when the sketch is run in p5js. I am not sure why this is, but perhaps it could be solved by adding a command for playing the audio on the user’s first mouse click. However, the desired effect is that the audio plays before the user clicks, just as ambient background music.

Areas for Improvement:

There are many areas of improvement, both in terms of efficiency of the code and functions and aesthetics I wish the program had. In terms of efficiency, it would be sleeker to have a “dragon selector” variable that would assign a number to each dragon, so instead of writing all of the code below to ensure that only one dragon is true at a time, I could just call the number of each dragon.

if (scene1Visible) {
    if (button1.click(mouseX, mouseY)) {
      dragon1Visible = true;
      dragon2Visible = false;
      dragon3Visible = false;
      dragon4Visible = false;
      dragon5Visible = false;
      dragon6Visible = false;
      mainDragonVisible = false;
    }

    if (button2.click(mouseX, mouseY)) {
      dragon1Visible = false;
      dragon2Visible = true;
      dragon3Visible = false;
      dragon4Visible = false;
      dragon5Visible = false;
      dragon6Visible = false;
      mainDragonVisible = false;
    }

    if (button3.click(mouseX, mouseY)) {
      dragon1Visible = false;
      dragon2Visible = false;
      dragon3Visible = true;
      dragon4Visible = false;
      dragon5Visible = false;
      dragon6Visible = false;
      mainDragonVisible = false;

      //**bug: sometimes dragon does not set back to
      //the default dragon but instead
      //shows dragon 3 as the default
      //when returning to the drawing page
    }

    if (button4.click(mouseX, mouseY)) {
      dragon1Visible = false;
      dragon2Visible = false;
      dragon3Visible = false;
      dragon4Visible = true;
      dragon5Visible = false;
      dragon6Visible = false;
      mainDragonVisible = false;
    }

    if (button5.click(mouseX, mouseY)) {
      dragon1Visible = false;
      dragon2Visible = false;
      dragon3Visible = false;
      dragon4Visible = false;
      dragon5Visible = true;
      dragon6Visible = false;
      mainDragonVisible = false;
    }

    if (button6.click(mouseX, mouseY)) {
      dragon1Visible = false;
      dragon2Visible = false;
      dragon3Visible = false;
      dragon4Visible = false;
      dragon5Visible = false;
      dragon6Visible = true;
      mainDragonVisible = false;
    }
  }
}

function keyPressed() {
  // code to find keyCode of letter keys:
  // console.log(keyCode);
  
  //return to homepage when left arrow is pressed
  //reset dragon to default dragon (sometimes does not work because bug)
  if (keyCode === LEFT_ARROW && homePageVisible === false) {
    homePageVisible = true;
    scene1Visible = false;

    mainDragonVisible = true;
    dragon1Visible = false;
    dragon2Visible = false;
    dragon3Visible = false;
    dragon4Visible = false;
    dragon5Visible = false;
    dragon6Visible = false;
  }

Additionally, since each of my buttons are performing the same hover and click functions, they could perhaps be stored in a button array, instead of being called individually every time:

button1.showButton();
  button2.showButton();
  button3.showButton();
  button4.showButton();
  button5.showButton();
  button6.showButton();

  button1.hover(mouseX, mouseY);
  button2.hover(mouseX, mouseY);
  button3.hover(mouseX, mouseY);
  button4.hover(mouseX, mouseY);
  button5.hover(mouseX, mouseY);
  button6.hover(mouseX, mouseY);

  button1.click(mouseX, mouseY);
  button2.click(mouseX, mouseY);
  button3.click(mouseX, mouseY);
  button4.click(mouseX, mouseY);
  button5.click(mouseX, mouseY);
  button6.click(mouseX, mouseY);

However, I am glad I did things “the long way” for this project, because it was much easier for me to know what each part of my program was doing when I could see every button I was creating, instead of everything being “hidden” in a for loop. I think making the code more efficient would have come at the cost of me understanding my program as I worked on it.

As for features, I wish I had time to add a key command to change background color, as well as a little “wardrobe” for the dragon (another scene that users could enter to select items, such as sunglasses or a shirt, that they could put on their dragon).

Resources:

 

  • Coding Train Tutorials:

  • & many thanks to Professor Shiloh and Zion for their help

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 progress #3

At this point after completing my template and look of my code, it may be simple but i translated what i shared in my last progress report. I am very proud of my code as it was quite challenging for me since i had some difficulties. i added an animation of a circle with 4 arches rotating to give an illusion that the record is spinning. I inserted a button that would make the record spin when pressed on and also pause the record when clicked on again. In the final sketch there will be a sprite sheet dancing character which will be dancing to a sample of music i created using the software “Logic”.

Initial sketch:

i sketched out my design on adobe illustrator to see how i would like my sketch to look like, and luckily it turned out exactly how i wanted it to be.

My final design:

My code:

// Declare a variable to store the button object
let btn;

// Variables to control rotation animation
let r = 0;
let angle = 0;

function setup() {
  createCanvas(500, 500); // Create a 500x500 pixel canvas
  background("#408080"); // Set the background color to a shade of blue-green
  btn = new Button(250, 400, 120, 50); // Create a button object at the specified position and dimensions
}

function draw() {
  record(250, 250); // Call the record function to draw a rotating shape
  btn.show(); // Call the show method of the button object to display it
}

// Function to draw a rotating shape
function record(x, y) {
  push();
  translate(x, y); // Translate the origin to the specified position

  // If r is set to 1, increment the angle for rotation
  if (r == 1) {
    angle += 0.1;
  }
  rotate(angle); // Rotate the subsequent shapes based on the angle

  fill(0); // Fill color for the central ellipse
  ellipse(0, 0, 200, 200); // Draw a central ellipse

  noFill();
  stroke(100); // Set stroke color
  strokeWeight(5); // Set stroke weight

  // Draw four arcs to create a pattern
  arc(0, 0, 150, 150, 0, PI/4);
  arc(0, 0, 120, 120, PI/4, PI/2);
  arc(0, 0, 100, 100, PI, 3 * PI/2);
  arc(0, 0, 150, 150, PI/2, PI);

  pop(); // Restore the previous drawing settings
}

// Function to respond to mouse clicks
function mouseClicked() {
  // Check if the mouse click is within the boundaries of the button
  if (mouseX > btn.x - btn.w / 2 && mouseX < btn.x + btn.w / 2 && mouseY > btn.y - btn.h / 2 && mouseY < btn.y + btn.h / 2) {
    // Toggle the value of r to start or stop the rotation animation
    if (r == 1) {
      r = 0;
    } else {
      r = 1;
    }
  }
}

Button code:

// Define a class called Button
class Button {
    // Constructor that initializes button position (x, y) and dimensions (w, h)
    constructor(x, y, w, h) {
        this.x = x; // X-coordinate of the button
        this.y = y; // Y-coordinate of the button
        this.w = w; // Width of the button
        this.h = h; // Height of the button
    }

    // Method to display the button
    show() {
        // Save the current drawing style
        push();

        // Set the rectangle drawing mode to center
        rectMode(CENTER);

        // Set the fill color to yellow
        fill(255, 255, 0);

        // Check if the mouse is within the button's boundaries
        if (mouseX > this.x - this.w / 2 && mouseX < this.x + this.w / 2 && mouseY > this.y - this.h / 2 && mouseY < this.y + this.h / 2) {
            // If the mouse is inside, change the fill color to a darker shade of yellow
            fill(200, 200, 0);
        }

        // Draw a rectangle with rounded corners at the specified position and dimensions
        rect(this.x, this.y, this.w, this.h, 10);

        // Restore the previous drawing style
        pop();
    }
}

 

Rotation of the arcs/ also a part of the code that made me proud:

I used the push and pop method we took in class to achieve this motion, also to achieve the arc “animation” i used the reference “arc()” on p5js website

arc() :

arc(50, 55, 50, 50, 0, HALF_PI);
noFill();
arc(50, 55, 60, 60, HALF_PI, PI);
arc(50, 55, 70, 70, PI, PI + QUARTER_PI);
arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);
describe(
  'A shattered outline of an ellipse with a quarter of a white circle at the bottom-right.'
);
// Function to draw a rotating shape
function record(x, y) {
  push();
  translate(x, y); // Translate the origin to the specified position

  // If r is set to 1, increment the angle for rotation
  if (r == 1) {
    angle += 0.1;
  }
  rotate(angle); // Rotate the subsequent shapes based on the angle

  fill(0); // Fill color for the central ellipse
  ellipse(0, 0, 200, 200); // Draw a central ellipse

  noFill();
  stroke(100); // Set stroke color
  strokeWeight(5); // Set stroke weight

  // Draw four arcs to create a pattern
  arc(0, 0, 150, 150, 0, PI/4);
  arc(0, 0, 120, 120, PI/4, PI/2);
  arc(0, 0, 100, 100, PI, 3 * PI/2);
  arc(0, 0, 150, 150, PI/2, PI);

  pop(); // Restore the previous drawing settings
}

 

I also used the function for the button to start and pause the record mouseClicked() :

From p5js website:

let cnv, d, g;
function setup() {
  cnv = createCanvas(100, 100);
  cnv.mouseClicked(changeGray); // attach listener for
  // activity on canvas only
  d = 10;
  g = 100;
}

function draw() {
  background(g);
  ellipse(width / 2, height / 2, d, d);
}

// this function fires after the mouse has been
// clicked anywhere
function mouseClicked() {
  d = d + 10;
}

// this function fires after the mouse has been
// clicked on canvas
function changeGray() {
  g = random(0, 255);
}
// Function to respond to mouse clicks
function mouseClicked() {
  // Check if the mouse click is within the boundaries of the button
  if (mouseX > btn.x - btn.w / 2 && mouseX < btn.x + btn.w / 2 && mouseY > btn.y - btn.h / 2 && mouseY < btn.y + btn.h / 2) {
    // Toggle the value of r to start or stop the rotation animation
    if (r == 1) {
      r = 0;
    } else {
      r = 1;
    }

Button function:

I created a class called button then set the x,y,w,h coordinates, in addition to the shape of the rectangle, and the color changes for when mouse is clicked

// Define a class called Button
class Button {
    // Constructor that initializes button position (x, y) and dimensions (w, h)
    constructor(x, y, w, h) {
        this.x = x; // X-coordinate of the button
        this.y = y; // Y-coordinate of the button
        this.w = w; // Width of the button
        this.h = h; // Height of the button
    }

    // Method to display the button
    show() {
        // Save the current drawing style
        push();

        // Set the rectangle drawing mode to center
        rectMode(CENTER);

        // Set the fill color to yellow
        fill(255, 255, 0);

        // Check if the mouse is within the button's boundaries
        if (mouseX > this.x - this.w / 2 && mouseX < this.x + this.w / 2 && mouseY > this.y - this.h / 2 && mouseY < this.y + this.h / 2) {
            // If the mouse is inside, change the fill color to a darker shade of yellow
            fill(200, 200, 0);
        }

        // Draw a rectangle with rounded corners at the specified position and dimensions
        rect(this.x, this.y, this.w, this.h, 10);

        // Restore the previous drawing style
        pop();
    }
}

 

Any difficulties? :

Fidgeting with the coordinates of the arc() function was tricky for me, its the first time for me to try and use it as it was not quite working for me, also figuring out the push and pop method was confusing at first. In future projects i would want to do something more complex and better my skills coding wise. I will be posting my final sketch soon.