Final Documentation

PROJECT

The journey through the final project has been quite a hurdle. In the initial stages, I wanted to simulate music concerts that required a dark room and little to no noise which would have been an issue given my observations today. As I was experimenting with music visualizations, I developed the idea to build a music box with cool LEDs dancing and screen visualization. One issue that was pointed out in class was the isolation of the components. I needed to think of a way to make my project holistic. That’s when I started thinking of Bob the Bot, the humanoid bot with a box head, and hands, and a screen as a body. This also came with its challenges but led to my discovery of two ball-like foamy materials for the final project. After spending a lot of time switching ideas, building and disabling different circuits, and trying to create a story with bob the bot, I decided to think about ways of achieving the expectations of the final projects in the time constraints. I was ready to work with what I had and understood for class.

For the final project which was demonstrated at the showcase, I extended the grab the food game I built earlier in the semester. I incorporated the two ball-like materials found earlier as controllers for the game and a button for restart. The two balls had in the force sensors to detect the force to which a user is squeezing the ball to translate into movement on processing. My main goal was to ensure that the interaction was clear to the user so the ball located on the left-hand side was to control left movements, the right-hand ball was to control right-hand movements. I had some texts on the screen to signify users if they don’t have an idea of how to approach it. Even though the addition was small, it really improved the user experience, and almost all the users who tried the game enjoyed interacting with the softballs to control objects on the screen.

Below are some of the videos of users interacting with the project at the showcase.

 

The code can be found on https://github.com/eric-asare/IM-Final

REFLECTIONS

I really enjoyed my time in class and working on all the assignments and projects. I am grateful for the discussions, and lessons that deepened my understanding of interactivity. Have a great winter break.😊

Work on Final Project : Bob the Bot

Final Project Idea 

My core idea for the final project was to integrate lights, music, and a screen.

I was initially going to do a music concert simulation but was challenged to be more creative. That’s was the beginning of Bob the Bot. Bob the Bot is a humanoid bot. Its head is a box and its body is a screen. For more details about the project plan, the sketches, and interactivity,  check the BobTheBot document.

 

 

  1. Refer to BobTheBot document for the role of Arduino and Processing.

I love music and light work so being able to work the music,  screen visualization, and lig ht simulation into the story for my final project made the building process more enjoyable and worth it in the end.

Process

Phase 1

Building the head

 

 

Coding

– Arduino

int angryEyes = 0; //false


const int buttonPin = 13;


void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
// change delay to wait()
  
  while (Serial.available()) {
    angryEyes = Serial.parseInt();
//    leftEye = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(2, angryEyes);
      digitalWrite(4, angryEyes);
      bool buttonState = digitalRead(buttonPin);
      delay(1);
      int sensor = analogRead(A0);
      delay(1);
      int sensor2 = analogRead(A1);
      delay(1);
      Serial.print(buttonState);
      Serial.print(',');
      Serial.print(sensor);
      Serial.print(',');
      Serial.println(sensor2);
    }
  }
}

-Processing

import processing.serial.*;
Serial myPort;
int xPos=0;
int yPos=0;
int currentStateOfPet = 1;
int prevStateOfPet = 0;
int petCount = 0;

PGraphics intro;
PGraphics second;
PFont f;

boolean onOff=false;


void setup(){
  //size(960,720);
  fullScreen();
  printArray(Serial.list());
  String portname=Serial.list()[4];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  
  intro = createGraphics(width, height);
  smooth(8);
  
  f = createFont("Arial", 48, true);
  
  //create an image made of text
  intro.beginDraw();
  intro.background(0);
  intro.fill(255);
  intro.textSize(80); // change text size
  intro.textAlign(CENTER);
  intro.textFont(f,80); // change font size
  intro.text("HI THERE", intro.width/2, intro.height/2 -100);
  intro.text("I'M BOB", intro.width/2, intro.height/2);
   intro.text("PET ME - ON MY HEAD", intro.width/2, intro.height/2+100);
  intro.endDraw();
  
  //second stage
  //create an image made of text
  //second.beginDraw();
  //second.background(0);
  //second.fill(255);
  //second.textSize(80); // change text size
  //second.textAlign(CENTER);
  ////second.textFont(f,100); // change font size
  //second.text("ONE MORE !!!!", intro.width/2, intro.height/2);
  //second.endDraw();
 
}

void draw(){
  background(0);

  if (onOff){
    
    textSize(80);
    textAlign(CENTER);
    text("ONE MORE!!!", width/2, height/2);
  }
  else{
      image(intro,0,0);
  }
 

  // 0 is HIGH (not pressed) , 1 is LOW ( Pressed)
  if (currentStateOfPet == 0 && prevStateOfPet == 1){
      onOff= !onOff;
    }
    
    prevStateOfPet = currentStateOfPet;
}

