[pcomp week 7] Space Laser! (midterm)

 

For our Physical Computing midterm project, Yiting and I made a game called Space Laser!. (The critical exclamation point was added at the suggestion of Tom.)

HOW IT WORKS

You have 30 seconds to hit all five aliens using your laser. When you successfully hit one, their eyes will dim and they’ll make a dying sound. When you only have 10 seconds left, the eyes will start to blink so that you know you’re running out of time.

IDEA

We originally came up with an entirely different idea for a game, but after some experimentation, decided that we wanted to do something with two servos on top of each other. This formed the basis for our laser pointer. But what good is a laser if you don’t have something to shoot at?

Everyone knows that aliens are the natural enemy of lasers, so we decided to make a space-themed game where you’d shoot a laser at aliens, who would react in various ways when they got hit.

There were two main parts of the project: the laser and the target board. We prototyped both pieces before we made the final versions.

LASER

One of the first things we did was attach a laser diode to a servo on top of another servo. One servo moved in the x-axis and the other moved in the y-axis, so when combined, they allowed a wide range of movement for the laser on top. We then connected it to a toggle switch to turn it on and off, and a joystick that mapped to the axes of the servos. We put them all together in a cardboard box for prototyping, which was simple enough.

IMG_0635

IMG_2798

 

Here’s where it got a bit more complicated. Neither Yiting nor I have any experience with fabrication, which was one of the biggest challenges in this project. We knew we wanted to make a more solid enclosure, but weren’t really sure how. When we found a piece of acrylic in the junk shelf, we thought hey, why not try to make something out of this?

IMG_2805 IMG_2804

We took some measurements, and Yiting lasercut the acrylic into rectangles, as well as the holes on top for the joystick and switch. I rather haphazardly glued the pieces together with acrylic cement.

It worked for this project, but I learned that going forward with future projects, I should use a different material or buy a pre-made enclosure.

box1

box2

TARGET BOARD

As with the box, we began with a cardboard prototype of a target.

boardPrototypr

After some testing, we confirmed that a laser could reliably make a spike in the photocell’s sensor reading, so it could easily be used as a target on each alien. We figured that having two types of feedback together for successfully hitting the target — audio and visual — would create a nice effect, so we used LEDs for the eyes, and decided to add a speaker as well. The eyes would dim and the speaker would make the “dying” sound once you hit an alien.

I found a large black foam board in the junk shelf in the back. (Who knew that it could be such a treasure trove?) This became the backdrop of our space fight.

We found some free assets online, and Yiting used her amazing Illustrator skills to mock up a design. We print the images out and cut them up.

Then the tedious part began!

IMG_0662IMG_0663

It’s funny how the unexpected things can take up the most time. For example, it took us an excruciatingly long time to successfully poke the legs of the photocells and LEDs through a piece of paper, a layer of cardboard, and a foamboard. We had 30 legs in total to poke through, and often each one took multiple attempts, even with the help of a sewing needle.

IMG_0666

In the end, we successfully gave each alien two LED eyes and a photocell target in its mouth.

Now, on to the wiring.

This next part was theoretically straightforward — each LED would need a resistor and a digital input, and each photocell would also need a photocell and an analog input. We taped an Arduino and a breadboard on the back, and after some testing with alligator clips, we began to solder.

IMG_0688 IMG_0691

This also took a very long time even with the two of us soldering together.

Happily, we wired it all up correctly and it all worked, even if it’s not pretty. In the future, I’ll make an effort to tidy up and organize wires better.

IMG_0759

The next part was both the easiest and probably the most rewarding. We thought it would be fun to add obstacles to the board to make the game harder, so we added three planets that moved back and forth automatically in front of the aliens, each controlled by a servo. This was simple but made the game immensely more dynamic and fun. It really confirmed for me what Tom said in class a few weeks ago, which was that servos really give us a lot of “bang for [our] buck.”

IMG_0704

The last component was sound. We attached a speaker to the board and designed three different types of sound: a “game start” sound, an “alien died” sound, and a “game over” sound. This audio effects also really added a lot of how dynamic and interactive the game felt.

END RESULT

IMG_0716

Yiting and I were both really pleased with how this little game turned out. It was a good lesson in making something from start to finish, and in collaboration.

Lessons learned for me:

  • Organize your wiring!
  • Prototyping before making a final version is necessary.
  • Learn more about fabricating enclosures, or just buy them.
  • Working with another person is extremely helpful.
  • The soldering irons in the ITP shop suck.
  • Giving a user more than one type of feedback makes the experience feel much more interactive.
  • Never try to poke the legs of photocells through foam board or cardboard, it is a terrible experience.

We used three Arduinos for this project, and the code for all three parts is below.

#include<Servo.h>
Servo myServo1;
Servo myServo2;


void setup() {
  Serial.begin(9600);
  myServo1.attach(10);
  myServo2.attach(11);
}

void loop() {
  int xAxis = analogRead(A1);
  int yAxis = analogRead(A2);
  int x = map(xAxis, 0, 1023, 50, 130);
  int y = map(yAxis, 0, 1023, 120, 60);

  if (millis() % 20 < 2) {
    myServo1.write(x);
    myServo2.write(y);
  }
}
//lights
int purpleLightsOn = 1;
int redLightsOn = 1;
int blueLightsOn = 1;
int greenLightsOn = 1;
int orangeLightsOn = 1;

//blink
int lights = 1;

int roomLight = 250;
long gameTime = 30000;
long startBlinkTime = 2 * gameTime / 3;
int blinkInterval = 200;
long currentMillis;
long previousMillis = startBlinkTime;

//sound
int duration = 50;
int endDuration = 300;


