Version of Robotron arcade game using LPC1768, a Gameduino shield, a serial EEPROM (for high scores), two microswitch joysticks and two buttons plus a box to put it in. 20 levels of mayhem.
Dependencies: 25LCxxx_SPI CommonTypes Gameduino mbed
GameRobotRic.cpp@6:8bbdb70bc11c, 2013-06-08 (annotated)
- Committer:
- RichardE
- Date:
- Sat Jun 08 15:50:38 2013 +0000
- Revision:
- 6:8bbdb70bc11c
- Parent:
- 5:0b0651ac7832
- Child:
- 9:fa7e7b37b632
Player can now fire bullets and they move. Mayhem!
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RichardE | 0:5fa232ee5fdf | 1 | /* |
RichardE | 0:5fa232ee5fdf | 2 | * SOURCE FILE : GameRobotRic.cpp |
RichardE | 0:5fa232ee5fdf | 3 | * |
RichardE | 0:5fa232ee5fdf | 4 | * The RobotRic game class. |
RichardE | 0:5fa232ee5fdf | 5 | * |
RichardE | 0:5fa232ee5fdf | 6 | */ |
RichardE | 0:5fa232ee5fdf | 7 | |
RichardE | 0:5fa232ee5fdf | 8 | #include "GameRobotRic.h" // this module's prototypes |
RichardE | 0:5fa232ee5fdf | 9 | #include "Types.h" // various integer types etc. |
RichardE | 0:5fa232ee5fdf | 10 | #include "LevelCollection.h" // all the levels |
RichardE | 2:bb0f631a6068 | 11 | #include "sprite.h" // sprite data |
RichardE | 2:bb0f631a6068 | 12 | #include "RobotRicCharacterSet.h" // character set used in this game |
RichardE | 4:673eb9735d44 | 13 | #include "HighScoreEntry.h" // for getting player's name for high score table |
RichardE | 4:673eb9735d44 | 14 | #include "GDExtra.h" // extra Gameduino functions |
RichardE | 4:673eb9735d44 | 15 | #include "GDConst.h" // a few more Gameduino constants |
RichardE | 4:673eb9735d44 | 16 | #include "ArenaConst.h" // gameplay arena constants |
RichardE | 0:5fa232ee5fdf | 17 | |
RichardE | 3:a6a0cd726ca0 | 18 | // Define following for debugging messages to serial port. |
RichardE | 3:a6a0cd726ca0 | 19 | #define CHATTY |
RichardE | 3:a6a0cd726ca0 | 20 | |
RichardE | 0:5fa232ee5fdf | 21 | // Number of lives player starts with. |
RichardE | 0:5fa232ee5fdf | 22 | #define START_LIVES 5 |
RichardE | 0:5fa232ee5fdf | 23 | |
RichardE | 3:a6a0cd726ca0 | 24 | // Serial link to PC over USB cable. Globally accessible. |
RichardE | 3:a6a0cd726ca0 | 25 | Serial pc( USBTX, USBRX ); |
RichardE | 3:a6a0cd726ca0 | 26 | |
RichardE | 0:5fa232ee5fdf | 27 | /**************************/ |
RichardE | 0:5fa232ee5fdf | 28 | /* CHECK FOR A HIGH SCORE */ |
RichardE | 0:5fa232ee5fdf | 29 | /**************************/ |
RichardE | 4:673eb9735d44 | 30 | // Pass pointer to a Gameduino to display on in gd. |
RichardE | 0:5fa232ee5fdf | 31 | // Pass pointer to high score table in highScores. |
RichardE | 0:5fa232ee5fdf | 32 | // Pass score that was achieved in score. |
RichardE | 4:673eb9735d44 | 33 | void GameRobotRic::CheckForHighScore( Gameduino *gd, HighScoreTable *highScores, UInt32 score ) { |
RichardE | 0:5fa232ee5fdf | 34 | UInt8 tablePos; |
RichardE | 0:5fa232ee5fdf | 35 | // Enter name into high score table if score is high enough. |
RichardE | 0:5fa232ee5fdf | 36 | if( ( tablePos = highScores->GetPositionInTable( player.Score ) ) < highScores->GetCapacity() ) { |
RichardE | 0:5fa232ee5fdf | 37 | // Player has made it onto the high score table. |
RichardE | 0:5fa232ee5fdf | 38 | // Get player to input name. |
RichardE | 0:5fa232ee5fdf | 39 | HighScoreEntry nameGetter; |
RichardE | 0:5fa232ee5fdf | 40 | PlayerName name; |
RichardE | 4:673eb9735d44 | 41 | nameGetter.GetName( &name, &controls, gd ); |
RichardE | 0:5fa232ee5fdf | 42 | // Add name and score to table. |
RichardE | 0:5fa232ee5fdf | 43 | highScores->Add( tablePos, &name, score ); |
RichardE | 0:5fa232ee5fdf | 44 | } |
RichardE | 0:5fa232ee5fdf | 45 | } |
RichardE | 0:5fa232ee5fdf | 46 | |
RichardE | 0:5fa232ee5fdf | 47 | /*****************/ |
RichardE | 0:5fa232ee5fdf | 48 | /* PLAY THE GAME */ |
RichardE | 0:5fa232ee5fdf | 49 | /*****************/ |
RichardE | 0:5fa232ee5fdf | 50 | // This NEVER exits. |
RichardE | 0:5fa232ee5fdf | 51 | void GameRobotRic::Play( void ) { |
RichardE | 6:8bbdb70bc11c | 52 | // Change baud rate on PC serial link. |
RichardE | 6:8bbdb70bc11c | 53 | pc.baud( 115200 ); |
RichardE | 6:8bbdb70bc11c | 54 | #ifdef CHATTY |
RichardE | 6:8bbdb70bc11c | 55 | pc.puts( "Program has restarted!\r\n" ); |
RichardE | 6:8bbdb70bc11c | 56 | #endif |
RichardE | 2:bb0f631a6068 | 57 | // Make a digital output for use as the Gameduino chip select pin. Deselect it. |
RichardE | 2:bb0f631a6068 | 58 | DigitalOut gameduinoCS( p8 ); |
RichardE | 2:bb0f631a6068 | 59 | gameduinoCS = 1; |
RichardE | 2:bb0f631a6068 | 60 | // Initialise an SPI link for communications with Gameduino and the serial EEPROM. |
RichardE | 2:bb0f631a6068 | 61 | // This is different from how the Maple version of RobotRic did it. It used an |
RichardE | 2:bb0f631a6068 | 62 | // I2C EEPROM. |
RichardE | 0:5fa232ee5fdf | 63 | // Use pin 5 for MOSI. |
RichardE | 0:5fa232ee5fdf | 64 | // Use pin 6 for MISO. |
RichardE | 0:5fa232ee5fdf | 65 | // Use pin 7 for SCK. |
RichardE | 0:5fa232ee5fdf | 66 | SPI spi( p5, p6, p7 ); |
RichardE | 0:5fa232ee5fdf | 67 | // 8MHz clock should be OK. |
RichardE | 0:5fa232ee5fdf | 68 | spi.frequency( 8000000 ); |
RichardE | 0:5fa232ee5fdf | 69 | // Set SPI format to use. |
RichardE | 0:5fa232ee5fdf | 70 | // Use 8 bits per SPI frame. |
RichardE | 3:a6a0cd726ca0 | 71 | // Use SPI mode 0. Clock normally low. Data captured on rising edge. |
RichardE | 0:5fa232ee5fdf | 72 | spi.format( 8, 0 ); |
RichardE | 0:5fa232ee5fdf | 73 | // Make a Gameduino and pass SPI link and digital output for chip select. |
RichardE | 2:bb0f631a6068 | 74 | Gameduino gd( &spi, &gameduinoCS ); |
RichardE | 0:5fa232ee5fdf | 75 | // Reset the Gameduino. |
RichardE | 0:5fa232ee5fdf | 76 | gd.begin(); |
RichardE | 2:bb0f631a6068 | 77 | gd.copy( Gameduino::RAM_SPRIMG, sprite_sprimg, sizeof( sprite_sprimg ) ); |
RichardE | 2:bb0f631a6068 | 78 | // Copy sprite palette data into Gameduino memory. |
RichardE | 2:bb0f631a6068 | 79 | gd.copy( Gameduino::RAM_SPRPAL, sprite_sprpal, sizeof( sprite_sprpal ) ); |
RichardE | 2:bb0f631a6068 | 80 | // Initialise character set pixel data RAM. |
RichardE | 2:bb0f631a6068 | 81 | gd.copy( Gameduino::RAM_CHR, RobotRicCharacterSet::PixelData, ( LAST_CHAR_IN_CHARACTER_SET + 1 ) << 4 ); |
RichardE | 2:bb0f631a6068 | 82 | // Initialise character set pixel palette RAM. |
RichardE | 2:bb0f631a6068 | 83 | gd.copy( Gameduino::RAM_PAL, RobotRicCharacterSet::PaletteData, ( LAST_CHAR_IN_CHARACTER_SET + 1 ) << 3 ); |
RichardE | 2:bb0f631a6068 | 84 | // Turn off JK collision detection. Every sprite collides with every other. |
RichardE | 2:bb0f631a6068 | 85 | // Did it this way because I could not resolve some problems with wandering humans. |
RichardE | 2:bb0f631a6068 | 86 | // Suppose JK collision detection were used. The player sprite is of type J and humans |
RichardE | 2:bb0f631a6068 | 87 | // are of type K so collisions between them will register allowing humans to be rescued. |
RichardE | 2:bb0f631a6068 | 88 | // However, I also need some enemies (Crushers for example) to be able to collide with |
RichardE | 2:bb0f631a6068 | 89 | // humans so they would need to be J type to collide with humans. But then player and |
RichardE | 2:bb0f631a6068 | 90 | // enemies are both J type and so collisions between players and enemies are not detected. |
RichardE | 2:bb0f631a6068 | 91 | gd.wr( Gameduino::JK_MODE, 0 ); |
RichardE | 2:bb0f631a6068 | 92 | // Initialise serial EEPROM object which is on same SPI bus as the Gameduino. |
RichardE | 3:a6a0cd726ca0 | 93 | Ser25LCxxx eeprom( &spi, p14, 32768, 64 ); |
RichardE | 0:5fa232ee5fdf | 94 | // Create a high score table that uses the EEPROM. |
RichardE | 0:5fa232ee5fdf | 95 | HighScoreTable highScores( &eeprom ); |
RichardE | 2:bb0f631a6068 | 96 | // Start on the attract level. |
RichardE | 2:bb0f631a6068 | 97 | UInt8 levelNumber = LevelCollection::AttractLevel; |
RichardE | 4:673eb9735d44 | 98 | player.Lives = START_LIVES; |
RichardE | 4:673eb9735d44 | 99 | LevelCollection levels; |
RichardE | 4:673eb9735d44 | 100 | Level *level; |
RichardE | 4:673eb9735d44 | 101 | Level::LevelExitCode exitCode; |
RichardE | 4:673eb9735d44 | 102 | // Initialise panel controls. |
RichardE | 4:673eb9735d44 | 103 | controls.InitialisePins(); |
RichardE | 4:673eb9735d44 | 104 | // Specify controls player should use. |
RichardE | 4:673eb9735d44 | 105 | player.SetControls( &controls ); |
RichardE | 4:673eb9735d44 | 106 | // Restrict players movement. |
RichardE | 4:673eb9735d44 | 107 | player.MovementRestricted = true; |
RichardE | 4:673eb9735d44 | 108 | player.Bounds = &ArenaRectangle; |
RichardE | 4:673eb9735d44 | 109 | // Repeat forever. |
RichardE | 4:673eb9735d44 | 110 | while( true ) { |
RichardE | 4:673eb9735d44 | 111 | // Get level specified by level number. |
RichardE | 4:673eb9735d44 | 112 | level = levels.GetLevel( levelNumber ); |
RichardE | 4:673eb9735d44 | 113 | // If failed to get level with that number go back to first normal level. |
RichardE | 4:673eb9735d44 | 114 | // This will happen if player completes last level. |
RichardE | 4:673eb9735d44 | 115 | if( level == NULL ) { |
RichardE | 4:673eb9735d44 | 116 | levelNumber = LevelCollection::FirstNormalLevel; |
RichardE | 4:673eb9735d44 | 117 | // Refetch level. |
RichardE | 4:673eb9735d44 | 118 | level = levels.GetLevel( levelNumber ); |
RichardE | 4:673eb9735d44 | 119 | } |
RichardE | 4:673eb9735d44 | 120 | // Pass reference to high score table. |
RichardE | 4:673eb9735d44 | 121 | level->SetHighScores( &highScores ); |
RichardE | 4:673eb9735d44 | 122 | // Set player that is playing the level. |
RichardE | 4:673eb9735d44 | 123 | level->SetPlayer( &player ); |
RichardE | 4:673eb9735d44 | 124 | // Set Gameduino to use. |
RichardE | 4:673eb9735d44 | 125 | level->SetGameduino( &gd ); |
RichardE | 4:673eb9735d44 | 126 | // Play the level. |
RichardE | 4:673eb9735d44 | 127 | exitCode = level->Play(); |
RichardE | 4:673eb9735d44 | 128 | // If player was killed then decrement lives otherwise |
RichardE | 4:673eb9735d44 | 129 | // advance to next level. |
RichardE | 4:673eb9735d44 | 130 | switch( exitCode ) { |
RichardE | 4:673eb9735d44 | 131 | case Level::GameOver : |
RichardE | 4:673eb9735d44 | 132 | // TODO : Do some sort of game over fuss. |
RichardE | 4:673eb9735d44 | 133 | CheckForHighScore( &gd, &highScores, player.Score ); |
RichardE | 4:673eb9735d44 | 134 | // Go back to attract level and reset player lives and score. |
RichardE | 4:673eb9735d44 | 135 | levelNumber = LevelCollection::AttractLevel; |
RichardE | 4:673eb9735d44 | 136 | player.Lives = START_LIVES; |
RichardE | 4:673eb9735d44 | 137 | player.Score = 0; |
RichardE | 4:673eb9735d44 | 138 | break; |
RichardE | 4:673eb9735d44 | 139 | case Level::Completed : |
RichardE | 4:673eb9735d44 | 140 | levelNumber++; |
RichardE | 4:673eb9735d44 | 141 | break; |
RichardE | 4:673eb9735d44 | 142 | } |
RichardE | 0:5fa232ee5fdf | 143 | } |
RichardE | 0:5fa232ee5fdf | 144 | } |
RichardE | 0:5fa232ee5fdf | 145 | |
RichardE | 4:673eb9735d44 | 146 | |
RichardE | 4:673eb9735d44 | 147 |