void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[]=int(split(s,','));
    if (values.length==3){
      currentStateOfPet = values[0];
      xPos=(int)map(values[1],0,1023,0, width);
      yPos=(int)map(values[2],0,1023,0, height);
      
    }
  }
  println(onOff);
  myPort.write(int(onOff)+"\n");
}
User Testing

Testing the first and second phases of Bob The Bot

 

Feedback / Next steps
  1. Be more creative with the visualization on-screen and music box head
  2. Ensure consistency of Interaction
  3. Make Interaction clear
  4. Use signifiers and cognitive mapping, etc.)

Attribution  Sleep Like A Child by MusicLFiles Link: https://filmmusic.io/song/7828-sleep-like-a-child License: https://filmmusic.io/standard-license http://responsivedesign.de/wp-content/uploads/2016/05/tutorial-06_processing-soundmapping2.pdf

Final Project Progress

Description

Finalize your idea,  determine whether it’s going to be a group/solo arrangement,  identify the materials/space you need, and identify what you think will be hardest to complete. Post your progress on the project so far.

Idea

For the final project, I would be creating music or sound visualizer.  There will be two forms of visualization. One on the screen and the other through a LED strip. The project will be reactive to sound made by the user or played by the user. I would be taking the input and analyzing the frequency to create the two visualizations. The LED strip will glow according to the rhythm of the music and the visualization will show the loudness or frequency of the music. Thinking of a very cool visualization.

Materials/ Space

  • A dark or low lit room
  • Laptop screen
  • Multicolored LEDs
  • Jump wires, Arduino, Transistor, Resistors

Hardest Part

Getting the Arduino and Processing to communicate. For now, I am going to use two different sources of input for both processing and Arduino. A sound sensor for Arduino and a computer’s microphone for Processing.

Progress

I have figured how to get input from the computer’s microphone and visualize. I have a ball which grows in size based on the amplitude of the sound

Final Project Proposal: Music Music

Description

Refine your final project proposal, including a finalized concept for the project, a description of what your Arduino program will do with each input and output and what it will send to and/or receive from Processing, and a description of what the processing program will do and what it will send to and/or receive from Arduino

Idea

For the final project, I want to simulate a music concert. I want to make a music rhythm visualizer both on screen and with LEDs such that a change in the music playing will change how the music is visualized.

Arduino

On the Arduino, I’m going to use a sensor to sense the rhythm of the music being played by a user.  I am also going to add multiple LEDs that will take the rhythm as input and dance to it. Depending on how this turns out, I am going to add a switch or sensor to send info to processing for a change in Music.

Processing

The processing at the same time receives the rhythm signals from the Arduino and shows a screen of the music visualization indicating the rise and fall of the beats.

The next step is to receive info from an Arduino sensor or switch to change the music being played as opposed to a user manually changing the music on a phone or device.

 

Serial Communication Examples

 Exercises 1

Make something that uses only one sensor on Arduino and makes the ellipse in processing move on the horizontal axis, in the middle of the screen, and nothing on Arduino is controlled by processing

– Arduino

int left = 0;
int right = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(2, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  // while the serial is available
  while (Serial.available()) {
    // info that we parse and send to processor 
    right = Serial.parseInt();
    left = Serial.parseInt();

    if (Serial.read() == '\n') {
      digitalWrite(2, right);
      digitalWrite(5, left);
      int sensor = analogRead(A0);
      delay(1);
      Serial.print(sensor);

    }
  }
}

 

– Processing

import processing.serial.*;
Serial myPort;
int xPos=0;
int yPos=0;
boolean onOff=false;
boolean onOff2=false;

void setup(){
  size(960,720);
  // print list of ports
  printArray(Serial.list());
  // find the arduino port in the list and choose the right index/port
  String portname=Serial.list()[3];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}

void draw(){
  background(255);
  // when mouse pressed, we change the onoff
  // if mouse is on right , turn on the light
  ellipse(xPos,height/2,30,30);
  
  if (mousePressed){
    if(mouseX<=width/2)
      onOff2=false;
    else
      onOff=false;
  }else{
    onOff=onOff2=true;
  }
  
}

void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[]=int(split(s,','));
    if (values.length==2){
      xPos=(int)map(values[0],0,1023,0, width);
    }
  }
  
 
  myPort.write(int(onOff)+","+int(onOff2)+"\n");
 
}

 

 Exercises 2

Make something that controls the LED brightness from processing
-Arduino
float brightness_led;

void setup() {
  Serial.begin(9600);
  Serial.println("0");
  pinMode(5, OUTPUT);
}

void loop() {
  while (Serial.available()) {
    
    brightness_led = Serial.parseFloat();
    
    if (Serial.read() == '\n') {
    
      analogWrite(5, brightness_led);
      Serial.println(brightness_led);
    }
  }
}


– Processing
import processing.serial.*;
Serial myPort;
int pos_x = 0;
int pos_y;

float brightness_led;

