Final Project : SPACE SURVIVAL 🚀💫

Description of the Assignment: 

Create a physically interactive system of your choice that relies on a multimedia computer for some sort of processing or data analysis. The Final should use BOTH Processing AND Arduino.Your focus should be on careful and timely sensing of the relevant actions of the person or people that you’re designing this for, and on clear, prompt, and effective responses. Any interactive system is going to involve systems of listening, thinking, and speaking from both parties. Whether it involves one cycle or many, the exchange should be engaging. You may work alone or in pairs.

Description of the Projects: 

This game is a typical 90s arcade space shooter game where you control a space ship and shoot bullets at the asteroid to protect yourself. In this version of the game, instead of using the basic key controls, the player uses the motions of the hand to control the space ship and shoot bullets at the asteroid.

Process: 

The  command for the motion of the ship is given via the ultrasonic sensor.The distance between the players hand and the ultrasonic sensor determines the x-coordinate  of the ship in the game. I used the   to detect the change in light when the player closes his/her fist to shoot bullets. I mapped the sensor reading from 0 to 1023, to 0 to 10. Then I divided the readings into 2. When the photoresistor read above or equal to 5, the bullets would shoot, and the red light would light up, otherwise the blue led would light up indicating that the value is below 5.

For the processing , I created stars and asteroid in a loop as a separate function by putting them in an Array with random values across the width of the screen. The values for the bullets too are kept in an Array, but their x coordinate starts from the x-coordinate of the ship +100 (center of the ship) and the same as y -coordinate of the ship . For the spaceship, I used the following picture, resized to 200 by 100.

 

Here is also a picture of the overall set up:

 

Video: 

 

Code: 

Arduino:

int left = 0;
int right = 0;
//int buzzer = 5;

const int echoPin = 2;  // attach pin D2 Arduino to pin Echo of HC-SR04
const int trigPin = 3; //attach pin D3 Arduino to pin Trig of HC-SR04

const int led_red = 9;
const int led_blue = 8;
const int photo = A0;


// defines variables
long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement

void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  //  pinMode(buzzer, OUTPUT);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode (led_red, OUTPUT);
  pinMode(led_blue, OUTPUT);
  pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT


}

void loop() {

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);

  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)

  int constrained_distance = constrain(distance, 0, 30); //constraining distance to be detected
  int mapped_distance = map(constrained_distance, 0, 30, 0, 1300); // mapping the values as per convinience 

  int light = analogRead(photo); // reading values from photoresistor
  int mapped_light = map(light, 0, 1023, 0, 10); //mapping the values from photoresistor as per convinience 
  int constrained_light = constrain(light, 900, 1000);
  
  int value = 0;
  int numReadings = 10;

  for (int i = 0; i < numReadings; i++) {
    value = value + mapped_distance;
    delay(1);
  }

  int selected_value = value / numReadings; //taking avg of numbers in group of 10
  int avg_value = selected_value / 4; //taking average of the above number 

  //establishing communication between processing and arduino

  while (Serial.available()) {
    right = Serial.parseInt();
    left = Serial.parseInt();
    if (Serial.read() == '\n') {
        
      Serial.print(avg_value);
      Serial.print(",");
      Serial.println(mapped_light);
     
    }
  }

  //condition for led lights to switch on and off
  if (mapped_light <= 5) {
    digitalWrite(led_red, HIGH); // turn the LED on
    digitalWrite(led_blue, LOW);
  } else {
    digitalWrite(led_red, LOW); // otherwise turn it off
    digitalWrite(led_blue, HIGH);
  }
}
}

Processing: 

import processing.serial.*;
import processing.sound.*;

Serial myPort;
SoundFile shoot;
SoundFile crash;
PImage ship;

int xPos=width/2;
int yPos=0;
float Ship;

ArrayList<Star> stars = new ArrayList<Star>(); //array for stars
int frequency = 4; //frequency of star


ArrayList<Asteroid> asteroids = new ArrayList<Asteroid>(); //array for asteroid
int asteroidFrequency = 25; //frequency of ateroid

ArrayList<Bullet> bullets = new ArrayList<Bullet>(); //array for bullets

int points;
boolean instruct = true;

EndScene end;

