Final Project – Go Ichi-Go!

3,2,1…Goooo Ichi-Go!!!

I can’t believe this is finally my final project. That was such an insane ride.

For my final project, I want to create a game called “Go Ichi-Go!”. The game features a character called Ichigo (Japanese for strawberry), who runs and has to jump over obstacles like jumping puddles of whipped cream, and towers of chocolate, and slide under floating slices of cake, to avoid being part of the sweet treat!. After each jump/dive, randomised text gives out cute strawberry themed puns. Once the player successfully finishes 10 obstacles, getting faster with each obstacle, and they win a sweet surprise- a strawberry candy, which is dispensed from a servo-motor operated candy dispenser. 

VIDEO DOCUMENTATION :

USERS DOCUMENTATION FROM IM SHOWCASE :

INTERACTION DESIGN:

The user is first greeted by a cute, pink kawaii style arcade set-up. A small console board shows three buttons – Start, Jump and Dive. The screen shows a short instruction guide and the title of the game. To start, we click the Start button, which takes us to the main game page. Here, Ichigo has to jump over a puddle of whipped cream or chocolate towers, and dive over floating cake slices. These obstacles are randomised, and after each succesfull pass, a strawberry/sweet themed pun is displayed. With each obstacle, the speed of the game increases, and the obstacles attack Ichigo faster. After the user finishes 10 obstacles, the screen shows a win page with the text to “Enjoy your candy”. Simultaneously, our servo motor candy dispenser turns its knob to shoot out a rain of sweet candy, rewarding the player for winning the game. If the player doesn’t win the game, the game over screen allows them to restart it by pressing the start button again.

ARDUINO CODE:

#include <Servo.h>

const int startBtn = 2;
const int jumpBtn = 3;
const int diveBtn = 4;

Servo candyServo;

void setup() {
  pinMode(startBtn, INPUT_PULLUP);
  pinMode(jumpBtn, INPUT_PULLUP);
  pinMode(diveBtn, INPUT_PULLUP);

  candyServo.attach(9); 
  candyServo.write(0);   

  Serial.begin(9600);
}

void loop() {
  if (digitalRead(startBtn) == LOW) {
    Serial.println("S ");
    delay(200);
  }
  if (digitalRead(jumpBtn) == LOW) {
    Serial.println("J ");
    delay(200);
  }
  if (digitalRead(diveBtn) == LOW) {
    Serial.println("D ");
    delay(200);
  }

  if (Serial.available()) {
  char cmd = Serial.read();
  Serial.println(cmd);  // Debug line
  if (cmd == 'C') {
    candyServo.write(180); //rotate servo cover 
    delay(3000); //3 second delay 
    candyServo.write(0); //reset
    delay(1000);
  }
  }
  
}


P5.JS CODE:

let serial;
let start;
let youWin;
let gameOver; //bg images
let font;
let bgImages = []; //game time bg images
let bgm; 
let ichigoNormal, ichigoJump, ichigoDive; //ichigo images
let obstacleImages = []; 
let obstacles = []; 
let ichigoY; 
let ichigoState = "normal"; 
let jumpTimer = 0; 
let diveTimer = 0;
let obstacleCount = 0; 
let currentState = "start"; 
let currentPun = "";
let bgIndex = 0;
let bgTimer = 0;
let obstacleSpeed = 5;   
const maxObstacleSpeed = 12; 

let puns = [ 
  "Berry sweet move!",
  "Shortcake success!",
  "Jam-tastic",
  "Berry nice move!",
  "Sweet! Just like Ichigo!",
  "Go Ichi-Gooooooal",
  "ICHI-WOWWWWW",
  "Sweet Strawberry WOW"
]; //puns array for each win


function preload() {
  font = loadFont('Minecraft.ttf');
  start=loadImage('start.png');
  youWin=loadImage('win.png');
  gameOver=loadImage('gameover.png');
  bgImages[0] = loadImage('1.png');
  bgImages[1] = loadImage('2.png');
  bgImages[2] = loadImage('3.png');
  bgImages[3] = loadImage('4.png');
  ichigoNormal = loadImage('ichigo.png'); 
  ichigoJump = loadImage('jump.png'); 
  ichigoDive = loadImage('dive.png');
  bgm = loadSound('bgm.mp3');
  obstacleImages[0] = loadImage('cream.png'); 
  obstacleImages[1] = loadImage('choc.png');
  obstacleImages[2] = loadImage('cake.png');
}