void setup() {
  size(960, 720);
  printArray(Serial.list());
  String portname=Serial.list()[5];
  println(portname);
  myPort = new Serial(this, portname, 9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}

void draw() {
  background(255);
  brightness_led = int(map(mouseX, 0, width, 0, 255));
  
  pos_y = height/2;
  ellipse(mouseX, pos_y, 30, 30);
}

void serialEvent(Serial myPort) {
  String s=myPort.readStringUntil('\n');
  s=trim(s);

  myPort.write(brightness_led+ "\n");
}

 Exercises 3

Take the gravity wind example and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor

-Processing

PVector velocity;
PVector gravity;
PVector position;
PVector acceleration;
PVector wind;
float drag = 0.99;
float mass = 50;
float hDampening;
int Mover = 0;

import processing.serial.*;
Serial myPort;
int speedWind;

int xPos=0;
int yPos=0;
boolean onOff=false;


void setup() {
  size(640,360);
  printArray(Serial.list());
  String portname=Serial.list()[5];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  
  noFill();
  position = new PVector(width/2, 0);
  velocity = new PVector(0,0);
  acceleration = new PVector(0,0);
  gravity = new PVector(0, 0.5*mass);
  wind = new PVector(0,0);
  hDampening=map(mass,15,80,.98,.96);
}

void draw() {
  background(255);
  if (!keyPressed){
    wind.x= speedWind;
    velocity.x*=hDampening;
  }
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x,position.y,mass,mass);
  if (position.y > height-mass/2) {
      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
    }
    
  
  
  println(velocity.y);
}


  
void applyForce(PVector force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  PVector f = PVector.div(force, mass);
  acceleration.add(f);
}

void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    
    int values[] = int(split(s,','));
    
    
    if (values.length == 2){
      if (values[0] > values[1]){
        speedWind = 10;
      }
      else if (values[0] < values[1]){
        speedWind = -10;
      }
      else if (values[1] == values[1]){
        speedWind = 0;
      }
    }
    
  }
    if (round(position.y + mass) > height && round(velocity.y)  != 0){
    onOff = true;
    }
    else{
      onOff = false;
    }
  
    myPort.write(int(onOff) + "\n");
  
}

void keyPressed(){
  if (keyCode==LEFT){
    wind.x=-1;
  }
  if (keyCode==RIGHT){
    wind.x=1;
  }
  if (key==' '){
    mass= random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}


– Arduino

int brightness = 0;
int previousValue = 0;
int moving = 0;
int onOff = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("0");
  pinMode(2, OUTPUT);
  
}
 
void loop() {
  while (Serial.available()) {
    onOff = Serial.parseInt();
    if (Serial.read() == '\n') {


      int sensor = analogRead(A0);
      delay(1);
      
      
      Serial.print(sensor);
      Serial.print(",");
      Serial.println(previousValue);

      previousValue = sensor;

      
      if (onOff == 1){
        analogWrite(2, 255);
      }
      else{
        analogWrite(2, 0);
      }
    }
  }
}

 Video

 

 

 

Rhythm & Eric : Melodic Piano

Description

 Rhythm and Eric are to make a musical instrument using at least one digital sensor(switch), and at least one analog sensor (photoresistor, potentiometer, or distance measuring sensor)

Idea

The piano is usually used to play two parts simultaneously. One musician plays all the chords and melody.  Chords and melodies both work together to create rhythm and harmony. A chord is when three or more notes are played together at the same time whilst melody is when single notes are played individually in a pattern or sequence.

Then comes the Eureka moment! We can have the melody which is 8 switches holding the single notes (do re me fa so la ti do)  and a chord which is a photoresistor that plays a melody using three or more notes.

Process

So the setup was done as described above, we had 8 switches connected in a row, a buzzer for sound, and a photoresistor. Each note above was connected to one switch. Data from the photoresistor was mapped to play a chord.

Final Work

 

Challenges

Our initial plan was to use 8 photoresistors and a switch but couldn’t figure how to connect the 8 photoresistors to Arduino. We experimented with the distance sensor as well but were getting a weird noise from the buzzer, we rechecked the connection and code but still couldn’t get it to work. We also had in mind to include drums but couldn’t get the buzzer to produce drum notes.

Code

-Main

#include "pitches.h"
int knobPin = A0;

int melody[] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5};
int noteDurations[] = {4, 8, 8, 4, 4, 4, 8, 4, 8, 4};

int duration = 100

// notes and their respective buttons
const int Dobbutton = 2;
const int Rebutton = 3;
const int Mibutton = 4;
const int Fabutton = 5;
const int Solbutton = 6;
const int Labutton = 7;
const int Tibutton = 8;
const int Dotbutton = 9;

// initial status of buttons
int DobButtonStatus = 0;
int ReButtonStatus = 0;
int MiButtonStatus = 0;
int FaButtonStatus = 0;
int SolButtonStatus = 0;
int LaButtonStatus = 0;
int TiButtonStatus = 0;
int DotButtonStatus = 0;


void setup()

