Final Project- Game: Space Survivor 🚀💫 [STATUS-90%]


Description of Project: 

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 game:

It is a space shooter game where there are spaceship has to protect itself from asteroids by either passing it by from a distance or by shooting it down. Each asteroid shot down is one point and to let  the asteroid  pass by is a negative point. As soon as your space ship crashes into an asteroid, the game is over and your final point are displayed on the screen.

Instead of a usual control as by a keyboard, this game is controlled by the movements of your hand. Using an ultrasonic sensor, the game using the distance between the the sensor and your hand, moves the spaceship along. A photo resistor is also installed in the glove, whose readings I have mapped from 0 to 10 and divided it in half, to help the with the shooting of the bullets by the player. Two led lights (red and blue) indicate if the shooting is taking place or no. Here’s a picture of the setup:

Here you can notice that the photo resistor is placed on the index  finger to give the player a better control to the shooting. all they have to do is close their finger or the entire hand, whatever is comfortable to them.

USER TESTING: 

Video: 

Feedback: 

  • ” You should add an instructions panel at the start of the game for the glove usage” –  I think that is a good idea and I will imply it next.
  • ” You should add sound” – This too I will imply next.
  • “The glove is not the most flexible with different hand sizes, maybe you can use disposable gloves and attach the sensor each time. It will also be easy to wear.” – I am not sure about the disposable gloves because it will create too much unnecessary waste, but I do agree with different hand sizes. I will try getting Professor’s take on this.

Next steps:

I will implement the above given suggestions and also work on the serial communication part of the game. I believe this game can be more smooth than what it is right now.

CODE:

processing:

import processing.serial.*;
Serial myPort;

int yPos=0;

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

Ship playerShip;

ArrayList<Asteroid> asteroids = new ArrayList<Asteroid>();
int asteroidFrequency = 60;

ArrayList<Bullet> bullets = new ArrayList<Bullet>();

int points;

EndScene end;

void setup() {
  printArray(Serial.list());
  String portname=Serial.list()[4];
  println(portname);
  myPort = new Serial(this, portname, 9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  fullScreen();
  playerShip = new Ship();
  points = 0;
}

void draw() {


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

    drawAsteroid();
    fill(255, 0, 0);
    stroke(255);
    playerShip.drawShip(myPort);
    drawBullet();
    

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

    checkCollision();
  }
}

void drawBullet() {
  serialBullet(myPort);
  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);
    if (a.checkCollision(playerShip) == true) {
      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 serialBullet(Serial myPort) {
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null) {
    println(s);
    int values[]=int(split(s, ','));
    if (values.length==2 && values[1] <= 5) {
      Bullet b = new Bullet(playerShip);
      bullets.add(b);
    }
  }
}

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

    void resetGame() {
      stars.clear();
      bullets.clear();
      asteroids.clear();
      playerShip = new Ship();
      end = null;
      points = 0;
    }

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

  int speed_asteroid = 5; //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 Ship) {
      Ship playerShip = (Ship) crash;
      float tan_shoot =  10*tan(60);
      float distance_ship= dist(x, y, playerShip.xPos, playerShip.y-tan_shoot);
      if (distance_ship< size/2 +tan_shoot){ //tan_shoot+ 10) {
        //background(255, 0, 0);
        fill(255, 0, 0, 100);
        rect(0, 0, width, height);
        fill(255);
        
        return true;
      }
    } else if (crash instanceof Bullet) {
      Bullet bullet = (Bullet) crash;
      float distance_bullet = dist(x, y, bullet.x, bullet.y); 
      //println(distance_bullet);
      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(Ship playerShip) {
    this.x = playerShip.xPos;
    this.y = playerShip.y - 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 Ship {
  PImage ship;
  float x;
  float y;
  float velocity_x;
  boolean leftPressed, rightPressed;
  int xPos=0;

  int speed = 6; //speed of ship

  Ship() {
    this.x = width/2;
    this.y = height - height/4;
    this.velocity_x = 0;
    ship = loadImage("spaceplane.png");
  }

  void drawShip(Serial myPort) {
    frameRate(60);
    String s=myPort.readStringUntil('\n');
    s=trim(s);
    if (s!=null) {
      println(s);
      int values[]=int(split(s, ','));
      if (values.length==2) {
        xPos=(int)map(values[0], 0, 30, 0, width);
        image(ship, xPos, y);
        ship.resize(200, 100);
      }
    }
  }
}

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);
  }
}

Arduino:

int left = 0; 
int right = 0; 

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(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() {
  while (Serial.available()){
    right = Serial.parseInt();
    left = Serial.parseInt(); 
  }

  digitalWrite(trigPin, LOW);
  digitalWrite(trigPin, HIGH);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (going and coming)
  int constrained_distance = constrain(distance, 0, 30);
  
  int light = analogRead(photo);
  int mapped_light = map(light, 0, 1023, 0, 10);
  int constrained_light = constrain(light, 900, 1000);

  if (mapped_light <= 5) {
    digitalWrite(led_red, HIGH);
    digitalWrite(led_blue, LOW);
  } else {
    digitalWrite(led_red, LOW);
    digitalWrite(led_blue, HIGH);
  }
  Serial.print(constrained_distance); 
  Serial.print(","); 
  Serial.println(mapped_light); 
  delayMicroseconds(100);
}

 

Leave a Reply