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

Files at this revision

API Documentation at this revision

Comitter:
RichardE
Date:
Sat Jun 08 14:40:47 2013 +0000
Parent:
4:673eb9735d44
Child:
6:8bbdb70bc11c
Commit message:
Now got first real level starting and player can be controlled using joysticks. No bullets, enemies, humans or sound yet.

Changed in this revision

BulletManager.cpp Show annotated file Show diff for this revision Revisions of this file
BulletManager.h Show annotated file Show diff for this revision Revisions of this file
BulletObject.h Show annotated file Show diff for this revision Revisions of this file
GDConst.h Show annotated file Show diff for this revision Revisions of this file
GameObject.cpp Show annotated file Show diff for this revision Revisions of this file
GameObject.h Show annotated file Show diff for this revision Revisions of this file
GameRobotRic.cpp Show annotated file Show diff for this revision Revisions of this file
Level0.cpp Show annotated file Show diff for this revision Revisions of this file
Level1.cpp Show annotated file Show diff for this revision Revisions of this file
LevelData.cpp Show annotated file Show diff for this revision Revisions of this file
LevelData.h Show annotated file Show diff for this revision Revisions of this file
LevelNormal.cpp Show annotated file Show diff for this revision Revisions of this file
LevelNormal.h Show annotated file Show diff for this revision Revisions of this file
PlayerObject.cpp Show annotated file Show diff for this revision Revisions of this file
PlayerObject.h Show annotated file Show diff for this revision Revisions of this file
SpriteNumber.h Show annotated file Show diff for this revision Revisions of this file
--- a/BulletManager.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/BulletManager.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -6,8 +6,8 @@
  */
 
 #include "BulletManager.h"
-// #include "BulletObject.h"
-// #include "ArenaConst.h"
+#include "BulletObject.h"
+#include "ArenaConst.h"
 #include "GDExtra.h"
 
 /***************/
@@ -16,7 +16,6 @@
 // Pass number of sprite to use for first bullet.
 // MaxBullets consequtive sprites will be used for bullets.
 BulletManager::BulletManager( UInt8 firstSpriteNumber ) {
-#if 0
   // Initialise aspects of bullets that never change.
   BulletObject *bullet;
   for( UInt8 b = 0; b < MaxBullets; ++b ) {
@@ -25,8 +24,9 @@
     bullet->PixelWidth = 6;
     bullet->PixelHeight = 6;
     bullet->Bounds = &ArenaRectangle;
+    // Make sure entry in bulletPointers array is NULL.
+    bulletPointers[ b ] = (GameObject*)NULL;
   }
-#endif
 }
 
 /**********************/
@@ -36,7 +36,6 @@
 // Pass bullet velocities in hv and vv (NOT pixel velocities).
 // Returns true if bullet was started successfully.
 bool BulletManager::StartBullet( Int16 x, Int16 y, Int16 hv, Int16 vv ) {
-#if 0
   // Try and find an unused bullet slot.
   UInt8 index;
   if( GameObject::FindUnusedObject( bulletPointers, MaxBullets, &index ) ) {
@@ -50,32 +49,28 @@
     // No free bullet slots.
     return false;
   }
-#else
-return false;
-#endif
 }
 
 /************************/
 /* KILL A SINGLE BULLET */
 /************************/
+// Pass pointer to Gameduino that displays bullets in gd.
 // Pass index of bullet in b.