function setup() {
  createCanvas(800, 400); 
  
  bgm.loop(); 
  
  //create serial connection
  serial = createSerial(); 
  serial.open(9600);
createButton("Connect")
  .position(10, 10)
  .mousePressed(() => serial.open(9600));

  ichigoY = height - 100; 
  imageMode(CENTER);
  textFont(font);
  textAlign(CENTER, CENTER); 
  textSize(24); 
}

//serial events
function serialEvent() {
  if (serial.available()) {
    let input = serial.readUntil('\n').trim();
    handleInput(input);
  }
}

function handleInput(input) {
  if (input === 'S') { 
    startGame(); //starting the game after creating Start button
  } else if (input === 'J' && currentState === 'game') { 
    ichigoState = "jump"; 
    jumpTimer = 20; 
    checkObstacle("jump"); //making ichigo jump after pressing Jump button
  } else if (input === 'D' && currentState === 'game') { 
    ichigoState = "dive";
    diveTimer = 20; 
    checkObstacle("dive");
  } //make ichigo dive after clicking Dive button
}

function startGame() {
  currentState = "game"; 
  obstacleCount = 0; 
  obstacles = []; 
  obstacleSpeed = 5; //set initial speed slow 
  nextObstacle(); 
  currentPun = ""; 
}

function nextObstacle() {
  let type = random(["jump", "dive"]); //randomise type of obstacle
  let y;
  if (type === "jump") {
    y = height - 80; 
  } else {
    y = height - 140; 
  } //set position of obstacle on canvas based on type

  obstacles.push({
    img: type === "jump" ? random([obstacleImages[0], obstacleImages[1]]) : obstacleImages[2],
    type: type,
    x: width + 100,
    y: y,
    cleared: false
  });
}

//check if player matches obstacle to jump/dive correctly 
function checkObstacle(action) {
  if (obstacles.length > 0) {
    let obs = obstacles[0];
    if (obs.x < 150 && obs.x > 50) {
      if (obs.type === action) {
        if (!obs.cleared) {
          obstacleCount++; 
          obstacleSpeed = min(obstacleSpeed + 0.5, maxObstacleSpeed); 
          currentPun = random(puns);
          obs.cleared = true;

          if (obstacleCount >= 10) {
            winGame(); //show win screen if 10 obstacles over
          }
        }
      } else {
        currentState = "gameover"; //game over screen 
      }
    }
  }
}

//win state
function winGame() {
  currentState = "win"; 
  serial.write('C\n'); 
  console.log('Sent C to Arduino'); 
  
}

function draw() {
  background(255); 

  serialEvent();
  
  if (currentState === "start") {
    image(start, width/2, height/2, width, height);
  } 
  else if (currentState === "game") {
    updateGame(); 
  } 
  else if (currentState === "win") {
    image(youWin, width/2, height/2, width, height);
  } 
  else if (currentState === "gameover") {
    image(gameOver, width/2, height/2, width, height);
  }
}


function updateGame() {
  
  //to change the background sky occasionally
  bgTimer++;
  if (bgTimer > 200) {
    bgIndex = (bgIndex + 1) % bgImages.length;
    bgTimer = 0;
  }

  if (bgImages[bgIndex]) {
    image(bgImages[bgIndex], width / 2, height / 2, width, height);
  }
  
  moveObstacles(); 

  let ichigoTop = ichigoY - 40;
  let ichigoBottom = ichigoY + 40;
  let ichigoLeft = 100 - 40;
  let ichigoRight = 100 + 40;

  if (ichigoState === "jump") {
    ichigoTop -= 120;
    ichigoBottom -= 120;
  } else if (ichigoState === "dive") {
    ichigoTop += 50;
    ichigoBottom += 50;
  }

  if (obstacles.length > 0) {
    let obs = obstacles[0];
    let obsLeft = obs.x - 30;
    let obsRight = obs.x + 30;
    let obsTop = (obs.type === "dive") ? height - 200 : height - 110;
    let obsBottom = (obs.type === "dive") ? height - 100 : height - 50;

    //check if ichigo and obstacle collide or not
    if (ichigoRight > obsLeft && ichigoLeft < obsRight &&
        ichigoBottom > obsTop && ichigoTop < obsBottom) {
      currentState = "gameover";
    }
  }

  if (ichigoState === "jump") {
    image(ichigoJump, 100, ichigoY - 50, 80, 80);
    jumpTimer--;
    if (jumpTimer <= 0) ichigoState = "normal";
  } else if (ichigoState === "dive") {
    image(ichigoDive, 100, ichigoY + 40, 80, 80);
    diveTimer--;
    if (diveTimer <= 0) ichigoState = "normal";
  } else {
    image(ichigoNormal, 100, ichigoY, 80, 80);
  }

  fill(0);
  text(`Obstacle ${obstacleCount + 1} / 10`, width / 2, 30); //display obstacle count
  fill(255,0,0);
  text(currentPun, width / 2, 100);
}