{

  Serial.begin(9600);
  pinMode(knobPin, INPUT);


  pinMode(Dobbutton, INPUT);
  pinMode(Rebutton, INPUT);
  pinMode(Mibutton , INPUT);
  pinMode(Fabutton, INPUT);
  pinMode(Solbutton, INPUT);
  pinMode(Labutton, INPUT);
  pinMode(Tibutton , INPUT);
  pinMode(Dotbutton, INPUT);
}

void loop() {
  int ldrStatus = analogRead(knobPin);
  int mappedValue = map(ldrStatus, 0, 1023, 0, 255);
//  Serial.println(mappedValue);


  // check for photoresistor value and play chord
  
  if (mappedValue > 200 ) {
    for (int i = 0; i < 10; i++) {
      int noteDuration = 1000 / noteDurations[i];
      tone(10, melody[i], noteDuration);
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      noTone(10);

    }

  }

  
  //read state of buttons
  DobButtonStatus = digitalRead(Dobbutton);
  ReButtonStatus = digitalRead(Rebutton);
  buttonMistatus = digitalRead(Mibutton);
  FaButtonStatus = digitalRead(Fabutton);
  SolButtonStatus = digitalRead(Solbutton);
  LaButtonStatus = digitalRead(Labutton);
  TiButtonStatus = digitalRead(Tibutton);
  DotButtonStatus = digitalRead(Dotbutton);
  
  
  if (DobButtonStatus == HIGH) {
    tone(10, dot, duration); 
  }
  if (ReButtonStatus == HIGH) {
    tone(10, re, duration);
  }
  if (buttonMistatus == HIGH) {
    tone(10, mi, duration);
  }
  if (FaButtonStatus == HIGH) {
    tone(10, fa, duration);
  }
  if (SolButtonStatus == HIGH) {
    tone(10, sol, duration);
  }
  if (LaButtonStatus == HIGH) {
    tone(10, la, duration);
  }
  if (TiButtonStatus == HIGH) {
    tone(10, si, duration);
  }
  if (DotButtonStatus == HIGH) {
    tone(10, dot, duration);
  }


}




– Pitches.h

#define dot  264 //first do
#define re   297
#define mi   330
#define fa   352
#define sol  396
#define la   440
#define si   495
#define dot  528// last do



#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  80
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435

 

Night Light

Description

 Get information from at least one analog sensor and at least one digital sensor (switch), and use this information to control at least two LEDs, one in a digital fashion and the other is an analog fashion, in some creative way.

Inspiration

LEDs usually go with a college dorm. Two good things usually happen in a college dorm – a sound sleep or a loud party. I want to recreate these two scenarios using LEDs, an analog sensor, and a digital switch.

Process

From very well mind  ,the color blue is associated with the feeling of calmness or serenity. It is peaceful, tranquil, and secure which is great for sleep. Yet as a cool color, blue can sometimes seem icy, distant, or even cold. Hence can also lower the pulse rate and body temperature- the best conditions for sleep.

I didn’t have to do research for party LED, we can agree, we are going disco and loud.

This is how the setup is going to work. A dark room will stimulate the photosensor, turning on the blue led, it’s time to sleep. However, there is a button to switch to a party mode, with a lot of colorful lights.

 

 

Final Work

 

Challenges

I struggled for a long time in fixing the button to control the party LEDs. I tried different positions and connections on the breadboard to make it work. I tried to draw my circuit in an Arduino simulator Tinkercad but couldn’t get the hang of it. I had a lot of wires all over the breadboard, I needed a bigger breadboard.

Code
const int knob = A0;

//button
int buttonPin = 11;
bool onOff = false;
bool prevButtonState = LOW;

//sleep
const int led = 13;


//party
const int Led2=2;
const int Led3=3;
const int Led4=4;
const int Led5=5;
const int Led6=6;
const int Led7=7;
const int Led8=8;
const int Led9=9;



int i;
int c;


void setup() {
  Serial.begin(9600);
   
 pinMode(led, OUTPUT);
 pinMode(knob, INPUT);
 pinMode(buttonPin, INPUT);


  pinMode(Led2,OUTPUT);
  pinMode(Led3,OUTPUT);
  pinMode(Led4,OUTPUT);
  pinMode(Led5,OUTPUT);
  pinMode(Led6,OUTPUT);
  pinMode(Led7,OUTPUT);
  pinMode(Led8,OUTPUT);
  pinMode(Led9,OUTPUT);

}

void loop() {

   int knobValue = analogRead(knob);
  

 if (knobValue > 300){
    digitalWrite(led,HIGH);
  }
  

  else{
    digitalWrite(led,LOW);
    }

    
 bool currentState = digitalRead(buttonPin);
  
  if(currentState == HIGH && prevButtonState == LOW){
      onOff = !onOff;
      Serial.println(onOff);
      if (onOff == true){
        digitalWrite(led,LOW);
        party();
       }

       else{
        noParty();
        }
    }

      prevButtonState = currentState;
  
}

