Final Project + User Testing – Mini Basketball Arcade Game

Concept of the Game

The aim of this Final Project is to build an interactive multimedia system that involves physical interaction and relies on a multimedia computer for processing or data analysis. To create a Mini Basketball Arcade Machine, I am using BOTH P5 AND Arduino. The mini Basketball Arcade Machine will be a tabletop-sized arcade game that will allow users to play basketball by shooting miniature basketballs into a hoop. Whenever the ball successfully passes through the hoop, it makes contact with the flex sensor causing alterations in its readings. As soon as a modification is identified in the flex sensor’s values, the player is credited with certain amount of points. Failing to score does not lead to a decrease in points. The game has a time limit, and when the time is up, a buzzer goes off to signify the end of the game. Players can see their score and the highest score achieved and can choose to play again. The machine utilizes Arduino to detect when the player shoots the basketball and p5.js to present the score and time on the scoreboard.

Implementation

INTERACTION DESIGN

The interaction design of the Mini Basketball Arcade Game is centered around the physical act of shooting a miniature basketball into the hoop, which is the primary user input. The flex sensor provides an accurate and responsive way to detect when the ball passes through the hoop, and the Arduino board processes this data and communicates it to the P5.js program. This allows the user to receive immediate feedback on their performance in the form of an updated score on the computer screen.

The P5.js program provides a visually appealing and intuitive interface for the user, with a scoreboard that displays the current score and time remaining in the game. The program also displays the basketball hoop and basketballs for the user to shoot, creating a realistic and immersive experience. When the user successfully shoots the ball through the hoop, the program responds with a satisfying feedback sound and updates the score accordingly.

The time limit of the game adds an additional layer of challenge and excitement to the interaction design, encouraging the user to stay engaged and focused. When the time runs out, a buzzer sounds, signaling the end of the game and allowing the user to view their final score and compare it to the highest score achieved.

Overall, the Mini Basketball Arcade Game is a well-designed and engaging interactive system that combines hardware and software to create a realistic and immersive basketball arcade experience.

P5.JS CODE

The code starts by defining the necessary variables and objects such as the background music, spritesheets, and sounds. The program also sets up the serial connection to the Arduino. The “preload()” function is used to load all the necessary assets such as the images and sounds. The “setup()” function initializes the canvas and sets up the game by creating instances of the “Game” class, loading the spritesheets and setting the font. The “draw()” function is used to draw all the different screens of the game, and it also determines which screen to display based on the game’s state.

// Set up the canvas with width and height of 600 pixels
function setup() {
  createCanvas(600, 600);

  // Set the text size to 18 pixels
  textSize(18);

  // Set up the serial port for communication with external devices
  setUpSerial();

  // Create a new instance of the Game class
  game = new Game();

  // Set text alignment to center
  textAlign(CENTER);

  // Set rectangle mode to center
  rectMode(CENTER);

  // Resize the spritesheet to half its original size
  spritesheet.resize(spritesheet.width / 2, spritesheet.height / 2);

  // Set the width and height of the individual basketball sprite
  w = spritesheet.width / 6;
  h = spritesheet.height;

  // Create an array of basketball sprites by extracting them from the spritesheet
  for (let i = 0; i < 6; i++) {
    bballSprite[i] = spritesheet.get(i * w, 0, w, h);
  }

  // Set the font to be used for text rendering
  textFont(font);
}
function draw() {
  // If the serial port is not active
  if (!serialActive) {
    fill(255);
    text("Press Space Bar to select Serial Port", 20, 30);
  }
  // If the serial port is active
  else {
    background(255);
    // If the game state is 0, call the click function
    if (game.state == 0) {
      game.click();
    }
    // If the game state is 1, call the menu function
    else if (game.state == 1) {
      game.menu();
    }
    // If the game state is 2, call the countdown function
    else if (game.state == 2) {
      game.countdown();
    }
    // If the game state is 3, call the game function
    else if (game.state == 3) {
      game.game();
    }
    // If the game state is 4, call the endScreen function
    else if (game.state == 4) {
      game.endScreen();
    }
  }
}

 

The game is a basketball shooting game where the objective is to score as many points as possible within the time limit of 45 seconds. The game is broken down into different states based on the stage of the game. The game has a starting screen, a menu, a countdown screen, the actual game screen, and the end screen. The program also uses sounds to add to the user experience. The program uses the p5.web-serial.js library to interact with the Arduino to receive data.

The game logic is handled by the “Game” class. The class constructor initializes the state of the game, and it has methods to handle each state of the game. The “click()” method displays a starting screen with instructions, and the “menu()” method displays the menu where the user can start the game. The “countdown()” method handles the countdown before the game starts. The “game()” method handles the actual game where the user interacts with the Arduino to shoot the basketball. The “endScreen()” method handles the display of the final score and provides an option to restart the game.

class Game {
  constructor() {
    // Initializes game state, score, time, and high score
    this.state = 0;
    this.score = 0;
    this.highScore = 0;
    this.time = 45;
  }

  click() {
    // Displays start message on click
    push();
    background(255,159,159);
    fill(0);
    textSize(width / 10);
    text("Click to start", width / 2, height / 2);
    pop();
  }