-void BulletManager::KillBullet( UInt8 b ) {
-#if 0
+void BulletManager::KillBullet( Gameduino *gd, UInt8 b ) {
     GameObject *bullet = bulletPointers[ b ];
     if( bullet != (GameObject*)NULL ) {
       bulletPointers[ b ] = (BulletObject*)NULL;
       // Hide bullet sprite by setting y coordinate to 400.
-      GDExtra::HideSprite( bullet->SpriteNumber );
+      GDExtra::HideSprite( gd, bullet->SpriteNumber );
     }
-#endif
 }
 
 /********************/
 /* KILL ALL BULLETS */
 /********************/
-void BulletManager::KillAllBullets( void ) {
+// Pass pointer to Gameduino that displays bullets in gd.
+void BulletManager::KillAllBullets( Gameduino *gd ) {
   for( UInt8 b = 0; b < MaxBullets; ++b ) {
-    KillBullet( b );
+    KillBullet( gd, b );
   }
 }
-
--- a/BulletManager.h	Sat Jun 08 11:24:05 2013 +0000
+++ b/BulletManager.h	Sat Jun 08 14:40:47 2013 +0000
@@ -11,6 +11,7 @@
   
   #include "Types.h"
   #include "BulletObject.h"
+  #include "Gameduino.h"
   
   class BulletManager {
   
@@ -38,13 +39,15 @@
     /************************/
     /* KILL A SINGLE BULLET */
     /************************/
+    // Pass pointer to Gameduino that displays bullets in gd.
     // Pass index of bullet in b.
-    void KillBullet( UInt8 b );
+    void KillBullet( Gameduino *gd, UInt8 b );
 
     /********************/
     /* KILL ALL BULLETS */
     /********************/
-    void KillAllBullets( void );
+    // Pass pointer to Gameduino that displays bullets in gd.
+    void KillAllBullets( Gameduino *gd );
     
     /************************************************/
     /* GET ARRAY CONTAINING POINTERS TO ALL BULLETS */
--- a/BulletObject.h	Sat Jun 08 11:24:05 2013 +0000
+++ b/BulletObject.h	Sat Jun 08 14:40:47 2013 +0000
@@ -64,10 +64,11 @@
     /************************/
     /* DRAW THE GAME OBJECT */
     /************************/
+    // Pass pointer to Gameduino to draw on in gd.
     // This is only called after it has been established that the
     // game object is visible.
-    virtual void Draw( void ) {
-      // GD.sprite( SpriteNumber, ToPixel( Xco ), ToPixel( Yco ), imageNumber, 0, 0, spriteGroup );
+    virtual void Draw( Gameduino *gd ) {
+      gd->sprite( SpriteNumber, ToPixel( Xco ), ToPixel( Yco ), imageNumber, 0, Gameduino::None, spriteGroup );
     }
    
   private :
--- a/GDConst.h	Sat Jun 08 11:24:05 2013 +0000
+++ b/GDConst.h	Sat Jun 08 14:40:47 2013 +0000
@@ -1,41 +1,30 @@
-/*
- * SOURCE FILE : GDConst.h
- *
- * A few more constants associated with the Gameduino hardware.
- *
- */
-
-#ifndef GDConstIncluded
-  
-  #define GDConstIncluded
-
-  #define RAM_PIC_SIZE 4096        // size of screen picture RAM
-  #define RAM_CHR_SIZE 4096        // size of character set pixel data RAM
-  #define RAM_PAL_SIZE 2048        // size of character set palette data RAM
-
-  #define SCREEN_CHAR_WIDTH 64     // character width of screen (entire screen, not just visible bit)
-  #define SCREEN_CHAR_HEIGHT 64    // character height of screen (entire screen, not just visible bit)
-  
-  #define VISIBLE_CHAR_WIDTH 50    // character width of visible screen
-  #define VISIBLE_CHAR_HEIGHT 37   // character height of visible screen (actually 37.5)
-
-  #define SPRITE_PIXEL_WIDTH 16
-  #define SPRITE_PIXEL_HEIGHT 16
-
-  #define SPRITE_COUNT 256
-  
-  enum SpriteTransform {
-    STNormal = 0,
-    STRotate90FlipY = 1,
-    STFlipX = 2,
-    STRotate90 = 3,
-    STFlipY = 4,
-    STRotate270 = 5,
-    STRotate180 = 6,
-    STRotate270FlipY = 7,
-  };
-  
-#endif
-
-/* END of GDConst.h */
+/*
+ * SOURCE FILE : GDConst.h
+ *
+ * A few more constants associated with the Gameduino hardware.
+ *
+ */
+
+#ifndef GDConstIncluded
+  
+  #define GDConstIncluded
+
+  #define RAM_PIC_SIZE 4096        // size of screen picture RAM
+  #define RAM_CHR_SIZE 4096        // size of character set pixel data RAM
+  #define RAM_PAL_SIZE 2048        // size of character set palette data RAM
 
+  #define SCREEN_CHAR_WIDTH 64     // character width of screen (entire screen, not just visible bit)
+  #define SCREEN_CHAR_HEIGHT 64    // character height of screen (entire screen, not just visible bit)
+  
+  #define VISIBLE_CHAR_WIDTH 50    // character width of visible screen
+  #define VISIBLE_CHAR_HEIGHT 37   // character height of visible screen (actually 37.5)
+
+  #define SPRITE_PIXEL_WIDTH 16
+  #define SPRITE_PIXEL_HEIGHT 16
+
+  #define SPRITE_COUNT 256
+  
+#endif
+
+/* END of GDConst.h */
+
--- a/GameObject.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/GameObject.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -46,16 +46,22 @@
 // Pass number of pointers in the array in objectCount.
 // Returns true if any non-null objects were found in the array.
 bool GameObject::MoveAll( GameObject **objects, UInt8 objectCount ) {
-  GameObject *object;
-  bool foundNonNull = false;
-  for( UInt8 i = 0; i < objectCount; ++i ) {
-    object = objects[ i ];
-    if( object != (GameObject*)NULL ) {
-      foundNonNull = true;
-      object->Move();
-    }
-  }
-  return foundNonNull;
+  if( objects != (GameObject**)NULL ) {
+      GameObject *object;
+      bool foundNonNull = false;
+      for( UInt8 i = 0; i < objectCount; ++i ) {
+        object = objects[ i ];
+        if( object != (GameObject*)NULL ) {
+          foundNonNull = true;
+          object->Move();
+        }
+      }
+      return foundNonNull;
+   }
+   else {
+      // A null pointer was passed. Do nothing.
+      return false;
+   }
 }
 
 /****************************/
--- a/GameObject.h	Sat Jun 08 11:24:05 2013 +0000
+++ b/GameObject.h	Sat Jun 08 14:40:47 2013 +0000
@@ -62,10 +62,10 @@
     // Indicates which Gameduino sprite is being used for this object.
     UInt8 SpriteNumber;
     
-        // Determines if object is retained on a level restart.
-        // Most enemy objects are retained on a level restart, although their positions change.
-        // However, enemy bullets (for example) are killed off on a level restart.
-        bool RetainOnLevelRestart;
+    // Determines if object is retained on a level restart.
+    // Most enemy objects are retained on a level restart, although their positions change.
+    // However, enemy bullets (for example) are killed off on a level restart.
+    bool RetainOnLevelRestart;
         
     /***************/
     /* CONSTRUCTOR */
@@ -81,7 +81,7 @@
       DeleteWhenRestricted( false ),
       RestrictionFlags( 0 ),
       SpriteNumber( 0 ),
-            RetainOnLevelRestart( true )
+      RetainOnLevelRestart( true )
     {
     }
 
@@ -172,9 +172,10 @@
     /************************/
     /* DRAW THE GAME OBJECT */
     /************************/
+    // Pass pointer to Gameduino to draw on in gd.
     // Note if Visible is false this should not draw anything
     // and/or hide the visible object.
-    virtual void Draw( void ) = 0;
+    virtual void Draw( Gameduino *gd ) = 0;
     
     /**********************************/
     /* INITIALISE AN ARRAY OF OBJECTS */
--- a/GameRobotRic.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/GameRobotRic.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -138,8 +138,6 @@
                 levelNumber++;
                 break;
         }
-        // Wait a bit.
-        wait( (float)2 );
     }
 }
 
--- a/Level0.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/Level0.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -8,9 +8,6 @@
 #include "Level0.h"
 #include "CharBlocks.h"
 
-// REMOVE THIS!
-extern Serial pc;
-
 /***************/
 /* CONSTRUCTOR */
 /***************/
@@ -98,10 +95,8 @@
         do {
           controls->Read();
           inputs = controls->GetInputs();
-          pc.printf( "Inputs = %04X\r\n", (int)inputs );
-        } while( true /* inputs == 0 */ );
+        } while( inputs == 0 );
       }
     }
     return Completed;
 }