void setup() {
  //sound
  pinMode(11, OUTPUT);

  //purple monster
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);

  //red monster
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

  //blue monster
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  //green monster
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

  //orange monster
  pinMode(10, OUTPUT);
  pinMode(12, OUTPUT);
}

void loop() {
  //game starts!
  if (millis() < startBlinkTime) {

    //start sound
    if (millis() < 400) {
      tone(11, 200, duration);
      delay(duration);
      tone(11, 300, duration);
      delay(duration);
      tone(11, 400, duration);
      delay(duration);
      tone(11, 500, duration);
      delay( duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 900, duration);
      delay(duration);
    }


    //purple monster
    int sensorPurple = analogRead(A4);
    if (sensorPurple > roomLight && purpleLightsOn == 1) {
      purpleLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
    }
    digitalWrite(2, purpleLightsOn);
    digitalWrite(3, purpleLightsOn);


    //red monster
    int sensorRed = analogRead(A3);
    if (sensorRed > roomLight && redLightsOn == 1) {
      redLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
    }
    digitalWrite(4, redLightsOn);
    digitalWrite(5, redLightsOn);


    //blue monster
    int sensorBlue = analogRead(A2);
    if (sensorBlue > roomLight && blueLightsOn == 1) {
      blueLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
    }
    digitalWrite(6, blueLightsOn);
    digitalWrite(7, blueLightsOn);


    //green monster

    int sensorGreen = analogRead(A1);
    if (sensorGreen > roomLight && greenLightsOn == 1) {
      greenLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
    }
    digitalWrite(8, greenLightsOn);
    digitalWrite(9, greenLightsOn);


    //orange monster

    int sensorOrange = analogRead(A0);
    if (sensorOrange > roomLight && orangeLightsOn == 1) {
      orangeLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
    }
    digitalWrite(10, orangeLightsOn);
    digitalWrite(12, orangeLightsOn);

  }

  // lights start blinking!
  if (millis() >= startBlinkTime && millis() <= gameTime  ) {
    currentMillis = millis();

    //purple monster
    int sensorPurple = analogRead(A4);
    if (sensorPurple > roomLight && purpleLightsOn == 1) {
      purpleLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
      digitalWrite(2, purpleLightsOn);
      digitalWrite(3, purpleLightsOn);
    }


    //red monster
    int sensorRed = analogRead(A3);
    if (sensorRed > roomLight && redLightsOn == 1) {
      redLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
      digitalWrite(4, redLightsOn);
      digitalWrite(5, redLightsOn);
    }


    //blue monster
    int sensorBlue = analogRead(A2);
    if (sensorBlue > roomLight && blueLightsOn == 1) {
      blueLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
      digitalWrite(6, blueLightsOn);
      digitalWrite(7, blueLightsOn);
    }


    //green monster
    int sensorGreen = analogRead(A1);
    if (sensorGreen > roomLight && greenLightsOn == 1) {
      greenLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
      digitalWrite(8, greenLightsOn);
      digitalWrite(9, greenLightsOn);
    }


    //orange monster
    int sensorOrange = analogRead(A0);
    if (sensorOrange > roomLight && orangeLightsOn == 1) {
      orangeLightsOn = 0;
      tone(11, 900, duration);
      delay(duration);
      tone(11, 800, duration);
      delay(duration);
      tone(11, 700, duration);
      delay(duration);
      tone(11, 600, duration);
      delay(duration);
      tone(11, 500, duration);
      digitalWrite(10, orangeLightsOn);
      digitalWrite(12, orangeLightsOn);
    }


    if (currentMillis - previousMillis > blinkInterval ) {
      previousMillis = currentMillis;
      if (lights == 1) {
        lights = 0;
      } else {
        lights = 1;
      }

      //purple lights blink
      if (purpleLightsOn == 1 ) {
        digitalWrite(2, lights);
        digitalWrite(3, lights);
      }


      //red lights blink
      if (redLightsOn == 1 ) {
        digitalWrite(4, lights);
        digitalWrite(5, lights);
      }

      //blue lights blink
      if (blueLightsOn == 1 ) {
        digitalWrite(6, lights);
        digitalWrite(7, lights);
      }

      //green lights blink
      if (greenLightsOn == 1) {
        digitalWrite(8, lights);
        digitalWrite(9, lights);
      }

      //orange lights blink
      if (orangeLightsOn == 1 ) {
        digitalWrite(10, lights);
        digitalWrite(12, lights);
      }
    }
  }


  //game's over!
  if (millis() > gameTime && millis() < gameTime + 2400) {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(12, LOW);
    tone(11, 900, endDuration);
    delay(endDuration);
    tone(11, 800, endDuration);
    delay(endDuration);
    tone(11, 700, endDuration);
    delay(endDuration);
    tone(11, 600, endDuration);
    delay( endDuration);
    tone(11, 500, endDuration);
    delay( endDuration);
    tone(11, 400, endDuration);
    delay(endDuration);
    tone(11, 300, 6 / 5 * endDuration);
    delay(6 / 5 * endDuration);
    tone(11, 200, 9 / 5 * endDuration);
    delay(9 / 5 * endDuration);
  }
}
#include<Servo.h>
Servo myServo1;
Servo myServo2;
Servo myServo3;

int pos = 0;

void setup() {
  Serial.begin(9600);
  myServo1.attach(9);
  myServo2.attach(10);
  myServo3.attach(11);
}

void loop()
{
  for (pos = 0; pos <= 180; pos += 1)
  {
    myServo1.write(pos / 2);
    myServo2.write(pos / 2);
    myServo3.write(pos);
    delay(15);
  }
  for (pos = 180; pos >= 0; pos -= 1)
  {
    myServo1.write(pos / 2);
    myServo2.write(pos / 2);
    myServo3.write(pos);
    delay(15);
  }
}


 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: