LIFE CRAFT 2024 – AUDREY SIERENDS – ERIC PARREN
“Collect your 2024 affirmations!”
CONCEPTION AND DESIGN:
The new year is coming and have you thought about your New Year’s resolutions? Life Craft is a game that combines meaningful reflection and interactive game and interaction, this project aims to provide an enjoyable and meaningful experience that supports individuals in their journey toward self-improvement and the manifestation of their dreams and goals in the next year, 2024.
1st draft of the design – Bubbles & PlayStation stick
The user will use the PlayStation stick and move it to the right and left to collect the affirmation bubbles on the screen.
The final product – Stars & Hat
Stars – In ancient times, people relied on stars as the guiding light, and stars are a symbol of reaching something extraordinary, dreams, and goals.
Hat – When you use the hat in your head and move it to the right and left, it is often associated with thinking, a gesture to convey thoughts and emotions.
Instruction:
Anybody can play this game, from kids to old people because all of us can have our affirmations and wishes for the new year. Overall, I learned that making an interactive game is not limited to only fun, but also gives meaningful reflection and impact for the user.
USER TESTING
Though people who tested the game were super excited and thought that the game was cool and meaningful, during the user testing they gave us a lot of insightful feedback that made our project more engaging. User testing is crucial for the project’s improvement.
Before user testing –
Appearance: blue bubbles and yellow rectangle
Sound: no sound
Time & Limit: no time and limit so people can play as long as they want
Interaction: PlayStation stick with a tilt sensor
Others: only laptop and it was not eye level so it was hard for people to see the words, no opening and closing.
After user testing –
Appearance: Universe theme (change bubbles into stars)
Sound: Background sound and sound whenever the user collects the stars
Time & Limit: The game will go to the ending page after the user collects 10-16 stars (random)
Interaction: Hat with a sign of “Life Craft 2024” made out of laser cutting 3 mm plywood and cardboard
Others: Box and Drawer made out of plywood (laser cutting), ending page “May all your wishes come true.
FABRICATION AND PRODUCTION:
In this project, we are using 3 crucial elements that we combined: Arduino, Processing, and Laser Cutting.
Hardware and Software Integrations:
- Arduino: Tilt sensor that is connected to the hat.
In the Arduino board, we connected the 220 resistors to the LED and then to the tilt sensor. We solder the tilt sensor to a longer jumper cable so that the tilt sensor can be put on the hat comfortably. We wanted to make the user make a thinking movement to collect the stars(wishes) and the tilt sensor is perfect to make it happen so when you move your head to the right and left, it gives the instruction to the rectangle to move to the right and left based on your movement with the hat. We connected sensors to the hat to detect when the rectangle touch(collect) the stars and used appropriate Arduino libraries to read input from the sensors and send signals to Processing.
2. Processing: Create the game graphics and manage the gameplay.
Receive input from Arduino to detect bubbles and collect action. Beginning and ending page and sound.
3. Laser Cutting – Box, drawer, and keychain.
The box was designed to make the laptop be at eye level and the drawer gave an element of surprise when people open and see the keychains as their gift.
PERSONAL TOUCH – Life Craft keychain as a gift and reminder
The keychain serves as a take-home gift and reminder, reminding them of their intentions and manifestations beyond the game. User can also write their name and their 3 chosen affirmation
MEMORABLE STORY from IMA SHOW & CONCLUSION
The life craft was a next-level awesome. The project goals turned into reality and we witnessed the interaction from moving their head to collecting the wishes until writing down their wishes on the keychain, it was wholesome! Some of them even asked us to play more than one time! Ninj and I were so happy to see that the project turned out exactly what we wanted it to be and engaged the user deeply.
As they selected their aspirations, their reaction was funny, expressing preferences like aiming for TRAVEL MORE and HEALTH, and at the same time, some of them also did not want to collect certain goals for the new year like “Nah, I do not want to forgive/ Nah, I don’t want creative coz I am already creative.”
Then, the reveal moment when they opened the drawer and saw the keychains, “AA THIS IS SO CUTE,” most of them said that to us! They started to grab the pen and wrote down their name and wishes. One person dreamt of going to New York for college, one person wanted to go to Iran so badly, and the most exciting part, THE KIDS!! Even if they might not understand the meaning of the aspirations, they were super excited to move the hat right and left and collect as many stars as they could. The kids wrote “more food and more candy” on their keychains, Ninj, I, and their parents were laughing together.
The IMA Show is one of the highlights of this project, it turned out to be more than just a showcase of our project, it became a heartwarming moment where users shared their stories and dreams with us, I am grateful that Life Craft 2024 could be a little piece of their journey, helping them kick off 2024 strongly!
However, if we have more time we will want to make my project compatible with the display, make it bigger and more interactive. Also, we will make the collected words appear in the rectangle.
Ultimately, Life Craft isn’t just a project; it’s a collective celebration of aspirations, laughter, and the shared human experience.
DISASSEMBLY:
FULL CODE
ARDUINO: byte ledPin = 13; byte switchPin = 3; void setup() { pinMode(ledPin, OUTPUT); pinMode(switchPin, INPUT_PULLUP); Serial.begin(9600); // Initialize serial communication } void loop() { if (digitalRead(switchPin) == LOW) { digitalWrite(ledPin, HIGH); Serial.println("1"); // Send "1" to indicate button pressed } else { digitalWrite(ledPin, LOW); Serial.println("0"); // Send "0" to indicate button not pressed } delay(100); // Add a small delay to avoid rapid serial communication }
PROCESSING:
import processing.sound.*; import processing.serial.*; int endTime; // Variable to store the end time int startTime; SoundFile sound1; SoundFile sound2; Serial serialPort; boolean gameEnded = false; float characterSize = 150; // Size of the character square float characterX, characterY; // Position of the character float characterSpeed = 25; // Speed of the character (increase this value for faster speed) float bubbleSize = 250; // Size of the bubbles float bubbleSpeed = 3; // Speed of the bubbles int numBubbles = 20; // Number of bubbles int score = 0; // Player's score float[] bubbleX; // Array to store bubble positions float[] bubbleY; // Array to store bubble positions String[] words; // Array to store bubble text float[] starX = new float[3]; float[] starY = new float[3]; float[] starSpeed = new float[3]; boolean openingScene = true; // Flag to indicate if the opening scene is being displayed PImage Image2; ArrayList<String> chosenWords = new ArrayList<String>(); void addChosenWord(String word) { chosenWords.add(word); } void setup() { fullScreen(); characterX = width / 2; characterY = height / 2; PImage Image; Image = loadImage("star.png"); // Load star image Image2 = loadImage("galaxy.jpg"); sound1 = new SoundFile(this, "arcade_sound.wav" ); sound2 = new SoundFile(this, "drive.mp3"); sound2.loop(); bubbleX = new float[numBubbles]; bubbleY = new float[numBubbles]; words = new String[numBubbles]; for (int i = 0; i < numBubbles; i++) { bubbleX[i] = random(width); // Randomize starting X position bubbleY[i] = -bubbleSize * i; // Set starting Y position above the screen //bubbleText[i] = "Text " + i; // Set bubble text words[0] = "CREATIVE"; words[1] = "MINDFUL"; words[2] = "RELAXED"; words[3] = "EXPLORE"; words[4] = "TRAVEL MORE"; words[5] = "HEALTH"; words[6] = "HUMBLE"; words[7] = "PRODUCTIVE"; words[8] = "FORGIVE"; words[9] = "CONSISTENT"; words[10] = "HAVE FUN"; words[11] = "EMBRACE"; words[12] = "BE BRAVE"; words[13] = "APPRECIATE"; words[14] = "BALANCE"; words[15] = "INSIPRE"; words[16] = "IMPROVE"; words[17] = "BRIGHT"; words[18] = "SELF-LOVE"; words[19] = "FIND LOVE"; } String portName = "/dev/cu.usbmodem14201"; // Specify the correct port name int baudRate = 9600; // Must match the Arduino baud rate serialPort = new Serial(this, portName, baudRate); } void draw() { if (openingScene) { displayOpeningScene(); } else { playGame(); } //println(millis()); } void displayOpeningScene() { background(0, 0, 51); // Set dark blue background for (int i = 0; i < 100; i++) { float x = random(width); float y = random(height); float starSize = random(10, 15); float alpha = random(150, 255); fill(255, 255, 0, alpha); noStroke(); ellipse(x, y, starSize, starSize); } float shootingStarX = -1000; float shootingStarY = random(height / 2); float shootingStarSpeed = random(5, 10); shootingStarX += shootingStarSpeed; shootingStarY += shootingStarSpeed / 2; // Draw shooting star fill(255, 255, 0); noStroke(); triangle(shootingStarX, shootingStarY, shootingStarX - 50, shootingStarY - 20, shootingStarX - 50, shootingStarY + 20); // Set text properties fill(254, 255, 70); textAlign(CENTER, CENTER); textSize(110); float textX = width / 2; float textY = height / 2; text("CHOOSE YOUR 2024 GOAL", textX, textY); if (millis() > 18000) { openingScene = false; } } void playGame() // Resize the background image to match the full screen size { Image2.resize(displayWidth, displayHeight); // Set the resized image as the background background(Image2); // Rest of your code... // Rest of your code... fill(#6B9EB4); rectMode(CENTER); rect(characterX, characterY, characterSize, characterSize); for (int i = 0; i < 100; i++) { float x = random(width); float y = random(height); float starSize = random(3, 6); float alpha = random(150, 255); fill(255, 255, 0, alpha); noStroke(); ellipse(x, y, starSize, starSize); } float shootingStarX = -1000; float shootingStarY = random(height / 2); float shootingStarSpeed = random(5, 10); shootingStarX += shootingStarSpeed; shootingStarY += shootingStarSpeed / 2; fill(255, 255, 0); noStroke(); triangle(shootingStarX, shootingStarY, shootingStarX - 50, shootingStarY - 20, shootingStarX - 50, shootingStarY + 20); // Draw stars for (int i = 0; i < numBubbles; i++) { fill(#FEFF46); drawStar(bubbleX[i], bubbleY[i], bubbleSize); bubbleY[i] += bubbleSpeed; // Move the star downwards // Check if the star has reached the bottom of the screen if (bubbleY[i] > height + bubbleSize / 2) { fill(255); bubbleX[i] = random(width); // Randomize X position bubbleY[i] = -bubbleSize; // Reset Y position above the screen } // Check collision with the character if ((dist(characterX, characterY, bubbleX[i], bubbleY[i]) < characterSize / 2 + bubbleSize / 2) && !gameEnded) { score++; addChosenWord(words[i]); fill(255); bubbleX[i] = random(width); // Randomize X position bubbleY[i] = random(-bubbleSize*2, -height*2); // Reset Y position above the screen sound1.play(); } // Display text inside stars fill(0); textAlign(CENTER, CENTER); textSize(30); text(words[i], bubbleX[i], bubbleY[i]); } // Display score fill(255); textAlign(LEFT); textSize(80); text("Word counts: " + score, 30, 80); // Read serial data from Arduino while (serialPort.available() > 0) { String data = serialPort.readString().trim(); if (data.equals("1")) { characterX -= characterSpeed; // Move character to the left } else if (data.equals("0")) { characterX += characterSpeed; // Move character to the right } } characterX = constrain(characterX, characterSize / 2, width - characterSize / 2); characterY = constrain(characterY, characterSize / 2, height - characterSize / 2); // Check if the game should end if (score >= 10) { if (endTime == 0) { endTime = millis() + 2000; // Set the end time 2 seconds (2000 milliseconds) from now } else if (millis() >= endTime) { endGame(); // Call the endGame() function when the specified time has elapsed } } } void drawStar(float x, float y, float size) { float angle = TWO_PI / 10; float halfAngle = angle / 2.0; float radius1 = size / 2.0; float radius2 = radius1 / 2.5; beginShape(); for (float a = 0; a < TWO_PI; a += angle) { float sx = x + cos(a) * radius1; float sy = y + sin(a) * radius1; vertex(sx, sy); sx = x + cos(a + halfAngle) * radius2; sy = y + sin(a + halfAngle) * radius2; vertex(sx, sy); } endShape(CLOSE); } void endGame() { sound1.stop(); gameEnded = true; background(#000033); // Set dark blue background for (int i = 0; i < 3; i++) { starX[i] = random(width); starY[i] = random(height); starSpeed[i] = random(3, 6); } for (int i = 0; i < 3; i++) { starX[i] += starSpeed[i]; if (starX[i] > width) { starX[i] = 0; starY[i] = random(height); starSpeed[i] = random(3, 6); } float starSize = random(10, 20); float alpha = random(100, 200); fill(#FFFF66, alpha); ellipse(starX[i], starY[i], starSize, starSize); } fill(#FEFF46); textAlign(CENTER, CENTER); textSize(95); text("YOU GAINED "+ score + " AFFIRMATIONS ", width / 2, height / 5); textSize(70); text("MAY ALL YOUR WISH COME TRUE IN 2024", width / 2, height / 2); String[] tempwordlist = chosenWords.toArray(new String[chosenWords.size()]); String combinedString = join(tempwordlist," "); text(combinedString, width/2,height/1.5); } void keyPressed() { if (keyCode == 32) { // Space bar key code if (openingScene) { openingScene = false; // Start the game here } else { openingScene = true; // Restart the game here score = 0; chosenWords.clear(); // Clear the chosenWords list for (int i = 0; i < numBubbles; i++) { bubbleX[i] = random(width); bubbleY[i] = -bubbleSize * i; } startTime = millis(); } } } void endGame2() { if (openingScene) { // Display the opening scene background(0); fill(255); textSize(50); textAlign(CENTER, CENTER); text("Game Over", width / 2, height / 2 - 100); text("Score: " + score, width / 2, height / 2); text("Press SPACE to restart", width / 2, height / 2 + 100); } else { // Ending scene with chosen words background(Image2); fill(#6B9EB4); rectMode(CENTER); rect(characterX, characterY, characterSize, characterSize); // Display the chosen words in a list fill(255); textSize(20); textAlign(LEFT, TOP); float wordListX = 30; float wordListY = 150; for (int i = 0; i < chosenWords.size(); i++) { text(chosenWords.get(i), wordListX, wordListY + i * 30); } for (int i = 0; i < 100; i++) { float x = random(width); float y = random(height); float starSize = random(3, 6); float alpha = random(150, 255); fill(255, 255, 0, alpha); noStroke(); ellipse(x, y, starSize, starSize); } float shootingStarX = -1000; float shootingStarY = random(height / 2); float shootingStarSpeed = random(5, 10); shootingStarX += shootingStarSpeed; shootingStarY += shootingStarSpeed / 2; fill(255, 255, 0); noStroke(); triangle(shootingStarX, shootingStarY, shootingStarX - 50, shootingStarY - 20, shootingStarX - 50, shootingStarY + 20); // Draw stars for (int i = 0; i < numBubbles; i++) { fill(#FEFF46); drawStar(bubbleX[i], bubbleY[i], bubbleSize); bubbleY[i] += bubbleSpeed; // Move the star downwards // Check if the jstar has reached the bottom of the screen if (bubbleY[i] > height + bubbleSize / 2) { fill(255); bubbleX[i] = random(width); // Randomize X position bubbleY[i] = -bubbleSize; // Reset Y position above the screen } // Check collision with the character if ((dist(characterX, characterY, bubbleX[i], bubbleY[i]) < characterSize / 2 + bubbleSize / 2) && !gameEnded) { score++; fill(255); bubbleX[i] = random(width); // Randomize X position bubbleY[i] = random(-bubbleSize*2, -height*2); // Reset Y position above the screen sound1.play(); } // Display text inside stars fill(0); textAlign(CENTER, CENTER); textSize(30); text(words[i], bubbleX[i], bubbleY[i]); } // Display score fill(255); textAlign(LEFT); textSize(80); text("Word counts: " + score, 30, 80); // Read serial data from Arduino while (serialPort.available() > 0) { String data = serialPort.readString().trim(); if (data.equals("1")) { characterX -= characterSpeed; // Move character to the left } else if (data.equals("0")) { characterX += characterSpeed; // Move character to the right } } characterX = constrain(characterX, characterSize / 2, width - characterSize / 2); characterY = constrain(characterY, characterSize / 2, height - characterSize / 2); if (score >= 10) { if (endTime == 0) { endTime = millis() + 2000; // Set the end time 2 seconds (2000 milliseconds) from now } else if (millis() >= endTime) { endGame(); // Call the endGame() function when the specified time has elapsed } } } }
MANY THANKS TO…
Many thanks to all the professors especially Professor Eric that teach us this incredible class, interaction lab, throughout the semester of the class, so that we understand how to build the project. Thank you to all the fellows and LAs who were very helpful in helping us make this project happen. Kevin who helped us with the code, Dalin and Sophia who helped us with all the laser cutting, and others gave us feedback for our instruction and during the user testing. Thank you to all the people in the user testing who helped us by providing the most valuable feedback so that Life Craft 2024 came out as what it is today. Finally and ultimately, to my partner Ninj who worked hard to make this project happen together!