void party(){
  
  
for(i=1;i< 100;i++)
  {
    if(i%2==0)
    {
       digitalWrite(Led2,HIGH);
       digitalWrite(Led4,HIGH);
       digitalWrite(Led6,HIGH);
       digitalWrite(Led8,HIGH);
       digitalWrite(Led3,LOW);
       digitalWrite(Led5,LOW);
       digitalWrite(Led7,LOW);
       digitalWrite(Led9,LOW);
       wait(100);
      
    }
    else
    {
      digitalWrite(Led3,HIGH);
      digitalWrite(Led5,HIGH);
      digitalWrite(Led7,HIGH);
      digitalWrite(Led9,HIGH);
      digitalWrite(Led2,LOW);
      digitalWrite(Led4,LOW);
      digitalWrite(Led6,LOW);
      digitalWrite(Led8,LOW);
      wait(100);
     
    }
  }
  for(i=0;i<100;i++)
    {
      for(c=2;c<=i/2;c++)
      {
        if(i%c==0)
        {
          digitalWrite(Led2,HIGH);
          digitalWrite(Led4,HIGH);
          digitalWrite(Led6,HIGH);
          digitalWrite(Led8,HIGH);
          digitalWrite(Led3,LOW);
          digitalWrite(Led5,LOW);
          digitalWrite(Led7,LOW);
          digitalWrite(Led9,LOW);
          wait((i*10));
         
        }
      }
      if(c>i/2)
      {
        digitalWrite(Led3,HIGH);
        digitalWrite(Led5,HIGH);
        digitalWrite(Led7,HIGH);
        digitalWrite(Led9,HIGH);
        digitalWrite(Led2,LOW);
        digitalWrite(Led4,LOW);
        digitalWrite(Led6,LOW);
        digitalWrite(Led8,LOW);
        wait((i*10));
      }
    }
  
  
  }


  void noParty(){
     digitalWrite(Led2,LOW);
       digitalWrite(Led4,LOW);
       digitalWrite(Led6,LOW);
       digitalWrite(Led8,LOW);
       digitalWrite(Led3,LOW);
       digitalWrite(Led5,LOW);
       digitalWrite(Led7,LOW);
       digitalWrite(Led9,LOW);
    
    
    }

void wait(int period){
   long time_now = millis();
    while(millis() < time_now + period){
        //wait
    }
  
}

 

Handless Switch : Sleep No More!

Description

Create an unusual switch that doesn’t require the use of your hands. Use Arduino digital input and output for the interaction.

Inspiration

Imagine you could identify all the listeners who sleep during your speaking sessions even if the listener sleeping is at the backbench. All you need is a LED that is positioned at a visible location and turns on immediately, a listener puts his or her head on the table.

Process

I started off by creating a simple circuit with an LED. I added a digital input pin on the Arduino and then, with code, I take the input and turn on the LED as a digital output. By bringing together the power pinned down by the resistor and the buttonPin, the LED turns on and when separated goes off. In order to bring the two together, I attached one to the forehead and the other to the table.

Final Work

Challenges

I wanted to attach one of the cables to my neck and the other one under my chin but it never worked so I decided to go with the idea above.

Code
const int ledPin = 2;
const int buttonPin = 3;


bool onOff = false;
bool prevButtonState = LOW;

void setup() {
   pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT);

}

void loop() {
  
  bool currentState = digitalRead(buttonPin);
  
 if(currentState == HIGH){
      digitalWrite(ledPin, true);
    }

  else{
    
     digitalWrite(ledPin, false);
    }

     
   

}

 

Midterm : The Grab Food Game

Hello there, we are back in the game! Let’s start off by recalling the inspiration.

Inspiration

On a Saturday night, NYUAD students tend to have more meal swipes than they need. Students face the dilemma of either stacking more food with their extra swipes or losing all the swipes the next day.

The idea then is to create a game where the player (student) would try to collect as much food as it can on a movable food tray.

To win this game, just make the most of your meal swipes, just be patient and stack away as much food as you can. Choose wisely, more healthy food is worth more points. You gonna lose the meal swipes any way so the more points you acquire, the better.

Oh, don’t forget we are working with time ( the 30seconds surprise) 😄.

What were the next steps?

1.  Create the assets

2. Work on the game mechanics

3. Add sound to make it lively

4. working mainly on the gameplay screen and polishing the start and end screen

Assets

Created an Item Class that has a draw function and a method to check whether an item collides with another. Using inheritance, I created a Player class and a Food class.

Let me spare you the details and focus on the fun part. So now to create a player, I just needed to use an image of a tray. To create the food items, I just needed to use png images of the food I wanted.

Game Scenes

The game has three scenes. The starting page, the game window, and the win/restart page. The starting page has instructions on how to start the game. The user is informed of the countdown timer. In the game scene, there is the score on the top right, the timer on the top left. There is also the player (student holding tray) and falling food. The win/ restart page just shows the text, the score, and the key to press to restart the game.

