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:
Thu Jun 06 20:11:28 2013 +0000
Revision:
2:bb0f631a6068
Parent:
1:dfd5eaaf96a3
Child:
3:a6a0cd726ca0
More code brought in from Maple version. Now uses fancy character set and displays Robotric logo. Started re-writing I2C EEPROM code as SPI EEPROM code since now using an SPI EEPROM but not finished yet.

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