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 15 19:27:36 2013 +0000
Parent:
15:d8ea0c7b7e64
Child:
17:194789db2215
Commit message:
Entering of high scores nearly there. Just requires code to allow you to backspace and confirm when you have finished.

Changed in this revision

CharFrame.cpp Show annotated file Show diff for this revision Revisions of this file
CharFrame.h Show annotated file Show diff for this revision Revisions of this file
FieldGrid.h Show annotated file Show diff for this revision Revisions of this file
FieldRow.h Show annotated file Show diff for this revision Revisions of this file
HighScoreEntry.cpp Show annotated file Show diff for this revision Revisions of this file
HighScoreEntry.h Show annotated file Show diff for this revision Revisions of this file
--- a/CharFrame.cpp	Sat Jun 15 15:05:19 2013 +0000
+++ b/CharFrame.cpp	Sat Jun 15 19:27:36 2013 +0000
@@ -55,3 +55,35 @@
   gd->wr( address, BottomRight );
 }
 
+/****************/
+/* WIPE A FRAME */
+/****************/
+// Pass Gameduino to draw on in gd.
+// Pass x coordinate of top left in x.
+// Pass y coordinate of top left in y.
+// Pass width in w.
+// Pass height in h.
+void CharFrame::Wipe( Gameduino *gd, UInt8 x, UInt8 y, UInt8 w, UInt8 h ) {
+  // Calculate address for top left.
+  unsigned int rowStart = Gameduino::RAM_PIC + y * SCREEN_CHAR_WIDTH + x;
+  unsigned int address;
+  UInt8 count;
+  // Wipe top edge.
+  address = rowStart;
+  for( count = w; count > 0; --count ) {
+    gd->wr( address++, TransparentChar );
+  }
+  // Wipe left and right edges.
+  address = rowStart + SCREEN_CHAR_WIDTH;
+  if( h > 2 ) {
+      for( count = h - 2; count > 0; --count ) {
+          gd->wr( address, TransparentChar );
+          gd->wr( address + w - 1, TransparentChar );
+      }
+  }
+  // Wipe bottom edge.
+  address = rowStart + SCREEN_CHAR_WIDTH * ( h - 1 );
+  for( count = w; count > 0; --count ) {
+    gd->wr( address++, TransparentChar );
+  }
+}
--- a/CharFrame.h	Sat Jun 15 15:05:19 2013 +0000
+++ b/CharFrame.h	Sat Jun 15 19:27:36 2013 +0000
@@ -26,6 +26,16 @@
     // Pass height in h.
     static void Draw( Gameduino *gd, UInt8 x, UInt8 y, UInt8 w, UInt8 h );
 
+    /****************/
+    /* WIPE A FRAME */
+    /****************/
+    // Pass Gameduino to draw on in gd.
+    // Pass x coordinate of top left in x.
+    // Pass y coordinate of top left in y.
+    // Pass width in w.
+    // Pass height in h.
+    static void Wipe( Gameduino *gd, UInt8 x, UInt8 y, UInt8 w, UInt8 h );
+
   };
   
 #endif
--- a/FieldGrid.h	Sat Jun 15 15:05:19 2013 +0000
+++ b/FieldGrid.h	Sat Jun 15 19:27:36 2013 +0000
@@ -44,6 +44,22 @@
         return rowCount;
     }
 
+    /*****************************************/
+    /* GET CELL AT PARTICULAR ROW AND COLUMN */
+    /*****************************************/
+    // Pass row number in rowNum.
+    // Pass column number in columnNum.
+    // Returns pointer to cell or NULL if cell does not exist.
+    FieldCell *GetCellAt( UInt8 rowNum, UInt8 columnNum ) {
+        FieldRow *row = GetRow( rowNum );
+        if( row != (FieldRow*)NULL ) {
+            return row->GetCellAt( columnNum );
+        }
+        else {
+            return (FieldCell*)NULL;
+        }
+    }
+    
   private :
   
     // Pointer to array of FieldRow objects, one for each row in the grid.
--- a/FieldRow.h	Sat Jun 15 15:05:19 2013 +0000
+++ b/FieldRow.h	Sat Jun 15 19:27:36 2013 +0000
@@ -72,7 +72,21 @@
         }
         return result;
     }
-    
+
+    /********************************/
+    /* GET NUMBER OF COLUMNS IN ROW */
+    /********************************/
+    // Returns number of columns in row.
+    UInt8 GetColumnCount( void ) {
+        UInt8 count = 0;
+        FieldCell *cell = GetFirstCell();
+        while( cell != (FieldCell*)NULL ) {
+            count++;
+            cell = GetNextCell();
+        }
+        return count;
+    }
+        
   private :
   
     // The root cell of the row.
--- 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;
+        }
+    }
+}
--- a/HighScoreEntry.h	Sat Jun 15 15:05:19 2013 +0000
+++ b/HighScoreEntry.h	Sat Jun 15 19:27:36 2013 +0000
@@ -40,9 +40,12 @@
 
 private :
 
-    // Position of cursor (zero for first character).
-    UInt8 cursorPos;
-
+    // Index of character being modified in the name.
+    UInt8 charIndex;
+    
+    // Grid row and column number for cursor.
+    UInt8 cursorRow, cursorColumn;
+    
     // Grid around which cursor moves.
     FieldGrid grid;
     
@@ -64,7 +67,8 @@
     /* DRAW THE SCREEN */
     /*******************/
     // Pass pointer to Gameduino to display on in gd.
-    void DrawScreen( Gameduino *gd );    
+    // Pass player name in name.
+    void DrawScreen( Gameduino *gd, PlayerName *name );
 
     /***************************/
     /* DRAW THE CHARACTER GRID */
@@ -85,6 +89,26 @@
     // Pass pointer to Gameduino to display on in gd.
     void Animate( Gameduino *gd );
 
+    /*******************/
+    /* WIPE THE CURSOR */
+    /*******************/
+    // Pass pointer to Gameduino to display on in gd.
+    // Pass cell to draw in cell.
+    void WipeCursor( Gameduino *gd, FieldCell *cell );
+
+    /*******************/
+    /* DRAW THE CURSOR */
+    /*******************/
+    // Pass pointer to Gameduino to display on in gd.
+    // Pass cell to draw in cell.
+    void DrawCursor( Gameduino *gd, FieldCell *cell );
+    
+    /**************************/
+    /* VALIDATE CURSOR COLUMN */
+    /**************************/
+    // If cursor column is beyond end of row then forces it back.
+    void ValidateCursorColumn( void );
+    
   };
 
 #endif