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

Committer:
RichardE
Date:
Mon Jun 17 15:10:43 2013 +0000
Revision:
18:70190f956a24
Parent:
17:194789db2215
Improved response to button 1 when entering high scores (HighScoreEntry.cpp).

Who changed what in which revision?

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