Game Mechanics

So as mentioned earlier, when the game begins, the food starts falling, and the player has to navigate the tray to catch as much food as it can within 30 seconds. The healthier the food, the more points the player accumulates.

Sound

There is the main theme song playing in the background and a catching sound ( boip).

Demo

 

Challenges

Timer!

Yeah I know I mentioned this earlier but the timer was still printing  negative values. I solved this by  starting the timer once the user press ENTER to begin the game.

Sound!

Since my theme music is short, I was getting this weird noise when the game state changes. I had to check whether the theme was not  playing so that I can play it again.

Also, the theme sound was drowning the catch sound. I fixed this by reducing the volume of the theme music when the game starts.

Code

– Timer

//credit : http://www.cs.du.edu/~leut/1671/09_Fall/ProcessingNotes7.pdf
// converted the display into a countdown 

class Timer
{
  long startTime ; // time in msecs that timer started
  long timeSoFar ; // use to hold total time of run so far, useful in
  // conjunction with pause and continueRunning
  boolean running ;
  int x, y ; // location of timer output

  Timer(int inX, int inY)
  {
    x = inX ;
    y = inY ;
    running = false ;
    timeSoFar = 0 ;
  }


  int currentTime()
  {
    if ( running )
      return ( (int) ( (millis() - startTime) / 1000.0) ) ;
    else
      return ( (int) (timeSoFar / 1000.0) ) ;
  }

  void start()
  {
    running = true ;
    startTime = millis() ;
  }

  void restart()
    // reset the timer to zero and restart, identical to start
  {
    start() ;
  }

  void pause()
  {
    if (running)
    {
      timeSoFar = millis() - startTime ;
      running = false ;
    }
    // else do nothing, pause already called
  }

  void continueRunning()
    // called after stop to restart the timer running
    // no effect if already running
  {
    if (!running)
    {
      startTime = millis() - timeSoFar ;
      running = true ;
    }
  }




  void DisplayTime(int totalTime)
  {
    int theTime ;
    String output = "";

    theTime = currentTime() ;
    output = output + (totalTime - theTime) ;

    // println("output = " + output) ;
    fill(150, 0, 200) ;
    PFont font ;
    font = loadFont("Avenir-Black-48.vlw") ;
    textFont(font) ;
    text(output, x, y) ;
  }
}

– Objects

//game objects
class Item {
  PImage image;
  float xlocation;
  float ylocation;
  float _width;
  float _height;

  Item( PImage _image, float _xlocation, float _ylocation, float new_width, float new_height) {
    image = _image;
    xlocation = _xlocation;
    ylocation = _ylocation;
    _width = new_width;
    _height =new_height;
  }

  // draw item on screen
  void draw() {
    image(image, xlocation, ylocation, _width, _height);
  }

  //check intersection
  Boolean Intersect(Item newItem) {
    float itemwidth = newItem._width;
    float itemheight = newItem._height;
    float  itemxloc = newItem.xlocation;
    float itemyloc = newItem.ylocation;

    if (itemxloc < xlocation + _width &&
      itemxloc + itemwidth > xlocation &&
      itemyloc < ylocation + _height &&
      itemheight + itemyloc - 50
      > ylocation) {
      return true;
    }


    return false;
  }
}

class Player extends Item {
  
  Player( PImage _image, float xloc, float yloc, float w, float h) {
    super(_image,xloc, yloc, w , h);
  }
  
  void moveLeft(){
    if (xlocation - 10 > 0 ){
       xlocation -= 10;
    }
    
  }
  
  void moveRight(){
     if (xlocation+_width+10 < width ){
       xlocation += 10;
    }
  }

}


class Food extends Item {
  
  float speed;
  float originalspeed;
  int value;
  
  Food( PImage _image, float xloc, float _speed , int _value, float w, float h) {
    super(_image,xloc, random(-300, -100), w, h);
      speed = _speed;
      originalspeed = _speed;
      value = _value; // food value
  }
  
  
  
  //fall
  void fall(){
    ylocation = ylocation + speed;
    
    // add some velocity
    
    speed += 0.05;
    
    // reset to 
    if ( ylocation > height){
       ylocation = random(-300, -100);
       speed = originalspeed;
    }
  }
 

}

– Game

// game itself

class Game {

  PImage bgimage;
  PImage playerimage;
  PImage [] foodimages;
  
  SoundFile catchSound;
  SoundFile backgroundMusic;

  Timer timer;
  int totalGameTime;
 
  
  Player player;

  Boolean timeOut;
  int score;

  ArrayList<Food> Fooditems; 

  int foodspeed;
  

