Game for 4180 Lab4

Dependencies:   4DGL-uLCD-SE 4180_lab4_tank_war_game Game_Synchronizer MMA8452 SDFileSystem mbed-rtos mbed wave_player

Dependents:   4180_lab4_tank_war_game

Files at this revision

API Documentation at this revision

Comitter:
ychen644
Date:
Mon Mar 13 21:23:17 2017 +0000
Commit message:
Uploading 4180 Lab4 game to Notebook wiki

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
Bullet/bullet.cpp Show annotated file Show diff for this revision Revisions of this file
Bullet/bullet.h Show annotated file Show diff for this revision Revisions of this file
EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
Game_Synchronizer.lib Show annotated file Show diff for this revision Revisions of this file
MMA8452.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
Sound/playSound.cpp Show annotated file Show diff for this revision Revisions of this file
Sound/playSound.h Show annotated file Show diff for this revision Revisions of this file
Tank/tank.cpp Show annotated file Show diff for this revision Revisions of this file
Tank/tank.h Show annotated file Show diff for this revision Revisions of this file
globals.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
wave_player.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r ffed9a3bc797 4DGL-uLCD-SE.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4DGL-uLCD-SE.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
diff -r 000000000000 -r ffed9a3bc797 Bullet/bullet.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bullet/bullet.cpp	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,133 @@
+#include "uLCD_4DGL.h"
+#include "bullet.h"
+#include "game_synchronizer.h"
+#include "globals.h"
+#include "math.h"
+#include "playSound.h"
+
+extern Serial pc;
+
+extern Game_Synchronizer sync;
+
+// Initialize the bullet. Don't have to do much here.
+// Keep a pointer to this bullet's tank.
+// Set the speed, and default the bullet to not in_flight.
+Bullet::Bullet(Tank* t) {
+    tank = t;
+    speed = 30;
+    powerups = 2;
+    power = 0;
+    in_flight = false;
+}
+
+// If in_flight, do nothing. Otherwise,
+// set the in_flight flag, and initialize values needed for
+// the trajectory calculations. (x0, y0), (vx0, vy0), time
+// Hint: tank->barrel_end(...) is useful here.
+void Bullet::shoot(void) {
+    if (!in_flight) {
+        in_flight = true;
+        tank->barrel_end(&x0, &y0);
+        x = x0;
+        y = y0;
+        vx0 = speed*cos(tank->barrel_theta);
+        vy0 = speed*sin(tank->barrel_theta);
+        vx = vx0;
+        vy = vy0;
+        bounce = 0;
+        time = 0;
+    }
+}
+
+void Bullet::changeSky(int SKY_COLOR2) {
+    SKY_COLOR = SKY_COLOR2;
+}
+
+// power up increases explosion size
+// you get 2 powerups per round
+void Bullet::powerUp(void) {
+    if (powerups > 0) {
+        // play sound for powerup
+        playSound("/sd/wavfiles/boing2.wav");
+        powerups = powerups - 1;
+        power = power + 1;
+    }
+}
+
+// If the bullet is in flight, calculate its new position
+// after a time delta dt.
+void Bullet::update_position(float dt) {
+    vx = vx;
+    vy = vy - 9.81*dt;
+    x = floor(x0 + vx*time);
+    y = floor(y0 + vy*time - 0.5*9.81*time*time);
+}
+
+void boing(void const *argument) {
+    playSound("/sd/wavfiles/boing2.wav");
+}
+
+int Bullet::time_step(float dt) {
+    // If the bullet hasn't hit anything, 
+    // redraw the bullet at its new location. 
+    // If it has hit something (obstacle, tank, edge of the screen), 
+    // set the in_flight flag back to false, explode the nearby area,
+    // and return one of the following codes.
+    //
+    // return codes:
+    //      BULLET_NO_COLLISION: no collision
+    //      BULLET_OFF_SCREEN:   off the side of the screen
+    //      Otherwise, return the color you've hit in 16bpp format.
+    if (in_flight) {
+        int x_old = x;
+        int y_old = y;
+        // old pixel
+        sync.pixel(x_old, y_old, SKY_COLOR);
+        sync.update();
+        time = time + dt;
+        update_position(dt);
+        // new pixel
+        int color = sync.read_pixel(x, y);
+        if (x_old == x && y_old == y) {
+            // no change
+            sync.pixel(x, y, tank->tank_color);
+            return BULLET_NO_COLLISION;
+        } else if (x < 0 || x > 128 || y < 0 || y > 128) {
+            // out of bounds
+            in_flight = false;
+            return BULLET_OFF_SCREEN;
+        } else if (sync.pixel_eq(color, SKY_COLOR)) {
+            // travelling in the sky
+            sync.pixel(x, y, tank->tank_color);
+            return BULLET_NO_COLLISION;
+        } else if (!sync.pixel_eq(color, SKY_COLOR)) {
+            // hit
+            if (sync.pixel_eq(color, GND_COLOR)) {
+                bounce = bounce + 1;
+                // bounce
+                if (bounce < 3) {
+                    vy = vy/2.0;
+                    sync.pixel(x, y, tank->tank_color);
+                    return BULLET_NO_COLLISION;
+                }
+            }
+            // hit
+            in_flight = false;
+            int i = 1;
+            // powerup increases explosion size
+            for(i = 1; i < 5 + (power * 3); i++) {
+                sync.filled_rectangle(x-i, y-i, x+i, y+i, tank->tank_color);
+                sync.update();
+                wait(0.1);
+            }
+            power = 0;
+            // make everything the sky afterwards
+            sync.filled_rectangle(x-i-1, y-i-1, x+i-1, y+i-1, SKY_COLOR);
+            sync.update();
+            // play the sound
+            playSound("/sd/wavfiles/splooge.wav");
+            return color;
+        }
+    }
+    return BULLET_NO_COLLISION;
+}
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 Bullet/bullet.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bullet/bullet.h	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,69 @@
+#ifndef BULLET_H__
+#define BULLET_H__
+
+#include "tank.h"
+
+#define BULLET_NO_COLLISION -1
+#define BULLET_OFF_SCREEN   -2
+
+class Bullet{
+    public:
+        // sky color
+        int SKY_COLOR;
+        
+        // (x0, y0) is the position of the bullet at the start of its trajectory.
+        int x0, y0;
+        
+        // The components of the bullet's initial velocity.
+        float vx0, vy0;
+        
+        // The current position of the bullet.
+        int x, y;
+        
+        // currernt velocity
+        float vx, vy;
+        int bounce;
+        
+        // power up
+        int powerups;
+        int power;
+        
+        // How fast is the bullet?
+        int speed;
+        
+        // Keep track of the time since the bullet was shot.
+        float time;
+        
+        // Keep track of whether the bullet is currently in flight.
+        // If it is in_flight, update its position. Otherwise, ignore it.
+        // Set in_flight when the bullet is shot.
+        // Reset in_flight when the bullet hits something.
+        bool in_flight;
+        
+        // Keep a pointer to the tank that shot this bullet. You'll need
+        // it to access information about the tank.
+        Tank* tank;
+        
+        // Create a bullet!
+        Bullet(Tank* t);
+        
+        // change sky
+        void changeSky(int SKY_COLOR2);
+        
+        // powerup
+        void powerUp(void);
+        
+        // Shoot the bullet!
+        void shoot(void);
+        
+        // given a time delta, calculate the new (x, y) coords of the bullet.
+        void update_position(float dt);
+        
+        // Once per frame, plug in the time since the last frame.
+        // Clear the old bullet and redraw it in the new place.
+        // Do collision detection here. Return a code describing what has
+        // (or hasn't) been hit.
+        int time_step(float dt);    
+};
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 EthernetInterface.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetInterface.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/ychen644/code/4180_lab4_tank_war_game/#d70f688d13d1
diff -r 000000000000 -r ffed9a3bc797 Game_Synchronizer.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game_Synchronizer.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/ECE2035-Spring-2015-TA/code/Game_Synchronizer/#0fe368b21ef9
diff -r 000000000000 -r ffed9a3bc797 MMA8452.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMA8452.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/ashleymills/code/MMA8452/#a92a632a0cc7
diff -r 000000000000 -r ffed9a3bc797 SDFileSystem.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/mbed_official/code/SDFileSystem/#8db0d3b02cec
diff -r 000000000000 -r ffed9a3bc797 Sound/playSound.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sound/playSound.cpp	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,26 @@
+#include "playSound.h"
+#include "uLCD_4DGL.h"
+#include "SDFileSystem.h"
+#include "wave_player.h"
+
+extern uLCD_4DGL uLCD;
+extern wave_player player;
+
+// Given the filename of a .wav file in the SD card, play the file over the speaker.
+void playSound(char * wav)
+{
+    // open wav file
+    FILE *wave_file;
+    wave_file=fopen(wav,"r");
+
+    if(wave_file == NULL){
+        uLCD.locate(0,4);
+        uLCD.printf("Error in SD");
+        return;
+    }
+    // play wav file
+    player.play(wave_file);
+
+    // close wav file
+    fclose(wave_file);
+}
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 Sound/playSound.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sound/playSound.h	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,6 @@
+#ifndef PLAYSOUND_H__
+#define PLAYSOUND_H__
+
+void playSound(char * wav);
+
+#endif //PLAYSOUND_H__
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 Tank/tank.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tank/tank.cpp	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,103 @@
+#include "tank.h"
+#include "globals.h"
+#include "math.h"
+#include "game_synchronizer.h"
+
+extern Game_Synchronizer sync;
+
+// sx is the x-coord of the bottom left corner of the tank
+// sy is the y-coord of the same corner
+// width is the width of the tank
+// height is the height of the tank
+Tank::Tank(int sx, int sy, int width, int height, int color) {
+    x = sx; y = sy;
+    w = width; h = height;
+    tank_color = color;
+    barrel_theta = PI/4.0;
+    barrel_length = w;
+    wheel_rad = 2.0;
+    draw();
+}
+
+void Tank::changeSky(int SKY_COLOR2) {
+    SKY_COLOR = SKY_COLOR2;
+}
+
+// Return the minimum x-coord of your tank's bounding box.
+int Tank::min_x(void) { 
+    return x;
+}    
+
+// Return the minimum y-coord of your tank's bounding box.
+int Tank::min_y(void) {
+    return y;
+}
+
+// Return the maximum x-coord of your tank's bounding box.
+int Tank::max_x(void) { 
+    return x + w;
+}
+
+// Return the maximum y-coord of your tank's bounding box.
+int Tank::max_y(void) {  
+    return y + h + wheel_rad;
+}
+
+void Tank::barrel_end(int* bx, int* by) {
+    // Set the x and y coords of the end of the barrel.
+    *bx = x + w/2.0 + barrel_length*cos(barrel_theta);
+    *by = y + h + wheel_rad + barrel_length*sin(barrel_theta);
+}
+
+void Tank::reposition(int dx, int dy, float dtheta) {
+    // Blank out the old tank position, and
+    //      Move the tank dx pixels in the x direction.
+    //      Move the tank dy pixels in the y direction.
+    //      Move the tank barrel by an angle dtheta. Don't allow it to go below parallel.
+    // Do collision detection to prevent the tank from hitting things. 
+    // (obstacles, side of the screen, other tanks, etc.)
+    
+    sync.filled_rectangle(min_x(), min_y(), max_x(), max_y(), SKY_COLOR );
+    sync.line(x + w/2.0, y+h+wheel_rad, x + w/2.0 + barrel_length*cos(barrel_theta), y+h+wheel_rad + barrel_length*sin(barrel_theta), SKY_COLOR);
+    // moving
+    if ((x + dx) < 0) {
+        // left boundary
+        x = 0;
+    } else if((x + w + dx) > 128) {
+        // right boundary
+        x = 128 - w;
+    } else if (dx < 0) {
+        // moving left
+        if ( (sync.pixel_eq(sync.read_pixel(min_x()+dx, min_y()), SKY_COLOR)) &&
+             (sync.pixel_eq(sync.read_pixel(min_x()+dx, min_y() + wheel_rad), SKY_COLOR)) ) {
+                x = x + dx;
+        }
+    } else if (dx > 0) {
+        // moving right
+        if ( (sync.pixel_eq(sync.read_pixel(max_x()+dx, min_y()), SKY_COLOR)) &&
+             (sync.pixel_eq(sync.read_pixel(max_x()+dx, min_y() + wheel_rad), SKY_COLOR)) ) {
+                x = x + dx;
+        }
+    }
+    // barrel moving
+    if ((barrel_theta + (PI/64.0) * dtheta) < 0) {
+        // not less than 0
+        barrel_theta = 0;
+    } else if ((barrel_theta + (PI/64.0) * dtheta) > PI) {
+        // not greater than pi
+        barrel_theta = PI;
+    } else {
+        // change barrel theta
+        barrel_theta = barrel_theta + (PI/64.0) * dtheta;
+    }
+    draw();
+}
+
+
+// Example tank draw function. We expect you to get creative on this one!
+void Tank::draw() {
+    sync.line(x + w/2.0, y+h+wheel_rad, x + w/2.0 + barrel_length*cos(barrel_theta), y+h+wheel_rad + barrel_length*sin(barrel_theta), BLACK);
+    sync.filled_rectangle(x, y+wheel_rad, x+w, y+h+wheel_rad, tank_color);
+    sync.filled_circle(x+wheel_rad, y+wheel_rad, wheel_rad, BLACK);
+    sync.filled_circle(x+w-wheel_rad, y+wheel_rad, wheel_rad, BLACK);
+}            
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 Tank/tank.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tank/tank.h	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,44 @@
+#ifndef TANK_H__
+#define TANK_H__
+
+// This class describes a tank. You may need to add
+// additional member variables (and maybe even member functions)
+// to draw your super cool new tank. 
+
+class Tank {
+    public:
+    
+        int x, y;               // Keep track of your tank's position.
+        int w;                  // Tank width.
+        int h;                  // Tank height. 
+        int tank_color;         // Tank color. Duh :)
+        float barrel_theta;     // Barrel angle. 
+        int barrel_length;      // Length of the barrel.
+        int wheel_rad;          // Radius of the wheels.
+        
+        int SKY_COLOR; // sky color
+        
+        // Construct a tank given its starting position (sx, sy),
+        // its width and height, and its color.
+        Tank(int sx, int sy, int width, int height, int color);
+        
+        // Calculate the bounding box of your tank for collision checking.
+        int min_x(void);
+        int min_y(void);
+        int max_x(void);
+        int max_y(void);
+        
+        // changeSky
+        void changeSky(int SKY_COLOR2);
+        
+        // Calculate the position of the end of the barrel.
+        void barrel_end(int* bx, int* by);
+        
+        // Reposition the tank!
+        void reposition(int dx, int dy, float dtheta);
+        
+        // Draw the tank!
+        void draw();
+};
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 globals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/globals.h	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,25 @@
+#ifndef GLOBAL_H__
+#define GLOBAL_H__
+
+#define GND_COLOR  0x66CD00
+#define TANK_RED   0xCD0000
+#define TANK_BLUE  0x000080
+#define PURPLE     0xcc00cc
+#define ORANGE     0xff9933
+#define AQUA       0x00ffff
+
+#define U_BUTTON 0
+#define R_BUTTON 1
+#define D_BUTTON 2
+#define L_BUTTON 3
+
+#define TURN_P1 0
+#define TURN_P2 1
+
+#define ACC_THRESHOLD 0.25
+
+#define PI  3.1415926535797
+
+
+
+#endif //GLOBAL_H__
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,434 @@
+// Student Side.
+
+#include "mbed.h"
+
+#include "SDFileSystem.h"
+#include "wave_player.h"
+#include "game_synchronizer.h"
+#include "tank.h"
+#include "bullet.h"
+#include "globals.h"
+#include "playSound.h"
+
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+DigitalIn pb_u(p21);                        // Up Button
+DigitalIn pb_r(p22);                        // Right Button
+DigitalIn pb_d(p23);                        // Down Button
+DigitalIn pb_l(p24);                        // Left Button
+
+Serial pc(USBTX, USBRX);                    // Serial connection to PC. Useful for debugging!
+MMA8452 acc(p9, p10, 100000);               // Accelerometer (SDA, SCL, Baudrate)
+uLCD_4DGL uLCD(p28,p27,p29);                // LCD (tx, rx, reset)
+SDFileSystem sd(p5, p6, p7, p8, "sd");      // SD  (mosi, miso, sck, cs)
+AnalogOut DACout(p18);                      // speaker
+wave_player player(&DACout);                // wav player
+Game_Synchronizer sync(PLAYER1);            // Game_Synchronizer (PLAYER)
+Timer frame_timer;                          // Timer
+
+// Global variables go here.
+
+int winner = -1;
+int whose_turn = PLAYER1;
+int p1score = 0;
+int p2score = 0;
+int skyChange = 0;
+int SKY_COLOR = 0x7EC0EE;
+int SKY_COLOR2 = 0x0033cc;
+
+
+// Ask the user whether to run the game in Single- or Multi-Player mode.
+// Note that this function uses uLCD instead of sync because it is only 
+// writing to the local (Player1) lcd. Sync hasn't been initialized yet,
+// so you can't use it anyway. For the same reason, you must access
+// the buttons directly e.g. if( !pb_r ) { do something; }.
+
+// return MULTI_PLAYER if the user selects multi-player.
+// return SINGLE_PLAYER if the user selects single-player.
+
+FILE *wave_file;
+int game_menu(void) {
+    uLCD.baudrate(BAUD_3000000);
+    
+    // the locate command tells the screen where to place the text.
+    uLCD.cls();
+    uLCD.locate(2,2);
+    uLCD.puts("Press Left for");
+    uLCD.locate(2,3);
+    uLCD.puts("Single Player");
+    uLCD.locate(2,5);
+    uLCD.puts("Press Right for");
+    uLCD.locate(2,6);
+    uLCD.puts("Multi-Player");
+    
+    // Button Example:
+    // Use !pb_r to access the player1 right button value.
+    // Eventually you should return SINGLE_PLAYER or MULTI_PLAYER
+    // depending on the user's choice.
+    
+    while(true) {
+        if (!pb_l) {
+            uLCD.cls();
+            uLCD.locate(2,2);
+            uLCD.puts("Press Up");
+            uLCD.locate(2,3);
+            uLCD.puts("For nighttime.");
+            uLCD.locate(2,5);
+            uLCD.puts("Press Down");
+            uLCD.locate(2,6);
+            uLCD.puts("For daytime.");
+            while(true) {
+                if (!pb_u) {
+                    skyChange = 1;
+                    SKY_COLOR = SKY_COLOR2;
+                    return SINGLE_PLAYER;
+                }
+                if (!pb_d) {
+                    return SINGLE_PLAYER;
+                }
+            }
+        }
+        if (!pb_r) {
+            uLCD.cls();
+            uLCD.locate(2,2);
+            uLCD.puts("Press Up");
+            uLCD.locate(2,3);
+            uLCD.puts("For nighttime.");
+            uLCD.locate(2,5);
+            uLCD.puts("Press Down");
+            uLCD.locate(2,6);
+            uLCD.puts("For daytime.");
+            while(true) {
+                if (!pb_u) {
+                    skyChange = 1;
+                    SKY_COLOR = SKY_COLOR2;
+                    return MULTI_PLAYER;
+                }
+                if (!pb_d) {
+                    return MULTI_PLAYER;
+                }
+            }
+        }
+    }
+}
+
+// Initialize the world map. I've provided a basic map here,
+// but as part of the assignment you must create more
+// interesting map(s).
+// Note that calls to sync.function() will run function()
+// on both players' LCDs (assuming you are in multiplayer mode).
+// In single player mode, only your lcd will be modified. (Makes sense, right?)
+void map_init() {
+    
+    // Fill the entire screen with sky blue.
+    sync.background_color(SKY_COLOR);
+    
+    // Call the clear screen function to force the LCD to redraw the screen
+    // with the new background color.
+    sync.cls();
+    
+    // Draw the ground in green.
+    sync.filled_rectangle(0,0,128,20, GND_COLOR);
+    
+    // Draw some obstacles. They don't have to be black, 
+    // but they shouldn't be the same color as the sky or your tanks.
+    // Get creative here. You could use brown and grey to draw a mountain
+    // or something cool like that.
+    
+    sync.filled_rectangle(40, 40, 45, 90, AQUA);
+    sync.filled_rectangle(50, 30, 55, 70, PURPLE);
+    sync.filled_rectangle(59, 20, 69, 60, BLACK);
+    sync.filled_rectangle(74, 30, 79, 70, PURPLE);
+    sync.filled_rectangle(84, 40, 89, 90, AQUA);
+    
+    // Before you write text on the screens, tell the LCD where to put it.
+    sync.locate(0,15);
+    
+    // Set the text background color to match the sky. Just for looks.
+    sync.textbackground_color(SKY_COLOR);
+    
+    // Display the game title.
+    char title[] = "       Tanks";
+    sync.puts(title, sizeof(title));
+    
+    // Flush the draw buffer and execute all the accumulated draw commands.
+    sync.update();          
+}
+
+// Initialize the game hardware. 
+// Call game_menu to find out which mode to play the game in (Single- or Multi-Player)
+// Initialize the game synchronizer.
+void game_init(void) {
+    
+    led1 = 0; led2 = 0; led3 = 0; led4 = 0;
+    
+    pb_u.mode(PullUp);
+    pb_r.mode(PullUp); 
+    pb_d.mode(PullUp);    
+    pb_l.mode(PullUp);
+    
+    int mode = game_menu();
+    sync.init(&uLCD, &acc, &pb_u, &pb_r, &pb_d, &pb_l, mode); // Connect to the other player.
+    map_init();
+}
+
+// Display some kind of game over screen which lets us know who won.
+// Play a cool sound!
+int game_over() {
+    int i = 0;
+    playSound("/sd/wavfiles/cheering.wav");
+    
+    // score keeping
+    char* toPrint1 = new char [7];
+    char* toPrint2 = new char [7];
+    toPrint1[6] = '\0';
+    toPrint2[6] = '\0';
+    sprintf(&toPrint1[0], "P1: %d", p1score);
+    sprintf(&toPrint2[0], "P2: %d", p2score);
+    
+    while(1) {
+        sync.cls();
+        // animated winning screen
+        sync.locate(i + 2, 10);
+        if (winner == PLAYER1) {
+            sync.puts("P1 WINS!\n", sizeof("P1 WINS!\n"));
+        } else if (winner == PLAYER2) {
+            sync.puts("P2 WINS!\n", sizeof("P2 WINS!\n"));
+        }
+        sync.locate(2, 8);
+        sync.puts(toPrint1, 8);
+        sync.locate(9, 8);
+        sync.puts(toPrint2, 8);
+        sync.locate(2, 6);
+        sync.puts("Press up to\n", sizeof("Press up to\n"));
+        sync.locate(2, 5);
+        sync.puts("continue!\n", sizeof("continue!\n"));
+        sync.update();
+        (++i) %= 7;
+        wait(0.1);
+        // restart the game if up is pressed
+        if (!pb_u) {
+            return 1;
+        }
+    }
+}
+
+void menuSound(void const *argument)
+{
+    FILE *wf;
+    wf=fopen("/sd/wavfiles/applause.wav","r");
+    player.play(wf);
+    fclose(wf);
+}
+
+
+int main (void) {
+    int* p1_buttons;
+    int* p2_buttons;
+    
+    float ax1, ay1, az1;
+    float ax2, ay2, az2;
+    
+    // play menu sound
+    Thread thread1(menuSound);
+    game_init();
+        
+    int restart = 1;
+    while (restart == 1) {
+        map_init();
+        
+        // Create your tanks.
+        Tank t1(4, 21, 12, 8, TANK_RED);            // (min_x, min_y, width, height, color)
+        Tank t2(111, 21, 12, 8, TANK_BLUE);         // (min_x, min_y, width, height, color)
+        
+        // For each tank, create a bullet.
+        Bullet b1(&t1);
+        Bullet b2(&t2);
+        
+        // change skycolor
+        t1.changeSky(SKY_COLOR);
+        t2.changeSky(SKY_COLOR);
+        b1.changeSky(SKY_COLOR);
+        b2.changeSky(SKY_COLOR);
+        
+        // reset these values at the start of every round
+        restart = 0;
+        whose_turn = PLAYER1;
+        frame_timer.start();
+        
+        // Your code starts here...
+        while(true) {
+    
+            // Get a pointer to the buttons for both sides.
+            // From now on, you can access the buttons for player x using
+            //
+            // px_buttons[U_BUTTON] 
+            // px_buttons[R_BUTTON] 
+            // px_buttons[D_BUTTON] 
+            // px_buttons[L_BUTTON]
+            
+            p1_buttons = sync.get_p1_buttons();
+            p2_buttons = sync.get_p2_buttons();
+            
+            led1 = p1_buttons[0] ^ p2_buttons[0];
+            led2 = p1_buttons[1] ^ p2_buttons[1];
+            led3 = p1_buttons[2] ^ p2_buttons[2];
+            led4 = p1_buttons[3] ^ p2_buttons[3];
+    
+            // Get the accelerometer values.
+            sync.get_p1_accel_data(&ax1, &ay1, &az1);
+            sync.get_p2_accel_data(&ax2, &ay2, &az2);
+    
+            if(whose_turn == PLAYER1) {
+                
+                // delete old triangle on the other player
+                sync.triangle(118, 120, 118, 125, 123, 120, SKY_COLOR);
+                // triangle above player's turn
+                sync.triangle(5, 120, 5, 125, 10, 120, GREEN);
+                sync.update();
+                
+                // Accelerometer
+                if(ax1 > ACC_THRESHOLD) { 
+                    // left
+                    t1.reposition(-1, 0, 0);          
+                } else if(ax1 < -1 * ACC_THRESHOLD) {
+                    //right
+                    t1.reposition(+1, 0, 0);          
+                }
+                if(ay1 > ACC_THRESHOLD) {
+                    // up
+                    t1.reposition(0, 0, +1);
+                } else if(ay1 < -1 * ACC_THRESHOLD) {
+                    // down
+                    t1.reposition(0, 0, -1);
+                }
+                
+                // power up button
+                if(p1_buttons[U_BUTTON]) { 
+                    b1.powerUp();
+                }
+                // shoot button
+                if(p1_buttons[D_BUTTON]) { 
+                    b1.shoot(); 
+                }
+                
+                float dt = frame_timer.read();
+                int intersection_code = b1.time_step(dt);
+                
+                // If you shot yourself, you lost.
+                if(sync.pixel_eq(intersection_code, t1.tank_color)) {
+                    sync.update();  // Is this necessary?
+                    winner = PLAYER2;
+                    p2score = p2score + 1;
+                    break;
+                }
+                // If you shot the other guy, you won!
+                if(sync.pixel_eq(intersection_code, t2.tank_color)) { 
+                    sync.update();
+                    winner = PLAYER1;
+                    p1score = p1score + 1;
+                    break;
+                }
+                // keep playing
+                if(intersection_code != BULLET_NO_COLLISION || intersection_code == BULLET_OFF_SCREEN) {
+                    whose_turn = PLAYER2;
+                }
+            } else if(whose_turn == PLAYER2) {
+                // I gave you a lot of the logic for Player1. It's up to you to figure out Player2!
+                // If you are in SINGLE_PLAYER mode, you should use the p1 inputs to control p2.
+                // In MULTI_PLAYER mode, you should use the p2 inputs to control p2.
+                //
+                // Hint: 
+                //         sync.play_mode will tell you if you are in MULTI_PLAYER or SINGLE_PLAYER mode.
+                //         
+                
+                // deletes triangle above other player
+                sync.triangle(5, 120, 5, 125, 10, 120, SKY_COLOR);
+                // triangle above player's turn
+                sync.triangle(118, 120, 118, 125, 123, 120, GREEN);
+                sync.update();
+                
+                if (sync.play_mode == SINGLE_PLAYER) {
+                    
+                    if(ax1 > ACC_THRESHOLD) { 
+                        // left
+                        t2.reposition(-1, 0, 0);          
+                    } else if(ax1 < -1 * ACC_THRESHOLD) {
+                        //right
+                        t2.reposition(+1, 0, 0);          
+                    }
+                    if(ay1 > ACC_THRESHOLD) {
+                        // up
+                        t2.reposition(0, 0, +1);
+                    } else if(ay1 < -1 * ACC_THRESHOLD) {
+                        // down
+                        t2.reposition(0, 0, -1);
+                    }
+                    
+                    // powerup button
+                    if(p1_buttons[U_BUTTON]) { 
+                        b2.powerUp();
+                    }
+                    // shoot button
+                    if(p1_buttons[D_BUTTON]) { 
+                        b2.shoot(); 
+                    }
+                } else if (sync.play_mode == MULTI_PLAYER) {
+                    if(ax2 > ACC_THRESHOLD) { 
+                        // left
+                        t2.reposition(+1, 0, 0);          
+                    } else if(ax2 < -1 * ACC_THRESHOLD) {
+                        //right
+                        t2.reposition(-1, 0, 0);          
+                    }
+                    if(ay2 > ACC_THRESHOLD) {
+                        // up
+                        t2.reposition(0, 0, +1);
+                    } else if(ay2 < -1 * ACC_THRESHOLD) {
+                        // down
+                        t2.reposition(0, 0, -1);
+                    }
+                    
+                    // powerup button
+                    if(p2_buttons[U_BUTTON]) { 
+                        b2.powerUp();
+                    }
+                    // shoot button
+                    if(p2_buttons[D_BUTTON]) { 
+                        b2.shoot(); 
+                    }
+                }
+                    
+                float dt = frame_timer.read();
+                int intersection_code = b2.time_step(dt); 
+                
+                // If you shot yourself, you lost.
+                if(sync.pixel_eq(intersection_code, t2.tank_color)) {
+                    sync.update();  // Is this necessary?
+                    winner = PLAYER1;
+                    p1score = p1score + 1;
+                    break;
+                }
+                // If you shot the other guy, you won!
+                if(sync.pixel_eq(intersection_code, t1.tank_color)) { 
+                    sync.update();
+                    winner = PLAYER2;
+                    p2score = p2score + 1;
+                    break;
+                }
+                // keep playing
+                if(intersection_code != BULLET_NO_COLLISION || intersection_code == BULLET_OFF_SCREEN) {
+                    whose_turn = PLAYER1;
+                }
+            }
+    
+            frame_timer.reset();
+            sync.update();     
+        }
+        restart = game_over();
+    }
+}
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 mbed-rtos.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#6c35e082773a
diff -r 000000000000 -r ffed9a3bc797 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e1686b8d5b90
\ No newline at end of file
diff -r 000000000000 -r ffed9a3bc797 wave_player.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wave_player.lib	Mon Mar 13 21:23:17 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/sravet/code/wave_player/#acc3e18e77ad