A reproduction of the 70's classic. Enjoy!

Dependencies:   NokiaLCD SDFileSystem SIgame mbed-rtos mbed wave_player

Files at this revision

API Documentation at this revision

Comitter:
zlee9
Date:
Thu Mar 07 02:59:24 2013 +0000
Child:
1:02e3c9b77580
Commit message:
This is the final version of Space Invaders

Changed in this revision

NokiaLCD.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
SIgame.lib 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NokiaLCD.lib	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/zlee9/code/NokiaLCD/#65a915f69fa2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/SDFileSystem/#c8f66dc765d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SIgame.lib	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/zlee9/code/SIgame/#4564efa43302
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,445 @@
+/***************************************************************/
+/***************************************************************/
+/***                                                         ***/
+/***  Space Invaders Simulator                               ***/
+/***                                                         ***/
+/***  ECE 4180 Developer Team: Space Pirates                 ***/
+/***     Members: David Gaspard, Zhe Cheng Lee               ***/
+/***                                                         ***/
+/***************************************************************/
+/***************************************************************/
+
+
+/***************************************************************/
+/*                                                             */
+/* Libaries                                                    */
+/*                                                             */
+/***************************************************************/
+#include "mbed.h"
+#include "NokiaLCD.h"
+#include "SIgame.h"
+#include "rtos.h"
+#include "SDFileSystem.h"
+#include "wave_player.h"
+
+/***************************************************************/
+/*                                                             */
+/* Classes and Global Variables                                */
+/*                                                             */
+/***************************************************************/
+NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type
+DigitalIn button(p20); // Pushbutton for firing laser
+AnalogIn horiz(p15); // From joystick for steering ship
+SDFileSystem sd(p11, p12, p13, p14, "sd"); //SD card
+AnalogOut DACout(p18);//Speaker out
+wave_player waver(&DACout);//Wave player
+
+int state;
+int doneski;//done playing start music?
+
+OBJECT wave[NUM_ALIEN_ROWS][NUM_ALIEN_COLS],
+       wave_old[NUM_ALIEN_ROWS][NUM_ALIEN_COLS];
+
+/***************************************************************/
+/*                                                             */
+/* Prototypes                                                  */
+/*                                                             */
+/***************************************************************/
+void start();
+int game();
+void lose();
+void win();
+void updateScreen(OBJECT ship, OBJECT ship_old, POINT ylaser, POINT ylaser_old,
+                  POINT elaser[], POINT elaser_old[], int lives_rem);
+
+void playstart(void const *args);
+void startmusic(void const *args);
+
+
+/***************************************************************/
+/*                                                             */
+/* Main program                                                */
+/*                                                             */
+/***************************************************************/
+int main()
+{
+    doneski=0;//Variable to declare that start screen music thread
+              //was terminated
+    Thread thread(playstart);//Satrt the sound effect thread
+    Thread startmu(startmusic);//start the trigger fire thread
+    state = START;//Begin the game
+    button.mode(PullUp);//Pull up the pushbutton
+
+    while (1) { // Game loop
+        switch (state) {
+            case START:
+                start(); // Start game
+                state = GAME;
+                break;
+
+            case GAME:
+                startmu.terminate();
+                doneski=1;
+                state = game(); // Actual game
+                break;
+
+            case LOSE:
+                lose(); // Losing screen
+                state = START;
+                break;
+
+            case WIN:
+                win(); // Winning screen
+                state = START;
+                break;
+        }
+    }
+}
+
+
+/***************************************************************/
+/*                                                             */
+/* Game-State Procedures                                       */
+/*                                                             */
+/***************************************************************/
+void start()
+{
+    /******
+     * start
+     *     Starts up game
+     ******/
+    lcd.cls();
+    lcd.locate(0,4);
+    lcd.printf("SPACE INVADERS");
+    lcd.locate(0,10);
+    lcd.printf("PRESS BUTTON TO CONTINUE");
+    WAIT4FULLPUSH(button);
+}
+
+
+int game()
+{
+    /******
+     * game
+     *     Handles the main gameplay. Prepares for win state if player destroys all
+     *     aliens and lose state if player loses all lives
+     ******/
+    POINT ylaser, ylaser_old, elaser[ELASER_CAP], elaser_old[ELASER_CAP];
+    OBJECT ship, ship_old, *sh_alien, *frontline[NUM_ALIEN_COLS];
+    int time, lives_rem, als_rem, i;
+    float hper;
+    bool reach, left, lcancel;
+
+    // Set display screen
+    lcd.cls();
+    lcd.background(BLACK);
+
+    // Initialize
+    lives_rem = NUM_LIVES_START;
+    als_rem = NUM_ALIENS_START;
+    reach = left = lcancel = false;
+    time = 0;
+    summonWave(); // Starting locations of all alien
+    memcpy(wave_old, wave, sizeof(wave)); // Make copy for aliens' old locations
+
+    // Keep track of aliens in front of respective columns
+    for (i = 0; i < NUM_ALIEN_COLS; i++)
+        frontline[i] = &wave[NUM_ALIEN_ROWS][i];
+
+    // Set up laser structures
+    elaser[0].collide = elaser[1].collide = elaser[2].collide =
+            elaser_old[0].collide = elaser_old[1].collide = elaser_old[2].collide
+                                    = ylaser.collide = ylaser_old.collide = true; // No lasers on screen yet
+    // Enemy lasers are white
+    elaser[0].color = elaser[1].color = elaser[2].color = WHITE;
+    ylaser.color = GREEN; // Player's laser is green
+
+    // Set up player's ship
+    ship = startShip();
+    memcpy(&ship_old, &ship, sizeof(ship)); // Save copy for ship's old locations
+
+    // Game goes on until player loses all lives, destroy all aliens, or allow
+    // any alien to reach screen border on player's side
+    while (!reach && lives_rem > 0 && als_rem > 0) {
+        /* Laser Movement */
+        /******************/
+        // Player's laser is on screen
+        if (!(ylaser.collide)) {
+            if (ylaser.y >= 0)
+                (ylaser.y)-= 3; // Laser travels up to aliens' side
+            else
+                ylaser.collide = true; // Laser vanishes at top of screen
+        }
+
+        // Enemy lasers is on screen
+        for (i = 0; i < ELASER_CAP; i++) {
+            if (elaser[i].y < SCREENHEIGHT) // Enemy lasers travel down to player's side
+                (elaser[i].y)++;
+            else // Enemy laser vanishes at bottom of screen
+                elaser[i].collide = true;
+        }
+
+        /* Controls       */
+        /******************/
+        // Player firing laser
+        if (button && ylaser.collide) {
+            // Initialize laser's locations according to ship's
+            ylaser.y = ship.y - 1;
+            ylaser.x = ship.x + (ship.width >> 1);
+            // Can fire next laser after current hits top of screen or other objects
+            ylaser.collide = false;
+        }
+
+        // Player steering ship
+        hper = horiz; // Read joystick's horizontal position.
+        if (GOLEFT(hper) && ship.x > 0)
+            (ship.x)--; // Ship moves left/
+
+        if (GORIGHT(hper) && ship.x < SCREENWIDTH - 1)
+            (ship.x)++; // Ship moves right
+
+        /* Alien Activity */
+        /******************/
+        // Move wave of aliens. Update whether any alien reaches screen on
+        // player's side
+        reach = moveAlienWave(&left);
+
+        // Enemy aliens firing lasers. Aliens fire lasers only after certain
+        // time intervals or when one of their lasers canceled out with player's
+        if (time >= RELOAD_TIME || lcancel) {
+            // Choose random front alien to fire laser. Ignore any invalid ones
+            // (those in columns that were completely wiped out have been set to
+            // NULL)
+            while ((sh_alien = frontline[rand() / (RAND_MAX/i + 1)]) == NULL);
+
+            // Find enemy laser structure not in use for display
+            if (elaser[0].collide)
+                i = 0;
+            else if (elaser[1].collide)
+                i = 1;
+            else
+                i = 2;
+
+            // Initialize laser's location according to chosen alien's
+            elaser[i].y = sh_alien->y + 1;
+            elaser[i].x = sh_alien->x + (ALIEN_WIDTH >> 1);
+            elaser[i].collide = lcancel = false;
+            time = 0; // Reset time for next enemy laser fire
+        }
+
+        /* Collisions      */
+        /*******************/
+        // Cancel out player's laser and enemy laser should they connect
+        lcancel = twoLasersCollide(&ylaser, elaser);
+
+        // Kill alien if player's laser hits one
+        destroyAlien(&als_rem, &ylaser, frontline);
+
+        // Check for any enemy laser touching ship
+        for (i = 0; i < ELASER_CAP; i++) {
+            if (!(elaser[i].collide) && elaser[i].y >= ship.y && elaser[i].y <=
+                    ship.y + ship.height && elaser[i].x >= ship.x && elaser[i].x
+                    <= ship.x + ship.width) {
+                // Plyaer loses life if hit by laser
+                lives_rem--;
+                ship.killed = elaser[i].collide = true;
+            }
+        }
+
+        updateScreen(ship, ship_old, ylaser, ylaser_old, elaser, elaser_old,
+                     lives_rem); // Update gameplay screen
+        ship.killed = false;
+        time++; // Time passes
+
+        // Update old locations to current
+        memcpy(wave_old, wave, sizeof(wave));
+        memcpy(elaser_old, elaser, sizeof(elaser));
+        ylaser_old = ylaser;
+        ship_old = ship;
+    } // End of main gameplay loop
+
+
+    // Game's outcomes
+    if (als_rem) // Lost all lives or aliens reached your border
+        return LOSE;
+    else // Destroyed all aliens
+        return WIN;
+}
+
+
+void win()
+{
+    /******
+     * win
+     *     Displays congratulation screen and prompt player to replay
+     ******/
+    // Congratulation screen
+    lcd.cls();
+    lcd.locate(0,3);
+    lcd.printf("WELL DONE\n\rEARTHLING");
+    lcd.locate(0,6);
+    lcd.printf("THIS TIME YOU WIN");
+    wait(2);
+
+    // Prompt player to play game again
+    lcd.cls();
+    lcd.locate(0,10);
+    lcd.printf("PRESS BUTTON TO PLAY AGAIN");
+    WAIT4FULLPUSH(button);
+}
+
+
+void lose()
+{
+    /******
+     * lose
+     *     Displays game-over screen and prompts player to replay
+     ******/
+    // Game-over screen
+    lcd.cls();
+    lcd.locate(4,3);
+    lcd.printf("YOU SUCK");
+    wait(2);
+
+    // Prompt player to play game again
+    lcd.locate(0,10);
+    lcd.printf("PRESS BUTTON TO PLAY AGAIN");
+    WAIT4FULLPUSH(button);
+}
+
+
+/***************************************************************/
+/*                                                             */
+/* Game-Drawing Funntion                                       */
+/*                                                             */
+/***************************************************************/
+void updateScreen(OBJECT ship, OBJECT ship_old, POINT ylaser, POINT ylaser_old,
+                  POINT elaser[], POINT elaser_old[], int lives_rem)
+{
+    /******
+     * updateScreen
+     *     Updates game display on Nokia LCD screen
+     ******/
+    int r, c;
+
+    // Old locations are drawn with black to erase previous images in display
+    // when redrawing images
+    wait(0.02);
+
+    // Redraw surviving aliens from their positions
+    for (c = 0; c < NUM_ALIEN_COLS; c++) {
+        for (r = 0; r < NUM_ALIEN_ROWS; r++) {
+            lcd.fill(wave_old[r][c].x, wave_old[r][c].y, wave_old[r][c].width,
+                     wave_old[r][c].height, BLACK);
+            // Aliens as white rectangles
+            if (!(wave[r][c].killed)) // Don't draw destroyed aliens
+                lcd.fill(wave[r][c].x, wave[r][c].y, wave[r][c].width,
+                         wave[r][c].height, wave[r][c].color);
+        }
+    }
+
+    // Redraw enemy lasers as single white pixels
+    for (c = 0; c < ELASER_CAP; c++) {
+        lcd.pixel(elaser_old[c].x, elaser_old[c].y, BLACK);
+        lcd.pixel(elaser_old[c].x+1, elaser_old[c].y, BLACK);
+        lcd.pixel(elaser_old[c].x, elaser_old[c].y+1, BLACK);
+        lcd.pixel(elaser_old[c].x+1, elaser_old[c].y+1, BLACK);
+        // Don't draw lasers that hit bottom screen border or other objects
+        if (!(elaser[c].collide)) {
+            lcd.pixel(elaser[c].x, elaser[c].y, elaser[c].color);
+            lcd.pixel(elaser[c].x+1, elaser[c].y, elaser[c].color);
+            lcd.pixel(elaser[c].x, elaser[c].y+1, elaser[c].color);
+            lcd.pixel(elaser[c].x+1, elaser[c].y+1, elaser[c].color);
+        }
+    }
+
+    // Redraw player's laser as single green pixel. Check that laser doesn't
+    // hit top screen border or other objects
+    lcd.pixel(ylaser_old.x, ylaser_old.y, BLACK);
+    lcd.pixel(ylaser_old.x+1, ylaser_old.y, BLACK);
+    lcd.pixel(ylaser_old.x, ylaser_old.y+1, BLACK);
+    lcd.pixel(ylaser_old.x+1, ylaser_old.y+1, BLACK);
+    if (!(ylaser.collide))
+        lcd.pixel(ylaser.x, ylaser.y, ylaser.color);
+        lcd.pixel(ylaser.x+1, ylaser.y, ylaser.color);
+        lcd.pixel(ylaser.x, ylaser.y+1, ylaser.color);
+        lcd.pixel(ylaser.x+1, ylaser.y+1, ylaser.color);
+
+    if (ship.killed) { // Ship is destroyed from being hit by laser
+        lcd.locate(0,15);
+        lcd.printf("LIVES: %d", lives_rem);
+        wait(2); // Game pauses for few seconds before player uses next life
+        lcd.cls(); // Clear lives message
+    }
+
+    // Redraw player's ship as green rectangle
+    lcd.fill(ship_old.x, ship_old.y, ship_old.width, ship_old.height, BLACK);
+    lcd.fill(ship.x, ship.y, ship.width, ship.height, ship.color);
+}
+
+
+/***************************************************************/
+/*                                                             */
+/* This function plays the lose/win screen music and generates */
+/* the firing sound effect                                     */
+/*                                                             */
+/***************************************************************/
+void playstart(void const *args)//Th
+{   //Depending on the state of the game,
+    //queue either screen music or play sound effect upon fire
+    while(true) {
+        FILE *wave_file;
+        //At the start screen, do nothing
+        while(state==START) {
+            Thread::wait(50);
+        }
+        
+        //wait 500ms after start screen music has been cutoff before
+        //continuing to avoid conflicts
+        while(!doneski) {
+            Thread::wait(500);
+        }
+        
+        //While in the game, play firing sound when the player fires
+        while(state==GAME) {
+            if(button) {
+
+                wave_file=fopen("/sd/mample4.wav","r");
+
+
+                waver.play(wave_file);
+                fclose(wave_file);
+            }
+        }
+        
+        //Play losing screen music
+        while(state==LOSE) {
+            wave_file=fopen("/sd/mample3.wav","r");
+            waver.play(wave_file);
+            fclose(wave_file);
+        }
+        
+        //Play winning screen music
+        while(state==WIN) {
+            wave_file=fopen("/sd/mample3.wav","r");
+            waver.play(wave_file);
+            fclose(wave_file);
+        }
+    }
+}
+
+
+/***************************************************************/
+/*                                                             */
+/* startmusic() plays the start screen music                   */
+/*                                                             */
+/***************************************************************/
+void startmusic(void const *args)
+{
+
+    FILE *wave_file;
+    wave_file=fopen("/sd/mample2.wav","r");
+    waver.play(wave_file);
+    fclose(wave_file);
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#53e6cccd8782
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/5e5da4a5990b
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wave_player.lib	Thu Mar 07 02:59:24 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/sravet/code/wave_player/#acc3e18e77ad