-
--- a/Level1.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/Level1.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -14,8 +14,8 @@
 /**************/
 // Returns code indicating how level ended.
 Level::LevelExitCode Level1::Play( void ) {
+  LevelData dataForThisLevel;
 #if 0
-  LevelData dataForThisLevel;
   GameObject **ptr = dataForThisLevel.Enemies;
   UInt8 i, humanCount, enemyCount = 0;
   // Enemies of type GruntObject.
@@ -44,10 +44,8 @@
   for( i = 0; i < humanCount; ++i ) {
     *ptr++ = humans + i;
   }
+#endif
   DataForLevel = &dataForThisLevel;
   return PlayLoop();
-#else
-  return Completed;
-#endif
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LevelData.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -0,0 +1,30 @@
+/*
+ * SOURCE FILE : LevelData.cpp
+ *
+ * Definition of class LevelData.
+ *
+ */
+
+#include "LevelData.h"
+
+/***************/
+/* CONSTRUCTOR */
+/***************/
+LevelData::LevelData() {
+  UInt8 i;
+  // Ensure all enemies are NULL initially.
+  for( i = 0; i < MaxEnemies; ++i ) {
+    Enemies[ i ] = (GameObject*)NULL;
+  }
+  // Ensure all humans are NULL initially.
+  for( i = 0; i < MaxHumans; ++i ) {
+    Humans[ i ] = (GameObject*)NULL;
+  }
+}
+
+/**************/
+/* DESTRUCTOR */
+/**************/
+LevelData::~LevelData() {
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LevelData.h	Sat Jun 08 14:40:47 2013 +0000
@@ -0,0 +1,55 @@
+/*
+ * SOURCE FILE : LevelData.h
+ *
+ * Definition of class LevelData.
+ *
+ */
+
+#ifndef LevelDataDefined
+
+  #define LevelDataDefined
+
+  #include "GameObject.h"
+  // #include "EnemyObject.h"
+  // #include "HumanObject.h"
+  // #include "MutantObject.h"
+  
+  class LevelData {
+
+  public :
+
+    enum {
+      MaxEnemies = 64,           // Maximum number of enemies you can have in a level
+      MaxHumans = 24,            // maximum number of humans you can have in a level
+            MaxMutants = MaxHumans,    // Maximum number of mutant humans you can have in a level
+    };
+    
+    // Array containing pointers to all the enemies in a level.
+    // A null pointer indicates an unused or dead enemy.
+    GameObject *Enemies[ MaxEnemies ];
+    
+    // Array containing pointers to all the humans in a level.
+    // A null pointer indicates an unused or rescued human.
+    GameObject *Humans[ MaxHumans ];
+    
+    // Array containing mutant humans (NOT pointers to mutants).
+    // Pointer to the mutants in this array are written into the Enemies array
+    // whenever a human is mutated by a brain.
+    // MutantObject Mutants[ MaxMutants ];
+
+    /***************/
+    /* CONSTRUCTOR */
+    /***************/
+    LevelData();
+
+    /**************/
+    /* DESTRUCTOR */
+    /**************/
+    virtual ~LevelData();
+
+  };
+
+#endif
+
+/* END of LevelData.h */
+
--- a/LevelNormal.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/LevelNormal.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -9,12 +9,19 @@
  *
  */
 
+// Define this for debugging messages.
+#define CHATTY
+
+#ifdef CHATTY
+    #include "mbed.h"
+    extern Serial pc;
+#endif
+
 #include "LevelNormal.h"
-#if 0
-    #include "GameObjectLocator.h"
-    #include "FrameCounter.h"
-    #include "SpriteNumber.h"
-#endif
+#include "GameObjectLocator.h"
+#include "FrameCounter.h"
+#include "SpriteNumber.h"
+#include "ArenaConst.h"
 
 // Current instance being processed.
 LevelNormal *LevelNormal::currentInstance;
@@ -22,93 +29,96 @@
 /***************/
 /* CONSTRUCTOR */
 /***************/
-LevelNormal::LevelNormal() {
+LevelNormal::LevelNormal()
+{
 }
 
 /**************/
 /* DESTRUCTOR */
 /**************/
-LevelNormal::~LevelNormal() {
+LevelNormal::~LevelNormal()
+{
 }
 
 /********************/
 /* INITIALISE LEVEL */
 /********************/
-void LevelNormal::InitialiseLevel( void ) {
-#if 0
+// Pass pointer to Gameduino to draw on in gd.
+void LevelNormal::InitialiseLevel( Gameduino *gd )
+{
     // Note that if you re-arrange the following code you may need to adjust the
     // SpriteNumber enumeration in SpriteNumber.h.
-  UInt8 spriteNumber = FirstEnemySprite;
-  // Initialise enemies.
-  GameObject::InitialiseAll( DataForLevel->Enemies, LevelData::MaxEnemies, &spriteNumber );
-  // Initialise humans.
+    UInt8 spriteNumber = FirstEnemySprite;
+    // Initialise enemies.
+    GameObject::InitialiseAll( DataForLevel->Enemies, LevelData::MaxEnemies, &spriteNumber );
+    // Initialise humans.
     spriteNumber = FirstHumanSprite;
-  GameObject::InitialiseAll( DataForLevel->Humans, LevelData::MaxHumans, &spriteNumber );
-  // Use next free sprite number for player.
-  player->SpriteNumber = PlayerSprite;
-  // Do futher initialisation for all enemies.
-  EnemyObject *object;
-  for( UInt8 e = 0; e < LevelData::MaxEnemies; ++e ) {
-    object = (EnemyObject*)DataForLevel->Enemies[ e ];
-    if( object != (EnemyObject*)NULL ) {
+    GameObject::InitialiseAll( DataForLevel->Humans, LevelData::MaxHumans, &spriteNumber );
+    // Use next free sprite number for player.
+    player->SpriteNumber = PlayerSprite;
+    // Do futher initialisation for all enemies.
+#if 0
+    EnemyObject *object;
+    for( UInt8 e = 0; e < LevelData::MaxEnemies; ++e ) {
+        object = (EnemyObject*)DataForLevel->Enemies[ e ];
+        if( object != (EnemyObject*)NULL ) {
             // Get enemy to chase the player.
-      object->SetChaseObject( player );
+            object->SetChaseObject( player );
             // Pass array of all enemies to this enemy.
             object->Enemies = DataForLevel->Enemies;
             // If enemy is a brain then tell it about the humans to chase.
             if( object->GetEnemyType() == Brain ) {
                 ((BrainObject*)object)->HumansToChase = DataForLevel->Humans;
             }
+        }
     }
-  }
-  // Put player in the centre of the arena.
-  player->Xco = PLAYER_START_X;
-  player->Yco = PLAYER_START_Y;
-  // Kill off all player's bullets.
-  player->KillAllBullets();
-  // Kill off all explosions.
-  ExplosionManager::Instance.KillAllExplosions();
 #endif
+    // Put player in the centre of the arena.
+    player->Xco = PLAYER_START_X;
+    player->Yco = PLAYER_START_Y;
+    // Kill off all player's bullets.
+    player->KillAllBullets( gd );
+    // Kill off all explosions.
+    // ExplosionManager::Instance.KillAllExplosions();
 }
 
 /**********************************/
 /* DRAW SCORE AND NUMBER OF LIVES */
 /**********************************/
-void LevelNormal::DrawScoreAndLives( void ) {
-#if 0
-  GDExtra::WriteBCDNumber( 16, 0, player->Score, 8 );
-  // Display number of lives but limit this to 20 lives displayed.
-  UInt8 lives = ( player->Lives > 20 ) ? 20 : player->Lives;
-  GD.fill( RAM_PIC + VISIBLE_CHAR_WIDTH - lives, MiniPlayer, lives );
-#endif
+void LevelNormal::DrawScoreAndLives( void )
+{
+    GDExtra::WriteBCDNumber( gd, 16, 0, player->Score, 8 );
+    // Display number of lives but limit this to 20 lives displayed.
+    UInt8 lives = ( player->Lives > 20 ) ? 20 : player->Lives;
+    gd->fill( Gameduino::RAM_PIC + VISIBLE_CHAR_WIDTH - lives, MiniPlayer, lives );
 }
 
 /******************/
 /* DRAW THE LEVEL */
 /******************/
-void LevelNormal::DrawLevel( void ) {
-  // Set screen background to black.
-  gd->wr( Gameduino::BG_COLOR, Gameduino::RGB( 0, 0, 0 ) );
-  // Clear the screen to zero characters.
-  GDExtra::ClearScreen( gd, TransparentChar );
-  // Hide all sprties.
-  GDExtra::HideAllSprites( gd );
-  // Display level number.
-  GDExtra::WriteProgString( gd, 0, 0, StringData::LevelString );
-  GDExtra::WriteUInt16( gd, 6, 0, LevelNumber, 10, 2 );
-  // Display score.
-  GDExtra::WriteProgString( gd, 10, 0, StringData::ScoreString );
-  #if 0
-  // Update score and lives.
-  DrawScoreAndLives();
-  // Draw border around screen.
-  CharFrame::Draw(
-    ARENA_BORDER_X,
-    ARENA_BORDER_Y,
-    ARENA_BORDER_WIDTH,
-    ARENA_BORDER_HEIGHT
-  );
-  #endif
+void LevelNormal::DrawLevel( void )
+{
+    // Set screen background to black.
+    gd->wr( Gameduino::BG_COLOR, Gameduino::RGB( 0, 0, 0 ) );
+    // Clear the screen to zero characters.
+    GDExtra::ClearScreen( gd, TransparentChar );
+    // Hide all sprties.
+    GDExtra::HideAllSprites( gd );
+    // Display level number.
+    GDExtra::WriteProgString( gd, 0, 0, StringData::LevelString );
+    GDExtra::WriteUInt16( gd, 6, 0, LevelNumber, 10, 2 );
+    // Display score.
+    GDExtra::WriteProgString( gd, 10, 0, StringData::ScoreString );
+    // Update score and lives.
+    DrawScoreAndLives();
+    // Draw border around screen.
+    CharFrame::Draw(
+        gd,
+        ARENA_BORDER_X,
+        ARENA_BORDER_Y,
+        ARENA_BORDER_WIDTH,
+        ARENA_BORDER_HEIGHT
+    );
 }
 
 /************************************************/
@@ -116,16 +126,17 @@
 /************************************************/
 // Pass index of human in level's humans array in humanIndex.
 // Pass sprite number of sprite that it hit in spriteNumber.
-void LevelNormal::HandleHumanCollision( UInt8 humanIndex, UInt8 spriteNumber ) {
+void LevelNormal::HandleHumanCollision( UInt8 humanIndex, UInt8 spriteNumber )
+{
 #if 0
-  // Point to array of enemy object pointers.
-  GameObject **enemies = currentInstance->DataForLevel->Enemies;
-  EnemyObject *enemy;
-  UInt8 enemyIndex, mutantIndex;
-  // Find an enemy with given sprite number.
-  if( GameObject::FindSpriteNumber( enemies, LevelData::MaxEnemies, spriteNumber, &enemyIndex ) ) {
-    // Found enemy. Check if it squashes humans.
-    enemy = (EnemyObject*)enemies[ enemyIndex ];
+    // Point to array of enemy object pointers.
+    GameObject **enemies = currentInstance->DataForLevel->Enemies;
+    EnemyObject *enemy;
+    UInt8 enemyIndex, mutantIndex;
+    // Find an enemy with given sprite number.
+    if( GameObject::FindSpriteNumber( enemies, LevelData::MaxEnemies, spriteNumber, &enemyIndex ) ) {
+        // Found enemy. Check if it squashes humans.
+        enemy = (EnemyObject*)enemies[ enemyIndex ];
         // Get hold of the human that is doomed.
         GameObject **humans = currentInstance->DataForLevel->Humans;
         HumanObject *human = (HumanObject*)humans[ humanIndex ];
@@ -136,8 +147,7 @@
                 human->CurrentState = HumanObject::Dead;
                 // Make a noise.
                 SoundManager::Instance.PlaySound( Sounds::HumanDies, 0, 0 );
-            }
-            else if( enemy->GetEnemyType() == Brain ) {
+            } else if( enemy->GetEnemyType() == Brain ) {
                 // Kill human by inserting a null into humans array.
                 humans[ humanIndex ] = (GameObject*)NULL;
                 // Find a free slot for a new enemy.
@@ -150,8 +160,7 @@
                     mutant->Start( human, currentInstance->player );
                     // Make a noise.
                     // TODO : SoundManager::Instance.PlaySound( Sounds::HumanMutates, 0, 0 );
-                }
-                else {
+                } else {
                     // Could not find a free slot for a new enemy so just erase the human sprite.
                     GDExtra::HideSprite( human->SpriteNumber );
                 }
@@ -166,16 +175,17 @@
 /********************************************************/
 // Pass index of bullet in player's bullet array in bulletIndex.
 // Pass sprite number of sprite that it hit in spriteNumber.
-void LevelNormal::HandleBulletCollision( UInt8 bulletIndex, UInt8 spriteNumber ) {
+void LevelNormal::HandleBulletCollision( UInt8 bulletIndex, UInt8 spriteNumber )
+{
 #if 0
-  // Point to array of enemy object pointers.
-  GameObject **enemies = currentInstance->DataForLevel->Enemies;
-  EnemyObject *enemy;
-  UInt8 enemyIndex;
-  // Find an enemy with given sprite number.
-  if( GameObject::FindSpriteNumber( enemies, LevelData::MaxEnemies, spriteNumber, &enemyIndex ) ) {
-    // Found enemy. Check if it is indestructable.
-    enemy = (EnemyObject*)enemies[ enemyIndex ];
+    // Point to array of enemy object pointers.
+    GameObject **enemies = currentInstance->DataForLevel->Enemies;
+    EnemyObject *enemy;
+    UInt8 enemyIndex;
+    // Find an enemy with given sprite number.
+    if( GameObject::FindSpriteNumber( enemies, LevelData::MaxEnemies, spriteNumber, &enemyIndex ) ) {
+        // Found enemy. Check if it is indestructable.
+        enemy = (EnemyObject*)enemies[ enemyIndex ];
         if( enemy->HitPoints != EnemyObject::Indestructable ) {
             // Enemy is not indestructable. Decrement hit points and die when it reaches zero.
             enemy->HitPoints--;
@@ -196,7 +206,7 @@
         SoundManager::Instance.PlaySound( Sounds::Explosion, 0, 0 );
         // Start explosion animation using coordinates of enemy.
         ExplosionManager::Instance.StartExplosion( enemy->Xco, enemy->Yco    );
-  }
+    }
 #endif
 }
 
@@ -204,29 +214,30 @@
 /* CHECK FOR COLLISIONS BETWEEN PLAYER AND OTHER OBJECTS */
 /*********************************************************/
 // Pass pointer to a flag that will be set true if player is dead in isDead parameter.
-void LevelNormal::CheckPlayerCollisions( bool *isDead ) {
+void LevelNormal::CheckPlayerCollisions( bool *isDead )
+{
 #if 0
-  UInt8 enemyIndex, humanIndex;
-  // Check if player sprite has hit another sprite.
-  UInt8 hitSpriteNumber = GD.rd( COLLISION + player->SpriteNumber );
-  // If you get 0xFF then no collision found.
-  if( hitSpriteNumber != 0xFF ) {
-    // Check for collision with an enemy.
-    if(
-      GameObject::FindSpriteNumber(
-        DataForLevel->Enemies, LevelData::MaxEnemies, hitSpriteNumber, &enemyIndex
-      )
-    ) {
-      // Hit an enemy. Player is dead.
-      *isDead = true;
-    }
-    // Check for collision with a human that has not already been rescued or killed.
-    else if(
-      GameObject::FindSpriteNumber(
-        DataForLevel->Humans, LevelData::MaxHumans, hitSpriteNumber, &humanIndex
-      )
-    ) {
-      HumanObject *human = (HumanObject*)DataForLevel->Humans[ humanIndex ];
+    UInt8 enemyIndex, humanIndex;
+    // Check if player sprite has hit another sprite.
+    UInt8 hitSpriteNumber = GD.rd( COLLISION + player->SpriteNumber );
+    // If you get 0xFF then no collision found.
+    if( hitSpriteNumber != 0xFF ) {
+        // Check for collision with an enemy.
+        if(
+            GameObject::FindSpriteNumber(
+                DataForLevel->Enemies, LevelData::MaxEnemies, hitSpriteNumber, &enemyIndex
+            )
+        ) {
+            // Hit an enemy. Player is dead.
+            *isDead = true;
+        }
+        // Check for collision with a human that has not already been rescued or killed.
+        else if(
+            GameObject::FindSpriteNumber(
+                DataForLevel->Humans, LevelData::MaxHumans, hitSpriteNumber, &humanIndex
+            )
+        ) {
+            HumanObject *human = (HumanObject*)DataForLevel->Humans[ humanIndex ];
             if( human->CurrentState == HumanObject::WalkingAbout ) {
                 // Change human state to rescued.
                 human->CurrentState = HumanObject::Rescued;
@@ -235,8 +246,8 @@
                 // Make a noise.
                 SoundManager::Instance.PlaySound( Sounds::RescueHuman, 0, 0 );
             }
-    }    
-  }
+        }
+    }
 #endif
 }
 
@@ -244,23 +255,24 @@
 /* WAIT UNTIL SLOT FREE FOR A NEW SOUND, PLAY IT AND WAIT FOR ALL SOUNDS TO FINISH */
 /***********************************************************************************/
 // Pass sound to play in soundToPlay parameter.
-void LevelNormal::PlaySoundAndWait( const UInt8 *soundToPlay ) {
+void LevelNormal::PlaySoundAndWait( const UInt8 *soundToPlay )
+{
 #if 0
-  // Keep trying to play sound until it works and meanwhile
-  // keep currently playing sounds going.
-  while( ! SoundManager::Instance.PlaySound( soundToPlay, 0, 0 ) ) {
-    // Update sound manager.
-    SoundManager::Instance.Update();
-    // Wait for frame flyback.
-    GD.waitvblank();
-  }
-  // Now wait until all sounds have finished.
-  while( SoundManager::Instance.CountSoundsPlaying() > 0 ) {
-    // Update sound manager.
-    SoundManager::Instance.Update();
-    // Wait for frame flyback.
-    GD.waitvblank();
-  }
+    // Keep trying to play sound until it works and meanwhile
+    // keep currently playing sounds going.
+    while( ! SoundManager::Instance.PlaySound( soundToPlay, 0, 0 ) ) {
+        // Update sound manager.
+        SoundManager::Instance.Update();
+        // Wait for frame flyback.
+        GD.waitvblank();
+    }
+    // Now wait until all sounds have finished.
+    while( SoundManager::Instance.CountSoundsPlaying() > 0 ) {
+        // Update sound manager.
+        SoundManager::Instance.Update();
+        // Wait for frame flyback.
+        GD.waitvblank();
+    }
 #endif
 }
 
@@ -271,108 +283,119 @@
 // This method should be called from the Play method after the
 // level data has been initialised and the return value returned
 // by the Play method.
-Level::LevelExitCode LevelNormal::PlayLoop( void ) {
-  // Do nothing if Gameduino has not been specified, level data is NULL or player has not been specified.
-  if( ( gd != (Gameduino*)NULL ) /* || ( DataForLevel != (LevelData*)NULL ) || ( player == (PlayerObject*)NULL ) */ ) {
-    // Point static pointer to current instance.
-    currentInstance = this;
-    // Do some initialisation first.
-    InitialiseLevel();
-    // Redraw the screen.
-    DrawLevel();
-    // Wait for frame flyback once before entering loop so collision data is recalculated.
-    // At this point there should not be any sprites on the screen so no collisions
-    // should be found.
-    gd->waitvblank();
+Level::LevelExitCode LevelNormal::PlayLoop( void )
+{
+    // Do nothing if Gameduino has not been specified, level data is NULL or player has not been specified.
+    if( ( gd != (Gameduino*)NULL ) || ( DataForLevel != (LevelData*)NULL ) || ( player == (PlayerObject*)NULL ) ) {
+        // Point static pointer to current instance.
+        currentInstance = this;
+        // Do some initialisation first.
+        InitialiseLevel( gd );
+        // Redraw the screen.
+        DrawLevel();
+        // Wait for frame flyback once before entering loop so collision data is recalculated.
+        // At this point there should not be any sprites on the screen so no collisions
+        // should be found.
+        gd->waitvblank();
+        // Repeat until all enemies are dead or player is dead.
+        bool allEnemiesAreDead = false;
+        bool playerIsDead = false;
+        bool gameIsOver = false;
+        bool firstDraw = true;
+        while( ! allEnemiesAreDead && ! gameIsOver ) {
+            // Update sound manager.
+            // SoundManager::Instance.Update();
+            // Wait for frame flyback.
+            gd->waitvblank();
+            // Check for collisions between player and other objects.
+            CheckPlayerCollisions( &playerIsDead );
+#if 0
+            // Check for collisions between humans and enemies that squash.
+            GameObject::FindCollisions( DataForLevel->Humans, LevelData::MaxHumans, &LevelNormal::HandleHumanCollision );
+            // Check for collisions between player bullets and enemies.
+            GameObject::FindCollisions( player->GetBullets(), BulletManager::MaxBullets, &LevelNormal::HandleBulletCollision );
+#endif
+            // Redraw the player's score and number of lives.
+            DrawScoreAndLives();
 #if 0
-    // Repeat until all enemies are dead or player is dead.
-    bool allEnemiesAreDead = false;
-    bool playerIsDead = false;
-    bool gameIsOver = false;
-    bool firstDraw = true;
-    while( ! allEnemiesAreDead && ! gameIsOver ) {
-      // Update sound manager.
-      SoundManager::Instance.Update();
-      // Wait for frame flyback.
-      GD.waitvblank();
-      // Check for collisions between player and other objects.
-      CheckPlayerCollisions( &playerIsDead );
-      // Check for collisions between humans and enemies that squash.
-      GameObject::FindCollisions( DataForLevel->Humans, LevelData::MaxHumans, &LevelNormal::HandleHumanCollision );
-      // Check for collisions between player bullets and enemies.
-      GameObject::FindCollisions( player->GetBullets(), BulletManager::MaxBullets, &LevelNormal::HandleBulletCollision );
-      // Redraw the player's score and number of lives.
-      DrawScoreAndLives();
-      // Draw all the enemies.
-      GameObject::DrawAll( DataForLevel->Enemies, LevelData::MaxEnemies );
-      // Draw all the humans.
-      GameObject::DrawAll( DataForLevel->Humans, LevelData::MaxHumans );
-      // Draw all the explosions.
-      GameObject::DrawAll( ExplosionManager::Instance.GetExplosions(), ExplosionManager::MaxExplosions );
-      // Draw the player.
-      player->Draw();
-      // Draw the player's bullets.
-      GameObject::DrawAll( player->GetBullets(), BulletManager::MaxBullets );
-      // Increment the frame counter.
-      FrameCounter++;
-      // After first redraw play level start sound and wait for it to end.
-      if( firstDraw ) {
-        PlaySoundAndWait( Sounds::StartLevel );
-        firstDraw = false;
-      }
-        // If player was killed then play death march and wait for it to finish.
-        if( playerIsDead ) {
-            // Player got killed.
-            PlaySoundAndWait( Sounds::PlayerDead );
-            // One less life for player.
-            if( player->Lives > 0 ) {
-                player->Lives--;
+            // Draw all the enemies.
+            GameObject::DrawAll( DataForLevel->Enemies, LevelData::MaxEnemies );
+            // Draw all the humans.
+            GameObject::DrawAll( DataForLevel->Humans, LevelData::MaxHumans );
+            // Draw all the explosions.
+            GameObject::DrawAll( ExplosionManager::Instance.GetExplosions(), ExplosionManager::MaxExplosions );
+#endif
+            // Draw the player.
+            player->Draw( gd );
+            // Draw the player's bullets.
+            GameObject::DrawAll( player->GetBullets(), BulletManager::MaxBullets );
+            // Increment the frame counter.
+            FrameCounter++;
+            // After first redraw play level start sound and wait for it to end.
+            if( firstDraw ) {
+                // PlaySoundAndWait( Sounds::StartLevel );
+                firstDraw = false;
             }
-            // Game is over when player has no more lives.
-            gameIsOver = ( player->Lives == 0 );
-            // If game is not over then re-initialise level using any remaining enemies.
-            if( ! gameIsOver ) {
-                // Remove all objects that do not survive a level restart (like enemy bullets).
-                GameObject::RemoveUnretainedObjects( DataForLevel->Enemies, LevelData::MaxEnemies );
-                InitialiseLevel();
-                DrawLevel();
-                GD.waitvblank();
-                playerIsDead = false;
-                firstDraw = true;
+            // If player was killed then play death march and wait for it to finish.
+            if( playerIsDead ) {
+                #ifdef CHATTY
+                    pc.puts( "Player got killed.\r\n" );
+                #endif
+                // Player got killed.
+                // PlaySoundAndWait( Sounds::PlayerDead );
+                // One less life for player.
+                if( player->Lives > 0 ) {
+                    player->Lives--;
+                }
+                // Game is over when player has no more lives.
+                gameIsOver = ( player->Lives == 0 );
+                // If game is not over then re-initialise level using any remaining enemies.
+                if( ! gameIsOver ) {
+                    #ifdef CHATTY
+                        pc.puts( "Game is over.\r\n" );
+                    #endif
+                    // Remove all objects that do not survive a level restart (like enemy bullets).
+                    GameObject::RemoveUnretainedObjects( DataForLevel->Enemies, LevelData::MaxEnemies );
+                    InitialiseLevel( gd );
+                    DrawLevel();
+                    gd->waitvblank();
+                    playerIsDead = false;
+                    firstDraw = true;
+                }
+            }
+            else {
+#if 0
+                // Move all the enemies and check if all dead.
+                allEnemiesAreDead = ! GameObject::MoveAll( DataForLevel->Enemies, LevelData::MaxEnemies );
+                // If there are still some enemies alive then check if those that remain are indestructable.
+                // If only indestructable enemies survive then act as if all enemies are dead.
+                // You need to do this or you would never be able to complete a level that had indestructable
+                // enemies on it.
+                if( ! allEnemiesAreDead ) {
+                    allEnemiesAreDead = EnemyObject::AreAllIndestructable(
+                                            (const EnemyObject**)DataForLevel->Enemies,
+                                            LevelData::MaxEnemies
+                                        );
+                }
+                // Move all the humans.
+                GameObject::MoveAll( DataForLevel->Humans, LevelData::MaxHumans );
+                // Move (update) all the explosions.
+                GameObject::MoveAll( ExplosionManager::Instance.GetExplosions(), ExplosionManager::MaxExplosions );
+#endif
+                // Read the player's controls.
+                player->ReadControls();
+                // Move the player.
+                player->Move();
+                // Move the player's bullets.
+                GameObject::MoveAll( player->GetBullets(), BulletManager::MaxBullets );
             }
         }
-        else {
-            // Move all the enemies and check if all dead.
-            allEnemiesAreDead = ! GameObject::MoveAll( DataForLevel->Enemies, LevelData::MaxEnemies );
-            // If there are still some enemies alive then check if those that remain are indestructable.
-            // If only indestructable enemies survive then act as if all enemies are dead.
-            // You need to do this or you would never be able to complete a level that had indestructable
-            // enemies on it.
-            if( ! allEnemiesAreDead ) {
-                allEnemiesAreDead = EnemyObject::AreAllIndestructable(
-                    (const EnemyObject**)DataForLevel->Enemies,
-                    LevelData::MaxEnemies
-                );
-            }
-            // Move all the humans.
-            GameObject::MoveAll( DataForLevel->Humans, LevelData::MaxHumans );
-            // Move (update) all the explosions.
-            GameObject::MoveAll( ExplosionManager::Instance.GetExplosions(), ExplosionManager::MaxExplosions );
-            // Read the player's controls.
-            player->ReadControls();
-            // Move the player.
-            player->Move();
-            // Move the player's bullets.
-            GameObject::MoveAll( player->GetBullets(), BulletManager::MaxBullets );
-        }
+        // Player completed level or game is over.
+        return gameIsOver ? GameOver : Completed;
     }
-#endif
-    // Player completed level or game is over.
-    return /* gameIsOver ? GameOver : */ Completed;
-  }
-  else {
-    // Level data or player were not specified.
-    return Completed;
-  }
+    else {
+        // Level data or player were not specified.
+        return Completed;
+    }
 }
 
--- a/LevelNormal.h	Sat Jun 08 11:24:05 2013 +0000
+++ b/LevelNormal.h	Sat Jun 08 14:40:47 2013 +0000
@@ -14,8 +14,8 @@
   #define LevelNormalDefined
 
   #include "Level.h"
+  #include "LevelData.h"
 #if 0
-  #include "LevelData.h"
   #include "ExplosionManager.h"
 #endif
   
@@ -37,7 +37,7 @@
 
     // Data defining the level.
     // You should write to this before calling PlayLoop.
-    // LevelData *DataForLevel;
+    LevelData *DataForLevel;
     
     /*************/
     /* PLAY LOOP */
@@ -56,7 +56,8 @@
     /********************/
     /* INITIALISE LEVEL */
     /********************/
-    void InitialiseLevel( void );
+    // Pass pointer to Gameduino to draw on in gd.
+    void InitialiseLevel( Gameduino *gd );
 
     /**********************************/
     /* DRAW SCORE AND NUMBER OF LIVES */
--- a/PlayerObject.cpp	Sat Jun 08 11:24:05 2013 +0000
+++ b/PlayerObject.cpp	Sat Jun 08 14:40:47 2013 +0000
@@ -5,10 +5,18 @@
  *
  */
 
+// Define this for debugging messages.
+#undef CHATTY
+
+#ifdef CHATTY
+    #include "mbed.h"
+    extern Serial pc;
+#endif
+
 #include "PlayerObject.h"
 // #include "SoundManager.h"
 // #include "Sounds.h"
-// #include "FrameCounter.h"
+#include "FrameCounter.h"
 
 // Bullet velocity information.
 BulletVelocities PlayerObject::bulletVelocities( FromPixel( 2 ), FromPixel( 2 ) );
@@ -38,15 +46,20 @@
 /* MOVE THE GAME OBJECT */
 /************************/
 void PlayerObject::ProtectedMove( void ) {
-#if 0
   // Do nothing if controls are not specified.
   if( controls != (PanelControls*)NULL ) {
     // Read joysticks and buttons. Buttons are not used.
     UInt16 map = controls->GetInputs();
     // Extract bits relating to joystick 1 (player movement).
     UInt16 joy1Map = ( map >> PanelControls::Joy1 ) & 0x0F;
+    #ifdef CHATTY
+        pc.printf( "Moving player. Joy 1 = %04X.\r\n", (int)joy1Map );
+    #endif
     // Fetch velocities associated with this combination of joystick inputs.
     const Int16Pair *pair = playerVelocities.GetVelocities( joy1Map );
+    #ifdef CHATTY
+        pc.printf( "dx = %d. dy = %d.\r\n", (int)pair->X, (int)pair->Y );
+    #endif
     // Add on velocities to player coordinates.
     Xco += pair->X;
     Yco += pair->Y;
@@ -64,24 +77,25 @@
         // Try and start a new bullet.
         if( playerBullets.StartBullet( Xco, Yco, pair->X, pair->Y ) ) {
           // If bullet was started then make a bullet sound.
+          #if 0
           SoundManager::Instance.PlaySound( Sounds::FireGun, 0, 0 );
+          #endif
         }
         // Reset countdown until another bullet can start.
         bulletCountdown = 8;
       }
     }
   }
-#endif
 }
 
 /************************/
 /* DRAW THE GAME OBJECT */
 /************************/
+// Pass pointer to Gameduino to draw on in gd.
 // This is only called after it has been established that the
 // game object is visible.
-void PlayerObject::Draw( void ) {
-#if 0
-  SpriteTransform transform;
+void PlayerObject::Draw( Gameduino *gd ) {
+  Gameduino::Rotation transform;
   SpriteImageId imageId;
   // Check controls have been specified.
   if( controls != (PanelControls*)NULL ) {
@@ -92,7 +106,7 @@
     bool leftFootUp = ( ( FrameCounter & 4 ) != 0 );
     if( map & PanelControls::Left2 ) {
       // Firing to the left.
-      transform = STNormal;
+      transform = Gameduino::None;
       if( map & PanelControls::Up2 ) {
         // Firing left and up.
         imageId = leftFootUp ? PlayerGunUpLeftFootUpImage : PlayerGunUpRightFootUpImage;
@@ -108,7 +122,7 @@
     }
     else if( map & PanelControls::Right2 ) {
       // Firing to the right.
-      transform = STFlipX;
+      transform = Gameduino::FlipX;
       if( map & PanelControls::Up2 ) {
         // Firing right and up. Image is flipped so left foot becomes right foot.
         imageId = leftFootUp ? PlayerGunUpRightFootUpImage : PlayerGunUpLeftFootUpImage;
@@ -124,18 +138,17 @@
     }
     else {
       // Firing up, down or not firing.
-      transform = leftFootUp ? STNormal : STFlipX;
+      transform = leftFootUp ? Gameduino::None : Gameduino::FlipX;
       // Use a different image if firing up.
       imageId = ( map & PanelControls::Up2 ) ? PlayerBothGunsUpImage : PlayerImage;
     }
   }
   else {
     // Controls have not been specified so use standing still image.
-    transform = STNormal;
+    transform = Gameduino::None;
     imageId = PlayerImage;
   }
-  GD.sprite( SpriteNumber, ToPixel( Xco ), ToPixel( Yco ), imageId, 0, transform, GoodGuy );
-#endif
+  gd->sprite( SpriteNumber, ToPixel( Xco ), ToPixel( Yco ), imageId, 0, transform, GoodGuy );
 }
 
 /*************************/
--- a/PlayerObject.h	Sat Jun 08 11:24:05 2013 +0000
+++ b/PlayerObject.h	Sat Jun 08 14:40:47 2013 +0000
@@ -77,23 +77,26 @@
     /************************/
     /* DRAW THE GAME OBJECT */
     /************************/
+    // Pass pointer to Gameduino to draw on in gd.
     // This is only called after it has been established that the
     // game object is visible.
-    virtual void Draw( void );
+    virtual void Draw( Gameduino *gd );
 
     /*********************************/
     /* KILL A SINGLE PLAYER'S BULLET */
     /*********************************/
+    // Pass pointer to Gameduino to draw on in gd.
     // Pass index of bullet in b.
-    void KillBullet( UInt8 b ) {
-      playerBullets.KillBullet( b );
+    void KillBullet( Gameduino *gd, UInt8 b ) {
+      playerBullets.KillBullet( gd, b );
     }
     
     /*****************************/
     /* KILL ALL PLAYER'S BULLETS */
     /*****************************/
-    void KillAllBullets( void ) {
-      playerBullets.KillAllBullets();
+    // Pass pointer to Gameduino to draw on in gd.
+    void KillAllBullets( Gameduino *gd ) {
+      playerBullets.KillAllBullets( gd );
     }
 
     /*********************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SpriteNumber.h	Sat Jun 08 14:40:47 2013 +0000
@@ -0,0 +1,29 @@
+/*
+ * SOURCE FILE : SpriteNumber.h
+ *
+ * Enumeration containing sprite numbers.
+ * Note that these are sprite numbers, NOT sprite image numbers.
+ * Each sprite can have any sprite image number it wants.
+ *
+ */
+
+#ifndef SpriteNumberDefined
+
+  #define SpriteNumberDefined
+
+  #include "LevelData.h"
+  // #include "ExplosionManager.h"
+    
+  enum SpriteNumber {
+        FirstEnemySprite = 0,
+        FirstHumanSprite = FirstEnemySprite + LevelData::MaxEnemies,
+        PlayerSprite = FirstHumanSprite + LevelData::MaxHumans,
+        #if 0
+        FirstExplosionSprite = PlayerSprite + 1,
+        NextFreeSprite = FirstExplosionSprite + ExplosionManager::MaxExplosions,
+        #endif
+  };
+
+#endif
+
+/* END of SpriteNumber.h */