//move obstacles across screen
function moveObstacles() {
  for (let i = obstacles.length - 1; i >= 0; i--) {
    let obs = obstacles[i];
    obs.x -= obstacleSpeed;
    image(obs.img, obs.x, obs.y, 60, 60);

    if (obs.x < -50) {
      obstacles.splice(i, 1);
      if (currentState === "game") nextObstacle();
    }
  }
}

SERIAL COMMUNICATION:

From Arduino to p5: 

Pressing the “Start” button sends an “S” to p5, to start/restart the game.

Pressing the “Jump” button sends a “J” to p5, triggering the character to jump.

Pressing the “Dive” button sends a “D” to p5, triggering the character to jump.

From p5 to Arduino:

At the end, when they win, P5 sends a “C” to Arduino, triggering the movement of the servo motor.

SCHEMATIC:

SOME ASPECTS OF THE PROJECT I’M PARTICULARLY PROUD OF

CANDY RAAAAAIN!

(i was so ready to say that during presentation time!)

I am very proud of the candy dispenser. It was very hard to create but it gave a sweet treat at the end (pun intended). I enjoyed implementing it, and definitely think that it gives the game a more interactive and fun vibe. I also love the overall aesthetic of the game and setup, and am very pleased with how it turned out. I also love how the game gets faster with each obstacle, which is something I added in after the user testing feedback. I really do think that added to the whole game experience.

I also am very proud of the project in itself with these aspects, especially seeing the user feedback after the showcase. Everyone loved playing the game, loved the graphics and was very shocked and happy to get candy at the end! Seeing the players interact with my game allowed me to see how fun and engaging the game was, especially towards at the end with “CANDY RAAAAAAAIN”!!!!

CHALLENGES:

This project was a ride of nervous excitement. I was all set and prepared with an arcade like setup, a whole board with arcade buttons and a connected box for the candy. However things quickly took a sharp turn when my arcade buttons mysteriously decided to malfunction (at midnight wow). A few hundred debugging attempts later, I realised that it was too late to try and fix it and had to start from scratch all over again.

However, in this whirlwind of chaos on the final day I learnt how to stay calm under pressure and focus on solving the problem. I quickly resolved the situation by fabricating a board by recycling my Arduino box and decorating it. While it wasn’t as big or cool as my initial arcade button setup, I managed to focus on the outcome of the project, and have fun making it. It also turned out super cute at the end (bonus)!

IMPROVEMENTS:

If I could make improvements to my project, I’d definitely try and get the candy dispenser to store more candy and shoot it out into a certain place, rather than the “candy rain” situation (although its super fun to see). I also think I should have made the “PRESS AND HOLD”instruction in the screen and not the box, because there were a few people who didn’t see it at first, and then noticed iut above the buttons. I would also try and use sound effects in the game itself, when Ichigo jumps or dives, like a boing! sound. I would also like to explore adding themes to the game, like Space Ichigo in a different planet, or chef Ichigo with other fruits.

All in all, I’m super happy with how this project turned out, and Introduction to Interactive Media was super super fun!! Sending lots of love and Ichigos to this amazing class <3

Week 13 – Final Project User Testing

For the final project’s user testing, I asked my friend Sarfraz to play my game “Go Ichi-Go!” Based on his feedback, and the feedback of two other players, I got some insight and areas for improvement.

A common struggle they all had was understanding the jump and dive buttons. To jump/dive, you have to press and hold the button. But all of them only pressed it the first try. This made me realise that I should probably mark these instructions either one of the console or in the instructions at the start of the game.

Another suggestion my friend gave me was that the game was too easy, and that it could be faster. So I decided to modify the game accordingly. Either make the whole thing faster, or make it faster with each obstacle.