void setup() {
  //establishing connection with Arduino
  String portname=Serial.list()[4];
  //println(portname);
  myPort = new Serial(this, portname, 9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  fullScreen();
  points = 0;
  ship = loadImage("spaceplane.png"); //loading image
  shoot = new SoundFile(this, "lazershoot_sound.wav");// shoot sound
  crash = new SoundFile(this, "space_crash.mp3");//crash sound
}

void draw() {

  if (end != null) {
    end.drawEndScene();
  } else {

    background(0);
    drawStar();

    serialEvent(myPort);
    fill(255);
    image(ship, xPos, height - height/4, 200, 100);
    drawBullet();
    if (instruct == true) {
      StartScene();
    } else {
      drawAsteroid();
      fill(255, 0, 0);
      stroke(255);



      stroke(255);
      fill(255);
      textSize(30);
      text("Points: " + points, 50, 50);

      checkCollision();
    }
  }
}


void drawBullet() {
  for (int i = 0; i<bullets.size(); i++) {
    bullets.get(i).drawBullet();
  }
}

void checkCollision() {
  for (int i = 0; i < asteroids.size(); i++) {
    Asteroid a = asteroids.get(i);
    float tan_shoot =  10*tan(60);
    float distance_ship= dist(a.x, a.y, xPos, (height-height/4)-tan_shoot);
    float distance_shipleft= dist(a.x, a.y, xPos+200, (height-height/4)+tan_shoot);
    if (distance_ship< a.size/2 +tan_shoot) {
      crash.play();
      end = new EndScene();
    }
    if (distance_shipleft<a.size/2+tan_shoot){
      crash.play();
      end = new EndScene();
    }
    for (int b = 0; b < bullets.size(); b++) {
      Bullet bullet = bullets.get(b);
      if (a.checkCollision(bullet) == true) {
        points++;

        asteroids.remove(a);
        bullets.remove(b);
      }
    }
  }
}


void drawAsteroid() {
  if (frameCount % asteroidFrequency == 0) {
    asteroids.add(new Asteroid(random(100, 250)));
  }
  for (int i = 0; i<asteroids.size(); i++) {
    Asteroid currentAsteroid = asteroids.get(i);
    currentAsteroid.drawAsteroid();
    if (currentAsteroid.y > height + currentAsteroid.size) {
      asteroids.remove(currentAsteroid);
      i--;
      points--;
    }
  }
}

void drawStar() {
  strokeWeight(1);
  stroke(255);
  if (frameCount % frequency == 0) {
    Star myStar = new Star();
    stars.add(myStar);
  }
  for (int i = 0; i<stars.size(); i++) {
    Star currentStar = stars.get(i);
    currentStar.drawStar();
  }
}

void serialEvent(Serial myPort) {
  loop();
  //frameRate(10);
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null) {
    println(s);
    int values[]=int(split(s, ','));
    if (values.length==2 ) {
      //if (values[0]>=0) {
      xPos=(int)map(values[0], 0, 325, 0, width);
      //println(values[0]);
      println(xPos);
      if (xPos < 0) {
        xPos = 0;
        //}
      }
      if (xPos > width) {
        xPos = width;
      }
    }

    if ( values[1] <= 5) {
      Bullet b = new Bullet();
      bullets.add(b);
      shoot.amp(0.4);
      //shoot.play();
    }
  }
  myPort.write("0"+"\n");
}


void mousePressed() {
  if (end != null && end.mouseOverButton() == true) {
    resetGame();
  }
}

void resetGame() {
  instruct= true; 
  stars.clear();
  bullets.clear();
  asteroids.clear();
  end = null;
  points = 0;
}

void StartScene() {
  strokeWeight(7);
  stroke(0);
  fill(255);
  textSize(30);
  textAlign(CENTER);
  text("Try to move you hand within the taped area on the table", width/2, height/2-100);
  text(" Try opening and closing your hand completely to shoot bullets", width/2, height/2);
  text("PRESS SHIFT TO PLAY", width/2, height/2+100);
  if (keyPressed) {
    if (keyCode == SHIFT) {
      instruct = false;
    }
  }
}


class Asteroid {
  float size;
  float x;
  float y;
  int num;

  int speed_asteroid = 10; //speed of asteroid

  Asteroid(float size) {
    this.size = size;
    this.x = random(width);
    this.y = 0;
  }

  void drawAsteroid() {
    fill(150);
    stroke(150);
    ellipse(x, y, size, size);
    y+=speed_asteroid;
  }

  boolean checkCollision( Object crash) {
    if (crash instanceof Bullet) {
      Bullet bullet = (Bullet) crash;
      float distance_bullet = dist(x, y, bullet.x, bullet.y);
      if (distance_bullet <= size + bullet.size/2 ) {
        //fill(0, 255, 0, 100);
        //rect(0, 0, width, height);
        fill(255);

        return true;
      }
    }
    return false;
  }
}


class Bullet {
  float x;
  float y;
  float velocity_y;
  float size;

  Bullet() {
    this.x = xPos;
    this.y = (height-height/4) - 15;
    this.velocity_y = -10;
    this.size = 10;
  }

  void drawBullet() {
    fill(255);
    ellipse(x+100, y, size, size);
    y +=velocity_y;
    
  }
}


class EndScene {
  int button_x;
  int button_y; 
  int button_width; 
  int button_height;


  EndScene() {
    this.button_width = 300;
    this.button_height = 100;
    this.button_x = width/2 - this.button_width/2;
    this.button_y = height/2 - this.button_height/2;
  }

  void drawEndScene() {
    //Background
    fill(#FAE714);
    rect(0, 0, width, height);
    rect(button_x, button_y, button_width, button_height);

    //Game over text
    stroke(0);
    fill(0);
    textSize(150);
    textAlign(CENTER);
    text("GAME OVER!", width/2, height/4);

    //Restart Button
    fill(0);
    stroke(200);
    rect(button_x, button_y, button_width, button_height);
    fill(200);
    textSize(60);
    textAlign(CENTER); 
    text("RETRY?", button_x+150, button_y+70);
    
    //Player Score 
    stroke(0);
    fill(0);
    textSize(80);
    textAlign(CENTER); 
    text("FINAL SCORE: " + points, width/2, height - height/4);
  }

  boolean mouseOverButton() {
    return (mouseX > button_x 
      && mouseX < button_x + button_width
      && mouseY > button_y
      && mouseY < button_y + button_height);
  }
}


class Star {
  float x;
  float y;
  int velocity_star;
  
  Star() { 
    this.x = random(width);
    this.y = 0;
    this.velocity_star = 10; //velocity of falling star
  }
  
  void drawStar() {
    y+=velocity_star;
    fill(#FCEB24);
    circle(x,y,5);
  }
}

 

Leave a Reply