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

Revision:
16:d0b142ba4362
Parent:
15:d8ea0c7b7e64
Child:
17:194789db2215
--- a/HighScoreEntry.cpp	Sat Jun 15 15:05:19 2013 +0000
+++ b/HighScoreEntry.cpp	Sat Jun 15 19:27:36 2013 +0000
@@ -14,9 +14,10 @@
 #include "CharBlocks.h"      // blocks of characters in program memory
 #include "CharFrame.h"       // for drawing frames made of characters
 #include "CharCodes.h"       // character codes
+#include "CharFrame.h"       // for drawing frames of characters
 
 // Define this for debugging messages on serial port.
-#define CHATTY
+#undef CHATTY
 
 #ifdef CHATTY
     extern Serial pc;
@@ -24,7 +25,7 @@
 
 // Grid constants.
 #define GRIDX 5
-#define GRIDY 14
+#define GRIDY 16
 #define GRIDCOLUMNS 20
 #define GRIDROWS 3
 #define GRIDCOLUMNSPACING 2
@@ -34,7 +35,9 @@
 /* CONSTRUCTOR */
 /***************/
 HighScoreEntry::HighScoreEntry() :
-  cursorPos( 0 ),
+  charIndex( 0 ),
+  cursorRow( 0 ),
+  cursorColumn( 0 ),
   grid( GRIDROWS )
 {
   // Initialise grid around which cursor moves.
@@ -69,22 +72,30 @@
 /* INITIALISE GRID */
 /*******************/
 void HighScoreEntry::InitialiseGrid( void ) {
-    UInt8 x, y = GRIDY;
-    for( UInt8 rowNumber = 0; rowNumber < GRIDROWS; ++rowNumber ) {
-        FieldRow *row = grid.GetRow( rowNumber );
+    UInt8 code = PlayerName::MinChar;
+    UInt8 x = GRIDX, y = GRIDY;
+    UInt8 columnNumber = 0, rowNumber = 0;;
+    FieldRow *row = grid.GetRow( rowNumber++ );
+    while( code <= PlayerName::MaxChar ) {
         if( row != (FieldRow*)NULL ) {
+            FieldCell *cell = new FieldCell();
+            cell->Rect.X1 = x - 1;
+            cell->Rect.Y1 = y - 1;
+            cell->Rect.X2 = x + 1;
+            cell->Rect.Y2 = y + 1;
+            row->AddCell( cell );
+        }
+        columnNumber++;
+        if( columnNumber >= GRIDCOLUMNS ) {
+            columnNumber = 0;
             x = GRIDX;
-            for( UInt8 columnNumber = 0; columnNumber < GRIDCOLUMNS; ++columnNumber ) {
-                FieldCell *cell = new FieldCell();
-                cell->Rect.X1 = ( x - 1 ) << 3;
-                cell->Rect.Y1 = ( y - 1 ) << 3;
-                cell->Rect.X2 = ( ( x + 1 ) << 3 ) + 7;
-                cell->Rect.Y2 = ( ( y + 1 ) << 3 ) + 7;
-                row->AddCell( cell );
-                x += GRIDCOLUMNSPACING;
-            }
+            y += GRIDROWSPACING;
+            row = grid.GetRow( rowNumber++ );
         }
-        y += GRIDROWSPACING;
+        else {
+            x += GRIDCOLUMNSPACING;
+        }
+        code++;
     }
 }
 
@@ -97,67 +108,87 @@
 void HighScoreEntry::GetName( PlayerName *name, PanelControls *controls, Gameduino *gd ) {
   UInt16 inputs;
   UInt8 countdown = 0;
-  char *curPtr;
   // Initialise name to all 'A' characters.
   for( UInt8 i = 0; i < PlayerName::Length; ++i ) {
     name->Name[ i ] = 'A';
   }
   // Draw screen.
-  DrawScreen( gd );
+  DrawScreen( gd, name );
   // Wait until player releases all controls.
   WaitControls( gd, controls, false );
-  // Start at leftmost character.
-  cursorPos = 0;
-  // Loop until cursor moves beyond rightmost character.
-  while( cursorPos < PlayerName::Length ) {
+  // Loop until player activates done cell.
+  bool done = false;
+  while( ! done ) {
     // Read panel controls.
     controls->Read();
     inputs = controls->GetInputs();
-    // Point to character under cursor.
-    curPtr = name->Name + cursorPos;
     // Only react to controls every so often to slow things down.
     if( countdown == 0 ) {
       countdown = 10;
+      bool cursorMoved = false;
+      // Point to current cell before changing.
+      FieldCell *lastCell = grid.GetCellAt( cursorRow, cursorColumn );      
       if( inputs & PanelControls::Up1 ) {
-        // Joystick up selects next character up.
-        if( *curPtr >= PlayerName::MaxChar ) {
-          *curPtr = PlayerName::MinChar;
-        }
-        else {
-          (*curPtr)++;
+        // Joystick up moves cursor up.
+        if( cursorRow > 0 ) {
+          cursorRow--;
+          ValidateCursorColumn();
+          cursorMoved = true;
         }
       }
       else if( inputs & PanelControls::Down1 ) {
-        // Joystick down selects previous character down.
-        if( *curPtr <= PlayerName::MinChar ) {
-          *curPtr = PlayerName::MaxChar;
-        }
-        else {
-          (*curPtr)--;
+        // Joystick down moves cursor down.
+        if( cursorRow < grid.GetRowCount() - 1 ) {
+          cursorRow++;
+          ValidateCursorColumn();
+          cursorMoved = true;
         }
       }
-      else if( inputs & PanelControls::Left1 ) {
-        // Joystick left moves cursor back.
-        if( cursorPos > 0 ) {
-          cursorPos--;
-          // Wait until all controls released.
-          WaitControls( gd, controls, false );
+      if( inputs & PanelControls::Left1 ) {
+        // Joystick left moves cursor left.
+        if( cursorColumn > 0 ) {
+          cursorColumn--;
+          cursorMoved = true;
         }
       }
       else if( inputs & PanelControls::Right1 ) {
-        // Joystick right moves cursor forwards.
-        cursorPos++;
-        // Wait until all controls released.
-        WaitControls( gd, controls, false );
+        // Joystick right moves cursor right.
+        FieldRow *row = grid.GetRow( cursorRow );
+        if( ( row != (FieldRow*)NULL ) && ( cursorColumn < row->GetColumnCount() - 1 ) ) {
+            cursorColumn++;
+            cursorMoved = true;
+        }
+      }
+      if( inputs & PanelControls::Button1 ) {
+          // Button 1 adds a character or possibly does something special.
+          if( cursorRow < grid.GetRowCount() ) {
+              char newChar = (char)( PlayerName::MinChar + cursorRow * GRIDCOLUMNS + cursorColumn );
+              name->Name[ charIndex ] = newChar;
+              if( charIndex < PlayerName::Length - 1 ) {
+                  charIndex++;
+              }
+          }
+          else {
+              // TODO. Special functions.
+          }
+          // Draw modified name.
+          gd->waitvblank();
+          DrawName( gd, name );
+          // Wait until player releases all controls.
+          WaitControls( gd, controls, false );
+      }
+      // If necessary redraw the cursor.
+      if( cursorMoved ) {
+          WipeCursor( gd, lastCell );
+          DrawCursor( gd, grid.GetCellAt( cursorRow, cursorColumn ) );
       }
     }
     else {
       countdown--;
     }
-    // Wait for vertical flyback. Then draw name and do animation.
+    // Wait for vertical flyback. Then do animation.
     gd->waitvblank();
     FrameCounter++;
-    DrawName( gd, name );
     Animate( gd );
   }
   // Wait until player releases all controls before returning.
@@ -190,7 +221,8 @@
 /* DRAW THE SCREEN */
 /*******************/
 // Pass pointer to Gameduino to draw on in gd.
-void HighScoreEntry::DrawScreen( Gameduino *gd ) {
+// Pass player name in name.
+void HighScoreEntry::DrawScreen( Gameduino *gd, PlayerName *name ) {
   gd->waitvblank();
   // Clear the screen to zero characters.
   gd->fill( Gameduino::RAM_PIC, 0, RAM_PIC_SIZE );
@@ -206,8 +238,12 @@
   gd->putstr( 2, 6,  " TO MOVE THE CURSOR. PRESS THE LEFT BUTTON TO" );
   gd->putstr( 2, 8,  "  ENTER EACH LETTER. MOVE CURSOR TO FOOT OF" );
   gd->putstr( 2, 10, " SCREEN AND PRESS LEFT BUTTON WHEN FINISHED." );
+  // Draw player's name.
+  DrawName( gd, name );
   // Draw character grid.
   DrawGrid( gd );
+  // Draw cursor.
+  DrawCursor( gd, grid.GetCellAt( cursorRow, cursorColumn ) );
 }
 
 /***************************/
@@ -240,10 +276,10 @@
 // Pass pointer to Gameduino to draw on in gd.
 // Pass player name in name.
 void HighScoreEntry::DrawName( Gameduino *gd, PlayerName *name ) {
-  gd->putstr( 21, 11, name->Name );
-  UInt16 address = Gameduino::RAM_PIC + 12 * SCREEN_CHAR_WIDTH + 21;
+  gd->putstr( 23, 13, name->Name );
+  UInt16 address = Gameduino::RAM_PIC + 14 * SCREEN_CHAR_WIDTH + 23;
   for( UInt8 i = 0; i < PlayerName::Length; ++i ) {
-    gd->wr( address, ( i == cursorPos ) ? ArrowUp : ' ' );
+    gd->wr( address, ( i == charIndex ) ? ArrowUp : ' ' );
     address++;
   }
 }
@@ -254,3 +290,39 @@
 // Pass pointer to Gameduino to display on in gd.
 void HighScoreEntry::Animate( Gameduino *gd ) {
 }
+
+/*******************/
+/* WIPE THE CURSOR */
+/*******************/
+// Pass pointer to Gameduino to display on in gd.
+// Pass cell to draw in cell.
+void HighScoreEntry::WipeCursor( Gameduino *gd, FieldCell *cell ) {
+    if( cell != (FieldCell*)NULL ) {
+        CharFrame::Wipe( gd, cell->Rect.X1, cell->Rect.Y1, cell->Rect.GetWidth(), cell->Rect.GetHeight() );
+    }
+}
+
+/*******************/
+/* DRAW THE CURSOR */
+/*******************/
+// Pass pointer to Gameduino to display on in gd.
+// Pass cell to draw in cell.
+void HighScoreEntry::DrawCursor( Gameduino *gd, FieldCell *cell ) {
+    if( cell != (FieldCell*)NULL ) {
+        CharFrame::Draw( gd, cell->Rect.X1, cell->Rect.Y1, cell->Rect.GetWidth(), cell->Rect.GetHeight() );
+    }
+}
+
+/**************************/
+/* VALIDATE CURSOR COLUMN */
+/**************************/
+// If cursor column is beyond end of row then forces it back.
+void HighScoreEntry::ValidateCursorColumn( void ) {
+    FieldRow *row = grid.GetRow( cursorRow );
+    if( row != (FieldRow*)NULL ) {
+        UInt8 columnCount = row->GetColumnCount();
+        if( cursorColumn >= columnCount ) {
+            cursorColumn = columnCount - 1;
+        }
+    }
+}