These suggestions helped me understand what can make my game more engaging and enjoyable. It also helped me understand where the players might be confused or lost.

Because my fabrication isn’t complete yet, my friends didn’t get the sweet treat at the end of the game, but they all loved the idea of it!

Video :

 

 

 

Week 12 – Final Concept – Go Ichi-Go!

Concept and Overview:

For my final project, I want to create a game called “Go Ichi-Go!”. So the game would have a character called Ichigo (strawberry), who runs and has to jump over obstacles like jumping puddles of whipped cream, and towers of chocolate, and slide under floating slices of cake. After each jump/dive, there would be randomised text giving cute strawberry themed puns. For this I’ll use an array of randomised puns. 

There would also be sound effects for each jump or dive. There would be two buttons to jump or dive, using Arduino, and a button to start/restart the game. The player wins after successfully overcoming 10 obstacles.

If they win, it would display a congratulations image and a restart option. This triggers the movement of the servo motor, which will dispense candy as the reward for winning.

If they fail to do so, then it would just go to a Game Over state with a restart button. 

Things I’ll need :

  1. Arduino Uno
  2. Breadboard
  3. Servo Motor
  4. Three arcade buttons
  5. Jumper wires
  6. Alligator clips/wires
  7. Laser print arcade box
  8. Candy box dispenser

The serial communication would be like this:

From Arduino to p5: 

Pressing the “Start” button sends an “S” to p5, to start/restart the game.

Pressing the “Jump” button sends a “J” to p5, triggering the character to jump.

Pressing the “Dive” button sends a “D” to p5, triggering the character to jump.

if (digitalRead(startBtn) == LOW) {
   Serial.println("S");
   delay(100);
 }
 if (digitalRead(jumpBtn) == LOW) {
   Serial.println("J");
   delay(100);
 }
 if (digitalRead(diveBtn) == LOW) {
   Serial.println("D");
   delay(100);
 }

From p5 to Arduino:

At the end, when they win, P5 sends a “C” to Arduino, triggering the movement of the servo motor. 

serial.write('C\n');

Schematic:

DESIGN :

I want to make this game in a very kawaii retro vibe, but also focus more on the interaction design on the game itself, something I learnt from my midterm. So this time, I used Canva to layer up the illustrations, instead of drawing them from scratch. 

I also want to laser cut a box to hold all this together and make it look like one of those retro arcade game boxes. 

So far, I’ve just started the basic outline of the code, so I haven’t gotten very far with it. 

Next steps

  1. Finish game interface and troubleshoot 
  2. Laser cut arcade box pieces
  3. Make a box structure for the candy dispenser

 



Week 11 – Reading Response – Design meets Disability

This reading explores how design and disability are intricately related, and how a constraint in designing from disability can lead to greater innovative efforts and contributions. The constraints due to disability basically serve as a catalyst for innovation. The author brings up several examples in history that illustrate the evolution of design with disability. Designing for disability shouldn’t solely focus on the functionality but it should also consider the aesthetics of the product, challenging the stigma around people with disabilities. Every single design, from furniture to eyewear to prosthetics to hearing aids, serve a purpose. That purpose is not only defined by its functionality, but also its aesthetic form. I was very interested in the aesthetics of Aimee Mullins’ prosthetics, and how it combines function, form and aesthetics. I do believe that inclusive designing helps to create a sense of identity and belonging for differently abled people. As a person who wears glasses, I think it is definitely important to consider the design of such products; it truly does give a sense of identity and expression. It is also important to create diverse, inclusive and collaborative work environments that promote the designing for the differently abled. I loved this quote from Steve Jobs mentioned here, “Most people make the mistake of thinking design is what it looks like. That’s not what we think design is. It’s not just what it looks like and feels like. Design is how it works.” This just highlights how all spheres of design must come together for it to be innovative and inclusive; both in functionality and aesthetics. 



Week 11 – Final Project Preliminary Concept – Go Ichi-Go!

For my final project, I want to create a game called “Go Ichi-Go!”, something like the Chrome Dinosaur Game, but a bit different. So the game would have a character called Ichigo (strawberry), who runs and has to jump over obstacles like jumping puddles of whipped cream, and towers of chocolate, and slide under floating slices of cake. After each jump/dive, there would be randomised text giving cute strawberry themed puns. There would also be sound effects for each jump or dive. There would be two buttons to jump or dive, using Arduino, and a button to start/restart the game. The player wins after successfully overcoming ten obstacles. This would display a congratulations image and a restart option. If they fail to do so, then it would just go yo a Game Over state with a restart button. If I do have the time/skill set for it, I want to add a treat component, where when they win, a sweet will be ejected out, probably using DC motors, but I’m not sure about this yet (really really want to try this). I want to make this game in a very kawaii retro vibe, but also focus more on the interaction design on the game itself.

Week 11 – Serial Communication

Group members : Liya Rafeeq, Kashish Satija

Exercise 11.1 :

  1. Make something that uses only one sensor  on Arduino and makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on arduino is controlled by p5 – for this we used a potentiometer. We mapped the values of the potentiometer to change the X coordinate of the ellipse, making it move along the horizontal axis.

P5.JS CODE :

let port;
let connectBtn;
let baudrate = 9600;

function setup() {
  createCanvas(400, 400);
  background(220);

  port = createSerial();

//serial connection
  let usedPorts = usedSerialPorts();
  if (usedPorts.length > 0) {
    port.open(usedPorts[0], baudrate);
  }
  let connectBtn = createButton("Connect to Serial");
  connectBtn.mousePressed(() => port.open(baudrate));
}

function draw() {
  
  
  //read from the serial port, complete string till the ""
  let str = port.readUntil("\n");
  if (str.length > 0) {
    background("white");
    ellipse(int(str),200,40,40); 
  }

}

ARDUINO CODE:

void setup() {
  Serial.begin(9600); // initialize serial communications
}
 
void loop() {
  // read the input pin:
  int potentiometer = analogRead(A1);                  
  // remap the pot value to 0-400:
  int mappedPotValue = map(potentiometer, 0, 1023, 0, 400); 
  // print the value to the serial port.
  Serial.println(mappedPotValue);
  // slight delay to stabilize the ADC:
  delay(1);                                            
  
  // Delay so we only send 10 times per second and don't
  // flood the serial connection leading to missed characters on the receiving side
  delay(100);
}

Exercise 11.2 :

2. Make something that controls the LED brightness from p5. For this, we made a circle that moves along the Y axis. According to the Y coordinates, the LED turns brighter or lower.

P5.JS. CODE:

let port;
let connectBtn;
let baudrate = 9600;

function setup() {
  createCanvas(255, 285);
  port = createSerial();

  // in setup, we can open ports we have used previously
  // without user interaction

  let usedPorts = usedSerialPorts();
  if (usedPorts.length > 0) {
  port.open(usedPorts[0], baudrate);
} else {
  connectBtn = createButton("Connect to Serial");
  connectBtn.mousePressed(() => port.open(baudrate));
}
}

function draw() {
  background(220);
  circle(128,mouseY,30,30)
  let sendtoArduino = String(mouseY) + "\n"
  port.write(sendtoArduino);
}

ARDUINO CODE:

int led = 5;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  while (Serial.available()) 
    {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
    int brightness = Serial.parseInt(); //get slider value from p5
     if (Serial.read() == '\n') {
       analogWrite(led, brightness);
    }
  }
}

Exercise 11.3:

Take the gravity wind example (https://editor.p5js.org/aaronsherwood/sketches/I7iQrNCul) 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: For this, we used the potentiometer as the analog sensor.

P5.JS CODE:

let baudrate = 9600;
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let str="";
let val;
let heightOfBall = 0;

function setup() {
  createCanvas(640, 360);
  noFill();
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.5*mass);
  wind = createVector(0,0);
  port = createSerial();

  // in setup, we can open ports we have used previously
  // without user interaction

  let usedPorts = usedSerialPorts();
  if (usedPorts.length > 0) {
  port.open(usedPorts[0], baudrate);
} else {
  connectBtn = createButton("Connect to Serial");
  connectBtn.mousePressed(() => port.open(baudrate));
}
}

function draw() {
  background(255);
  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;
      heightOfBall = 1;
    } else {
      heightOfBall = 0;
    }
  str = port.readUntil("\n");
  val=int(str);
  if (!isNaN(val)) {
  breeze(val);
  }
}
function applyForce(force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}

function breeze(val){
  if (val<400){
    wind.x=-1;
  }
  else if (val>500 && val<900){
    wind.x=1;
  } else {
    wind.x=0
  }
  let sendToArduino = String(heightOfBall)  + "\n";
  port.write(sendToArduino);
}
function keyPressed(){
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}

