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