  menu() {
    // Animates the basketball sprite and displays the menu
    if (frameCount % 5 == 0) {
      step++;
      if (step == 6) {
        x += w;
        step = 0;
      }
      if (x >= width) {
        x = 0;
      }
    }
    push();
    imageMode(CORNER);
    image(menu, 0, 0, width, height);
    pop();
    push();
    // Displays the basketball sprite, fade animation, and start button
    image(bballSprite[step], x, (2 * height) / 3);
    if (fade < 255) {
      fade += 2;
    }
    fill(0, 150);
    rect(width / 2, (4.9 * height) / 9, width / 4, height / 7, 20);
    fill(178, fade);
    textSize(width / 10);
    textFont(font);
    text("Start", width / 2, (3 * height) / 5);
    pop();
  }

  countdown() {
    // Displays countdown before starting the game
    push();
    background(0);
    fill(255);
    textSize(width / 12);
    text(cd, width / 2, height / 2);
    if ((frameCount - startTime) % 45 == 0) {
      cd--;
    }
    if (cd == 0) {
      // Plays crowd sound and updates game state when countdown is over
      crowdSound.setVolume(0.5);
      crowdSound.loop();
      this.state++;
      startTime = frameCount;
    }
    pop();
  }

  game() {
    push();
    // Displays game background and score/time counters
    imageMode(CORNER);
    image(crowd, 0, 0, width, height);
    pop();
    push();
    textSize(width / 15);
    if ((frameCount - startTime) % 45 == 0) {
      gameTime--;
    }
    fill(0);
    text("Time left: " + gameTime, width / 4, height / 8);
    text("Score: " + this.score, width / 4, (10 * height) / 11);
    if (newVal < prevVal - 7 && time < frameCount - 30){
      // Plays a random sound effect and increases score when a shot is detected
      let rand = int(random(6));
      sounds[rand].play();
      this.score+=3;
      time = frameCount;
    }
    if (gameTime == 0) {
      // Plays buzzer sound and updates game state when time is up
      buzzer.play();
      this.state++;
      if (this.score > this.highScore) {
        this.highScore = this.score;
      }
    }
    pop();
  }

  endScreen() {
    push();
    // Displays game background and score/high score
    imageMode(CORNER);
    imageMode(CORNER);
    image(crowd, 0, 0, width, height);
    pop();
    push();
    fill(0);
    textSize(width / 14);
    text("Game Over", width / 4, height / 2);
    text("Score: " + this.score, (1.5 * width) / 7, height / 4);
    text("High Score: " + this.highScore, (5 * width) / 7, height / 4);
    fill(0);
    text("Play Again", width / 4, (7 * height) / 9);
    pop();
  }
}

Next, I implemented the feature to make the game fullscreen when the user clicks the start screen. I accomplished this by resizing the canvas and using the fullscreen() function.

// This function is triggered when the mouse is pressed
function mousePressed() {
// Check if game state is 0 (menu screen)
if (game.state == 0) {
// Play music and set canvas to fullscreen
music.setVolume(0.5);
music.loop();
let fs = fullscreen();
fullscreen(!fs);
resizeCanvas(displayWidth, displayHeight);
// Change game state
game.state++;
}
// Check if game state is 1 (countdown screen)
else if (
game.state == 1 &&
mouseX < width / 2 + width / 8 &&
mouseX > width / 2 - width / 8 &&
mouseY < (5 * height) / 9 + height / 14 &&
mouseY > (5 * height) / 9 - height / 14
) {
// Stop music and change game state
music.stop();
game.state++;
startTime = frameCount;
}
// Check if game state is 4 (end screen)
else if (
game.state == 4 &&
mouseX < width / 4 + width / 4 &&
mouseX > width / 4 - width / 4 &&
mouseY < (7 * height) / 9 + height / 5 &&
mouseY > (7 * height) / 9 - height / 5
) {
// Reset game state, score, countdown timer and game timer
game.state = 2;
game.score = 0;
cd = 3;
gameTime = 45;
}
}

ARDUINO CODE

The Arduino program will read the sensor input to determine when the ball has been shot and passed through the hoop. The circuit will consist of a flex sensor and a resistor, with the flex sensor connected to an analog input on the Arduino board. The Arduino program will read the analog input to determine the current value of the flex sensor, which will change whenever a basketball passes through the hoop and contacts the sensor.

This Arduino code is designed to read analog input from a flex sensor connected to pin A0. In this case I built a sample circuit with LED to monitor if the flex sensor is working properly. The code begins by declaring constants for the LED pin (3) and the flex sensor pin (A0), and a variable to store the analog input value. In the setup function, the LED pin is set as an output pin, and serial communication is initialized at a baud rate of 9600.

The loop function continuously reads the analog value from the flex sensor using analogRead(), and then prints this value to the serial monitor using Serial.println(). The analog value is then mapped from the range 700-900 to the range 0-255 using the map() function. The resulting value is then used to control the brightness of the LED using analogWrite(), which sends a PWM signal to the LED pin. Finally, there is a small delay of 100ms before the loop starts again.

//Constants:
const int ledPin = 3;   //pin 3 has PWM funtion
const int flexPin = A0; //pin A0 to read analog input
//Variables:
int value; //save analog value
void setup(){
  
  pinMode(ledPin, OUTPUT);  //Set pin 3 as 'output'
  Serial.begin(9600);       //Begin serial communication
  while(Serial.available() <= 0) {
     Serial.println("0,0");
    }
}
void loop(){
  
  value = analogRead(flexPin);         //Read and save analog value
  Serial.println(value);               //Print value
  value = map(value, 700, 900, 0, 255);//Map value 0-1023 to 0-255 (PWM)
  analogWrite(ledPin, value);          //Send PWM value to led
  delay(100);                          //Small delay
  
}

