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:
Sat Jun 08 14:40:47 2013 +0000
Revision:
5:0b0651ac7832
Parent:
4:673eb9735d44
Child:
6:8bbdb70bc11c
Now got first real level starting and player can be controlled using joysticks. No bullets, enemies, humans or sound 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 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 4:673eb9735d44 52 #ifdef CHATTY
RichardE 4:673eb9735d44 53 pc.puts( "Program has restarted!\r\n" );
RichardE 4:673eb9735d44 54 #endif
RichardE 2:bb0f631a6068 55 // Make a digital output for use as the Gameduino chip select pin. Deselect it.
RichardE 2:bb0f631a6068 56 DigitalOut gameduinoCS( p8 );
RichardE 2:bb0f631a6068 57 gameduinoCS = 1;
RichardE 2:bb0f631a6068 58 // Initialise an SPI link for communications with Gameduino and the serial EEPROM.
RichardE 2:bb0f631a6068 59 // This is different from how the Maple version of RobotRic did it. It used an
RichardE 2:bb0f631a6068 60 // I2C EEPROM.
RichardE 0:5fa232ee5fdf 61 // Use pin 5 for MOSI.
RichardE 0:5fa232ee5fdf 62 // Use pin 6 for MISO.
RichardE 0:5fa232ee5fdf 63 // Use pin 7 for SCK.
RichardE 0:5fa232ee5fdf 64 SPI spi( p5, p6, p7 );
RichardE 0:5fa232ee5fdf 65 // 8MHz clock should be OK.
RichardE 0:5fa232ee5fdf 66 spi.frequency( 8000000 );
RichardE 0:5fa232ee5fdf 67 // Set SPI format to use.
RichardE 0:5fa232ee5fdf 68 // Use 8 bits per SPI frame.
RichardE 3:a6a0cd726ca0 69 // Use SPI mode 0. Clock normally low. Data captured on rising edge.
RichardE 0:5fa232ee5fdf 70 spi.format( 8, 0 );
RichardE 0:5fa232ee5fdf 71 // Make a Gameduino and pass SPI link and digital output for chip select.
RichardE 2:bb0f631a6068 72 Gameduino gd( &spi, &gameduinoCS );
RichardE 0:5fa232ee5fdf 73 // Reset the Gameduino.
RichardE 0:5fa232ee5fdf 74 gd.begin();
RichardE 2:bb0f631a6068 75 gd.copy( Gameduino::RAM_SPRIMG, sprite_sprimg, sizeof( sprite_sprimg ) );
RichardE 2:bb0f631a6068 76 // Copy sprite palette data into Gameduino memory.
RichardE 2:bb0f631a6068 77 gd.copy( Gameduino::RAM_SPRPAL, sprite_sprpal, sizeof( sprite_sprpal ) );
RichardE 2:bb0f631a6068 78 // Initialise character set pixel data RAM.
RichardE 2:bb0f631a6068 79 gd.copy( Gameduino::RAM_CHR, RobotRicCharacterSet::PixelData, ( LAST_CHAR_IN_CHARACTER_SET + 1 ) << 4 );
RichardE 2:bb0f631a6068 80 // Initialise character set pixel palette RAM.
RichardE 2:bb0f631a6068 81 gd.copy( Gameduino::RAM_PAL, RobotRicCharacterSet::PaletteData, ( LAST_CHAR_IN_CHARACTER_SET + 1 ) << 3 );
RichardE 2:bb0f631a6068 82 // Turn off JK collision detection. Every sprite collides with every other.
RichardE 2:bb0f631a6068 83 // Did it this way because I could not resolve some problems with wandering humans.
RichardE 2:bb0f631a6068 84 // Suppose JK collision detection were used. The player sprite is of type J and humans
RichardE 2:bb0f631a6068 85 // are of type K so collisions between them will register allowing humans to be rescued.
RichardE 2:bb0f631a6068 86 // However, I also need some enemies (Crushers for example) to be able to collide with
RichardE 2:bb0f631a6068 87 // humans so they would need to be J type to collide with humans. But then player and
RichardE 2:bb0f631a6068 88 // enemies are both J type and so collisions between players and enemies are not detected.
RichardE 2:bb0f631a6068 89 gd.wr( Gameduino::JK_MODE, 0 );
RichardE 2:bb0f631a6068 90 // Initialise serial EEPROM object which is on same SPI bus as the Gameduino.
RichardE 3:a6a0cd726ca0 91 Ser25LCxxx eeprom( &spi, p14, 32768, 64 );
RichardE 0:5fa232ee5fdf 92 // Create a high score table that uses the EEPROM.
RichardE 0:5fa232ee5fdf 93 HighScoreTable highScores( &eeprom );
RichardE 2:bb0f631a6068 94 // Start on the attract level.
RichardE 2:bb0f631a6068 95 UInt8 levelNumber = LevelCollection::AttractLevel;
RichardE 4:673eb9735d44 96 player.Lives = START_LIVES;
RichardE 4:673eb9735d44 97 LevelCollection levels;
RichardE 4:673eb9735d44 98 Level *level;
RichardE 4:673eb9735d44 99 Level::LevelExitCode exitCode;
RichardE 4:673eb9735d44 100 // Initialise panel controls.
RichardE 4:673eb9735d44 101 controls.InitialisePins();
RichardE 4:673eb9735d44 102 // Specify controls player should use.
RichardE 4:673eb9735d44 103 player.SetControls( &controls );
RichardE 4:673eb9735d44 104 // Restrict players movement.
RichardE 4:673eb9735d44 105 player.MovementRestricted = true;
RichardE 4:673eb9735d44 106 player.Bounds = &ArenaRectangle;
RichardE 4:673eb9735d44 107 // Repeat forever.
RichardE 4:673eb9735d44 108 while( true ) {
RichardE 4:673eb9735d44 109 // Get level specified by level number.
RichardE 4:673eb9735d44 110 level = levels.GetLevel( levelNumber );
RichardE 4:673eb9735d44 111 // If failed to get level with that number go back to first normal level.
RichardE 4:673eb9735d44 112 // This will happen if player completes last level.
RichardE 4:673eb9735d44 113 if( level == NULL ) {
RichardE 4:673eb9735d44 114 levelNumber = LevelCollection::FirstNormalLevel;
RichardE 4:673eb9735d44 115 // Refetch level.
RichardE 4:673eb9735d44 116 level = levels.GetLevel( levelNumber );
RichardE 4:673eb9735d44 117 }
RichardE 4:673eb9735d44 118 // Pass reference to high score table.
RichardE 4:673eb9735d44 119 level->SetHighScores( &highScores );
RichardE 4:673eb9735d44 120 // Set player that is playing the level.
RichardE 4:673eb9735d44 121 level->SetPlayer( &player );
RichardE 4:673eb9735d44 122 // Set Gameduino to use.
RichardE 4:673eb9735d44 123 level->SetGameduino( &gd );
RichardE 4:673eb9735d44 124 // Play the level.
RichardE 4:673eb9735d44 125 exitCode = level->Play();
RichardE 4:673eb9735d44 126 // If player was killed then decrement lives otherwise
RichardE 4:673eb9735d44 127 // advance to next level.
RichardE 4:673eb9735d44 128 switch( exitCode ) {
RichardE 4:673eb9735d44 129 case Level::GameOver :
RichardE 4:673eb9735d44 130 // TODO : Do some sort of game over fuss.
RichardE 4:673eb9735d44 131 CheckForHighScore( &gd, &highScores, player.Score );
RichardE 4:673eb9735d44 132 // Go back to attract level and reset player lives and score.
RichardE 4:673eb9735d44 133 levelNumber = LevelCollection::AttractLevel;
RichardE 4:673eb9735d44 134 player.Lives = START_LIVES;
RichardE 4:673eb9735d44 135 player.Score = 0;
RichardE 4:673eb9735d44 136 break;
RichardE 4:673eb9735d44 137 case Level::Completed :
RichardE 4:673eb9735d44 138 levelNumber++;
RichardE 4:673eb9735d44 139 break;
RichardE 4:673eb9735d44 140 }
RichardE 0:5fa232ee5fdf 141 }
RichardE 0:5fa232ee5fdf 142 }
RichardE 0:5fa232ee5fdf 143
RichardE 4:673eb9735d44 144
RichardE 4:673eb9735d44 145