  Game(PImage _bgimage, PImage _playerimage, Timer _timer, PImage [] _foodimages, SoundFile _catchSound , SoundFile _backgroundMusic) {
    bgimage = _bgimage;
    playerimage = _playerimage;
    foodimages = _foodimages;
    timer = _timer;
    catchSound = _catchSound;
    backgroundMusic = _backgroundMusic;


    totalGameTime = 30; // 30 seconds
    timeOut = false;
   

    Fooditems = new ArrayList<Food>();

    score = 0;
    foodspeed = 3;
    
    player = new Player(playerimage, width/2, height - 80,200,100);
    createFood();
  }
  
  
  void play(){
    backgroundMusic.amp(0.1);
    
     if(!backgroundMusic.isPlaying()){
        backgroundMusic.play();
     }
     
    drawGameScene();
    moveFood();
    checkIntersection();
    checkGameOver();
  }
  
  void createFood(){
    // food value is based on food type
    // height and width of food is 10% of original size
    // the x coordinates of each food is random
     
     for ( int i = 1; i < 7; i++){
       int foodtype = int(random(5));
       Fooditems.add(new Food(foodimages[foodtype],random(30,width-100), foodspeed, foodtype,foodimages[foodtype].width*0.1,foodimages[foodtype].height*0.1));
     }
   
   
  }
   
  void drawGameScene(){
     timer.DisplayTime(totalGameTime);
     showScore();
    
    // draw fruits
    for (int i =0 ; i < Fooditems.size() ; i++){
      Fooditems.get(i).draw();  
    }
    
    // draw player
    player.draw();  
  }
  

  void moveFood(){
     for (int i =0 ; i < Fooditems.size() ; i++){
        Fooditems.get(i).fall();
    } 
  }
  
  // stockFood once one is removed from stack
  void stockFood(){
     int foodtype = int(random(5));
     Fooditems.add(new Food(foodimages[foodtype],random(30,width-100), foodspeed, foodtype,foodimages[foodtype].width*0.1,foodimages[foodtype].height*0.1));
     
  }
  
  
  // check if player touches food 
  
  void checkIntersection(){
    
     for (int i =0 ; i < Fooditems.size() ; i++){
       if (player.Intersect(Fooditems.get(i))){
           score  += Fooditems.get(i).value;
           Fooditems.remove(Fooditems.get(i));
           catchSound.play();
           stockFood();
       }
    }
  }
  
  
  void checkGameOver(){
     if(timer.currentTime() == totalGameTime){
        timeOut = true;
        timer.pause();
     }
     
  }
  
   void restartGame(){
     timer.restart();
     timeOut = false;
     score = 0;
   
   }
     
  
  
  void showScore(){
       fill(60);
       text("Score: " + str(score), width - 140, 60);
  }
  
  void showGameOver(){
    
     if(!backgroundMusic.isPlaying()){
        backgroundMusic.play();
     }
     
     
    
     backgroundMusic.amp(1.0);
   
     text("Meal swipes well spent!", width/2, 80);
       
     text("SCORE: " + str(score), width/2,height/2);
     
     text("Press R to restart ", width/2,height/2 + 100);
  
  }
  
  
}

– Main

import processing.sound.*;

// THE TWO MAIN SCREENS
// 0: Start Page (Instructions)
// 1: Game Window and Restart


SoundFile backgroundMusic;
SoundFile catchSound;

PImage backgroundImg;
PImage fruitImg;
PImage fruit2Img;
PImage playerImg;

PFont times;

int gameScreen = 0;

Timer timer ;

Game game1;

void setup() {
  size(640, 425);

  backgroundMusic= new SoundFile(this, "theme.mp3"); //change song length
  catchSound= new SoundFile(this, "boip.mp3");

  backgroundImg = loadImage("data/wood.jpg");

  playerImg =  loadImage("data/holdingplate.png");

  PImage [] foodsimgs = { loadImage("data/pizza.png"), loadImage("data/coke.png"),
    loadImage("data/fries.png"), loadImage("data/yoghurt.png"),
    loadImage("data/salad.png") };

  timer = new Timer(35, 60) ; // make the display at location (35,60)

  frameRate(30);
  

  game1 = new Game(backgroundImg, playerImg, timer, foodsimgs, catchSound, backgroundMusic);

  backgroundMusic.play();
}

void keyPressed() {
  if (key == CODED) {
    if (keyCode == LEFT) {
      game1.player.moveLeft();
    }

    if (keyCode == RIGHT) {
      game1.player.moveRight();
    }
  }
}



void draw() {
  

  if (gameScreen == 0) {
    startScreen();
  } else {
    background(game1.bgimage);
    if (!game1.timeOut) {
      game1.play();
    } else {
      game1.showGameOver();

      if (keyPressed && (key == 'R' || key == 'r') ) {
        game1.restartGame();
      }
    }
  }
}