Additionally, I tested photoresistor and infrared distance measurer as potential types of sensors for detecting when the basketball passes through the hoop. Based on my testing I determined that flex sensor is the most accurate and well-designed option.

COMMUNICATION BETWEEN ARDUINO/ P5.JS

The communication between Arduino and P5.js in the Mini Basketball Arcade Game is crucial for the game to function properly. The Arduino program reads the analog input from the flex sensor, which detects when the basketball passes through the hoop. Once the flex sensor value changes, the Arduino program sends this data to the P5.js program for processing and display on the scoreboard.

In order to establish communication between the two programs, the Arduino program uses the Serial communication protocol to send the sensor data to the P5.js program. The data is transmitted as a series of bytes that represent the flex sensor value. The P5.js program receives this data using the Serial communication library, which provides a way for the P5.js program to listen to the serial port and read the incoming data.

Once the P5.js program receives the flex sensor data from the Arduino program, it uses this data to update the score on the scoreboard. When data is received, the P5.js program reads the data and stores it in a variable. The P5.js program then uses this variable to update the player’s score based on the successful shots made by the player. The P5.js program also keeps track of the time remaining in the game and displays this information on the scoreboard.

What are some aspects of the project that you’re particularly proud of?

The main aspect I am very proud of in this project is the Mini Basketball Arcade Gaming Box that I created.  I did not expect it to take so much time to build and design a game box, but I still enjoyed the process and came up with really user-friendly solution. I constructed a rectangular frame to support the basketball hoop, which also featured a ramp for the ball to return to the user, making it more convenient for the users to collect the balls after shooting. Following the initial user testing, I decided to enlarge the size of the frame, allowing more space for missed shots to fall onto the ramp and roll back to the user.

 

As you can observe from pictures above, I specifically created a path for the basketball to slide because in the first cases of user-testing I received a feedback about balls being stuck in the frame so I designed a path and additional section where used balls are stored.

To create the hoop, I repurposed a paper coffee container, and the ball was a ping pong ball that I borrowed from the Fitness Center.

What are some areas for future improvement?

  • One potential area is to improve the accuracy and precision of the flex sensor readings. The flex sensor used in the project is known to be sensitive to changes in temperature, humidity, and other environmental factors. Also the right positioning of the flex sensor is crucial because it needs to be centered so that it would 100% detect the falling ball. Because I used tennis balls the attachment to the hoop also caused substantial issues resulting in faulty detections.
  • Another potential game level could involve increasing the difficulty of the shots required to score points. For example, the basket could be moved to different locations or the size of the basket could be decreased. To implement this, the code would need to randomly generate new positions for the basket and adjust the size of the basket accordingly. The code would also need to calculate the trajectory of the ball and determine whether it goes through the basket.

User Testing

 

For the final user testing, I asked Aaron and Symbat to test my  game without giving them any prompts/instructions . User testing was important to identifying what to work on in my project.

Are they able to figure it out? Where do they get confused and why? Do they understand the mapping between the controls and what happens in the experience?

It was very straightforward because I made the design of the game box and even tennis balls obviously basketball themed and there was not any confusion in figuring out the interaction design. They both immediately understood how to play the game and the mapping between the controls and what happens in the experience. Physical act of shooting a miniature basketball into the hoop, which is the primary user input was well implemented and tested.

What parts of the experience are working well? What areas could be improved?

The whole interaction design part is working surprisingly well.  P5.js program offers an interactive and immersive basketball game, featuring a visually appealing interface with a scoreboard showing the current score and time remaining. Users can shoot basketballs through the hoop, and the program responds with feedback sounds and updates the score. The game also includes a time limit, adding an extra layer of excitement and challenge. A buzzer sounds when the time runs out, and the user can view their final score and compare it with the highest score achieved.

As mentioned before, one potential area is to improve the accuracy and precision of the flex sensor readings because sometimes when the flex sensor is tilted from its position it might count faulty results. Additionally, because I am using very light tennis ball it compromises the best positioning of sensor by getting a bit heavier ball of same size the accuracy would be perfect.

What parts of your project did you feel the need to explain? How could you make these areas more clear to someone that is experiencing your project for the first time?

I received some questions about how the shoots are detected and what sensors I used. I could provide more information about the different types of sensors being tested (photoresistor and infrared distance measurer) and how they work. This would help the user understand the reasoning behind using a flex sensor and how it compares to other potential sensor options. I can also explain about the materials and components required to build the physical arcade machine. This would give the user a better understanding of the physical aspects of the project and how they fit together.

Final Project Proposal: Mini Basketball Arcade Game

Concept

The goal of this Final Project is to create a physically interactive system that relies on a multimedia computer for some sort of processing or data analysis. My Final Project uses BOTH P5 AND Arduino to create a Mini Basketball Arcade Machine. The mini Basketball Arcade Machine will be a tabletop-sized arcade game that will allow users to play basketball by shooting miniature basketballs into a hoop. Whenever the ball successfully passes through the hoop, it makes contact with the flex sensor causing alterations in its readings. As soon as a modification is identified in the flex sensor’s values, the player is credited with certain amount of points. Failing to score does not result in any reduction in points. The game has a time limit, and when the time runs out, a buzzer sounds, signaling the end of the game. The player can then view their score and the highest score achieved, and they have the option of playing again. The machine will use Arduino to sense when the user shoots the basketball and p5.js to display the score and time on the scoreboard.

