Daniel RothfuszBrandon StanleyIsabelle ScottJohann Pally
Published © GPL3+

Super Smash Blows

Playing with toy cars and buttons has never been so fun!

IntermediateFull instructions provided3 hours873
Super Smash Blows

Things used in this project

Hardware components

EK-TM4C123GXL TM4C Tiva LaunchPad
Texas Instruments EK-TM4C123GXL TM4C Tiva LaunchPad
×1
Seeed Studio Sidekick Basic Kit for TI Launchpad
Using: -RGB LED -Button (2) -Breadboard (3) -Assorted Wires
×1
Grove Starter Kit for LaunchPad
Seeed Studio Grove Starter Kit for LaunchPad
Using: -Expansion Board -Piezzo Buzzer -Ultrasonic Sensor (2) -4 digit display
×1
Hot Wheels Car
×2

Software apps and online services

Energia
Texas Instruments Energia

Story

Read more

Schematics

Diagrams for Sensors and Cars

A layout of how the different attachments can be aligned and affixed for easy transport and set-up

Wiring Diagram

Rough Diagram detailing ports and sensor connections to the microcontroller.

Code

SSBCode

C/C++
How we modularized our code and handled exception case logic and random logic!
#include <TM1637.h>
#include <Ultrasonic.h>

#define ULTRASONIC_PIN1   24
#define ULTRASONIC_PIN2   25
#define BUZZER_PORT  36
#define CLK 38
#define DIO 37

#define NOTE_G3  196
#define NOTE_A3  220
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_G4  392

#define MAX_SCORE 7


const int buttonPin1 = 9;
const int buttonPin2 = 10;

Ultrasonic ultrasonic1(ULTRASONIC_PIN1);
Ultrasonic ultrasonic2(ULTRASONIC_PIN2);
TM1637 tm1637(CLK, DIO);

int buttonState1 = 0;         // variable for reading the pushbutton status
int buttonState2 = 0;
int distance1 = 0;
int distance2 = 0; 
int score1 = 0;
int score2 = 0;
bool scoring1 = true;
bool scoring2 = true;
char state = 'w';    // w = wait; d = delay; g = game; e = endgame AVENGERS YAAAA
String LEDstate = "green";
int LEDcount = 0;
int randNumber = 0;
int pauseBetweenNotes = 1000/2 * 3;
//Initialize any constants or variables we will use in the later code

void setup() {
  //Determine the input/output statues of the different ports we write to
  pinMode(buttonPin1, INPUT_PULLUP);   
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
  randomSeed(analogRead(A0));
  tm1637.init();
  tm1637.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  digitalWrite(BLUE_LED, LOW);
  //Initialize Serial Monitor
  Serial.begin(9600);
}

void loop() {
  //Constantly check the status of the distance sensors and buttons
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  distance1 = ultrasonic1.MeasureInCentimeters();
  distance2 = ultrasonic2.MeasureInCentimeters();

  //Waiting State, the state when the device is turned on or when game is reset in End State
  if(state == 'w'){
    //Waits until the two buttons are pressed and distance sensors sense that the cars are far away enough at thei starting distances
    if(distance1 > 10 and distance2 > 10 and buttonState1 == LOW and buttonState2 == LOW){
      //Once satisfied, start the countdown and display 3... 2... 1... and play notes and vary LED
      digitalWrite(BLUE_LED, HIGH);
      Serial.println("Wating ended...");
      state = 'g';
      delay(1000);
      //delay -> WdRdWdRdG
      tm1637.display(1, 3);
      tm1637.display(3, 3);
      digitalWrite(RED_LED, LOW);
      tone(36, NOTE_C4,1000/2);
      delay(pauseBetweenNotes);

      tm1637.display(1, 2);
      tm1637.display(3, 2);
      tone(36, NOTE_C4,1000/2);
      delay(pauseBetweenNotes);

      tm1637.display(1, 1);
      tm1637.display(3, 1);
      tone(36, NOTE_G4,1000/2);
      digitalWrite(RED_LED, HIGH);
      digitalWrite(GREEN_LED, LOW);
      delay(pauseBetweenNotes);
      
      tm1637.display(1, 0);
      tm1637.display(3, 0);
      tm1637.point(POINT_ON);
    }
  }

  //Game state
  else if(state == 'g'){
    //Serial.println(scoring1);
    //Serial.println(scoring2);
    //Serial.println(score1);
    //Serial.println(score2);
    //Serial.println(distance1);
    //Serial.println(score2);

    //Scoring logic, avoids when a player is within the distance of the sensor, that the sensor doesn't keep counting up the score
    if(scoring1){
      if(distance1 <= 2){
        //Pitch is played, score is incremeneted
        score1 += 1;
        tone(36, NOTE_C4,1000/4);
        scoring1 = false;
      }
    }
    else{
      //Scoring logic reset
      if(distance1 > 10){
        scoring1 = true;
      }
    }

   //Scoring logic for player two
    if(scoring2){
      if(distance2 <= 2){
        //Pitch is played, score is incremeneted
        score2 += 1;
        tone(36, NOTE_G4,1000/4);
        scoring2 = false;
      }
    }
    else{
      //Scoring logic reset
      if(distance2 > 10){
        scoring2 = true;
      }
    }

    //Bonus LED button random state change logic
    if(LEDstate == "green"){
      //Turns LED red at random time
      randNumber = random(1,400);
      Serial.println(randNumber);
      if(randNumber == 2){
        digitalWrite(RED_LED, LOW);
        digitalWrite(GREEN_LED, HIGH);
        LEDstate = "red";
      }
    }

    //LED scoring logic
    if(LEDstate == "red"){
      LEDcount += 1;
      if(buttonState1 == LOW){
        //play tune and adjust score
        LEDcount = 0;
        LEDstate = "green";
        digitalWrite(RED_LED, HIGH);
        digitalWrite(GREEN_LED, LOW);
        tone(36, NOTE_C4,1000/4);
        score1 += 2;
      }
      else if(buttonState2 == LOW){
        LEDcount = 0;
        LEDstate = "green";
        digitalWrite(RED_LED, HIGH);
        digitalWrite(GREEN_LED, LOW);
        tone(36, NOTE_G4,1000/4);
        score2 += 2;
      }
      //Turn LED back to green from red if no one presses it in time
      if(LEDcount >= 100){
        LEDcount = 0;
        LEDstate = "green";
        digitalWrite(RED_LED, HIGH);
        digitalWrite(GREEN_LED, LOW);
      }
    }

    //Display score
    int digit2p1 = score1 % 10;
    int digit1p1 = score1 / 10;
    int digit2p2 = score2 % 10;
    int digit1p2 = score2 / 10;
    if (digit1p1 != 0){
       tm1637.display(0, digit1p1);
    }
    
    tm1637.display(1, digit2p1);
    if (digit1p2 != 0){
       tm1637.display(2, digit1p2);
    }
    tm1637.display(3, digit2p2);

    //Check to see if anyone has won the game yet
    if(score2 >= MAX_SCORE or score1 >= MAX_SCORE){
      state = 'e';
    }
  }

  //End state
  else if(state == 'e'){
    //Display final scores 
    int digit2p1 = score1 % 10;
    int digit1p1 = score1 / 10;
    int digit2p2 = score2 % 10;
    int digit1p2 = score2 / 10;
    //Play melody
    int melody[] = {
    NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};

    // note durations: 4 = quarter note, 8 = eighth note, etc.:
    int noteDurations[] = {
      4, 8, 8, 4,4,4,4,4 };
    digitalWrite(RED_LED, LOW);
    digitalWrite(GREEN_LED, LOW);
    digitalWrite(BLUE_LED, LOW);
    pauseBetweenNotes = 1000/2;
    for (int thisNote = 0; thisNote < 8; thisNote++) {
      // to calculate the note duration, take one second 
      // divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      int noteDuration = 500/noteDurations[thisNote];
      tone(BUZZER_PORT, melody[thisNote],noteDuration);
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      delay(100);
      // stop the tone playing:
      noTone(BUZZER_PORT);
    }
    
    digitalWrite(BLUE_LED, HIGH);

    //Flash score, LED, and wait till the reset conditions (same as start game conditions) are satisfied and then send state back to Waiting State
    bool cond = false;
    while(not cond){
      buttonState1 = digitalRead(buttonPin1);
      buttonState2 = digitalRead(buttonPin2);
      distance1 = ultrasonic1.MeasureInCentimeters();
      distance2 = ultrasonic2.MeasureInCentimeters();
      tm1637.set(BRIGHT_TYPICAL);
      digitalWrite(RED_LED, HIGH);
      digitalWrite(GREEN_LED, LOW);
      if (digit1p1 != 0){
       tm1637.display(0, digit1p1);
      }
      
      tm1637.display(1, digit2p1);
      if (digit1p2 != 0){
         tm1637.display(2, digit1p2);
      }
      tm1637.display(3, digit2p2);
      delay(1000);
      
      tm1637.set(0);
      digitalWrite(RED_LED, LOW);
      digitalWrite(GREEN_LED, HIGH);
      if (digit1p1 != 0){
       tm1637.display(0, digit1p1);
      }
      
      tm1637.display(1, digit2p1);
      if (digit1p2 != 0){
         tm1637.display(2, digit1p2);
      }
      tm1637.display(3, digit2p2);
      delay(1000);
    }
    if(distance1 > 10 and distance2 > 10 and buttonState1 == LOW and buttonState2 == LOW){
      cond = true;
      state = 'w';
    }
  }
  delay(30);
}

Credits

Daniel Rothfusz
2 projects • 5 followers
Contact
Brandon Stanley
2 projects • 3 followers
Contact
Isabelle Scott
2 projects • 4 followers
Contact
Johann Pally
1 project • 1 follower
Contact

Comments

Please log in or sign up to comment.