Final Project: Block adventure

Concept

What if instead of moving the hero, you can move the environment instead? In this game, I try to let the user into the environment building process. Where should I put the platform? How high, how low should it be so that the character should jump across? This is a puzzle game, in which player needs to find the right placement for the physical box – representing the in-game platform – to allow the character to jump across. For the design, I decide to use basic shapes to amplify the theme of the game – building the world from the most basic blocks.

Implementation

For the interaction design, I created a simple instruction scene using basic shapes and minimal text, as users often overlook instructions with too many words. For the physical component, I used red tape to clearly indicate the area where the box could be moved. Additionally, I tried to keep the sensors and connecting components inside the cardboard as discreet as possible by using paper clips instead of tape or glue.

Instructions on how to navigate the game

This game project is rather p5js heavy. For the game mechanism, I design one class for the block, and one class for the platforms.

The hero class include:

  • checkGround(): check if the hero is on which platform
  • move(): move the hero
  • display(): display the hero on screen

The box (platform) class include:

  • changeable parameters for x, y, width and height
  • display method

P5js code

Arduino

For the interaction between Arduino and P5js, I use the data read from Arduino photoresistors and send it to P5js.

int right1 = A0;
int right2 = A1; 
int front1 = A2;
int front2 = A3;
int prevFront = 0;
int prevRight = 0;
int front1Read;
int front2Read;
int right1Read;
int right2Read;
int minFront;
int minRight;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(right1,INPUT);
  pinMode(right2,INPUT);
  pinMode(front1,INPUT);
  pinMode(front2,INPUT);
}

void loop() {

  front1Read = map(analogRead(front1),60,100,750,850); //map this value to front2 sensor range
  front2Read = analogRead(front2);
  minFront = min(front1Read,front2Read); //choose the smaller value (the box is infront of this sensor)

  right1Read = map(analogRead(right1),40,60,700,780);
  right2Read = analogRead(right2);
  minRight = min(right1Read,right2Read);

  if(abs(minFront - prevFront) > 40){
    //only update if the difference is bigger than 40(prevent noise)
    Serial.print(minFront);
      prevFront = minFront;
  }else{
    Serial.print(prevFront);
  }
  Serial.print(',');

  if(abs(minRight - prevRight)>40){
    Serial.println(minRight);
      prevRight = minRight;
  }else{
    Serial.println(prevRight);
  }

}

Schematic for Arduino

User interaction video

Struggle

Due to time constraint, I had to cut a lot of parts during the development process. I initially want to incorporate the moving position of the box, however, due to problems with the photoresistors that I could not resolve, I had to do away with this feature in the end. Using photoresistors also cause me multiple problems, mainly due to the different lightings when moving environment. This lead to my having to fix the parameters every time the lightings change. This is particular problematic and the main issue with my project that I hope to improve in the future.

Reflection

For future project, I think I could have more proper planning, including researching the tools (i.e. Arduino sensors) to know which best fit for the project and avoid significant problems. Other than that, I think the user experience design for this final project has improved from my previous midterm. For this final, I try to make the design as intuitive as possible without using a lot of words. Instead, I try to use symbols and colors (red for stop, do not cross the line). I am also invested in the idea of being able to move the environment although it did not turn out as good as expected due to the implementation. In the future, I would love to work on this idea more, particularly the game mechanism.

 

Final Project – User Testing

User design

Specifically for the user interaction, I design an instruction at the start of the game. Learning from my midterm project, where user did not know intuitively which button to press, I wrote a small instruction to let user know they could press any button to continue the experience. For the physical component, because the moveable box could not move out of the limits, I put a red tape to signify which area to move and which not to.

Schematic

The project uses 4 photoresistors for sensing position of the box and its size.


User testing video

User testing feedback

After letting my friends try out the game, most of them understood which button to press and that they could only move the box within the red line. However, the enlargement of the box during movement appeared too jittery and abrupt, making it difficult for users to associate their physical movements with the box on the screen. At this part, I need to step in to explain that the box is controlling the platform on the screen. The primary issue to address is the abrupt interaction, which is mainly caused by the photoresistor generating noisy values.

 

Week 12 – Final Project Progress

Concept

I have decided to work on the idea to use a box to control the platform for the hero. There will be 1 box that the user can move (physical part) that will control the platform in p5js. The project is inspired by the game “My Shadows are Bright” from GMTK game jam 2024.

For my game, the physical/arduino part will include a cardboard box that can be moved on the x, y axis by the user. Depends on the position of the box, it will be drawn on the screen in p5js in form of a platform. If the box is nearer to the front sensor (or user), it will be drawn bigger, and if it’s further away it will be smaller. This game is a puzzle game type, where the user have to move the box to get the correct size and position for the game character to move from the left side of the screen to the right side.

In terms of the story, I want to tell a story of how rejection is not always bad, sometimes it leads you to a path that is more suitable. It will be carried out using the character prince who is always rejected by the princess.

Implementation

Arduino

  • 2 photoresistors/ultrasonic sensors: 1 in front and 1 on right hand side
  • 1 LED to show game started
  • Resistors and wires
  • cardboards

P5js

  • Platform/box class
  • Hero class
  • Collision detection: detect when hero is standing on the platform and when not standing on the platform
  • Stages (introduction, game play, ending)

Progress

I am not sure if this project is feasible or not so I make a small prototype to see if I can use arduino to track the position of the box. In this code I get analog read value from photoresistor and draw a box based on how near or far it is from the sensor. It seems feasible so far.

Week 11 – Production Exercises

Exercise 1

  • Drawing an ellipse and making it move horizontally based on photoresistor

Code:

let x=0;

function setup() {
  createCanvas(400,400);
  textSize(18);
}

function draw() {
  if (serialActive){
    background("white");
    ellipse(map(x,0,1023,0,400),height/2,50,50);
  }else{
    background("white");
    console.log("not connected");
  }
}

function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function readSerial(data) {
  
  if (data != null) {
    x = int(data);
  }else{
    x = 0;
  }
}

//Arduino code
// void setup() {
//     Serial.begin(9600);
//     pinMode(A0, INPUT);
// }

// void loop() {
//   Serial.println(analogRead(A0));
// }

Exercise 2

  • Increase the brightness of the LED with mouse click

Code:

let bright=0;

function setup() {
  createCanvas(400,400);
  textSize(18);
}

function draw() {
  if (serialActive){
    background("white");
    text(bright,10,10);
  }else{
    background("white");
    console.log("not connected");
  }
}

function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function mousePressed(){
  if(serialActive){
    bright+=1;
    writeSerial(bright);
  }
  
}
function readSerial(data) {
  
}

//Arduino code
// int brightness;
// void setup() {
//     Serial.begin(9600);
//     pinMode(9, OUTPUT);
// }

// void loop() {
//   brightness = Serial.parseInt();
//   analogWrite(9,brightness);
// }

Exercise 3

  • Turning on LED when the ball bounces and use photoresistor to control wind movement

Circuit

Video:

Code:

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let bounce = 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);
}

function draw() {
  background(255);
  if(!serialActive){
    console.log("PRESS a TO CONNECT");
  }
   else{
    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;
        bounce = 1;
      }else{
        bounce = 0; 
      }
    
  }
}

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 keyPressed(){
  if (keyCode==LEFT_ARROW){
    wind.x=-1;
  }
  if (keyCode==RIGHT_ARROW){
    wind.x=1;
  }
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
   if (key == "a") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}
function readSerial(data) {
  if (data != null) {
        console.log(data);
        wind.x = map(int(data), 0, 1023, -2, 2);
        writeSerial(bounce + '\n');
  }
}

//Arduino code
// int bounce;
// void setup() {
//   Serial.begin(9600);
//   pinMode(9,OUTPUT);
//   while (Serial.available() <= 0) {
//     Serial.println("0"); // send a starting message
//   }
// }

// void loop() {
//   while(Serial.available()){
    
//     bounce = Serial.parseInt();
//     if (Serial.read() == '\n') {
//       digitalWrite(9,bounce);
      
//     }
    
//   }
//   int sensor = analogRead(A1);
//   Serial.println(sensor);
//   // Serial.println(analogRead(A0));
  
// }

 

 

Final project concept

Concept

For my final project, I plan to create a game using Arduino and P5js. This game will allow user to use physical components (boxes, figures) in real life to control the game happening on the computer.

Particularly, I want to create a platformer game where player can alter the platforms or the obstacles. The physical components will include some card board boxes that looks like the platforms on the computer. When player moves these boxes or obstacles, the platforms on computer will also move. Based on this mechanism, I will design a few levels of puzzle for the player. The goal of the game is to move the boxes around so that the game character on the computer can get from one point to another.

An introductory or example of this game can be moving the boxes (2 different platforms) so that the game character can jump across.

Week 10 – Reading Response

For this reading, I agree with the author on the limitation of the types of interaction we are using today. He criticized today’s digital device for only limited to “pictures under class”. Of course this type of interaction only allow the hands to feel and receive limited signals. The “pictures under class” leaves out the potentials of texture, weight and multiple other factors, for example, playing piano on a screen does not have the same satisfying feelings as playing on the real piano with hands interaction feedback.

However, I disagree with the author in two main points. The reading focuses too much on the capability of humans but does not take into consideration how we can use that capability to fit our needs. Of course we can have a more dynamic medium, but would that be better than the functionality of the Iphone? Iphones are designed compact and multifunctional, which I think can only achieved best through the “pictures under glass” interaction type. The second thing is that even though our hands are magnificent in many ways, other body parts can create interactions that are not less interesting. For example, the eyes can calculate the distance between objects, recognizing colors, emotions, etc. The “picture under glass” fits well to this capability of the eyes. Hence, I think it’s not a bad medium, it’s just a medium that makes use of other human capability.

Week 10 – Musical Instrument

Implementation
Tinh and I going into this were slightly stuck on the creative idea first. However, during a brainstorm session, we came across a video of a ballerina music box – inspiring us to create something similar to this whilst sticking to the ‘instrument’ concept of the assignments. As we did not have a mini ballerina, I had a mini figurine nonetheless – a small penguin rubber (Basil Jr). Now that we had a figurine, we had to figure out how to implement the ‘instrument’ concept into this, as we did not want to make it into a passive music box.

Therefore, we decided we wanted to control the movement of the penguin with the instrument. We ended up deciding that buttons could be used as the method to control movement — we decided that each button would correspond to a note, and each note has a specific rotation. Originally, we wanted to use 8 buttons to correspond to the 8 notes, however, due to the limited space on our breadboard, we chose to stick with three – C,D,E.
Implementation

Circuit: Servo Motor, Sound sensors, 3 buttons, resistor, photoresistor.


In the code, we use 2 functions for moving the motor and creating sound. The input button from the user will be recorded and passed into the function accordingly.

#include <Servo.h>
#include "pitches.h"


const int photoPin = A0;        // Photoresistor analog pin
const int ledPin = 6;           // LED pin
const int buttonPins[] = {2, 3, 4};  // Button pins for sound triggers
const int photoThreshold = 100; // Threshold for photoresistor reading
const int speakerPin = 8;

Servo penguinServo;             // Create servo object
const int servoPin = 9;         // Servo pin

void setup() {
    // Initialize the photoresistor, LED, and buttons
    pinMode(ledPin, OUTPUT);
    for (int i = 0; i < 3; i++) {
        pinMode(buttonPins[i], INPUT_PULLUP);  // Using internal pull-up resistor
    }

    // Attach servo to pin
    penguinServo.attach(servoPin);

    Serial.begin(9600);  // For debugging if needed
}

void loop() {
    // Read the photoresistor value
    int photoValue = analogRead(photoPin);
    Serial.println(photoValue);

    // Control the LED based on photoresistor value
    if (photoValue < photoThreshold) {
        digitalWrite(ledPin, HIGH);  // Turn on LED if it's dark
    } else {
        digitalWrite(ledPin, LOW);   // Turn off LED otherwise
    }

    // Check each button 
    for (int i = 0; i < 3; i++) {
        if (digitalRead(buttonPins[i]) == LOW) { // Button pressed
            playPitch(i);
            movePenguin(i);  // Move penguin based on button pressed
        }
    }
}