Arduino

The Arduino program will read the sensor input to determine when the ball has been shot and passed through the hoop. The circuit will consist of a flex sensor and a resistor, with the flex sensor connected to an analog input on the Arduino board. The Arduino program will read the analog input to determine the current value of the flex sensor, which will change whenever a basketball passes through the hoop and contacts the sensor.

The Arduino program will send this flex sensor value to the P5.js program for processing and display on the scoreboard. The P5.js program will receive this data from the Arduino program and use it to update the score based on the number of successful shots made by the player. In summary, the Arduino program for the mini basketball arcade machine will read the flex sensor value from the circuit, send this value to the P5.js program for processing and display, and keep track of the time limit of the game.

Additionally, I am planning to test photoresistor and infrared distance measurer as potential types of sensors for detecting when the basketball passes through the hoop. Based on my testing I would determine whether flex sensor is the most accurate and well-designed option.

P5.js

The P5.js program for the mini basketball arcade machine will be responsible for displaying the game interface, keeping track of the player’s score, and communicating with the Arduino program to receive data about the current state of the game. The P5.js program will display the scoreboard on the computer screen, showing the player’s current score and the time remaining in the game. It will also display the basketball hoop and the basketballs for the player to shoot.

When the player shoots a basketball and it passes through the hoop, the flex sensor in the circuit will detect the change in resistance, and the Arduino program will send this data to the P5.js program. The P5.js program will receive the data from the Arduino program and update the player’s score based on the successful shot.

Final Project Concept – Mini Basketball Arcade Game

Concept

The goal of this Final Project is to create a physically interactive system that relies on a multimedia computer for some sort of processing or data analysis. My Final Project uses BOTH P5 AND Arduino to create a Mini Basketball Arcade Machine. The mini Basketball Arcade Machine will be a tabletop-sized arcade game that will allow users to play basketball by shooting miniature basketballs into a hoop. The game will have a digital scoreboard that will display the player’s score and time remaining. The machine will use Arduino to sense when the user shoots the basketball and p5.js to display the score and time on the scoreboard.

Implementation

The user will start the game by pressing a pushbutton, which will light up an LED on the scoreboard and start the timer. The user will then have a set amount of time to shoot as many mini basketballs into the hoop as possible. Arduino will detect when the user shoots the basketball by using a sensor attached to the hoop. Each time the user makes a shot, the scoreboard will update the score and display it on the LED screen. When the time is up, the game will end, and the final score will be displayed on the scoreboard.

The mini Basketball Arcade Machine will provide an interactive and engaging experience for users. It will rely on careful and timely sensing of the user’s actions and provide clear, prompt, and effective responses through the use of Arduino and p5.js.

Week 11 – In-class Exercises (moving ellipse, LED brightness, Gravity wind example)

Group mates: Swostik Pati and Irem Naz Celen

Task 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

The code provided in the lecture notes for both Arduino and P5.js was used as-is, except for the draw function in P5.js. We modified the code to make the ellipse’s horizontal location change when the potentiometer was turned, and the vertical location change when the LDR input was changed. To prevent multiple visual responses from P5.js when the potentiometer and LDR were manipulated, we removed the background and fill functions.

Code:

Arduino Code

p5.js code

Video:

 

Task 2:

make something that controls the LED brightness from p5

We made some changes to both the Arduino and P5.js code for this task. To adjust the brightness of the LED, we utilized the keyboard’s Up and Down arrows as the input for the P5.js code. This changing value was then sent to the LED connected to PWM pin 5. We used analog write to this pin, which increased or decreased the LED value. If the value exceeded 255, it reset to 0 and vice versa.

Code:

Arduino Code

p5.js code

Video:

Task 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

To complete the exercise, we made changes only to the P5.js code by incorporating the gravity wind example. The original Arduino code from the lecture notes remained unchanged. We divided the range of the potentiometer into three intervals, which set the wind vector to -1, 0, and 1 depending on its direction. These values are acceptable for the wind. We also implemented a collision detection flag. When a collision occurs, the LED on pin 2 is turned on. Whenever there is no collision, the LED is turned off.

Code:

Arduino Code

p5.js code

Video:

Week 10 – Musical Instrument

Concept

Our project is a musical instrument that uses an ultrasonic sensor to measure the distance between the sensor and an object and plays different notes based on the distance. A note is played when a push button is pressed. The distance measurement is then mapped to an array of notes to play on a piezo buzzer.

 

IMPLEMENTATION

We have started from setting up a circuit that uses next components: ultrasonic sensor, piezo buzzer, 10 jumper wires, pushbutton, and 10k resistor. The ultrasonic sensor was used to measure the distance of the object from the instrument, and the piezo buzzer was used to play the musical notes based on the measured distance. The pushbutton was used to activate the instrument and play the notes, and the 10k resistor was used as a resistor for the button. We connected all these components using jumper wires to establish a circuit that would form the foundation for the instrument.

We have then moved onto adding a code component. In the setup() function we have set the pinMode for each of the pins used in the circuit. We have also used the Serial.begin() function to start serial communication between the Arduino and the computer, which would allow us to view debug messages.

The first part of the loop function was used to read the distance measurement from the ultrasonic sensor using the pulseIn() function. We then used this distance measurement to calculate which note to play on the piezo buzzer. We mapped the distance to a note by dividing the range of distances by the number of notes we wanted to play (in this case, five).

