Overall Concept
Link to Sketch: https://editor.p5js.org/mk7592/full/Q3_SYFuO6
Whenever I’m traveling to someplace new, driving around my hometown, or even walking down a new street, I am always intrigued by that one small, cozy cafe sitting at the corner of the street. The ones with soft, lo-fi music playing in the background with fairy lights hanging all around. For my midterm, I thought of replicating that thought and creating a similar experience but with one important addition: Interaction. I decided to sway away from making games for once and to try something new that I would enjoy just as much. So I came to the conclusion of making a small but interactive cafe experience in p5.
The whole concept behind my idea is to let the user explore the artwork on their own and immerse themselves in the calm environment of the cafe. The way I would make this work is to add small interactable elements in the cafe like books that the user can read, some wall art that they can view, or a boombox that they can use to change the music. All of these elements will be subtle but noticeable enough to make the user want to interact with them. This way, the user will be able to experience something new in every corner.
I decided to keep the design simple but intuitive. The color scheme would be soft and pastel-like and the overall design of the objects in the canvas would replicate SVG images. The cafe would have a calm and relaxing feel to it with soothing music and close-to-real-life sound effects, such as the sound of opening a door when it is clicked.
Initial wireframes I drew for my project:
Workflow/ Parts that Went Well
- Switching the user perspective from scene-to-scene. For example, displaying the outside of the cafe at first, and then changing the perspective to view the inside of the cafe when the user clicks on the cafe’s entrance. Creating a separate SceneManager class to handle user interactions and changing the layers of the scene proved to be quite useful in organizing my code because if there was a bug with the layers I knew the problem was somewhere inside the SceneManager class. Updating layer booleans upon mouseclicks and updating the scenes accordingly worked side-by-side:
function mouseClicked() { // checking which object the user has clicked on and then displaying the relevant layer if (scene.onDoor) { console.log("Door clicked!"); // if yes move inside the cafe scene.layer1 = false; scene.layer2 = true; // start playing the music dooropen.play(); if (canStartMusic) { sounds[0].play(); canStartMusic = false; // to prtevent music playing on top whenever the door is clicked } currentsound = sounds[0]; currentsoundIndex = 0; } if (scene.onSmallBoombox) { console.log("boombox clicked!"); // if yes zoom into boombox // layer 1 is already false as we're in layer 2 scene.layer2 = false; scene.layer3 = true; }
- Drawing! Utilizing vector images, Canva, and Procreate on my iPad to design the stuff I wanted. Drawing on the same size as my p5 canvas (100x600px) worked very nicely because I didn’t have to worry a lot about positioning the individual interactive pieces inside the p5 canvas. I did have to create a lot of the same images with small tweaks in them, like highlighting a certain wall art frame with the same background. Had I made separate images for small interactables and then positioned them on the canvas, it would have taken a lot of time.
- Creating a working boombox. The forward and back buttons were tricky to implement because at first, I didn’t realize I had to first check if the music was playing or not and pause it if it was otherwise the next track would play on top of the previous one. Also, simply modding over the list of songs wasn’t enough to switch back and forth between the tracks. There was this little bug that I spent a lot of time on and it happened when we were at the first song in the list and pressed the back button. It should have switched to the last song on the list but instead, it was playing another song in the list. Turns out, it was going on a negative index which was then throwing an out-of-bounds error or playing the wrong song. Separating out the zero index condition solved this issue:
if (scene.onBackButton) { // play the previous song console.log("back clicked!"); // same as in next sound but the only difference is we have to take care of index 0 if (currentsound.isPlaying()) { currentsound.pause(); // if the current sound is playing, pause it first if (currentsoundIndex == 0) { sounds[sounds.length - 1].play(); // if we're at index 0, play the last song in the list currentsoundIndex = sounds.length - 1; currentsound = sounds[currentsoundIndex]; } else { sounds[(currentsoundIndex - 1) % sounds.length].play(); // otherwise play the previous one currentsoundIndex = (currentsoundIndex - 1) % sounds.length; currentsound = sounds[currentsoundIndex]; } } else if (currentsound.isPaused) { // if it's paused already, repaet the steps without the pausing step if (currentsoundIndex == 0) { sounds[sounds.length - 1].play(); currentsoundIndex = sounds.length - 1; currentsound = sounds[currentsoundIndex]; } else { sounds[(currentsoundIndex - 1) % sounds.length].play(); currentsoundIndex = (currentsoundIndex - 1) % sounds.length; currentsound = sounds[currentsoundIndex]; } } }
- Embedding a previous project (my Japanese tree) inside this project. I did this as a little surprise when the user clicks on one of the frames that looks like a purple tree. It takes the user to a Japanese tree that I made for another project. While doing user testing, everyone really admired this little surprise.
- I tried to pay special attention to small things like hovering over the door creates a knocking sound but it doesn’t repeat as you’re hovering over it. It will only knock again if you move the cursor out of the door and back on it again. Only playing the initial music when the first time the door is opened and not every time since that would play the music on top of the one that’s already playing: another thing I found on user testing.
let canKnock = true; // to prevent continuous knocking while on door let canStartMusic = true; // to prevent music playing on top whenever we enter ... // inside the display() function of the SceneManager class // playing knocking sound when mouse is over the door if (this.onDoor) { if (!knocking.isPlaying() && canKnock) { console.log("inside if"); knocking.play(); canKnock = false; // so that we don't repeatedly knock while the mouse hovers over the door } } else if (!this.onDoor) { // making it true back again since we moved the mouse away from the door canKnock = true; }
- Switching content inside the books on the shelf. Positioning the text inside the book’s area was somehow a real hassle, eventually, I had to tweak the position till it fit the area of the book I wanted. Especially since the quotes were of varying lengths. I made the quote file myself using my favorite ones and separated them from author names using semicolons. Although this was a bit time-consuming because I had to find enough quotes to make it seem randomized and too repetitive. This was so that I could make the experience more personalized and so that I could add more quotes in the future.
Areas for Improvement
- I thought about adding an instruction set to let the user know what they’re supposed to do. I’m still a bit conflicted on this idea because the project was meant to be explored by the user as an interactive art piece that would be filled with little surprises. However, having a guide does prove useful to some users. I could make the cafe menu interactable and turn it into an instruction guide inside the cafe, but I think the experience is simple enough for the user to understand for now.
- A better way to detect clicking on images? I compared mousePos with the coordinates of my objects which was a hassle, but I couldn’t find anything concrete that would help me detect hovers/mouseclicks on images very easily on p5. Then again, some of the images have a transparent background around them which I don’t want to include while detecting mouse interactions, so maybe working with coordinates was in fact the way to go?
- Adding more interactions with coffee, having the user brew some using a machine. What’s a cafe experience without coffee? I wished to add some features that would let the user play with a coffee machine, but I was going off on a tangent by starting to implement a game using that, which I decided to call off at the end due to time constraints. I would love to add this to my cafe in the future though.