// Function to move the penguin based on the button pressed
void movePenguin(int buttonIndex) {
    switch (buttonIndex) {
        case 0:
            penguinServo.write(0);   // Move penguin in one direction
            break;
        case 1:
            penguinServo.write(90);  // Move penguin to center
            break;
        case 2:
            penguinServo.write(180); // Move penguin in the other direction
            break;
    }
    delay(1000);  // Hold position for 1 second
    penguinServo.write(90);  // Return to center
}


void playPitch(int buttonIndex) {
    switch (buttonIndex) {
        case 0:
            tone(speakerPin, NOTE_C4, 300); // Play note C4
            break;
        case 1:
            tone(speakerPin, NOTE_D4, 300); // Play note D4
            break;
        case 2:
            tone(speakerPin, NOTE_E4, 300); // Play note E4
            break;
    }
    delay(300);
    noTone(speakerPin);
}

Final Product

Week 9 – Production Post

Idea

For this assignment, I came up with a simple idea of creating a personal space invasion detector. The circuit has two mode, turned on and off using digital input (switch), the space detection using analog input (photoresistor). If the hand comes to close the person, the yellow light will dim. I use the yellow LED because it normally symbolizes happiness, which means when it dims, the person becomes less happy because someone invaded his personal space.

Implementation

I drew a circuit of the detector, including 2 LEDs, 1 photoresistor, 1 resistor and 1 switch. The switch I use is the rectangular one with three connecting points. If points 1-2 are connected, turn on the red LED, if 2-3 are connected, turn on yellow LED (connected to photoresistor).

Video

Week 8 – Reading response

Small things overlooked

We often overlook small details and focus too much on assumed important features such as usability or practicality. In the reading “Her Code Got Humans on the Moon”, the suggestion to put a warning on a project was disregard because the assumption that the users are trained enough. This resulted in a disastrous problem, deleting all data when the astronauts actually press it. I think this example is similar to small lines of code or comments that we often consider insignificant. These parts may not make a project immensely better, but without them, issues could arise, as seen in the astronaut example.

Another takeaway from the reading is the importance of not making assumptions about users. Good design should account for worst-case scenarios or consider the perspective of someone with no prior knowledge of the product.

Similarly, Norman’s reading said that small details like warnings or the aesthetics of an interaction may not add specific usability to an object. However, it’s important to view design from multiple perspectives, not just functionality. While it’s logical to prioritize functionality, good aesthetics can sometimes offset weaknesses in other areas. In some cases, strong aesthetics prompt users to engage more based on emotional appeal rather than logical reasons. A good example of this is the vintage trend, such as using vinyl records or old flip phones. While these items don’t offer more functionality than recent models, they attract users by evoking nostalgia and a unique aesthetic.

Week 8: Hugging switch

Idea

For this project, my initial idea was to use a simple interaction as a switch to light up the LED light. I think hugs is the most suitable, because hugs usually gives us warmth and energy, which can symbolically ‘light up’ a light.

Implementation

I create a simple circuit like in this one:

Arduino LED - Complete Tutorial - The Robotics Back-End

I connect the 3.3V to the resistor -> LED -> ground. However, from the 3.3V to the bread board, instead of connecting the wire directly to the resistor, I attach it with a piece of tin foil to my plushy. I also attach another tin foil on my T-shirt, this tin foil is attached to a wire, which is connected to the resistor. Hence, when I hug the plushy, the tin foils touch, completing the circuit and turn on the light.

Video

 

My project implementation was fairly simple, so I did not encounter many problems. Nevertheless, I do have some tips from my first experience working with Arduino. Initially, I tried connecting the wires with regular tape, which didn’t work at all since it isn’t conductive. I then switched to tin foil and wrapped it around the connecting points. Next time, I would use conductive tape or male-to-female wires instead.

Reflection

I enjoyed creating this project. I think the components provided in the Arduino kit make building physical projects much easier. I also try to look at “switch” in a different perspective to come up with a switch which is not only unusual but also has some kinds of meaning.