The code then checked the state of the pushbutton using the digitalRead() function. If the pushbutton was not pressed, the piezo buzzer would not play any sound, and a message would be printed to the serial monitor. If the pushbutton was pressed, the corresponding note would play on the piezo buzzer, and a message indicating the button’s state and the note being played would be printed to the serial monitor.

// 
// Project name: "HW7: Musical Instrument"
// Names: Adina & Aibar
// Class: Intro to IM
// Professor: Michael Shiloh
//

int trigPin = 10;
int echoPin = 11;
int buttonPin = 2;
int buzzerPin = 12;

long duration;
long distance;

int buttonState;

void setup() {
  //distance pins
  pinMode(echoPin, INPUT);
  pinMode(trigPin, OUTPUT);
  //button pin
  pinMode(buttonPin, INPUT);
  //buzzer pin
  pinMode(buzzerPin, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  digitalWrite(trigPin, LOW); //triggers on/off and then reads data
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) * .0344; //speed of sound converted into cms

  int notes[5] = {261, 294, 329, 349, 392}; //array of notes
  //          mid  C    D    E    F    G 

  buttonState = digitalRead(buttonPin);
  if (buttonState == 0) { //if not pressed
    noTone(12);
    Serial.println("button not pressed");
  }

  else if ((buttonState == 1)) {  //if pressed
    int sound = map(distance, 0, 30, 0, 5);  //map distance to the array of notes
    tone(buzzerPin, notes[sound]);  //play a note
    //checking if works through serial monitor
    Serial.print("button pressed, ");
    Serial.print(buttonState);
    Serial.print(", ");
    Serial.println(sound);
  }
}

Schematic Diagram

VIDEO DEMO

If the video window doesn’t show, use this link to see the demo of the musical instrument.

 

 

CHALLENGES AND SOLUTIONS

Our biggest challenge was ensuring that the distance reader could detect the object in front of it accurately. When the reader did not detect the object correctly, the instrument played a weird sound that sounded like a very high pitch, which was not the sound we were hoping to achieve. It took several attempts to get the distance reader to work correctly. A solution that we came up with was decreasing the max distance when mapping the sound to the distance and using a solid object like the back of the phone, rather than a hand. By decreasing the maximum distance for the object, we were able to make sure that the distance reader could pick up on the object’s presence.

 

Week 9 – Analog and Digital Input and LEDs

Concept

For the purpose of this Assignment we had to get information from at least one analog sensor and at least one digital sensor, and use this information to control at least two LEDs, one in a digital fashion and the other in an analog fashion, in some creative way. What can be more creative than a game?! So I decided to create a mini game using photoresistor, button and three different LEDs. The aim of the game is to try to get all the three LEDs on and catching that moment by clicking the button. If you would be able to simultaneously light up all three LEDs and press the button you won the game which will be indicated by mini disco show at the end. This game is not easy as the gamer should predict the distance of his finger from the photoresistor and find that sweet spot where all the three LED conditions for turning on are satisfied. Furthermore, player needs to use his/her reflexes to immediately click on the button.

Circuit

Implementation

The Arduino board has three LED lights, with three of them being regulated by an analog input device called a photoresistor. The photoresistor will determine the intensity of the red, blue, and yellow lights. I created a sensor value variable which is

sensorValue = analogRead(LDR);
depending on its value the different LEDs are on if the conditions are satisfies. In the case when the 700 < sensorValue < 800 and if all other if conditions are not satisfied the analogWrite is 0 for all three colors.  See the code below:
sensorValue = analogRead(LDR);
  
  if(sensorValue < 620){
    analogWrite(blue, 255);
    analogWrite(green, 0);
    
  }
  else if(sensorValue > 520 and sensorValue < 610){
    analogWrite(blue, 255);
    analogWrite(green, 255);
    analogWrite(yellow,255);
   
  }
  else if(sensorValue > 520 and sensorValue < 650){
    analogWrite(blue, 0);
    analogWrite(green, 255);
    
  }

For the digital interaction the led lights will be controlled by digital input, the button, and under very specific circumstances when the all three LEDs are on and the player was able to successfully catch that second and click the button the mini discoteca show at the end will depict their win. The code below if for this function:

void discoteca(){
  digitalWrite(yellow, HIGH);
  delay(100);
  digitalWrite(yellow, LOW);
  
  digitalWrite(green, HIGH);
  delay(100);
  digitalWrite(green, LOW);
  
  digitalWrite(blue, HIGH);
  delay(100);
  digitalWrite(blue, LOW);

  delay(200);
  
}

if( digitalRead(yellow)==1 and digitalRead(blue)==1 and digitalRead(green)==1 and digitalRead(SWITCH)==HIGH) {
    digitalWrite(yellow, HIGH);
    delay(400);
    disoteca();
    disoteca();
    disoteca();
  }

Schematic Diagram

Video Demo

 

Reflection & Future Improvements

Developing this Arduino project was an exciting and challenging experience for me. It allowed me to combine my knowledge of analog and digital sensors, LED lights, and programming to create an entertaining mini game. there are several areas where I can improve it in the future. For instance, I could incorporate a timer that counts down the seconds before the LEDs turn off, which would add an additional level of difficulty to the game. Another possible improvement would be to incorporate different levels of difficulty, such as changing the optimal distance of the player’s finger from the photoresistor or increasing the number of LEDs required to win the game. Overall, this project was a great learning experience for me, and I look forward to implementing these improvements and exploring other creative Arduino projects in the future.

Week 8 – Unusual Switch – Sea Level Detector