ARDUINO CODE:

int led = 5;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(led, OUTPUT);
}

void loop() {
// put your main code here, to run repeatedly:
while (Serial.available())
{
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int brightness = Serial.parseInt(); //get slider value from p5
if (Serial.read() == '\n') {
analogWrite(led, brightness);
}
}
}

VIDEO and SCHEMATIC:

 

 

Week 10 – Musical Instrument – Mary had a Little Piano

Groupmates : Liya and Shamma

CONCEPT and working :

For our group assignment, we built a simple digital musical instrument using an Arduino board. Our project was inspired by the children’s song Mary Had a Little Lamb, and we recreated the melody using four push buttons for four of the notes, C, D, E and G respectively. Each button acts as a digital sensor, triggering specific musical notes when pressed. The tones are played through a mini speaker connected to the Arduino, allowing the tune to be heard clearly. This created a very basic piano-style interface, with each button mapped to one of the notes in the song.

In addition to the buttons, we used a potentiometer as our analog sensor. This allowed us to control the frequency of the sound in real time. As the knob is turned, the pitch of the notes changes slightly, giving the player the ability to customize how the melody sounds. We mapped the frequency from 500-1000 Hz for this. It made the experience more interactive and demonstrated how analog inputs can add expressive control to digital systems. We also added some labels to the buttons so that it would be easier to play the music.

videos of testing :

(Sorry in advance, I’m not a singer, I just needed to show the song)

https://youtube.com/shorts/6OhDN7k7KAc?si=WBNaPPqKeTkQCIui

https://youtube.com/shorts/vH0wLT3W5Jk?si=3K7I34cpMZWwC9Ly

The code :

const int buttonPins[4] = {3, 5, 8, 9}; // buttons 

//frequency for each button 
int frequencies[4] = {262, 293, 330, 392}; //C, D , E , G notes
int potValue = 0; //to store potentiometer value

