ECE2036 Lab5 (SHIP Game)
Dependencies: 4DGL-uLCD-SE mbed PinDetect SDFileSystem mbed-rtos
Fork of mythermostat by
This is a Lab assignment for ECE 2036. This program uses the object oriented methodology to design a LAME attack ship game. Pushbuttons, speaker and uLCD are used in LPC1768. Sample video is posted by the instructor to assist the design of this Game at: https://youtu.be/d8ekTKvMWqw
Diff: main.cpp
- Revision:
- 5:d6c2e01b0596
- Parent:
- 4:9a4d22a279b3
--- a/main.cpp Thu Jan 23 16:47:05 2014 +0000 +++ b/main.cpp Sat Mar 18 14:24:26 2017 +0000 @@ -1,141 +1,415 @@ -// skeleton code for ECE 2036 thermostat lab -// code must be added by students #include "mbed.h" -#include "TMP36.h" #include "SDFileSystem.h" #include "uLCD_4DGL.h" #include "PinDetect.h" #include "Speaker.h" -// must add your new class code to the project file Shiftbrite.h -#include "Shiftbrite.h" +#include <string> +#include <cstdlib> +#include <ctime> +#include <vector> +#include <iterator> +#include <algorithm> -// use class to setup temperature sensor pins -TMP36 myTMP36(p15); //Analog in +#define SHIP_HEIGHT 4 +#define SHIP_WIDTH 15 +#define ALIEN_HEIGHT 8 +#define ALIEN_WIDTH 11 + +#define _ 0x000000 // BLACK +#define X 0xFFFFFF // WHITE +#define Y 0x0000FF // Blue +using namespace std; +uLCD_4DGL uLCD(p28, p27, p29); +Speaker mySpeaker(p21); +PinDetect left(p17); +PinDetect shoot(p18); +PinDetect right(p16); +Timer timer; // For measuring Elapsed time -// use class to setup microSD card filesystem -SDFileSystem sd(p5, p6, p7, p8, "sd"); +static int shipx = 57; +static int shipy = 120; +static int bulletx = 65; +static int bullety = 115; +static bool movement = false; +static bool direction = false; +static bool fire = false; +int clear[8*11] = { + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y, + Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y +}; -// use class to setup the Color LCD -uLCD_4DGL uLCD(p28, p27, p29); // create a global uLCD object +int alienAli_sprite[ALIEN_HEIGHT * ALIEN_WIDTH] = { + X,X,X,_,_,_,_,_,X,X,X, + X,X,X,_,_,_,_,X,X,X,_, + X,X,X,_,_,X,X,X,_,_,_, + X,X,X,X,X,X,_,_,_,_,_, + X,X,X,X,X,X,X,_,_,_,_, + X,X,X,_,_,X,X,X,_,_,_, + X,X,X,_,_,_,_,X,X,X,_, + X,X,X,_,_,_,_,_,X,X,X +}; +int alienAlice_sprite[ALIEN_HEIGHT * ALIEN_WIDTH] = { + _,_,_,_,X,X,X,_,_,_,_, + _,X,X,X,X,X,X,X,X,X,_, + X,X,X,X,X,X,X,X,X,X,X, + X,X,X,_,_,X,_,_,X,X,X, + X,X,X,X,X,X,X,X,X,X,X, + _,_,_,X,X,_,X,X,_,_,_, + _,_,X,X,_,_,_,X,X,_,_, + X,X,_,_,_,X,_,_,_,X,X +}; +int alienBobDown_sprite[ALIEN_HEIGHT * ALIEN_WIDTH] = { + _,_,X,_,_,_,_,_,X,_,_, + _,_,_,X,_,_,_,X,_,_,_, + _,_,X,X,X,X,X,X,X,_,_, + _,X,X,_,X,X,X,_,X,X,_, + X,X,X,X,X,X,X,X,X,X,X, + X,_,X,X,X,X,X,X,X,_,X, + X,_,X,_,_,_,_,_,X,_,X, + _,_,_,X,X,_,X,X,_,_,_ +}; -// use class to setup pushbuttons pins -PinDetect pb1(p23); -PinDetect pb2(p24); -PinDetect pb3(p25); +int alienBobUp_sprite[ALIEN_HEIGHT * ALIEN_WIDTH] = { + _,_,X,_,_,_,_,_,X,_,_, + X,_,_,X,_,_,_,X,_,_,X, + X,_,X,X,X,X,X,X,X,_,X, + X,X,X,_,X,X,X,_,X,X,X, + X,X,X,X,X,X,X,X,X,X,X, + _,_,X,X,X,X,X,X,X,_,_, + _,_,X,_,_,_,_,_,X,_,_, + _,X,_,_,_,_,_,_,_,X,_ +}; + +// Base Class +class ScreenAliens +{ +public: + ScreenAliens(string, int, int); -// use class to setup speaker pin -Speaker mySpeaker(p21); //PWM out + virtual void draw() = 0; + virtual void update() = 0; + + void setName(string); + void setxPos(int); + void setyPos(int); + void setDir(int); + + string getName(); + int getxPos(); + int getyPos(); + int getDir(); +private: + + string name; + int xPos; + int yPos; + int dir; +}; -// use class to setup Shiftbrite pins -Shiftbrite myShiftbrite(p9, p10, p11, p12, p13);// ei li di n/c ci +ScreenAliens::ScreenAliens(string name, int xPos, int yPos) +{ + setName(name); + setxPos(xPos); + setyPos(yPos); + srand(time(NULL)); + int status = rand()%2; + setDir(status); +} + +void ScreenAliens::setName(string name) +{ + this -> name = name; +} + +void ScreenAliens::setxPos(int xPos) +{ + this -> xPos = xPos; +} + +void ScreenAliens::setyPos(int yPos) +{ + this -> yPos = yPos; +} -// use class to setup Mbed's four on-board LEDs -DigitalOut myLED1(LED1); -DigitalOut myLED2(LED2); -DigitalOut myLED3(LED3); -DigitalOut myLED4(LED4); +void ScreenAliens::setDir(int dir) +{ + this -> dir = dir; +} + +string ScreenAliens::getName() +{ + return name; +} +int ScreenAliens::getxPos() +{ + return xPos; +} + +int ScreenAliens::getyPos() +{ + return yPos; +} + +int ScreenAliens::getDir() +{ + return dir; +} -//also setting any unused analog input pins to digital outputs reduces A/D noise a bit -//see http://mbed.org/users/chris/notebook/Getting-best-ADC-performance/ -DigitalOut P16(p16); -DigitalOut P17(p17); -DigitalOut P18(p18); -DigitalOut P19(p19); -DigitalOut P20(p20); +// Derived class AlienBob +class AlienBob:public ScreenAliens +{ + +public: + AlienBob(int xPos, int yPos):ScreenAliens("AlienBob", xPos, yPos) { + int status; + srand(time(NULL)); + status = rand()%2; + setUpDown(status); + } + + void setUpDown(int upDown) { + this -> upDown = upDown; + } + + int getUpDown() { + return upDown; + } + + virtual void draw() { + if (getUpDown() == 0) { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH, ALIEN_HEIGHT, alienBobDown_sprite); + setUpDown(1); + } else { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH, ALIEN_HEIGHT, alienBobUp_sprite); + setUpDown(0); + } + } + + virtual void update() { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH,ALIEN_HEIGHT, clear); + if (ScreenAliens::getDir() == 0) { + if (ScreenAliens::getxPos() - 5 <= 0 ) { + ScreenAliens::setDir(1); + ScreenAliens::setxPos(ScreenAliens::getxPos() + 5); + } else { + ScreenAliens::setxPos(ScreenAliens::getxPos() - 5); + } + draw(); + } else { + if (ScreenAliens::getxPos() + 5 + ALIEN_WIDTH >= 128) { + ScreenAliens::setDir(0); + ScreenAliens::setxPos(ScreenAliens::getxPos() - 5); + } else { + ScreenAliens::setxPos(ScreenAliens::getxPos() + 5); + } + draw(); + } + } +private: + int upDown; +}; + +class AlienAlice:public ScreenAliens +{ +public: + AlienAlice(int xPos, int yPos):ScreenAliens("AlienAlice", xPos, yPos) {} + virtual void draw() { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH, ALIEN_HEIGHT, alienAlice_sprite); + } + + virtual void update() { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH,ALIEN_HEIGHT, clear); + if (ScreenAliens::getDir() == 0) { + if (ScreenAliens::getxPos() - 8 <= 0 ) { + ScreenAliens::setDir(1); + ScreenAliens::setxPos(ScreenAliens::getxPos() + 8); + } else { + ScreenAliens::setxPos(ScreenAliens::getxPos() - 8); + } + draw(); + } else { + if (ScreenAliens::getxPos() + 8 + ALIEN_WIDTH >= 128) { + ScreenAliens::setDir(0); + ScreenAliens::setxPos(ScreenAliens::getxPos() - 8); + } else { + ScreenAliens::setxPos(ScreenAliens::getxPos() + 8); + } + draw(); + } + } +}; + +class AlienAli:public ScreenAliens +{ + +public: + + AlienAli(int xPos, int yPos):ScreenAliens("AlienAli", xPos, yPos) {} + + virtual void draw() { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH, ALIEN_HEIGHT, alienAli_sprite); + } + + virtual void update() { + uLCD.BLIT(ScreenAliens::getxPos(),ScreenAliens::getyPos(), ALIEN_WIDTH,ALIEN_HEIGHT, clear); + if (ScreenAliens::getDir() == 0) { + if (ScreenAliens::getxPos() - 10 <= 0 ) { + ScreenAliens::setDir(1); + ScreenAliens::setxPos(ScreenAliens::getxPos() + 10); + } else { + ScreenAliens::setxPos(ScreenAliens::getxPos() - 10); + } + draw(); + } else { + if (ScreenAliens::getxPos() + 10 + ALIEN_WIDTH >= 128) { + ScreenAliens::setDir(0); + ScreenAliens::setxPos(ScreenAliens::getxPos() - 10); + } else { + ScreenAliens::setxPos(ScreenAliens::getxPos() + 10); + } + draw(); + } + } +}; -// Global variables used in callbacks and main program -// C variables in interrupt routines should use volatile keyword -int volatile heat_setting=78; // heat to temp -int volatile cool_setting=68; // cool to temp -bool volatile mode=false; // heat or cool mode +vector <ScreenAliens*> aliens(6); -// Callback routine is interrupt activated by a debounced pb1 hit -void pb1_hit_callback (void) +//Code for the function of the pushbuttons +void left_hit_callback(void) { -// ADD CODE HERE + movement = true; + direction = false; } -// Callback routine is interrupt activated by a debounced pb2 hit -void pb2_hit_callback (void) + +void right_hit_callback (void) { -// ADD CODE HERE -} -// Callback routine is interrupt activated by a debounced pb3 hit -void pb3_hit_callback (void) -{ -// ADD CODE HERE + movement = true; + direction = true; } +void shoot_hit_callback (void) +{ + if (!fire) { + bulletx = shipx + 8; + } + fire = true; +} +void start() +{ + + srand(time(0)); + int randomNum[6]; + int xpos[6]; + for (int i = 0; i < aliens.size(); i++) { + randomNum[i] = rand()%3 + 1; + xpos[i] = rand()%117 + 1; + } + + for (int i = 0; i < 6; i++) { + if (randomNum[i] == 1) { + aliens[i] = new AlienBob(xpos[i], i*10 + 10); + } else if (randomNum[i] == 2) { + aliens[i] = new AlienAlice(xpos[i], i*10 + 10); + } else if (randomNum[i] == 3) { + aliens[i] = new AlienAli(xpos[i], i*10 + 10); + } + } + + aliens[0] -> draw(); + aliens[1] -> draw(); + aliens[2] -> draw(); + aliens[3] -> draw(); + aliens[4] -> draw(); + aliens[5] -> draw(); + + uLCD.filled_rectangle(shipx,shipy,shipx+SHIP_WIDTH,shipy+SHIP_HEIGHT, X); +} int main() { - float Current_temp=0.0; + uLCD.background_color(BLUE); // Background color blue - // Use internal pullups for the three pushbuttons - pb1.mode(PullUp); - pb2.mode(PullUp); - pb3.mode(PullUp); - // Delay for initial pullup to take effect - wait(.01); - // Setup Interrupt callback functions for a pb hit - pb1.attach_deasserted(&pb1_hit_callback); - pb2.attach_deasserted(&pb2_hit_callback); - pb3.attach_deasserted(&pb3_hit_callback); - // Start sampling pb inputs using interrupts - pb1.setSampleFrequency(); - pb2.setSampleFrequency(); - pb3.setSampleFrequency(); - // pushbuttons now setup and running + left.mode(PullUp); + right.mode(PullUp); + shoot.mode(PullUp); + + uLCD.printf("\n\nLAME Attack Game!"); // Welcome message + wait(2.0); //1 pause system for 2.0 + uLCD.cls(); // clear screen - // start I/O examples - DELETE THIS IN YOUR CODE..BUT WILL USE THESE I/O IDEAS ELSEWHERE - // since all this compiles - the needed *.h files for these are in the project - // - Current_temp = myTMP36; //Read temp sensor - printf("Hello PC World\n\r"); // need terminal application running on PC to see this output - uLCD.printf("\n\rHello LCD World\n\r"); // LCD - mySpeaker.PlayNote(500.0, 1.0, 1.0); // Speaker buzz - myShiftbrite.write( 0, 50 ,0); // Green RGB LED - // SD card write file example - prints error message on PC when running until SD card hooked up - // Delete to avoid run time error - mkdir("/sd/mydir", 0777); // set up directory and permissions - FILE *fp = fopen("/sd/mydir/sdtest.txt", "w"); //open SD - if(fp == NULL) { - error("Could not open file for write\n"); - } - fprintf(fp, "Hello SD Card World!"); // write SD - fclose(fp); // close SD card - // - // end I/O examples + // Setup Interrupt callback functions for a pb hit + left.attach_deasserted(&left_hit_callback); + right.attach_deasserted(&right_hit_callback); + shoot.attach_deasserted(&shoot_hit_callback); - + // Start sampling pb inputs using interrupts + left.setSampleFrequency(); + right.setSampleFrequency(); + shoot.setSampleFrequency(); + start(); + timer.start(); // Starting timer to keep track how much time taken + int startT = timer.read_ms(); + while (aliens.size() > 0) { - - // State machine code below will need changes and additions - while (1) { - { - enum Statetype { Heat_off = 0, Heat_on }; - Statetype state = Heat_off; - while(1) { - switch (state) { - case Heat_off: - myLED4 = 0; - state = Heat_on; - break; - case Heat_on: - myLED4 = 1; - state = Heat_off; - break; + for (int i = 0; i < aliens.size(); i++) { + aliens[i] -> update(); + } + if (fire) { + uLCD.filled_rectangle(bulletx, bullety, bulletx + 2, bullety +4, Y); + for (int i = 0; i < aliens.size(); i++) { + if (((*aliens[i]).getxPos()- 4 <= bulletx) && (bulletx + 2 <= (*aliens[i]).getxPos() + ALIEN_WIDTH + 4) + && ((*aliens[i]).getyPos()- 8 <= bullety) && ((*aliens[i]).getyPos()+8 >= bullety - ALIEN_HEIGHT )) { + uLCD.BLIT((*aliens[i]).getxPos(),(*aliens[i]).getyPos(), ALIEN_WIDTH,ALIEN_HEIGHT, clear); + fire = false; + bullety = 115; + aliens.erase(aliens.begin()+i); + mySpeaker.PlayNote(100.0, 0.25, 0.01); + } else if (bullety < 0) { + fire = false; + bullety = 115; } - wait(0.33); - // heartbeat LED - common debug tool - // blinks as long as code is running and not locked up - myLED1=!myLED1; + } + if (fire) { + bullety = bullety - 8; + uLCD.filled_rectangle(bulletx, bullety, bulletx + 2, bullety + 4, RED); } } + if (movement) { + uLCD.filled_rectangle(shipx,shipy,shipx+SHIP_WIDTH,shipy+SHIP_HEIGHT,Y); + if (direction) { + if (shipx + SHIP_WIDTH + ALIEN_WIDTH > 128) { + shipx = 128-SHIP_WIDTH; + } else { + shipx = shipx + ALIEN_WIDTH; + } + } else { + if (shipx - ALIEN_WIDTH < 0) { + shipx = 0; + } else { + shipx = shipx - ALIEN_WIDTH; + } + } + movement = false; + uLCD.filled_rectangle(shipx, shipy, shipx+SHIP_WIDTH,shipy+SHIP_HEIGHT,X); + } } + wait(1.0); + mySpeaker.PlayNote(800.0, 1.0, 0.25); + int endT = timer.read_ms(); + timer.stop(); // End of timer + int total = (endT - startT)/1000; + uLCD.cls(); + uLCD.printf("Earth Saved!\n\n%d seconds.", total); } \ No newline at end of file