Concept

For this assignment I decided to create a potentially useful and practical switch that can be utilized in real world for detecting the sea level. My switch lights up with three red LEDs indicating that the water level at sea is above a certain point. Sea Level Detector does not use a traditional sensor. Instead, it relies on the conductivity of saltwater to complete the circuit and activate the LEDs.

This project is a great way to raise awareness about rising sea levels and the impact of climate change. By using simple materials and basic electronics, it is accessible to anyone interested in building their own Sea Level Detector. The project can also be modified to include additional features, such as data logging or remote monitoring, to make it even more useful and informative.

Implementation

The Sea Level Detector uses two metal rods, which are connected to the Arduino board and placed in the saltwater. As the water level rises, it comes into contact with both rods, completing the circuit and allowing electricity to flow between them. This results in the LEDs lighting up, indicating that the water level has reached a certain point.

The conductivity of saltwater is due to the presence of ions, specifically Na+ (sodium ions) and Cl- (chloride ions). These ions allow the water to conduct electricity, which is the principle behind the Sea Level Detector.


First picture depicts a high level of water which touches the metal rods conducting electricity through water lighting up the three red LEDs. In contrast, second picture shows the low level of water where rods are not in contact with water thus not conducting the electricity and LEDs are off.

Schematic Diagram

Video Demo

 

The Martian – Midterm Project

The Martian

Sketch link

To play the game in fullscreen click this link -> Click Here to Play the Game

The project code -> Code

Overall Concept

For this Midterm Project I created a game using everything I have learned so far in class. The game is be called “The Martian” and the objective of the game is to guide the Mars Rover through the treacherous terrain of Mars, collecting valuable resources and avoiding hostile alien spaceships and rocks on the surface. The player will have to navigate using keyboard and mouse as they progress through the game. In “The Martian” the player will experience the thrill of driving a Mars Rover on the surface of the red planet. With challenging terrain, hostile aliens, and valuable resources to collect, the game will offer hours of exciting gameplay. The use of p5.js will enable the creation of a visually stunning and engaging game.

The overall concept of this game is a space-themed adventure where the player takes on the role of a NASA satellite specialist who is tasked with rescuing the PERSEVERANCE probe from an alien threat. The game has two modes: collection mode and exploration mode.  Your primary objective is to protect it from any danger by avoiding all the obstacles and enemy UFOs. In pause mode, the obstacles and UFOs will not harm you.

Implementation and Design

How this project works

In the game you are a satellite specialist at NASA, and the probe PERSEVERANCE, is being chased by an alien! It’s your task to save it! Avoid the stones and enemy UFO’s to save it! You will have to use the Space and Down keys to control the rover. I also decided to implement two different modes to the game:

  1. In collection mode- Collecting a Uranium atom is worth 5 points and collecting a water is worth 10 points. While collecting points, remember to dodge the UFO’s and stones on the surface of the red planet.
  2. In exploration mode crossing certain distance automatically gives 1 point. All you have to do is to dodge the UFO’s and stones on the surface of the red planet.

Technical Design/Good technical decisions

The starting screen of the game has three buttons:

  1. Mode button in which you can choose between Collection and Exploration modes according to your preference.
  2. Start button to start the game.
  3. Rules button which gives precise instructions on how to play and control the game.

This creates a user friendly experience where users can easily manage the different aspects of the game from the main page.

The technical decision I am particularly proud of is implementing the two different modes of the game. I initially thought that it would be only Collection mode where you can earn points by collecting really scientifically valuable resources like Uranium atom and Water in Mars. But after I asked my friends for user testing one of them gave me a feedback that not every user wants to collect something to play the game. Considering this feedback I also realized that in the games like Geometry Dash the main goal was to survive not to collect the resources. And this fits the logic because whats the point of your resources if you are dead?! That way the Exploration mode was made.

Collection mode:

Exploration mode:

Code for the two modes:

switch (mode) {
      case "exploration" : score+=0.01;
                      score$=Math.round(score);
                      water.visible=false;
                      atom.visible=false;
                      break;
      case "collection" : water.velocityX=-4;
                          atom.velocityX=-4;
                          if(rover.isTouching(water)) {
                              score+=10;
                              score$=score;
                              water.x=width+Math.round(random(1000,1400));
                              water.y=Math.round(random(rover.y,height-300));
                              jump.play();
                          }
                          if(rover.isTouching(atom)) {
                              score+=5;
                              score$=score;
                              atom.x=width+Math.round(random(299,499));
                              atom.y=Math.round(random(rover.y,height-300));
                              jump.play();
                          }
                          water.visible=true;
                          atom.visible=true;
                          break;
  }

Another technical design I am proud of is the collision detection algorithm/logic. The idea is to detect the collision between Mars Rover and other objects like valuable resources and hostile alien spaceships or rocks. I  came up with an algorithm to distinguish between these various collisions with different objects. Because if the Mars Rover collides with valuable resources the Score should increase and if it collides with the rock or alien spaceship it should end the game and display the restart button.

case "collection" : water.velocityX=-4;
                    atom.velocityX=-4;
                    if(rover.isTouching(water)) {
                        score+=10;
                        score$=score;
                        water.x=width+Math.round(random(1000,1400));
                        water.y=Math.round(random(rover.y,height-300));
                        jump.play();
                    }
                    if(rover.isTouching(atom)) {
                        score+=5;
                        score$=score;
                        atom.x=width+Math.round(random(299,499));
                        atom.y=Math.round(random(rover.y,height-300));
                        jump.play();
                    }
                    water.visible=true;
                    atom.visible=true;
                    break;