void setup() {
  //initialising buttons pins
  for (int i = 0; i < 4; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
  
  //for debugging
  Serial.begin(9600);
  
  //speaker pin for output
  pinMode(12, OUTPUT);
}

void loop() {
  //read the potentiometer value
  potValue = analogRead(A0);
  
  //map the potentiometer value to a frequency range 500-1000
  int adjustedFrequency = map(potValue, 0, 1023, 500, 1000);
  
  //for button and the corresponding note
  for (int i = 0; i < 4; i++) {
    if (digitalRead(buttonPins[i]) == LOW) { // Button is pressed (LOW because of INPUT_PULLUP)
      tone(12, frequencies[i] + adjustedFrequency);
      Serial.print("Button ");
      Serial.print(i+1);
      Serial.print(" pressed. Frequency: ");
      Serial.println(frequencies[i] + adjustedFrequency); //serial monitor 
      delay(200);
    }
  }
  
  //to stop the tone when buttons arent being pressed
  if (digitalRead(buttonPins[0]) == HIGH && digitalRead(buttonPins[1]) == HIGH &&
      digitalRead(buttonPins[2]) == HIGH && digitalRead(buttonPins[3]) == HIGH) {
    noTone(12);
  }
}

PROBLEMS / IMPROVEMENTS :

As for problems or challenges, we didnt really have any specific problems with the circuit other than loose wires or something which was fixed after debugging and checking again. Something we understood from working together is that having two different perspectives helps a lot in solving problems and finding ideas.

We see a lot of potential for expanding this project in the future. One idea is to add a distance sensor to control volume based on hand proximity, making it even more dynamic. Another would be adding LEDs that light up with each button press to provide a visual cue for the notes being played. We’re also considering increasing the number of buttons to allow more complex songs, and possibly adding a recording function so users can capture and replay their melodies.

It was a fun and educational project that helped us better understand the relationship between hardware inputs and interactive sound output. It was exciting to bring a classic tune to life through code, sensors, and a mini speaker!

Week 10 – Reading Response

Bret Victor’s “A Brief Rant on the Future of Interaction Design” calls out future interfaces to be mere pictures under glass. He argues that this approach is ignoring the amazing capabilities of the human hands. Current trends focus too much on visual interactions, neglecting our sense of touch. Hands are powerful tools for a sense of dexterity and manipulation, something currently absent in a lot of touch based technologies. He takes inspiration from Alan Key’s early vision of the iPad, and encourages designers to explore our mediums that can potentially improve user experiences by engaging us both visually and sensually. A lot of his argument actually makes sense. It is human nature, from being babies to be attracted to bring screens, but our immediate reaction to anything is to touch it, see if it turns, or moves, or if its a switch or a knob. We always seek some sense of physical manipulation in objects, and I do think modern technologies are limiting this to a far more visual approach. Even when I type essays, I prefer using a laptop keyboard over my iPad screen, because I genuinely like the touch-and-feel of clicking and clacking on the keyboard keys- it somehow motivates me to write better. Even though this isn’t a full usage of hands and body movements, this minute degree of change in physical interaction itself makes me more interested. “With an entire body at your command, do you seriously think the Future Of Interaction should be a single finger?” – this statement really opened my eyes to how much technology has been reshaped to fit users to a limited physical experience. 

In the response article, he answers some of the questions people had. I can admit that I too was unsure of the stylus situation. And I’m not sure how styluses can be made to be dynamic. I fully agree with him on the voice input part- I never found that to be appealing or better. Overall, I’d say Vistor’s rant on the future of interaction design is completely justifiable- to be futuristic doesn’t mean to be deprived of sensuality. Rather embracing the movements of our hands and channeling a sense of physical interaction can definitely aid us in improving the future of interaction.



Week 9 – Serial/Analog Input – Smile and Wink!

CONCEPT:

For this week’s assignment, I made a smiley face with two glowing eyes, where they “wink” in between. One of the LEDs brightness was controlled using a photoresistor, and the other turned on/off using a switch.

MATERIALS USED:

Arduino UNO

Breadboard

Photoresistor

10K Ohm resistor

330 Ohm resistor

Switch

LED

Jumper wires

WORKING:

So one of the LEDs are controlled using the photoresistor. It gets brighter when the photoresistor is covered(less light), and vice versa. The other LED is controlled using the switch. The code for it is as follows:

const int button = 2;
const int led1 = 13;
const int led2 = 9;
const int ldr = A0;

int state = LOW; //state of LED1
int brightness = 0; //brightness of LED2
int ldrValue = 0; //photoresistor value

void setup() {
  pinMode(button, INPUT_PULLUP); 
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  
  //serial monitor for debugging
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(button) == LOW) {
    state = HIGH;  //turn LED1 on
  } else {
    state = LOW;   //turn LED1 off
  }
  
  //read photoresistor value and map it to LED2 brightness (0 to 120)
  ldrValue = analogRead(ldr);
  brightness = map(ldrValue, 0, 1023, 0, 120);
  
  Serial.print("LDR Value: ");
  Serial.println(ldrValue);
  
  //control LED1 using switch (physical input)
  digitalWrite(led1, state);
  
  //control LED2 brightness using analog input
  analogWrite(led2, brightness);

  delay(100);  //small delay for stability
}

CHALLENGES :

The challenging part about this was my biggest careless mistake! I put the LED on oppositely (anode and cathode), so I spent a good 30 minutes trying to figure out what went wrong. I also used the serial monitor to help with debugging.

Hand drawn schematic:

LINK TO VIDEO :

https://youtube.com/shorts/UVZ-qTWX1aE?feature=share

IMPROVEMENTS :

I would like the photoresistor-controlled LED to be better, maybe some other form of coding that makes it more…interesting. I also realised that we wink using our eyelids and not the eyes themselves, but overall, as a form of cartoonish smiley-ness, I’m happy with this project. It was a fresh start after the spring break!

Reading Response 9.b – Making Interactive Art: Set the Stage, Then Shut Up and Listen

This article covers topics like physical interaction and interaction design. The author argues that the artist should have a shift in perspective regarding the expression and interpretation of their own artwork. He argues that artists pre-describe and set their own interpretation, telling the participants how to think and act. 

However, the only primary task an artist has is the interactive framework. Once this is done, the artist should “shut up and listen”. The static artwork must shift into a dynamic performance, with the audience being the central character. The conversation doesn’t only rely on the artist letting the audience speak, but also in listening to the audience, their comments and analysis. 

This reading made me realise how much collaboration and listening is important in creating artworks. I realised that over-explaining artworks and projects really takes away from the whole experience of the audience. The true beauty in immersion and interaction lies in the audience being allowed to freely communicate with the artwork. This also allows both of us to interact and learn from each others’ interpretations, creating a wider space for creative freedom and expression.