For our final project we made an interactive dollhouse. From our final project proposal we made a few changes to the interaction for the house.
CONCEPT:
For each room in our house, we wanted a functionality and a type of interaction.
We initially wanted to have multiple interactions for every room as well as have virtual tasks that one could complete in processing. However, given the time constraints, this was not very feasible. As such we decided to pivot.
Currently, the user can interact with the dollhouse by placing a doll at the front of the room. When the doll is placed in front of the room the lights in the room turn on and the display [currently a computer screen] will display wallpaper and play one form of media, either a video, audio, or both depending on the room. Each room consists of three LEDs connected in series to avoid running multiple long wires to the breadboard.
PROCESS:
Our process included a lot of side-by-side physical and technical work.
The first steps were to create a physical dollhouse, which was made out of cardboard and measured to fit exactly on a laptop, to make the background the screen of it. For the coding, we worked on being able to separately trigger each part on the screen that corresponds to the room, and we did this with buttons.
Next, the dollhouse was fit with LEDs and pressure sensors. To do this, we needed longer wires — from Aayush’s Circuit Breakers class– and to solder the wires together to connect them to the breadboard. We also used pressure sensors from Suzan’s Sensors Body and Motion class, which was perfect for the main room trigger. We wanted to have some additional functionalities, such as a button for the doorbell, a physical game room, and a button to switch between sceneries on the balcony, however were limited with equipment, so settled for that. At this point, there was also time spent on creating the furniture for the dollhouse, like couches, chairs, tables, and beds.
Next, we had to put it all together. Once we met more and discussed, we decided to let go of the idea of a physical game, and instead created a bathroom, where the sensor triggers a flush. At this point, we worked on the software functionalities of each room; such as playing the sounds or movies, as well as software design and illustrations, and physical refinements like the wallpaper, wall decor, and tidying up the wires.
We placed all the wires and Arduino in the attic of the house and covered the attic from the front. We also decorated the house more and cleaned it up.
Rooms:
Balcony:
When triggered, music is played on loop because of the piano, and the view is a moving scenery. This was created by layering the hand-drawn png illustration with an animated scenery found on youtube, creating the window look.
Bathroom:
The bathroom plays a flushing noise once when you enter.
Bedroom:
Same as the balcony room, the illustration is a png layer on top of the video found on youtube, with the dimensions of the window being empty.
Living Room:
This room plays a TV in the background, the video of choice being Happy, by pharell williams
Dining room:
This is playing a small gif, (which we converted to a movie), of the smoke on the pot moving, just to show that there is a movement happening.
Each room was paired with 3 LED’s that light up upon entry.
OBSTACLES:
Thankfully, we didn’t encounter any big obstacles, but some things that were not the smoothest.
Running the wires was a bit difficult to manage
We had a soldering accident when trying to connect a sensor to a wire, and burnt the sensor
Some of the furniture (like the toilet or the piano) was difficult to figure out how to create
Adding the video to processing
We initially had a 15 second long flush, and couldn’t shorten it on processing, so we had to find another flush audio
REFLECTION:
We are really happy with how this finally turned out, and even joke about creating a start up. We wish we could have added more interactions and functionalities, and also a doll, but are happy with it anyway.
Right after Wednesday’s class last week, I bought a hot glue gun, and used the quarantine Blue Mart Cardboard box to start working on creating the dollhouse. This task was mostly fun, but a bit frustrating because the cardboard was so thick I needed a knife to cut most of it. Measuring all the pieces and getting straight lines with a knife were probably the most difficult parts.
I created the dimensions of the dollhouse so that the background of the rooms matched perfectly to the screen of my laptop. I also had to create a bit of a stand so that it didn’t rest on the laptop, and also fit in a way were it was perfectly centered without relying on the user to adjust it.
Next, Aayush and I discussed what each room could do, and what kind of interactivities we could incorporate. Here’s what we decided:
Bedroom: The background scenery changed from day to night
Game room: A small, interactive game starts (user can play)
Balcony: has a piano that plays music, scenery can change, as well as whether
Living room: A tv where a movie can play
Dining room: Food starts sizzling/ food is made/ kettle ..etc
While Aayush created a prototype of the triggers of each room, I created simple ‘wallpapers’ of how the dollhouse may look. Here is what we have:
For clarification, this is what the dollhouse looks like in comparison to the laptop:
I wanted to create the popular game Flappy Bird, but using the distance sensor and my hand to control the movement of the bird.
PROCESS:
I started by creating an array of rectangles that formed at a distance apart, and at random heights. For some reason, this was my most frustrating part because I didn’t realise how quickly I could forget Java. Eventually figured out how to move the screen, and the ball, to make it seem like the bird was moving.
ARDUINO:
This was the first time I was using the Distance sensor so it took me some time to understand it, but some research and help from my peers did the trick. Once I kept experimenting using my hand, I constrained the results to a distance I thought seemed appropriate, which was between 1 and 10 inches. After that, I connected the Arduino and processing using the sendBytetoProcessing example and was happy to have found that process easy for me.
FINAL TOUCHES:
I added a collision if statement, to end the game, and also added some fun graphics to have the game seem more fun!
OBSTACLES:
I couldn’t manage to get the bird to mimic my hand movements exactly, The bird seemed to keep bouncing. I played around a lot with constrain, mapping, time, and framerate, but am still not sure what exactly the issue is. I would love some insight if anyone knows!
As a singer, one of the things I struggle with is finding nice harmonies, as I am really new at that. That’s what inspired me to create an instrument where you can pick a note, and fine the Soprano, Alto, Tenor, and Bass notes for it.
I decided to go for a range of notes that was close to my vocal range, so I went for 15 notes, from D3 to A5. I set up 4 buttons, one resembling each note, soprano being the original melody. The goal was to use the Potentiometer to pick a note, listen to it with the red button (soprano), and then find the 4 part harmony with the other buttons. In the end I should be able to press all four, and hear the harmony.
I mapped the analogue to match the notes I wanted to use, and each button just jumped a few notes from the original, to be a harmony. I only went through a few hours of debugging and creating this, but when I finished I encountered an obstacle i didn’t know how to fix. My sound was very muffled. When I would only have 1 button in use in the code, the sound would be fine. When I tried the code one button at a time, each button worked perfectly. But when I put it together, the sound sounded muffled, laggy, and muddy. The notes also didn’t come outright. At first I realised i had the resistor in the wrong place in some buttons, so when I fixed that it helped, but the issue didnt seem to go away anymore. Im not sure if this is an issue with the button being so small, or not.
#include "pitches.h"
int knob = A0;
int soprano = 11;
int alto = 10;
int tenor = 9;
int bass = 8;
int notes [15] = {NOTE_D3 , NOTE_E3 , NOTE_F3 , NOTE_G3 , NOTE_A4 , NOTE_B4 , NOTE_C4 , NOTE_D4 , NOTE_E4 , NOTE_F4 , NOTE_G4 , NOTE_A5};
//int whichNote = 0;
void setup() {
pinMode(soprano, INPUT);
pinMode(alto, INPUT);
pinMode(tenor, INPUT);
pinMode(bass, INPUT);
Serial.begin(9600);
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
int knobValue = analogRead(knob);
int sopranoState = digitalRead(soprano);
int altoState = digitalRead(alto);
int tenorState = digitalRead(tenor);
int bassState = digitalRead(bass);
Serial.println (sopranoState);
//mapping the potentiometer values from 0 - 800 for easy reference
int mappedValue = map(knobValue, 0, 1023, 0, 15);
//
if (sopranoState == HIGH) {
tone(4, notes[mappedValue]);
} else {
tone(4, 0);
}
if (altoState == HIGH) {
tone(4, notes[(mappedValue -2 )]);
} else {
tone(4, 0);
}
if (tenorState == HIGH) {
tone(4, notes[(mappedValue- 6)]);
} else {
tone(4, 0);
}
if (bassState == HIGH) {
tone(4, notes[(mappedValue- 8)]);
} else {
tone(4, 0);
}
}
My first thing to do this week was to brainstorm some ideas. My most prominent one was that I really wanted to play with many lights, almost like a carousel of lights. After noting down some random notes, I decided to aim for a code in which I could have a bunch of lights, and have my analogue reader blend through the lights. In this case I wanted to use the potentiometer, just because it seemed the most appropriate for me.
Setting up the circuit was much smoother than last week for me, I knew what I was doing way more. The first thing i needed to do was get the code to work where the lights would pass through. It came really easy for me, I just mapped the analogue reads from 0 – 800, just because that could make it easily divisible by 8 (my number of lights), without changing the values too much. Then I created a bunch of if-statements on when to light up. When I first did this, it made the leds light up and not shut off. Although this was also a cool effect, it wasnt what I wanted. I figured this out using ‘else statements.’
But that gave me the idea on what to use with a digital reading. I decided that once the button was clicked, the setting would change, and the led’s would turn on one after the other without turning each off as they go. After that, I realised I faced an issue where once they were all on, there would be no way (in that setting to turn them off). While washing my dishes, I kept thinking about how to code a way to fix that, and I found it. I measured the previous analogue reading, if it was higher than the current one that means the pattern was moving down, so I set the LED’s to turn off. If the previous reading was lower, the pattern was moving up, making the LED’s turn on. This meant switching the direction of the potentiometer would change whether you are turning the lights on or off.
Finally, I started adding some small features (such as all the lights turning on at the highest reading, and debugging). Here is the final project ! (I accidentally filmed vertically)
int button = 2;
int led1 = 3;
int led2 = 4;
int led3 = 5;
int led4 = 6;
int led5 = 7;
int led6 = 8;
int led7 = 9;
int led8 = 10;
bool buttonState = false;
bool prevState = false;
int knob = A0;
int prevLed = 0;
void setup() {
// put your setup code here, to run once:
pinMode(button,INPUT);
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(led5,OUTPUT);
pinMode(led6,OUTPUT);
pinMode(led7,OUTPUT);
pinMode(led8,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
changeState();
int knobValue = analogRead(knob);
//mapping the potentiometer values from 0 - 800 for easy reference
int mappedValue = map(knobValue, 0,1023, 0, 800);
//Button setting 1: where each light only appears individually
if (buttonState == false){
if (mappedValue >= 0 && mappedValue <100){
digitalWrite(led1, HIGH);
} else {
digitalWrite(led1, 0);
}
if (mappedValue >= 100 && mappedValue <200){
digitalWrite(led2, HIGH);
} else {
digitalWrite(led2, 0);
}
if (mappedValue >= 200 && mappedValue <300){
digitalWrite(led3, mappedValue );
} else {
digitalWrite(led3, 0);
}
if (mappedValue >= 300 && mappedValue <400){
digitalWrite(led4, mappedValue );
} else {
digitalWrite(led4, 0);
}
if (mappedValue >= 400 && mappedValue <500){
digitalWrite(led5, mappedValue );
} else {
digitalWrite(led5, 0);
}
if (mappedValue >= 500 && mappedValue <600){
digitalWrite(led6, mappedValue );
} else {
digitalWrite(led6, 0);
}
if (mappedValue >= 600 && mappedValue <700){
digitalWrite(led7, mappedValue );
} else {
digitalWrite(led7, 0);
}
if (mappedValue >= 700 && mappedValue <800){
digitalWrite(led8, mappedValue );
} else {
digitalWrite(led8, 0);
}
//if the potentiometer is at its max, all lights turn on
if (mappedValue ==800 ){
digitalWrite(led1, mappedValue );
digitalWrite(led2, mappedValue );
digitalWrite(led3, mappedValue );
digitalWrite(led4, mappedValue );
digitalWrite(led5, mappedValue );
digitalWrite(led6, mappedValue );
digitalWrite(led7, mappedValue );
digitalWrite(led8, mappedValue );
}
}
//button state 2, where the lights turn on and off after one another
if (buttonState == true){
//if analogue is increasing, they are turning on
if (prevLed <= mappedValue){
if (mappedValue >= 0 && mappedValue <100){
digitalWrite(led1, HIGH);
prevLed = mappedValue;
}
if (mappedValue >= 100 && mappedValue <200){
digitalWrite(led2, HIGH);
prevLed = mappedValue;
}
if (mappedValue >= 200 && mappedValue <300){
digitalWrite(led3, mappedValue );
prevLed = mappedValue;
}
if (mappedValue >= 300 && mappedValue <400){
digitalWrite(led4, mappedValue );
prevLed = mappedValue;
}
if (mappedValue >= 400 && mappedValue <500){
digitalWrite(led5, mappedValue );
prevLed = mappedValue;
}
if (mappedValue >= 500 && mappedValue <600){
digitalWrite(led6, mappedValue );
prevLed = mappedValue;
}
if (mappedValue >= 600 && mappedValue <700){
digitalWrite(led7, mappedValue );
prevLed = mappedValue;
}
if (mappedValue >= 700 && mappedValue <800){
digitalWrite(led8, mappedValue );
prevLed = mappedValue;
}
//if analogue is decreasing, they are turning off
} else if (prevLed >= mappedValue){
if (mappedValue >= 0 && mappedValue <100){
digitalWrite(led1, 0);
prevLed = mappedValue;
}
if (mappedValue >= 100 && mappedValue <200){
digitalWrite(led2, 0);
prevLed = mappedValue;
}
if (mappedValue >= 200 && mappedValue <300){
digitalWrite(led3,0 );
prevLed = mappedValue;
}
if (mappedValue >= 300 && mappedValue <400){
digitalWrite(led4, 0);
prevLed = mappedValue;
}
if (mappedValue >= 400 && mappedValue <500){
digitalWrite(led5, 0 );
prevLed = mappedValue;
}
if (mappedValue >= 500 && mappedValue <600){
digitalWrite(led6, 0 );
prevLed = mappedValue;
}
if (mappedValue >= 600 && mappedValue <700){
digitalWrite(led7, 0);
prevLed = mappedValue;
}
if (mappedValue >= 700 && mappedValue <800){
digitalWrite(led8, 0 );
prevLed = mappedValue;
}
}
}
Serial.print(knobValue);
Serial.print(" ");
Serial.println(mappedValue);
}
//toggling the button state
void changeState() {
if (digitalRead(button) == HIGH && prevState == LOW) {
if (buttonState) {
buttonState= false;
} else if (!buttonState) {
buttonState= true;
}
}
prevState = digitalRead(button);
}
My first idea for this assignment was to create a sort of pattern game where the lights show a pattern, and you are required to mimic that pattern to unlock the fourth (blue light). Unfortunately, I wasn’t entirely sure how to accomplish that, so decided to experiment with other ideas. Here is what my code does:
Red button: turns on each led one at a time, consecutively, then all off.
Blue button: turns all LEDs on at the same time, for 3 seconds then turns them off.
Green button: usually just turns green like a regular switch, but when pushed after the red button, will turn on both green and red
Yellow button: does a pattern where two lights are turned on at once.
This assignment was particularly interesting because when I faced an issue, I was unsure whether I should debug from the code or from the physical board. At some points, even though I was sure that everything in the circuit was working fine, my green button never turned off and I began considering a fault in the circuit. (ultimately it was my code). I also faced a lot of problems getting the initial circuit to work, because of the number of wires and resistors, and small breadboard. Eventually what worked for me was colour coordinating the wires to the colors (i used white for power, instead of red just this time so that I could colour coordinate).
int greenButton = 2;
int greenLed = 3;
int yellowButton = 4;
int yellowLed = 5;
int redButton = 6;
int redLed = 7;
int blueButton = 8;
int blueLed = 9;
int redState = LOW;
int redButtonState = LOW;
void setup() {
// set pin modes
pinMode(redLed, OUTPUT);
pinMode(redButton, INPUT);
Serial.begin(9600);
pinMode(greenLed, OUTPUT);
pinMode(greenButton, INPUT);
Serial.begin(9600);
pinMode(yellowLed, OUTPUT);
pinMode(yellowButton, INPUT);
Serial.begin(9600);
pinMode(blueLed, OUTPUT);
pinMode(blueButton, INPUT);
Serial.begin(9600);
}
void loop() {
//green button that lights green regularly, but if pushed after the red button, the red lights up too
int greenState = digitalRead(greenButton);
Serial.println(greenLed);
digitalWrite(greenLed, greenState);
if (greenState == HIGH && redButtonState == HIGH){
digitalWrite(redLed, greenState);
delay(1000);
redButtonState = LOW;
}
int redState = digitalRead(redButton);
Serial.println(redLed);
digitalWrite(redLed, redState);
//yellow makes a pattern appear- two leds at a time
int yellowState = digitalRead(yellowButton);
Serial.println(yellowLed);
digitalWrite(yellowLed, yellowState);
if (yellowState == HIGH){
digitalWrite(blueLed, yellowState);
digitalWrite(yellowLed, yellowState);
delay(500);
digitalWrite(greenLed, yellowState);
digitalWrite(redLed, yellowState);
delay(500);
}
// turns all the leds at once, for 3 seconds
int blueState = digitalRead(blueButton);
Serial.println(blueLed);
digitalWrite(blueLed, blueState);
if (blueState == HIGH ) {
digitalWrite(redLed, blueState);
digitalWrite(greenLed, blueState);
digitalWrite(yellowLed, blueState);
delay(3000);
}
// turns each led one at a time with a one second delay
if (redState == HIGH) {
delay(1000);
digitalWrite(blueLed, redState);
delay(1000);
digitalWrite(greenLed, redState);
delay(1000);
digitalWrite(yellowLed, redState);
delay(1000);
digitalWrite(redLed, redState);
delay(1000);
redButtonState = HIGH;
}
}
Remind me to never create a sound-based game again.
This project was a roller coaster, there were some days where I would take the entire day just to debug one tiny thing, and some days where I could make a huge advancement with little resistance. Thankfully, I am happy to where I got.
Since I already had a python based code, starting the game was easy. Myfirst few elements, the image, the map, the player were easy to achieve, but it changed fast. When I got to the borders, I had to redo a large aspect of what it used to be. I refined them, which was time-consuming because of how I had to keep track of X and Y values of the borders since I individually drew them. Then figuring out the movement of the player in relation to the borders was a nightmare. It was nothing related to my previous code, and after spending the whole day on it, I resorted to pencil and paper, trying to figure out how to code the movement. Here’s my sad sketch:
After that celebratory dance, I was on to other elements, like the cats. This proved to be relatively easy, since I had coded this kind of thing before. You hit a cat, you die. It was simple. It was so easy, as a matter of fact, I thought it would be great if I would add another element, humans. I thought “they’re so simple, and I could just make it so that if I hit them, I lose points and time, I don’t die.” After spending a few hours sketching 5 illustrations of humans, and adding it to my code, I realised I had misjudged how ‘easy’ it was. My issue was that I had my code so that whenthe distance between the player and the object is less than an amount, the score decreases. The issue with this is that it would continuously decrease until the object is out of bounds when I just wanted it to decrease once. Eventually, I did it in a way where once it hits the object, a boolean is triggered to true, you lose the points, and then after 1 second, the boolean goes back to false, and you can hit it again. (you probably shouldn’t though).
Other elements I was excited to add were things like adding a score, where it was calculated based on your time (the faster the better) and each sound you find, and it tells you your score at the end. (A very small thing I added was changing the score to green when it’s positive, red when it’s negative). Another thing was also adding a tally on the top left of the screen, to see how many sounds left to find, as playing it I realized I was always wondering how many I had left.
Another element I added (although it doesn’t look as nice as I wanted it to), was having the location you are at glow in gold for a second to indicate that you found the sound in that spot. I also made a ‘ding’ sound to be heard when you get a point, so that you know it happened. I changed the main players’ face to my off-brand illustration of the NYUAD falcon, which I’m not a fan of, but someone pointed out to me that with the addition of humans, the player cannot be sure which one they are controlling.
The sound was tricky, because there were so many bugs that kept showing up. Java only allows sound in the main program, not in classes, so I had to keep experimenting and trying to see how to fix these issues. For example, having the sounds in an array didn’t work. Often times the sounds would overlap because of the draw loop triggered over and over again, especially when mixed with restarting, the sounds would layer over each other. My main solution was to make sure that when the game runs, all the sounds are playing but on mute, so when a location is triggered, the sound unmutes, instead of just playing at a random tempo. Also made sure for the song to keep playing when you win, so you can hear your music, but to stop playing when you die.
Moving on to the restart, instruction, and game over screens. These where also a struggle to figure out, because instead of having most of my initiations in a class like I would normally do, I had it in the main page to correlate with the sounds. Eventually, I figured it out, having functions for each screen, and then debugging for a while. I also had to redesign a few elements for the screens.
int gameScreen = 0;
PImage dead, won, instructions;
boolean trigger = false;
Game game;
Creature creature;
Cats[] cats;
Humans[] humans;
Borders[] horizentalBorders;
Borders[] verticalBorders;
Locations[] locations;
//SoundFile[] sounds;
SoundFile backgroundSound, meow, ding, baraha, alarm, dining, library, knock, palms, theatre;
void setup() {
//This trigger is just fir the cat meow
trigger = false;
creature = new Creature (50, 450, 10);
game = new Game (1024, 786, 585);
cats = new Cats[3];
humans = new Humans[3];
//for displaying the cats and humans, in random places and speeds
for ( int g = 0; g< 3; g++) {
cats[g] = new Cats (int(random(200, 900)), int(random(200, 600)), 15, 70, 70, 200, 800);
humans[g] = new Humans (int(random(200, 900)), int(random(200, 900)), 15, 70, 70, 200, 800);
}
//Creating the locations for the sound to br triggered. These dont change
locations = new Locations[7];
locations[0] = new Locations (250, 270, 100); // library
locations[1] = new Locations ( 250, 470, 100); // Palms
locations[2] = new Locations (400, 310, 50); //baraha
locations[3] = new Locations (790, 250, 100); //theatre
locations[4] = new Locations (950, 400, 100); //dining
locations[5] = new Locations (800, 620, 200); // knock
locations[6] = new Locations (570, 570, 200); // alarm
size(1024, 768);
background(255, 255, 255);
//borders of the map, where you cannot enter from
horizentalBorders = new Borders[14];
verticalBorders = new Borders[13];
horizentalBorders[1] = new Borders (444, 286, 575, 286); //h
horizentalBorders[2] = new Borders (442, 346, 520, 346); //h
horizentalBorders[3] = new Borders (402, 470, 502, 470); //h
horizentalBorders[4] = new Borders (590, 472, 712, 472); //h
horizentalBorders[5] = new Borders (754, 493, 812, 493); //h
horizentalBorders[6] = new Borders (70, 175, 440, 175); // h
horizentalBorders[7] = new Borders (70, 375, 422, 375); //h
horizentalBorders[8] = new Borders (310, 725, 970, 725); //h
horizentalBorders[9] = new Borders (530, 527, 586, 527); //h
horizentalBorders[10] = new Borders (536, 595, 586, 595); // h
horizentalBorders[11] = new Borders (350, 614, 396, 614); //h
horizentalBorders[12] = new Borders (754, 602, 808, 602); // h
horizentalBorders[0] = new Borders (756, 640, 808, 640); // h
verticalBorders[12] = new Borders (440, 175, 440, 270); //h
verticalBorders[1] = new Borders (540, 346, 540, 455); //v
verticalBorders[2] = new Borders (582, 286, 582, 456);// v
verticalBorders[3] = new Borders (70, 175, 70, 375); //v
verticalBorders[4] = new Borders (310, 572, 310, 725); //v
verticalBorders[5] = new Borders (970, 525, 970, 725); // v
verticalBorders[6] = new Borders (775, 675, 775, 720); // v
verticalBorders[7] = new Borders (800, 675, 800, 720); //v
verticalBorders[8] = new Borders (586, 527, 586, 595); // v
verticalBorders[9] = new Borders (536, 529, 536, 595); //v
verticalBorders[10] = new Borders (396, 614, 396, 664); //v
verticalBorders[11] = new Borders (808, 602, 808, 640); // v
verticalBorders[0] = new Borders (756, 602, 756, 640); // v
//if you die- page
dead = loadImage("sorry.png");
//if you win - page
won = loadImage("finalpage.png");
//instructional page
instructions = loadImage("instructions.png");
//loading the sounds of the song
backgroundSound = new SoundFile(this, "OriginalBacktrack.mp3");
baraha = new SoundFile(this, "CardSwipe.mp3");
knock= new SoundFile(this, "Knock_RA.mp3");
theatre = new SoundFile(this, "SneezeCough.mp3");
library = new SoundFile(this, "Typing_clicking.mp3");
palms = new SoundFile(this, "Birds.mp3");
dining = new SoundFile(this, "Didyoudothereading.mp3");
alarm = new SoundFile(this, "iPhoneAlarm.mp3");
meow = new SoundFile(this, "meow.mp3");
ding = new SoundFile(this, "Ding.mp3");
//playing all the sounds in loop for easier restart (less bugs), all on mute except background,
// this is so that whenever they are triggered they are still on tempo for the song
backgroundSound.play();
baraha.loop();
baraha.amp(0.0);
knock.loop();
knock.amp(0.0);
theatre.loop();
theatre.amp(0.0);
library.loop();
library.amp(0.0);
dining.loop();
dining.amp(0.0);
alarm.loop();
alarm.amp(0.0);
meow.amp(0.5);
//restart();
}
void sound() {
// locating each location for their respective sound, because an array of sounds did not work
if ( locations[0].trigger == true) {
library.amp(1.0);
println("library");
}
if ( locations[1].trigger == true) {
palms.amp(1.0);
}
if ( locations[2].trigger == true) {
baraha.amp(1.0);
}
if ( locations[3].trigger == true) {
theatre.amp(1.0);
}
if ( locations[4].trigger == true) {
dining.amp(1.0);
}
if ( locations[5].trigger == true) {
knock.amp(1.0);
}
if ( locations[6].trigger == true) {
alarm.amp(1.0);
}
}
void initScreen() {
//initial screen, instruction page
image(instructions, 0, 0);
text("Click anywhere to begin ! ", 300, 700);
}
void restart() {
// upon restart
// this was a response to a cat bug
trigger = false;
creature = new Creature (50, 450, 10);
game = new Game (1024, 786, 585);
cats = new Cats[3];
humans = new Humans[3];
for ( int g = 0; g< 3; g++) {
cats[g] = new Cats (int(random(200, 900)), int(random(200, 600)), 15, 70, 70, 200, 800);
humans[g] = new Humans (int(random(200, 900)), int(random(200, 900)), 15, 70, 70, 200, 900);
}
locations = new Locations[7];
locations[0] = new Locations (250, 270, 100); // library
locations[1] = new Locations ( 250, 470, 100); // Palms
locations[2] = new Locations (400, 310, 50); //baraha
locations[3] = new Locations (790, 250, 100); //theatre
locations[4] = new Locations (950, 400, 100); //dining
locations[5] = new Locations (800, 620, 200); // knock
locations[6] = new Locations (570, 570, 200); // alarm
backgroundSound.loop();
baraha.loop();
baraha.amp(0.0);
knock.loop();
knock.amp(0.0);
theatre.loop();
theatre.amp(0.0);
library.loop();
library.amp(0.0);
dining.loop();
dining.amp(0.0);
alarm.loop();
alarm.amp(0.0);
//meow.loop();
meow.amp(0.5);
}
void draw () {
// to make it easier which game scteen we are on
if (gameScreen == 0) {
// instructions page
initScreen();
} else if (gameScreen == 1) {
// the game
gameScreen();
} else if (gameScreen == 2) {
// if you lose
gameOverScreen();
} else if (gameScreen == 3) {
// if you win
gameWinScreen();
}
}
void gameScreen() {
game.display();
creature.display();
for ( int g = 0; g< 3; g++) {
cats[g].display();
humans[g].display();
}
for ( int n = 0; n < 12; n ++) {
horizentalBorders[n].displayBorders();
}
for ( int m = 0; m < 13; m ++) {
verticalBorders[m].displayBorders();
}
for ( int l = 0; l <7; l ++) {
// checking if the locations are triggered
locations[l].display();
locations[l].trigger();
}
if (game.count <= 0) {
// if the time runs our, you lose
creature.alive = false;
creature.win = false;
}
if (creature. alive == false && creature.win == true) {
// if you win
gameScreen=3 ;
gameWinScreen();
}
if (creature. alive == false && creature.win == false) {
// if you lose
gameScreen=2 ;
gameOverScreen();
}
}
void gameOverScreen() {
// lost screen
image (dead, 187, 59);
}
void gameWinScreen() {
// won screen, dsplaying score as well
image (won, 187, 59);
text("Your Score: " + int(game.scorecount), 420, 420);
}
void mouseClicked() {
if ( gameScreen == 0) {
gameScreen= 1;
}
if (gameScreen == 2 || gameScreen == 3) {
restart();
gameScreen= 1;
println("restart");
}
}
// class borders for the map
class Borders{
float x, y, x2, y2;
Borders (int _x, int _y, int _x2, int _y2 ){
x = _x;
y = _y;
x2 = _x2;
y2 = _y2;
}
void displayBorders(){
//stroke(200);
noStroke();
line(x,y,x2,y2);
}
}
// creature cats
class Cats {
float x, y, r, w, h, x1, x2;
float vy = 0;
float vx = 0;
boolean alive = true;
PImage img;
Cats (float _x, float _y, int _r, int _w, int _h, int _x1, int _x2) {
x = _x;
y = _y;
r = _r;
vy = 0;
vx = random(1, 3);
w = _w;
h = _h;
x1 = _x1;
x2 = _x2;
// picking a random image of the 3 cat versions
img = loadImage("cat" + str(int(random(1, 4))) + ".png");
}
void display() {
update();
noFill();
noStroke();
image( img, x-r, y-r, 50, 50);
circle(x, y, r*2);
}
void update() {
// movement of the cats
y += vy;
x += vx;
// for the cats to move back and forth
if (x < x1) {
vx *= -1;
} else if ( x > x2) {
vx *= -1;
}
}
float distance(int tarX, int tarY) {
// to calculate the distance between the cat and another object
return (pow( (pow(( x - tarX), 2) + pow((y - tarY), 2)), 0.5));
}
boolean trigger() {
return false;
}
}
//Clas for player
class Creature {
int x, y, r;
float vy = 0;
float vx = 0;
int directionH = 0;
int numloc = 0;
boolean alive = true;
boolean win = false;
boolean borderCheckY = true;
boolean borderCheckX = true;
PImage img, green;
boolean leftKey = false;
boolean rightKey = false;
boolean upKey = false;
boolean downKey = false;
int previousTime = 0;
float timePassed = 1000;
Creature (int _x, int _y, int _r) {
x = _x;
y = _y;
r = _r;
vy = 0;
vx = 0;
img = loadImage("player.png");
}
void sound() {
// function to equate each sound to its respective location, play the sound upon trigger
if ( locations[0].trigger == true) {
library.amp(1.0);
}
if ( locations[1].trigger == true) {
palms.amp(1.0);
}
if ( locations[2].trigger == true) {
baraha.amp(1.0);
}
if ( locations[3].trigger == true) {
theatre.amp(1.0);
}
if ( locations[4].trigger == true) {
dining.amp(1.0);
}
if ( locations[5].trigger == true) {
knock.amp(1.0);
}
if ( locations[6].trigger == true) {
alarm.amp(1.0);
}
}
void display() {
update();
noFill();
noStroke();
image( img, x-r, y-r, 50, 50);
circle(x, y, r*2);
}
void update() {
keyPressed();
y += vy;
x += vx;
// for movement of the player and keys + game borders
if ( leftKey == true && x>=0) {
directionH = 1;
vx = -1;
} else if ( rightKey == true && x + r <= 1024) {
vx = 1;
directionH = 0;
} else if ( downKey == true && y +r <= 784) {
vy = 1;
} else if ( upKey == true && y >= 0 ) {
vy = -1;
} else {
vx = 0;
vy = 0;
}
// checking for collision of map borders
collisionY();
collisionX();
for ( int g = 0; g< 3; g++) {
if (cats[g].distance(x, y) <= r +cats[g].r ) {
// when player hits a cat
if (trigger == false) {
// mouse sound effect + you die, and the sounds stop
meow.play();
palms.amp(0.0);
baraha.amp(0.0);
library.amp(0.0);
theatre.amp(0.0);
dining.amp(0.0);
knock.amp(0.0);
alarm.amp(0.0);
println("meow");
trigger = true;
alive = false;
win = false;
}
}
// if you hit a human, your score goes down, and you lose 10 seconds off your timer
if (humans[g].distance(x, y) <= r +humans[g].r) {
if (humans[g].trigger == false) {
game.count -=10;
game.scorecount-=20;
previousTime = millis();
humans[g].trigger = true;
game.display();
}
if ( millis() > previousTime + timePassed) {
previousTime= millis();
humans[g].trigger = false;
}
}
}
// probably one of the most important parts. Code to see if you hit a location
for ( int o = 0; o< 7; o++) {
if (locations[o].trigger == false) {
if (locations[o].distance(x, y) <= 20) {
locations[o].trigger = true;
if (tally.size() >0) {
// adds to your score
numloc +=1;
game.scorecount += ((120 - (millis()/1000))*creature.numloc);
println(game.scorecount);
// removes a string on top left to see how many you have left
tally.remove(0);
locations[o].display2();
// ding as an indicator that you got one
ding.play();
sound();
//image (green, height, width);
println(tally);
}
}
// check for a win. If the string length == 0, you won
} else if (tally.size() == 0) {
win = true;
alive = false;
}
}
}
// checking to see if you hit the horizontal borders. makes you stop moving
void collisionY() {
for (int i = 0; i <13; i++ ) {
if ( vy + y + r >= horizentalBorders[i].y &&
vx + x + r >= horizentalBorders[i].x &&
x + vx +r <= horizentalBorders[i].x2 &&
vy + y + r <= horizentalBorders[i].y2) {
vy = 0;
}
}
}
// collision with vertical borders.
void collisionX() {
for (int j = 0; j < 11; j++) {
if ( vx + x + (r*2) <= verticalBorders[j].x &&
vx + x + (r*2) >= verticalBorders[j].x2 &&
y + vy + r >= verticalBorders[j].y &&
vy + y + r <= verticalBorders[j].y2) {
//println("stop3");
vx = 0;
}
}
}
// equating key pressed with players movements
void keyPressed() {
if (keyPressed && keyCode == LEFT ) {
leftKey = true;
} else {
leftKey = false;
}
if (keyPressed && keyCode == RIGHT) { //&& x+r <= game.w
rightKey = true;
} else {
rightKey = false;
}
if (keyPressed && keyCode == UP) {
upKey = true;
} else {
upKey = false;
}
if (keyPressed && keyCode == DOWN) { // && y+r <= game.h
downKey = true;
} else {
downKey = false;
}
}
float distanceCreature(int tarX, int tarY) {
return (pow( (pow(( x - tarX), 2) + pow((y - tarY), 2)), 0.5));
}
}
import processing.sound.*;
PImage img;
StringList tally;
class Game {
float w, h, g;
int count = 120;
float scorecount = 0;
Game(int _w, int _h, int _g) {
w = _w;
h = _h;
g = _g;
img = loadImage("map.jpg");
tally = new StringList("I", "I", "I", "I", "I", "I", "I" );
}
void display () {
// map image
image (img, 0, 0);
fill (0, 0, 0);
textSize(25);
// 3d effect on timer
text("Time Remaining: " + count, 365, 50);
fill(255, 255, 255);
textSize(25);
text("Time Remaining: " + count, 363, 48 );
fill (255, 255, 255);
// displaying the tally on the left
for (int i = 0; i <tally.size(); i++) {
text (tally.get(i), 50+(i*10), 50);
}
fill(150, 17, 17);
for (int i = 0; i <tally.size(); i++) {
text (tally.get(i), 50+(i*10), 50);
}
fill (255, 255, 255);
text ("Score: " + int(scorecount), 850, 50);
// displaying score, with 3d effect and also green if positive, red if negative
if (scorecount <=0) {
fill(150, 17, 17);
text ("Score: " + int(scorecount), 849, 49);
} else if (scorecount >=0) {
fill(17, 150, 17);
text ("Score: " + int(scorecount), 849, 49);
}
// for decreasing time
if (creature.alive == true) {
if (frameCount % 60 == 0) {
//println (frameCount);
count -=1;
}
if (count <= 0) {
creature.win=false;
creature.alive = false;
}
}
}
}
// creature cats
class Humans {
float x, y, r, w, h, y1, y2;
float vy = 0;
float vx = 0;
boolean alive = true;
PImage img;
boolean trigger = false;
Humans (float _x, float _y, int _r, int _w, int _h, int _y1, int _y2) {
x = _x;
y = _y;
r = _r;
vx = 0;
vy = random(1, 3);
w = _w;
h = _h;
y1 = _y1;
y2 = _y2;
img = loadImage("human" + str(int(random(1, 6))) + ".png");
}
void display() {
update();
noFill();
noStroke();
image( img, x-r, y-r, 50, 50);
circle(x, y, r*2);
}
void update() {
y += vy;
x += vx;
if (y < y1) {
vy *= -1;
} else if ( y > y2) {
vy *= -1;
}
}
float distance(int tarX, int tarY) {
return (pow( (pow(( x - tarX), 2) + pow((y - tarY), 2)), 0.5));
}
boolean trigger() {
return false;
}
}
For the game I would like to do for this midterm, I am developing a game I created a year ago called Sounds Like NYUAD.
Concept:
The layout is the Nyuad campus, which I illustrated myself last year. The player’s goal is to find the hidden ‘sounds’ located in various NYUAD locations, and each sound is an addition to the final ‘song’ made up of NYUAD sounds. The sounds were also recorded, edited, and produced by me last year. In the song, there are sounds like the NYUAD birds, the Card Swipe, someone sneezing, and coughing (pre-covid times).
Implementation:
The main thing I have to make sure of is that all sounds begin at the same time, but remain muted until they are triggered. This is because it is crucial that all the sounds play like one song, and stay on beat to the song I am playing. When the player comes close to the marker, the sound will be triggered, and that part is added.
Process:
The game is currently coded on Python, and so translating it to Java is my first step. This is really exercising everything I learnt on Java, and also trying to keep track of which language I am using. Next I have some developments I would like to add, and bugs I would like to fix.
Adding a instruction page
More clear indicator when you trigger a sound (and fixing the bug when it is repeated twice).
Inidcating how many sounds are left
Hints/clues where to find them
Score calculated based on how many sounds + how fast
Leadership list
Fix bugs: such as cats and borders + A clear Indicator when you have hit a border
Sample:
Game game;
Creature creature;
Borders borders;
void setup(){
size(1024, 768);
background(255, 255, 255);
game = new Game ();
creature = new Creature ();
borders = new Borders ();
}
void draw (){
game.drawGame();
}
class Borders{
float x, y, x2, y2;
Borders (){
displayBorders();
}
void displayBorders(){
stroke(200);
line(x,y,x2,y2);
}
}
I’ve got to say, I was really disappointed when I was writing this title and I realized we were only on week 5 :/
I was really excited for this assignment, and the idea I wanted to create. I wanted to create a Mosaic Image. Unfortunately, because of time constraints and also << talent >> constraints, I decided to go for a more simple Interactive Image.
I had a few issues with creating the Mosaic image:
I could not find enough filler images on time – Especially ones that matched the final images
I had technical constraints, such as I didn’t know how to create a code that could go through several images and find a small (but not too small) section in one with an average RGB value to match the original image.
To accomplish this, it would have to be so many images that i would be able to zoom on each pixel and see the image, but when I zoom out I should still be able to make out what the original photo was
I had more, but these were some. I took a lot of time reading other codes online, but they were difficult to understand. I do still have it as a goal to accomplish a code like this, and hopefully, I’ll manage to do it.
For my actual assignment, my main obstacle was trying to understand the mechanism of my idea: which was to change the image upon hover. After I figured it out it seemed so simple, but sometimes I overthink things.
I also added interactivity where you can change the size of the ‘window’ you are viewing from, using the right or left arrows, which I thought added a nice touch.
Special thanks for my dog Coco, for being this week’s Model:
The second image is when she was younger (and no doubt much cuter, sorry Coco). It was also nice to play around with either using pixels/ellipses, and this image looked very… classy?
This was a disaster to figure out, but it was worth it at the end. (I had a very long victory dance).
My initial idea is that i wanted something on an animated text, with a ball moving around. I drew a sketch on procreate to illustrate:
My first of many hurdles was getting a font of mine to work. I kept getting errors, (and sometimes processing would display the text different than i expected). Next, I created two of the text, and placed them away from each other to mirror the illustration I had in mind. After trying and trying to figure out how to get the ball to slide like I did in my illustration, I decided to try something else. I used the example shown (The Bubble One) in class to create circles in each point, and wanted to print them out one by one so that the text could be drawn. After spending a full day on this (no really, a full day), I found my mistake -I had accidentally called noLoop();.
After that, it was pretty smooth. I figured out my speed, how I wanted it to look, as well as how to toggle the colour to make it fade from black to red back and forth.
import geomerative.*;
import java.util.concurrent.TimeUnit;
RFont font;
RPoint[] pnts;
float xValue = 0;
float yValue = 0;
int a = 175;
int i = 0;
int previousTime = 0;
float timePassed = 0.1;
int r = 255;
boolean b = true;
void setup(){
frameRate(120);
background(255);
size (500, 500);
RG.init(this);
// set the font, the size, and left, center, or right adjusted
font = new RFont("LeckerliOne-Regular.ttf", 150, RFont.CENTER);
// get the points along a String
pnts = getPoints("Media");
System.out.println(pnts);
noFill();
//noLoop();
stroke(0,100);
}
void update () {
//stroke( 0, 0, 0, a);
noStroke();
fill( r, 0, 0);
circle(xValue, yValue, 6);
}
void draw() {
int time = -1;
pushMatrix();
translate(width/2, height/1.5);
if ( millis() > previousTime + timePassed){
previousTime= millis();
//println("it works");
if ( i <pnts.length ){
update();
if ( r >= 0 && b == true){
r -= 1;
b = true;
}
else if (r == 225 && b == false){
r -= 1;
b = true;
}
else {
r +=1;
b = false;
}
//float diam = random(5,15);
xValue = pnts[i].x;
yValue = pnts[i].y;
i++;
//System.out.println("This is Xvalue:" + xValue);
//System.out.println("This is yvalue:" + yValue);
}
}
popMatrix();
}
// function that returns an array of RPoints based on a string
RPoint[] getPoints(String str) {
// change this number to change the resolution of points outlining the circle
RCommand.setSegmentLength(1);
RCommand.setSegmentator(RCommand.UNIFORMLENGTH);
RGroup grp;
grp = font.toGroup(str);
grp = grp.toPolygonGroup();
return grp.getPoints();
}
void mousePressed(){
xValue-=1;
update();
}