Galaga
Introduction
This page shows the code and pin connections for a retro style Galaga game. The game consists of a space ship with horizontal capability of moving left and right and the ability to shoot missiles at enemy intruders. The intruders start at the top of the screen and make their way towards the space craft. The goal is to shoot your missiles and destroy your enemies before your enemies get to you.
Devices used:
- SD Card
- Class D Amplifier
- uLCD
- Haptic Feedback Motor
- 2N3904 NPN BJT (including 1Kohm resistor)
- Potentiometer
Pin connections made
mbed | Device |
---|---|
p18 | Class D + In |
p27 | uLCD RX |
p29 | uLCD Reset |
p28 | uLCD TX |
p6 | SD DO |
p7 | SD SCK |
p8 | SD CS |
p6 | SD DO |
p5 | SD DI |
p16 | Nav U |
p15 | Nav C |
p14 | Nav L |
p13 | Nav D |
p12 | Nav R |
p21 | Transistor Base in series with 1Kohm |
Class D Amp | Device |
---|---|
Out + | Speaker + |
Out- | Speaker - |
Pwr - | Gnd |
Pwr+ | VCC |
Vol(3) | Potentiometer |
Haptic Feedback | Connection |
---|---|
Red wire | VCC |
Blue wire | BJT Collector |
Gnd | BJT Emitter |
Import programGalaga
Mbed Galaga Game
Program Code
Mbed Galaga
#include "mbed.h" #include "uLCD_4DGL.h" #include "wave_player.h" #include "SDFileSystem.h" //#include "enemies.h" #include <vector> #include "rtos.h" uLCD_4DGL uLCD(p28,p27,p29); AnalogOut DACout(p18); DigitalOut vib(p21); wave_player waver(&DACout); SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sck, cs BusOut mbedleds(LED1,LED2,LED3,LED4); //BusOut/In is faster than multiple DigitalOut/Ins int playLaser = 0;int playEnemyExplode = 0;int playerExplode = 0;//variables to trigger the speaker to play sounds void sdcard_thread(void const *argument)//thread to play the sounds { while(1) { if(playLaser){//play sound if player fires FILE *wave_file; wave_file=fopen("/sd/laser.wav","r"); waver.play(wave_file); fclose(wave_file); playLaser = 0; } if(playerExplode) { //play sound if player dies FILE *wave_file; wave_file=fopen("/sd/Bomb.wav","r"); waver.play(wave_file); fclose(wave_file); playerExplode = 0; } if(playEnemyExplode){//play sound if enemies get hit FILE *wave_file; wave_file=fopen("/sd/Bombnew.wav","r"); waver.play(wave_file); fclose(wave_file); playEnemyExplode = 0; } Thread::wait(50); } } class Nav_Switch { public: Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire); int read(); //boolean functions to test each switch bool up(); bool down(); bool left(); bool right(); bool fire(); //automatic read on RHS operator int (); //index to any switch array style bool operator[](int index) { return _pins[index]; }; private: BusIn _pins; }; Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire): _pins(up, down, left, right, fire) { _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise wait(0.001); //delays just a bit for pullups to pull inputs high } inline bool Nav_Switch::up() { return !(_pins[0]); } inline bool Nav_Switch::down() { return !(_pins[1]); } inline bool Nav_Switch::left() { return !(_pins[2]); } inline bool Nav_Switch::right() { return !(_pins[3]); } inline bool Nav_Switch::fire() { return !(_pins[4]); } inline int Nav_Switch::read() { return _pins.read(); } inline Nav_Switch::operator int () { return _pins.read(); } // Declar player dimensions int playerWidth = 7; int playerHeight = 3; int playerDelta = 3; int playerXpos = 64; int playerYpos = 113; #define maxNumPlayerMissiles 5 #define numEnemies 10 //struct for missiles typedef struct { int x; ///< The x-coordinate of missile current position int y; ///< The y-coordinate of missile current position int status; ///< The missile status, see MISSILE_STATUS } playerMissile; // infomration about missile position and status //struct for enemies typedef struct { int x; int y; int size; int status; } enemy; enemy enemies[numEnemies];//create a struct array of enemies // initialize the player's position, missile status, draw player, void player_draw(int x, int y, int playerColor) { uLCD.filled_rectangle(x, y, x+playerWidth, y+playerHeight, playerColor); uLCD.filled_rectangle(x+playerDelta, y-playerDelta, x+playerWidth-playerDelta, y+playerHeight, playerColor); } playerMissile playerMissiles[maxNumPlayerMissiles]; //struct array of player missiles //function to fire a missile void player_fire(void){ playerMissile PM; PM.x = playerXpos + (playerWidth/2); PM.y = playerYpos-playerDelta; PM.status = 1; for(int i=0;i<maxNumPlayerMissiles;i++){ if(playerMissiles[i].status==0){ playerMissiles[i]=PM; break; } } } //function to update all parts of the game void updateGame(){ for(int i=0;i<maxNumPlayerMissiles;i++){ // update all missiles if(playerMissiles[i].status == 1){ uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0x0); playerMissiles[i].y-=5; uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0xFF0000); } if(playerMissiles[i].y==0 || playerMissiles[i].status==0){ uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0x0); playerMissiles[i].status = 0; } //update all enemies for(int j=0;j<numEnemies;j++){ if(playerMissiles[i].status==1 && enemies[j].status==1 && playerMissiles[i].x>enemies[j].x && playerMissiles[i].x<enemies[j].x+enemies[j].size && playerMissiles[i].y>enemies[j].y && playerMissiles[i].y<enemies[j].y+enemies[j].size){ enemies[j].status = 0; playerMissiles[i].status = 0; playEnemyExplode=1; uLCD.filled_rectangle(enemies[j].x,enemies[j].y,enemies[j].x+enemies[j].size,enemies[j].y+enemies[j].size,0x0); } } } } //function to set initial position of enemies void enemies_init(void){ enemies[0].x = 1;enemies[0].y = 1;enemies[0].size = 8; enemies[1].x = 26;enemies[1].y = 1;enemies[1].size = 8; enemies[2].x = 51;enemies[2].y = 1;enemies[2].size = 8; enemies[3].x = 76;enemies[3].y = 1;enemies[3].size = 8; enemies[4].x = 101;enemies[4].y = 1;enemies[4].size = 8; enemies[5].x = 1;enemies[5].y = 20;enemies[5].size = 8; enemies[6].x = 26;enemies[6].y = 20;enemies[6].size = 8; enemies[7].x = 51;enemies[7].y = 20;enemies[7].size = 8; enemies[8].x = 76;enemies[8].y = 20;enemies[8].size = 8; enemies[9].x = 101;enemies[9].y = 20;enemies[9].size = 8; } Nav_Switch myNav( p15, p12, p13, p11, p14); //pin order on Sparkfun breakout int main() { Thread thread1(sdcard_thread); int ctr = 0;int distance=5;int vertical = 1;int win = 1;int numDeadEnemies=0; //initialize enemy statuses enemies[0].status = 1;enemies[1].status = 1;enemies[2].status = 1;enemies[3].status = 1;enemies[4].status = 1; enemies[5].status = 1;enemies[6].status = 1;enemies[7].status = 1;enemies[8].status = 1;enemies[9].status = 1; enemies_init(); //draw enemies for(int i=0;i<numEnemies;i++){ uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x00FF00); } int i; while(1) { //with pullups a button hit is a "0" - "~" inverts data to leds if(ctr%10==0){ for(i=0;i<numEnemies;i++){ if(enemies[i].status!=0){ //update enemy positions uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x0); if(vertical<0){enemies[i].x+=distance;}else{enemies[i].y+=5;} uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x00FF00); } } if(vertical<0){distance*=-1;}vertical*=-1; } mbedleds = ~(myNav & 0x0F); //update leds with nav switch direction inputs if(myNav.fire()){//fire missile vib = 1; Thread::wait(100); vib=0; playLaser = 1; player_fire(); mbedleds = 0x0F; //special all leds on case for fire (center button) } //or use - if(myNav[4]==0) mbedleds = 0x0F; //can index a switch bit like this if(myNav.right() && playerXpos <= 110){//player moves right player_draw(playerXpos,playerYpos,0x0); playerXpos+=5; } if(myNav.left() && playerXpos >= 0){//player moves left player_draw(playerXpos,playerYpos,0x0); playerXpos-=5; } player_draw(playerXpos,playerYpos,0xFFFF00);//draw the player updateGame(); //check if player has been hit for(i=0;i<numEnemies;i++){ if(enemies[i].status==1 && playerXpos>enemies[i].x && playerXpos<enemies[i].x+enemies[i].size && playerYpos>enemies[i].y && playerYpos<enemies[i].y+enemies[i].size){ player_draw(playerXpos,playerYpos,0x0);win=0;playerExplode=1;vib=1; } if(enemies[i].status==0)numDeadEnemies++; if(enemies[i].y>128)enemies[i].y=1; } // check for end game conditions if(numDeadEnemies==numEnemies){Thread::wait(1000);break;} if(!win){Thread::wait(1000);vib=0;playerExplode=0;break;} numDeadEnemies = 0; ctr++; Thread::wait(10); } uLCD.locate(5,5); if(win){ uLCD.printf("You Win!!"); }else{ uLCD.printf("GAME OVER"); } }
Breadboard Overview
YouTube Link
Please log in to post comments.