Midterm- Life Under the Sea

Concept:

For my midterm, I envisioned creating an immersive underwater experience, inspired by my childhood favorite movie “Finding Nemo.” The whole idea is to bring human interaction to the fish world. As a result, I wanted to create a street feel life but under the sea. There fish can go shopping and view artworks in a museum.

I created the whole atmosphere from scratch. I combined vector-based images for the background and other objects using Illustrator. I saved the files as PNG and then added them to P5JS.

Highlight:

The code was the most challenging part mainly for creating layers and buttons to click on. I started the process of implementation by trying to figure out all the variables I needed for each part. Then I loaded all the images and audio I wanted to use for the project. After that, I began to find the logic for moving from one scene to the next. I created a class called experience manager where I give instructions on what to display in the layers when a specific button is clicked. This class is a boolean. As a result, when a specific variable is set to be true it will be visible on the screen: the sound, the images, and the buttons.

// class to manage which slide to display.
class ExperienceManager {
  constructor() {
    this.onHome = true;
    this.onStreet = false;
    this.onMall = false;
    this.onMuseum = false;
  }
  display() {
    if (this.onHome) {
      image(HomeImg, 0, 0, 500, 500);
      SoundWaves.play();
      SoundMall.stop();
      SoundMuseum.stop();
      fishObj = new ClickedObj(fish, 215, 320, 90, 90);
      // Call the textGraphics function
      Title("Life Under the Sea", width / 2, 90, 30);
      // Call the instruction box function
      drawInstructionBox(110, 130, 280, 180, 23);
      this.onStreet = false;
      this.onMall = false;
      this.onMuseum = false;
    } else if (this.onStreet) {
      SoundWaves.play();
      SoundMall.stop();
      SoundMuseum.stop();
      image(seaSt, 0, 0, 500, 500);
      arrowStObj = new ClickedObj(arrow, 10, 20, 25, 25);
      mallObj = new ClickedObj(malltrn, 25, 320, 150, 150);
      museumObj = new ClickedObj(museumtrn, 38, 190, 110, 110);
      this.onHome = false;
      this.onMall = false;
      this.onMuseum = false;
    } else if (this.onMall) {
      //     hide clicks
      SoundMall.play();
      SoundMuseum.stop();
      SoundWaves.stop();
      fishObj.x = -100;
      museumObj.x = -100;
      // bags on click display
      image(mall, 0, 0, 500, 500);
      arrowMallObj = new ClickedObj(arrow, 10, 20, 25, 25);

      this.onStreet = false;
      this.onHome = false;
      this.onMuseum = false;
    } else if (this.onMuseum) {
      image(museum, 0, 0, 500, 500);
      SoundWaves.stop();
      SoundMall.stop();
      SoundMuseum.play();
      arrowMuseumObj = new ClickedObj(arrow, 10, 20, 25, 25);
      this.onHome = false;
      this.onMall = false;
      this.onStreet = false;
    }
  }
}

I also created a class for clickable objects like the fish, and arrows that go to the previous layer, the mall, the museum, the bags, and artworks. This class has a lot of conditionals in it. For some, I made clickable images but for the bags and artwork, I felt it’s better to have curser values that refer to a specific bag of artwork and then display an image for that. Then I created a function for the home screen instructions and passed the text through an array of strings. And added a rectangle behind it. Finally, I added the title of the interaction set a color, and a font in the title function.

// this class helps because it removes alot of hard coding so when I change the coordinates of an inage the program will recognise and so i dont need to change it everywhere.
class ClickedObj {
  constructor(imgFileName, x, y, imgWidth, imgHeight) {
    this.imgFileName = imgFileName;
    this.x = x;
    this.y = y;
    this.imgWidth = imgWidth;
    this.imgHeight = imgHeight;
    this.drawObjct();
  }
  drawObjct() {
    if (this.imgFileName) {
      image(this.imgFileName, this.x, this.y, this.imgWidth, this.imgHeight);
      // print("image draw sucessfull");
    }
  }
  isSelected() {
    if (
      mouseX > this.x &&
      mouseX < this.x + this.imgWidth &&
      mouseY > this.y &&
      mouseY < this.y + this.imgHeight
    ) {
      return true;
    } else return false;
  }
}

// to go to the next layer of the street so all clickable objects are here.
function mouseClicked() {
  //  to go  back to the home layer and instructions and click other objects like the fish etc.
  if (expMgr.onHome) {
    if (fishObj.isSelected()) {
      // print("fish 1 is clicked");
      expMgr.onHome = false;
      expMgr.onStreet = true;
      expMgr.onMall = false;
      expMgr.onMuseum = false;
      expMgr.display();
      //print("done")
    }
  } else if (expMgr.onStreet) {
    if (mallObj.isSelected()) {
      // print("mall is clicked");
      expMgr.onHome = false;
      expMgr.onStreet = false;
      expMgr.onMall = true;
      expMgr.onMuseum = false;
      expMgr.display();
    } else if (museumObj.isSelected()) {
      // print("museum is clicked");
      expMgr.onHome = false;
      expMgr.onStreet = false;
      expMgr.onMall = false;
      expMgr.onMuseum = true;
      expMgr.display();
    } else if (arrowStObj.isSelected()) {
      // print("arrow is clicked");
      expMgr.onHome = true;
      expMgr.onStreet = false;
      expMgr.onMall = false;
      expMgr.onMuseum = false;
      expMgr.display();
    }
  } else if (expMgr.onMall) {
    if (arrowMallObj.isSelected()) {
      // print("arrow is clicked");
      expMgr.onHome = false;
      expMgr.onStreet = true;
      expMgr.onMall = false;
      expMgr.onMuseum = false;
      expMgr.display();
    } else if (mouseX >= 83 && mouseX <= 124 && mouseY >= 90 && mouseY <= 135) {
      image(rdBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 83 &&
      mouseX <= 120 &&
      mouseY >= 200 &&
      mouseY <= 236
    ) {
      image(LneBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 83 &&
      mouseX <= 121 &&
      mouseY >= 220 &&
      mouseY <= 331
    ) {
      image(BrwnBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 353 &&
      mouseX <= 379 &&
      mouseY >= 91 &&
      mouseY <= 140
    ) {
      image(YlwBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 391 &&
      mouseX <= 422 &&
      mouseY >= 96 &&
      mouseY <= 141
    ) {
      image(OrngBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 345 &&
      mouseX <= 381 &&
      mouseY >= 192 &&
      mouseY <= 238
    ) {
      image(bluBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 397 &&
      mouseX <= 423 &&
      mouseY >= 202 &&
      mouseY <= 235
    ) {
      image(GrnBg, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 355 &&
      mouseX <= 381 &&
      mouseY >= 297 &&
      mouseY <= 336
    ) {
      image(pnkBag, width / 4, height / 4, 210, 210);
    } else if (
      mouseX >= 391 &&
      mouseX <= 427 &&
      mouseY >= 312 &&
      mouseY <= 332
    ) {
      image(whtBag, width / 4, height / 4, 210, 210);
    }
  } else if (expMgr.onMuseum) {
    if (arrowMuseumObj.isSelected()) {
      // print("arrow is clicked");
      expMgr.onHome = false;
      expMgr.onStreet = true;
      expMgr.onMall = false;
      expMgr.onMuseum = false;
      expMgr.display();
    } else if (
      mouseX >= 126 &&
      mouseX <= 177 &&
      mouseY >= 96 &&
      mouseY <= 199
    ) {
      image(art1, width / 3, height / 3, 250, 300);
    } else if (
      mouseX >= 212 &&
      mouseX <= 293 &&
      mouseY >= 102 &&
      mouseY <= 179
    ) {
      image(art3, width / 3, height / 3, 250, 300);
    } else if (
      mouseX >= 330 &&
      mouseX <= 384 &&
      mouseY >= 97 &&
      mouseY <= 191
    ) {
      image(art2, width / 3, height / 3, 250, 300);
    }
  }
}

To be honest the hardest part was the clickable objects class because at the beginning the objects would layer on one another and would still be clickable even if they were not visible. However, I fixed it by passing the clicks to the specific experience they fit in. I also faced a lot of bugs because P5js is case-sensitive, and it would take me hours to realize that but now I know, and it is the first thing I look for if I have a bug.

 

Reflection and ideas for future work or improvements:

I am satisfied with the overall result of the project. For the future, I would add more places to visit and add some motion to the website. Maybe a fish moving, some submarine. I would also want to add a music icon where users can pick a song and pause it if they want. I also want the home page to be more interactive, maybe create graphics with text or water bubbles that move around the canvas.

Resources:

https://itch.io/games/made-with-p5js

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

https://www.youtube.com/results?search_query=p5js+object+orianted+

https://p5js.org/reference/#/p5/REMOVE

https://p5js.org/examples/sound-load-and-play-sound.html

https://www.rapidtables.com/web/color/blue-color.html

https://p5js.org/examples/interaction-snake-game.html

https://stackoverflow.com/questions/58477636/transitioning-from-one-scene-to-the-next-with-p5-js

 

 

Leave a Reply