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:
Fri Jun 07 20:29:59 2013 +0000
Revision:
3:a6a0cd726ca0
Parent:
2:bb0f631a6068
Child:
4:673eb9735d44
Abandoned writing serial EEPROM class and used Ser25LCxxx library instead. HighScoreTable class appears to be reading and writing correctly to EEPROM and high scores are displayed correctly.

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