void startScreen() {
  background(loadImage("data/market.png"));
  
  
   times = createFont("Times New Roman",60);

  
  textFont(times);
  textAlign(CENTER);
  fill(0, 408, 612, 204);
  textSize(60);
  text("It's Saturday Night", width/2, height/2-40);
  textSize(18);
  text("Stack Up as much food as you can by moving left and right with the arrow keys.", width/2, height/2);
  text("The clock is ticking!", width/2, height/2 + 50);
  textSize(20);

  //added rectangle as a highlighter to serve as a signal to the user
  rectMode(CENTER);
  rect(width/2, height-100, height/2, 30, 10);
  fill(255);
  text("Press Enter to start !", width/2, height-95);
}

void keyReleased()
{
  if ((keyCode == ENTER))
  {
    gameScreen = 1 ;
    game1.timer.start();
  }
}

Here is a link to the code repo on Github

Credits

Let’s show appreciation to  http://www.cs.du.edu/~leut/1671/09_Fall/ProcessingNotes7.pdf and https://github.com/jb3dahmen/CatchTheFruitComplete for the timer class and  game mechanics idea respectively.

 

Midterm: progress in retrogress

Inspiration

On a Saturday night, NYUAD students tend to have more meal swipes than they need. Students face the dilemma of either stacking more food with their extra swipes or losing all the swipes the next day.

The idea then is to create a game where the player (student) would try to stack as much food as can be balanced on an unstable food tray.

To win and make the most of your meal swipes, just be patient and stack away. Oh, don’t forget we are working with time😄

Process 

To build this game, I need

1. Start / Instructions page

2. Game window

3. Win / Lose / Restart Page

4. Sound Integration

Progress Work

Let’s get to work

I explored how I would be changing the game screens based on the stage of the game. I created functions to take care of each of the 3 main stages of the game: start, gameplay, and game over. I represented the different screens with 3 different colors.

I moved on to integrate a timer for the gameplay screen which when runs out and automatically changes the screen to indicate game over. That’s when I started facing difficulties.

I added some buttons and signal text to make the user’s life easier.

Demo

 

Challenges

Timer!

For some reason, I couldn’t figure it out for a long time, my timer was not working as expected, the gameplay screen didn’t change even if the timer was out. Oh, I get it now! I fell into the trap of not scoping my variables properly. I experimented with the location of my timer function and I finally got it to work when I globalized the variables accessed by the timer function.

Please stay we me, we are not done with the timer yet! I decided to print the timer values on the game screen and I was getting negative seconds. How? Yeah, I was confused as you are. Still haven’t figured why but it seems to work fine now.

// THE THREE SCREENS
// 0: Start Page (Instructions)
// 1: Game Window
// 2: Win / Lose Page ( GameOver)


int gameScreen = 0;
int score = 0;
int totalTime = 10; // 10 seconds
int savedTime = second();
int passedTime;


void setup() {
  size(640, 640);
}

void draw() {
  // Display the contents of the current screen
  if (gameScreen == 0) {
    startScreen();
  } else if (gameScreen == 1) {
    gameWindow();
    timer();
  } else if (gameScreen == 2) {
    gameOverScreen();
  }
}



// THE THREE SCREENS
void startScreen() {
  background(#6f00ff);
  textAlign(CENTER);
  textSize(70);
  text("It's Saturday Night", width/2, height/2-50);
  textSize(20);
  text("Stack Up as much food as you can while you have the time.", width/2, height/2);
  text("Click on the Start button, The clock is ticking!", width/2, height/2 + 50);
  textSize(20);

  // start button
  noFill();
  rectMode(CENTER);
  rect(width/2, height-100, 120, 30, 10);
  text("Click to start", width/2, height-95);
}


void gameWindow() {
  background(#a75502);
  textSize(50);
  text("Timer!", width/2, 95);
}

void gameOverScreen() {
  background(#6f00ff);
  textAlign(CENTER);
  fill(236, 240, 241);
  textSize(15);
  text("Your Score", width/2, height/2 - 120);
  textSize(130);
  text(score, width/2, height/2);

  // restart button
  noFill();
  rectMode(CENTER);
  rect(width/2, height-100, 150, 30, 10);
  textSize(20);
  text("Click to Restart", width/2, height-95);
}


// SCREEN CHANGERS
void  startGame() {
  gameScreen=1;
}

void gameOver() {
  gameScreen=2;
}

// RESTART

void restart() {
  score = 0;
  savedTime = second();
  startGame();
}


// TIMER

void timer() {
  passedTime = second() - savedTime;
  textSize(100);
  text(passedTime, width/2, height/2 + 30);
  if (passedTime > totalTime) {
    gameOver();
  }
}



// BUTTON CONTROLS
void mousePressed() {
  // toggle between instructions and restart when mouse is clicked
  if (gameScreen==0) {
    startGame();
  }
  if (gameScreen==2) {
    restart();
  }
}

Next Steps

It’s going to be more fun and challenging. I will be working mainly on the gameplay screen and polishing the start and end screen

1.  Create the assets ( the food to be stacked) and the unstable tray block

2. Work on the game mechanics ( counting length of the food stack )

3. Add sound to make it lively

PS. Would appreciate any resources to achieve the above steps. I know it’s going to be existing!