else if(touches[0].y<restart.position.y+50&&touches[0].y>restart.position.y-50) {
    if(touches[0].x<restart.position.x+50&&touches[0].x>restart.position.x-50) {
        state="start";
        rover.visible=true;

        water.x=width+Math.round(random(1000,1400));
        water.y=Math.round(random(rover.y,height-300));

        atom.x=width+Math.round(random(299,499));
        atom.y=Math.round(random(rover.y,height-300));

        score=0;

        switchPBtn.visible=false;
        restart.visible=false;
        ufo$.destroyEach();

        click.play();

        frameCount=0;
    }
}
if(water.x==0) {
           water.x=width+Math.round(random(1000,1400));
           water.y=Math.round(random(rover.y,height-300));
       }
if(atom.x==0) {
           atom.x=width+Math.round(random(299,499));
           atom.y=Math.round(random(rover.y,height-300));
       }

Good Game Design

I paid particular attention to my game design elements and UI interface to create the best possible user experience.

Uranium Atom Resource
Water Resouce

 

Mars Rock
Alien Spaceship

For the User Interface elements and buttons I utilized internet and created some of them using Photoshop tool.

Rules Button
Pause Button
Selection Circle

I am proud of my Pause functionality which not a lot of games of these type have. I think it is essential for the user to have an access to Pause button as he can be busy with other important matter and it would be pity to lose your progress just because of that. Code for Pause Logis:

else if(state=="pause") {

       sd=0;

       rover.velocityY=0;

       atom.velocityX=0;
       water.velocityX=0;
       stone.velocityX=0;
       ufo$.setVelocityXEach(0);

       textSize(20);
       textFont(font);
       fill(rgb(40,99, 235));
       text("Score- " + score$,width/2-30,100);

       restart.visible=true;
       switchPBtn.visible=true;
       switchBtn.visible=false;

       block[0].velocityX=0;
       block[1].velocityX=0;
       block[2].velocityX=0;
       block[3].velocityX=0;
       block[4].velocityX=0;

       block$.velocityXEach=0;
       block$.destroyEach();

       ufo$.velocityXEach=0;
       
       if(touches.length>0) {
           if(touches[0].y<switchPBtn.position.y+50&&touches[0].y>switchPBtn.position.y-50) {
               if(touches[0].x<switchPBtn.position.x+50&&touches[0].x>switchPBtn.position.x-50) {
                   switchPBtn.visible=!true;
                   switchBtn.visible=false;
                   restart.visible=false;

                   block[0].velocityX=-4;
                   block[1].velocityX=-4;
                   block[2].velocityX=-4;
                   block[3].velocityX=-4;
                   block[4].velocityX=-4;

                   click.play();

                   block$.velocityXEach=-4;

                   sd=2;
                   //alert("UP");
               }
           }
           else if(touches[0].y<restart.position.y+50&&touches[0].y>restart.position.y-50) {
               if(touches[0].x<restart.position.x+50&&touches[0].x>restart.position.x-50) {
                   state="start";
                   rover.visible=true;

                   water.x=width+Math.round(random(1000,1400));
                   water.y=Math.round(random(rover.y,height-300));

                   atom.x=width+Math.round(random(299,499));
                   atom.y=Math.round(random(rover.y,height-300));

                   score=0;

                   switchPBtn.visible=false;
                   restart.visible=false;
                   ufo$.destroyEach();

                   click.play();

                   frameCount=0;
               }
           }
       }

Potential Improvements and Challenges

Possible future improvements/ideas enhancing the game’s overall experience:

  • Power-ups can be added to the game to give the player temporary advantages such as invincibility or increased speed. This will make the game more engaging and provide players with a sense of accomplishment.
  • Multiple levels can be included in the game to provide players with different challenges as they progress. Each level can have its own unique obstacles and enemy UFOs, making the game more varied and exciting.
  • Including a high score system in the game can add a sense of competition, encouraging players to try and beat each other’s scores. This will also give players a reason to keep playing and trying to improve their skills.

Challenges

  •  Because I didn’t have any previous background in using sound and animation libraries I have spent quite some time figuring out ways of implementation and tested them extensively.
  • As mentioned in Midterm Progress post  for me the most frightening  or complex part of this midterm project was to implement a collision detection algorithm. I also have to somehow come up with an algorithm to distinguish between these various collisions with different objects. Because if the Mars Rover collides with valuable resources the Score should increase and if it collides with the rock or alien spaceship it should end the game and display the restart button. Luckily it was easier than I expected.
  • Putting different screen views into action and moving between them was a bit challenging for me. Particularly, finding my way back to the Main Page from The End screen without refreshing the sketch took some time to figure out. Eventually, I created a straightforward system that relied on flags to accomplish this.

 

Midterm Progress “The Martian”

Concept & Design

For this Midterm Project I would like to create a game using everything I have learned so far in class. The game will be called “The Martian” and the objective of the game is to guide the Mars Rover through the treacherous terrain of Mars, collecting valuable resources and avoiding hostile alien spaceships and rocks on the surface. The player will have to navigate using keyboard and mouse as they progress through the game. In “The Martian” the player will experience the thrill of driving a Mars Rover on the surface of the red planet. With challenging terrain, hostile aliens, and valuable resources to collect, the game will offer hours of exciting gameplay. The use of p5.js will enable the creation of a visually stunning and engaging game.

Potential Design Elements

Complex part of midterm project

For me personally the most frightening  or complex part of this midterm project is to implement a collision detection algorithm. The idea is to detect the collision between Mars Rover and other objects like valuable resources and hostile alien spaceships or rocks. I also have to somehow come up with an algorithm to distinguish between these various collisions with different objects. Because if the Mars Rover collides with valuable resources the Score should increase and if it collides with the rock or alien spaceship it should end the game and display the restart button. Also because I didn’t have any previous background in using sound and animation libraries I would have to test them out.

Implementation & Reducing the risk

Here I wrote some code for the collision algorithm between Mars Rover and Rock:

if(ufo$.isTouching(rover)||stone.isTouching(rover)) {
            console.log("end");
            state="end";
            ufo$.destroyEach();
            stone.x=width+400;
            stone.velocityX=0;
            rover.visible=false;

            gmov.play();
               
            textSize(30);
            textFont(font);
            fill("black");
            text("The End",width/2,height/2);
        }

        if(mousePressedOver(switchBtn)) {
            sd=1;
            click.play();
        }
        if(sd==1) {
            state="pause";
        }

I also tried to implement the spawn of Alien Spaceships:

function spawnEnemy() {
    ufo=createSprite(width+50,Math.round(random(xp-100,xp+20)),80,80);
    ufo.velocityX=-5;
    ufo.addAnimation("ufo",ufo_);
    ufo.scale=0.2;
    ufo.lifetime=Math.round(width/3)+15;

    //ufo.debug=true;

    ufo.setCollider("circle",0,0,200);

    ufo$.add(ufo);
    console.log(xp);
    cx-=4;
}

 

Week 4 – Global Temperature Anomaly Visualization

Concept & Idea

This visualization shows the change in global temperature anomaly (the difference between the actual temperature and the long-term average temperature) over time, based on publicly available data. The visualization uses a line chart to represent the data, with the x-axis representing the years from 1753 to 2015 and the y-axis representing the temperature anomaly in degrees Celsius.

 

Implementation

The chart is generated using the p5.js library for drawing and the d3.js library for data manipulation. The code first loads the JSON data from a publicly available URL and extracts the necessary data. It then draws the x-axis and y-axis of the chart, with tick marks and labels indicating the years and temperature values. Finally, it draws the data points as small circles with color representing the temperature anomaly value, and connects them with lines to form the line chart.

let data; // variable to hold the JSON data
let minYear, maxYear, minTemp, maxTemp;

function preload() {
  // load the JSON data from a publicly available URL
  let url = 'https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json';
  data = loadJSON(url);
}

function setup() {
  createCanvas(800, 400);
  textAlign(CENTER);
  textSize(16);
  noLoop();

  // extract the necessary data from the JSON
  let monthlyData = data.monthlyVariance;
  minYear = monthlyData[0].year;
  maxYear = monthlyData[monthlyData.length - 1].year;
  minTemp = data.baseTemperature + d3.min(monthlyData, d => d.variance);
  maxTemp = data.baseTemperature + d3.max(monthlyData, d => d.variance);
}

function draw() {
  background(255);

  // draw the x-axis
  stroke(0);
  line(50, height - 50, width - 50, height - 50);
  for (let year = minYear; year <= maxYear; year += 10) {
    let x = map(year, minYear, maxYear, 50, width - 50);
    textAlign(CENTER);
    text(year, x, height - 30);
    stroke(200);
    line(x, height - 50, x, 60);
    stroke(0);
  }

  // draw the y-axis
  line(50, height - 50, 50, 60);
  textAlign(CENTER);
  push();
  translate(30, height / 2);
  rotate(-HALF_PI);
  text("Temperature Anomaly (°C)", 0, -15);
  pop();
  for (let temp = Math.floor(minTemp); temp <= Math.ceil(maxTemp); temp += 1) {
    let y = map(temp, minTemp, maxTemp, height - 50, 60);
    textAlign(RIGHT);
    text(temp, 40, y + 5);
    stroke(200);
    line(50, y, width - 50, y);
    stroke(0);
  }

  // draw the data points and connecting lines
  noFill();
  beginShape();
  for (let i = 0; i < data.monthlyVariance.length; i++) {
    let x = map(data.monthlyVariance[i].year, minYear, maxYear, 50, width - 50);
    let y = map(data.baseTemperature + data.monthlyVariance[i].variance, minTemp, maxTemp, height - 50, 60);
    stroke(255 - map(data.monthlyVariance[i].variance, -7, 7, 0, 255), 0, map(data.monthlyVariance[i].variance, -7, 7, 0, 255));
    ellipse(x, y, 4, 4);
    vertex(x, y);
  }
  endShape();
  
  // add the title and data source
  textAlign(CENTER);
  text("Global Temperature Anomaly (°C) " + minYear + " - " + maxYear, width / 2, 30);
}

Reflection & Future Improvements

This visualization allows users to easily see the trend in global temperature anomaly over time, as well as the magnitude of the variation in temperature from year to year. The color-coded data points also highlight areas of particularly high or low temperature anomalies, drawing attention to potentially significant events or trends in global climate. There are several potential improvements that could be made to this visualization. For instance, the visualization could be made more interactive by allowing users to hover over data points to see the exact temperature anomaly value and the year, or to zoom in on specific areas of the chart to see more detail. Users could also be given the ability to adjust the time frame shown on the chart or to select specific temperature ranges to focus on.