Louis Mayencourt / Mbed OS NRFBOY

Files at this revision

API Documentation at this revision

Comitter:
lmayencou
Date:
Sat Jan 07 12:43:36 2017 +0000
Parent:
2:e3ef9f476913
Child:
4:63cfe7ff1c02
Commit message:
add frame timer - game working - bug with high scores

Changed in this revision

abstractarduboy.cpp Show annotated file Show diff for this revision Revisions of this file
abstractarduboy.h Show annotated file Show diff for this revision Revisions of this file
ardubreakout.hpp Show annotated file Show diff for this revision Revisions of this file
breakout_bitmaps.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbedboy.hpp Show annotated file Show diff for this revision Revisions of this file
--- a/abstractarduboy.cpp	Fri Jan 06 22:29:05 2017 +0000
+++ b/abstractarduboy.cpp	Sat Jan 07 12:43:36 2017 +0000
@@ -1,11 +1,5 @@
 #include "abstractarduboy.h"
 
-#define _BV(b) (1UL << (b))
-#define min(a,b) (((a)<(b))?(a):(b))
-#define max(a,b) (((a)>(b))?(a):(b))
-#define abs(a) (((a) < 0) ? -(a) : (a))
-#define pgm_read_byte(a) 1
-
 AbstractArduboy::AbstractArduboy()
 {
     frameRate = 60;
@@ -141,11 +135,21 @@
   fillScreen(0);
 }
 
+void AbstractArduboy::clear()
+{
+    fillScreen(0);    
+}
+
 void AbstractArduboy::clearDisplay()
 {
     fillScreen(0);
 }
 
+void AbstractArduboy::display()
+{
+  this->drawScreen(sBuffer);
+}
+
 void AbstractArduboy::drawPixel(int x, int y, uint8_t color)
 {
 #ifdef PIXEL_SAFE_MODE
@@ -669,7 +673,5 @@
     b = t;
 }
 
-void AbstractArduboy::display()
-{
-  this->drawScreen(sBuffer);
-}
+bool AbstractArduboy::ArduboyAudio::enabled()
+{}
--- a/abstractarduboy.h	Fri Jan 06 22:29:05 2017 +0000
+++ b/abstractarduboy.h	Sat Jan 07 12:43:36 2017 +0000
@@ -13,6 +13,22 @@
 #define COLUMN_ADDRESS_END (WIDTH - 1) & 0x7F
 #define PAGE_ADDRESS_END ((HEIGHT/8)-1) & 0x07
 
+#define _BV(b) (1UL << (b))
+#define min(a,b) (((a)<(b))?(a):(b))
+#define max(a,b) (((a)>(b))?(a):(b))
+#define abs(a) (((a) < 0) ? -(a) : (a))
+#define pgm_read_byte(a) 1
+
+#define LEFT_BUTTON _BV(0)
+#define RIGHT_BUTTON _BV(1)
+#define UP_BUTTON _BV(2)
+#define DOWN_BUTTON _BV(3)
+#define A_BUTTON _BV(4)
+#define B_BUTTON _BV(5)
+
+typedef bool boolean;
+typedef uint8_t byte;
+
 class AbstractArduboy
 {
 public:
@@ -32,6 +48,9 @@
     // virtual
     virtual void idle();
     virtual void saveMuchPower();
+    
+    // init
+    void begin(){start();};
 
     // frame management
     void setFrameRate(uint8_t rate);
@@ -49,6 +68,7 @@
 
     // graphics
     void blank();
+    void clear();
     void clearDisplay();
     void display();
     void drawPixel(int x, int y, uint8_t color);
@@ -68,14 +88,28 @@
     void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint8_t color);
     void drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color);
 
-    /// Draw a text character at a specified pixel location
     void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size);
-    /// Draw a text character at the text cursor location
     uint8_t writeChar(uint8_t);
-    /// Set the text cursor location, based on the size of the text
-    inline void setTextCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; };
+    inline void setCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; };
+    void setTextSize(uint8_t s) {textsize = max(1,s); };
 
     static inline void swap(int16_t &a, int16_t &b);
+    
+    // Audio
+    class ArduboyAudio
+    {
+      public:
+        ArduboyAudio(){audio_enabled = false;};
+        void setup();
+        void on();
+        void off();
+        void saveOnOff();
+        bool enabled();
+        void tone(unsigned int frequency, unsigned long duration);
+    
+      protected:
+        bool audio_enabled;
+    }audio;
 
 protected:
     uint8_t frameRate;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ardubreakout.hpp	Sat Jan 07 12:43:36 2017 +0000
@@ -0,0 +1,719 @@
+ /**
+  * @filename ArduBreakout.ino
+  * \brief Breakout
+  * \details 
+  * Copyright (C) 2011 Sebastian Goscik
+  * All rights reserved.
+
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  */
+
+//#include <Arduboy.h>
+#include "mbedboy.hpp"
+
+#include "breakout_bitmaps.h"
+
+MbedBoy arduboy;
+
+const unsigned int COLUMNS = 13; //Columns of bricks
+const unsigned int ROWS = 4;     //Rows of bricks
+int dx = -1;                     //Initial movement of ball
+int dy = -1;                     //Initial movement of ball
+int xb;                          //Balls starting possition
+int yb;                          //Balls starting possition
+boolean released;                //If the ball has been released by the player
+boolean paused = false;          //If the game has been paused
+byte xPaddle;                    //X position of paddle
+boolean isHit[ROWS][COLUMNS];    //Array of if bricks are hit or not
+boolean bounced=false;           //Used to fix double bounce glitch
+byte lives = 3;                  //Amount of lives
+byte level = 1;                  //Current level
+unsigned int score=0;            //Score for the game
+unsigned int brickCount;         //Amount of bricks hit
+byte pad,pad2,pad3;              //Button press buffer to stop pause repeating
+byte oldpad,oldpad2,oldpad3;
+char text_buffer[16];            //General string buffer
+boolean start=false;             //If in menu or in game
+boolean initialDraw=false;       //If the inital draw has happened
+char initials[3];                //Initials used in high score
+
+//Ball Bounds used in collision detection
+byte leftBall;
+byte rightBall;
+byte topBall;
+byte bottomBall;
+
+//Brick Bounds used in collision detection
+byte leftBrick;
+byte rightBrick;
+byte topBrick;
+byte bottomBrick;
+
+byte tick;
+
+// Method declaration
+void movePaddle();
+void moveBall();
+void drawBall();
+void drawPaddle();
+void drawLives();
+void drawGameOver();
+void pause();
+void Score();
+void newLevel();
+boolean pollFireButton(int n);
+boolean displayHighScores(byte file);
+boolean titleScreen();
+void enterInitials();
+
+
+/// Wrap the Arduino tone function
+void playTone(unsigned int frequency, unsigned long duration)
+{
+  if (arduboy.audio.enabled() == true)
+  {
+    //tone(PIN_SPEAKER_1, frequency, duration);
+  }
+}
+
+void setup()
+{
+  arduboy.begin();
+  arduboy.setFrameRate(25);
+}
+
+void loop()
+{ 
+  // pause render until it's time for the next frame
+  if (!(arduboy.nextFrame()))
+    return;
+
+
+  //Title screen loop switches from title screen
+  //and high scores until FIRE is pressed
+  while (!start)
+  {
+    start = titleScreen();
+    if (!start)
+    {
+      start = displayHighScores(2);
+    }
+  }
+
+  //Initial level draw
+  if (!initialDraw)
+  {
+    //Clears the screen
+    arduboy.clear();
+    //Selects Font
+    //Draws the new level
+    newLevel();
+    initialDraw=true;
+  }
+
+  if (lives > 0)
+  {
+    drawPaddle();
+
+    //Pause game if FIRE pressed
+    pad = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
+
+    if(pad > 1 && oldpad == 0 && released)
+    {
+      oldpad2=0; //Forces pad loop 2 to run once
+      pause();
+    }
+
+    oldpad = pad;
+    drawBall();
+
+    if(brickCount == ROWS * COLUMNS)
+    {
+      level++;
+      newLevel();
+    }
+  }
+  else
+  {
+    drawGameOver();
+//    if (score > 0)
+//    {
+//      enterHighScore(2);
+//    }
+
+    arduboy.clear();
+    initialDraw = false;
+    start = false;
+    lives = 3;
+    score = 0;
+    newLevel();
+  }
+
+  arduboy.display();
+}
+
+void movePaddle()
+{
+  //Move right
+  if(xPaddle < WIDTH - 12)
+  {
+    if (arduboy.pressed(RIGHT_BUTTON))
+      xPaddle += 2;
+  }
+
+  //Move left
+  if(xPaddle > 0)
+  {
+    if (arduboy.pressed(LEFT_BUTTON))
+      xPaddle -= 2;
+  }
+}
+
+void moveBall()
+{
+  tick++;
+  if(released)
+  {
+    //Move ball
+    if (abs(dx) == 2)
+    {
+      xb += dx / 2;
+      // 2x speed is really 1.5 speed
+      if (tick % 2 == 0)
+        xb += dx / 2;
+    }
+    else
+      xb += dx;
+    yb = yb + dy;
+
+    //Set bounds
+    leftBall = xb;
+    rightBall = xb + 2;
+    topBall = yb;
+    bottomBall = yb + 2;
+
+    //Bounce off top edge
+    if (yb <= 0)
+    {
+      yb = 2;
+      dy = -dy;
+      playTone(523, 250);
+    }
+
+    //Lose a life if bottom edge hit
+    if (yb >= 64)
+    {
+      arduboy.drawRect(xPaddle, 63, 11, 1, 0);
+      xPaddle = 54;
+      yb=60;
+      released = false;
+      lives--;
+      drawLives();
+      playTone(175, 250);
+      if (rand()%2 == 0)
+        dx = 1;
+      else
+        dx = -1;
+    }
+
+    //Bounce off left side
+    if (xb <= 0)
+    {
+      xb = 2;
+      dx = -dx;
+      playTone(523, 250);
+    }
+
+    //Bounce off right side
+    if (xb >= WIDTH - 2)
+    {
+      xb = WIDTH - 4;
+      dx = -dx;
+      playTone(523, 250);
+    }
+
+    //Bounce off paddle
+    if (xb + 1 >= xPaddle && xb <= xPaddle + 12 && yb + 2 >= 63 && yb <= 64)
+    {
+      dy = -dy;
+      dx = ((xb - (xPaddle + 6)) / 3); //Applies spin on the ball
+      // prevent straight bounce
+      if (dx == 0)
+        dx = (rand()%2 == 1) ? 1 : -1;
+      playTone(200, 250);
+    }
+
+    //Bounce off Bricks
+    for (byte row = 0; row < ROWS; row++)
+    {
+      for (byte column = 0; column < COLUMNS; column++)
+      {
+        if (!isHit[row][column])
+        {
+          //Sets Brick bounds
+          leftBrick = 10 * column;
+          rightBrick = 10 * column + 10;
+          topBrick = 6 * row + 1;
+          bottomBrick = 6 * row + 7;
+
+          //If A collison has occured
+          if (topBall <= bottomBrick && bottomBall >= topBrick &&
+              leftBall <= rightBrick && rightBall >= leftBrick)
+          {
+            Score();
+            brickCount++;
+            isHit[row][column] = true;
+            arduboy.drawRect(10 * column, 2 + 6 * row, 8, 4, 0);
+
+            //Vertical collision
+            if (bottomBall > bottomBrick || topBall < topBrick)
+            {
+              //Only bounce once each ball move
+              if(!bounced)
+              {
+                dy =- dy;
+                yb += dy;
+                bounced = true;
+                playTone(261, 250);
+              }
+            }
+
+            //Hoizontal collision
+            if (leftBall < leftBrick || rightBall > rightBrick)
+            {
+              //Only bounce once brick each ball move
+              if(!bounced)
+              {
+                dx =- dx;
+                xb += dx;
+                bounced = true;
+                playTone(261, 250);
+              }
+            }
+          }
+        }
+      }
+    }
+    //Reset Bounce
+    bounced = false;
+  }
+  else
+  {
+    //Ball follows paddle
+    xb=xPaddle + 5;
+
+    //Release ball if FIRE pressed
+    pad3 = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
+    if (pad3 == 1 && oldpad3 == 0)
+    {
+      released=true;
+
+      //Apply random direction to ball on release
+      if (rand()%2 == 0)
+      {
+        dx = 1;
+      }
+      else
+      {
+        dx = -1;
+      }
+      //Makes sure the ball heads upwards
+      dy = -1;
+    }
+    oldpad3 = pad3;
+  }
+}
+
+void drawBall()
+{
+  // arduboy.setCursor(0,0);
+  // arduboy.printf(arduboy.cpuLoad());
+  // arduboy.printf("  ");
+  arduboy.drawPixel(xb,   yb,   0);
+  arduboy.drawPixel(xb+1, yb,   0);
+  arduboy.drawPixel(xb,   yb+1, 0);
+  arduboy.drawPixel(xb+1, yb+1, 0);
+
+  moveBall();
+
+  arduboy.drawPixel(xb,   yb,   1);
+  arduboy.drawPixel(xb+1, yb,   1);
+  arduboy.drawPixel(xb,   yb+1, 1);
+  arduboy.drawPixel(xb+1, yb+1, 1);
+}
+
+void drawPaddle()
+{
+  arduboy.drawRect(xPaddle, 63, 11, 1, 0);
+  movePaddle();
+  arduboy.drawRect(xPaddle, 63, 11, 1, 1);
+}
+
+void drawLives()
+{
+  sprintf(text_buffer, "LIVES:%u", lives);
+  arduboy.setCursor(0, 90);
+  arduboy.printf(text_buffer);
+}
+
+void drawGameOver()
+{
+  arduboy.drawPixel(xb,   yb,   0);
+  arduboy.drawPixel(xb+1, yb,   0);
+  arduboy.drawPixel(xb,   yb+1, 0);
+  arduboy.drawPixel(xb+1, yb+1, 0);
+  arduboy.setCursor(52, 42);
+  arduboy.printf( "Game");
+  arduboy.setCursor(52, 54);
+  arduboy.printf("Over");
+  arduboy.display();
+  wait_ms(4000);
+}
+
+void pause()
+{
+  paused = true;
+  //Draw pause to the screen
+  arduboy.setCursor(52, 45);
+  arduboy.printf("PAUSE");
+  arduboy.display();
+  while (paused)
+  {
+    wait_ms(150);
+    //Unpause if FIRE is pressed
+    pad2 = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
+    if (pad2 > 1 && oldpad2 == 0 && released)
+    {
+        arduboy.fillRect(52, 45, 30, 11, 0);
+
+        paused=false;
+    }
+    oldpad2=pad2;
+  }
+}
+
+void Score()
+{
+  score += (level*10);
+  sprintf(text_buffer, "SCORE:%u", score);
+  arduboy.setCursor(80, 90);
+  arduboy.printf(text_buffer);
+}
+
+void newLevel(){
+  //Undraw paddle
+  arduboy.drawRect(xPaddle, 63, 11, 1, 0);
+
+  //Undraw ball
+  arduboy.drawPixel(xb,   yb,   0);
+  arduboy.drawPixel(xb+1, yb,   0);
+  arduboy.drawPixel(xb,   yb+1, 0);
+  arduboy.drawPixel(xb+1, yb+1, 0);
+
+  //Alter various variables to reset the game
+  xPaddle = 54;
+  yb = 60;
+  brickCount = 0;
+  released = false;
+
+  //Draws new bricks and resets their values
+  for (byte row = 0; row < 4; row++)
+  {
+    for (byte column = 0; column < 13; column++)
+    {
+      isHit[row][column] = false;
+      arduboy.drawRect(10 * column, 2 + 6 * row, 8, 4, 1);
+    }
+  }
+
+  //Draws the initial lives
+  drawLives();
+
+  //Draws the initial score
+  sprintf(text_buffer, "SCORE:%u", score);
+  arduboy.setCursor(80, 90);
+  arduboy.printf(text_buffer);
+}
+
+//Used to delay images while reading button input
+boolean pollFireButton(int n)
+{
+  for (int i = 0; i < n; i++)
+  {
+    wait_ms(15);
+    pad = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
+    if (pad == 1 && oldpad == 0)
+    {
+      oldpad3 = 1; //Forces pad loop 3 to run once
+      return true;
+    }
+    oldpad = pad;
+  }
+  return false;
+}
+
+//Function by nootropic design to display highscores
+boolean displayHighScores(byte file)
+{
+  byte y = 10;
+  byte x = 24;
+  // Each block of EEPROM has 10 high scores, and each high score entry
+  // is 5 bytes long:  3 bytes for initials and two bytes for score.
+  int address = file*10*5;
+  byte hi, lo;
+  arduboy.clear();
+  arduboy.setCursor(32, 0);
+  arduboy.printf("HIGH SCORES");
+  arduboy.display();
+
+  for(int i = 0; i < 10; i++)
+  {
+    sprintf(text_buffer, "%2d", i+1);
+    arduboy.setCursor(x,y+(i*8));
+    arduboy.printf(text_buffer);
+    arduboy.display();
+//    hi = EEPROM.read(address + (5*i));
+//    lo = EEPROM.read(address + (5*i) + 1);
+    hi = 0xff;
+    lo = 0xff;
+
+    if ((hi == 0xFF) && (lo == 0xFF))
+      score = 0;
+    else
+      score = (hi << 8) | lo;
+
+//    initials[0] = (char)EEPROM.read(address + (5*i) + 2);
+//    initials[1] = (char)EEPROM.read(address + (5*i) + 3);
+//    initials[2] = (char)EEPROM.read(address + (5*i) + 4);
+    initials[0] = 'A';
+    initials[1] = 'B';
+    initials[2] = 'C';
+
+    if (score > 0)
+    {
+      sprintf(text_buffer, "%c%c%c %u", initials[0], initials[1], initials[2], score);
+      arduboy.setCursor(x + 24, y + (i*8));
+      arduboy.printf(text_buffer);
+      arduboy.display();
+    }
+  }
+
+  if (pollFireButton(300))
+    return true;
+
+  return false;
+  arduboy.display();
+}
+
+boolean titleScreen()
+{
+  //Clears the screen
+  arduboy.clear();
+  arduboy.setCursor(16,22);
+  arduboy.setTextSize(2);
+  arduboy.printf("ARAKNOID");
+  arduboy.setTextSize(1);
+  arduboy.display();
+
+  if (pollFireButton(25))
+    return true;
+
+  //Flash "Press FIRE" 5 times
+  for(byte i = 0; i < 5; i++)
+  {
+    //Draws "Press FIRE"
+    //arduboy.bitmap(31, 53, fire);  arduboy.display();
+    arduboy.setCursor(31, 53);
+    arduboy.printf("PRESS FIRE!");
+    arduboy.display();
+
+    if (pollFireButton(50))
+      return true;
+
+    //Removes "Press FIRE"
+    arduboy.clear();
+    arduboy.setCursor(16,22);
+    arduboy.setTextSize(2);
+    arduboy.printf("ARAKNOID");
+    arduboy.setTextSize(1);
+    arduboy.display();
+
+    arduboy.display();
+    if (pollFireButton(25))
+      return true;
+  }
+
+  return false;
+}
+
+//Function by nootropic design to add high scores
+void enterInitials()
+{
+  char index = 0;
+
+  arduboy.clear();
+
+  initials[0] = ' ';
+  initials[1] = ' ';
+  initials[2] = ' ';
+
+  while (true)
+  {
+    arduboy.display();
+    arduboy.clear();
+
+    arduboy.setCursor(16,0);
+    arduboy.printf("HIGH SCORE");
+    sprintf(text_buffer, "%u", score);
+    arduboy.setCursor(88, 0);
+    arduboy.printf(text_buffer);
+    arduboy.setCursor(56, 20);
+    arduboy.printf("%c", initials[0]);
+    arduboy.setCursor(64, 20);
+    arduboy.printf("%c", initials[1]);
+    arduboy.setCursor(72, 20);
+    arduboy.printf("%c", initials[2]);
+
+    for(byte i = 0; i < 3; i++)
+      arduboy.drawLine(56 + (i*8), 27, 56 + (i*8) + 6, 27, 1);
+
+    arduboy.drawLine(56, 28, 88, 28, 0);
+    arduboy.drawLine(56 + (index*8), 28, 56 + (index*8) + 6, 28, 1);
+
+    wait_ms(150);
+
+    if (arduboy.pressed(LEFT_BUTTON) || arduboy.pressed(B_BUTTON))
+    {
+      index--;
+      if (index < 0)
+        index = 0;
+      else
+        playTone(1046, 250);
+    }
+
+    if (arduboy.pressed(RIGHT_BUTTON))
+    {
+      index++;
+      if (index > 2)
+        index = 2;
+      else
+        playTone(1046, 250);
+    }
+
+    if (arduboy.pressed(DOWN_BUTTON))
+    {
+      initials[index]++;
+      playTone(523, 250);
+      // A-Z 0-9 :-? !-/ ' '
+      if (initials[index] == '0')
+        initials[index] = ' ';
+      if (initials[index] == '!')
+        initials[index] = 'A';
+      if (initials[index] == '[')
+        initials[index] = '0';
+      if (initials[index] == '@')
+        initials[index] = '!';
+    }
+
+    if (arduboy.pressed(UP_BUTTON))
+    {
+      initials[index]--;
+      playTone(523, 250);
+      if (initials[index] == ' ')
+        initials[index] = '?';
+      if (initials[index] == '/')
+        initials[index] = 'Z';
+      if (initials[index] == 31)
+        initials[index] = '/';
+      if (initials[index] == '@')
+        initials[index] = ' ';
+    }
+
+    if (arduboy.pressed(A_BUTTON))
+    {
+      if (index < 2)
+      {
+        index++;
+        playTone(1046, 250);
+      } else {
+        playTone(1046, 250);
+        return;
+      }
+    }
+  }
+
+}
+
+#if 0
+void enterHighScore(byte file)
+{
+  // Each block of EEPROM has 10 high scores, and each high score entry
+  // is 5 bytes long:  3 bytes for initials and two bytes for score.
+  int address = file * 10 * 5;
+  byte hi, lo;
+  char tmpInitials[3];
+  unsigned int tmpScore = 0;
+
+  // High score processing
+  for(byte i = 0; i < 10; i++)
+  {
+    hi = EEPROM.read(address + (5 * i));
+    lo = EEPROM.read(address + (5 * i) + 1);
+    if ((hi == 0xFF) && (lo == 0xFF))
+    {
+      // The values are uninitialized, so treat this entry
+      // as a score of 0.
+      tmpScore = 0;
+    } else
+    {
+      tmpScore = (hi << 8) | lo;
+    }
+    if (score > tmpScore)
+    {
+      enterInitials();
+      for(byte j = i; j < 10; j++)
+      {
+        hi = EEPROM.read(address + (5 * j));
+        lo = EEPROM.read(address + (5 * j) + 1);
+
+        if ((hi == 0xFF) && (lo == 0xFF))
+        {
+        tmpScore = 0;
+        }
+        else
+        {
+          tmpScore = (hi << 8) | lo;
+        }
+
+        tmpInitials[0] = (char)EEPROM.read(address + (5*j) + 2);
+        tmpInitials[1] = (char)EEPROM.read(address + (5*j) + 3);
+        tmpInitials[2] = (char)EEPROM.read(address + (5*j) + 4);
+
+        // write score and initials to current slot
+        EEPROM.write(address + (5*j), ((score >> 8) & 0xFF));
+        EEPROM.write(address + (5*j) + 1, (score & 0xFF));
+        EEPROM.write(address + (5*j) + 2, initials[0]);
+        EEPROM.write(address + (5*j) + 3, initials[1]);
+        EEPROM.write(address + (5*j) + 4, initials[2]);
+
+        // tmpScore and tmpInitials now hold what we want to
+        //write in the next slot.
+        score = tmpScore;
+        initials[0] = tmpInitials[0];
+        initials[1] = tmpInitials[1];
+        initials[2] = tmpInitials[2];
+      }
+
+      score = 0;
+      initials[0] = ' ';
+      initials[1] = ' ';
+      initials[2] = ' ';
+
+      return;
+    }
+  }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakout_bitmaps.h	Sat Jan 07 12:43:36 2017 +0000
@@ -0,0 +1,128 @@
+#ifndef BREAKOUT_BITMAPS_H
+#define BREAKOUT_BITMAPS_H
+
+const unsigned char title[] =
+{
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x07,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,
+  0x00,0x08,0x00,0x60,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x03,0xF4,0x10,0x00,
+  0x00,0x0B,0xFF,0x10,0x00,0x00,0x00,0x20,0x80,0x00,0x00,0x04,0x09,0xD0,0x00,
+  0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0xB8,0x00,0x00,0x05,0xE1,0xD0,0x00,
+  0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0x44,0x00,0x00,0x05,0xE1,0xD0,0x00,
+  0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0x34,0x00,0x00,0x05,0xE1,0xD0,0x00,
+  0x00,0x0B,0x83,0xCF,0xFF,0xF9,0xFF,0xAE,0x35,0xFF,0x7C,0xF9,0xE1,0xD0,0x00,
+  0x00,0x0B,0x83,0xC0,0x00,0x06,0x00,0x4E,0x66,0x00,0x83,0x01,0xE1,0xD0,0x00,
+  0x00,0x0B,0xFF,0x13,0xE7,0xF0,0xFF,0x0F,0xE0,0x7E,0x38,0x73,0xF9,0xD0,0x00,
+  0x00,0x0B,0xFF,0x13,0xE7,0xF0,0xFF,0x0F,0xC0,0x7E,0x38,0x73,0xF9,0xD0,0x00,
+  0x00,0x0B,0x83,0xDC,0x0E,0x0C,0x01,0xCF,0x80,0xE1,0x38,0x71,0xE1,0xD0,0x00,
+  0x00,0x0B,0x83,0xDC,0xCE,0x0C,0x01,0xCF,0xC0,0xE1,0x38,0x71,0xE1,0xD0,0x00,
+  0x00,0x0B,0x83,0xDD,0x2F,0xF0,0x7F,0xCE,0xE0,0xE1,0x38,0x71,0xE0,0x10,0x00,
+  0x00,0x0B,0x83,0xDD,0x2F,0xF0,0xFF,0xCE,0x70,0xE1,0x38,0x71,0xE0,0x10,0x00,
+  0x00,0x0B,0x83,0xDD,0x2E,0x00,0x81,0xCE,0x38,0xE1,0x38,0x71,0xE1,0xD0,0x00,
+  0x00,0x0B,0xFF,0x1D,0x27,0xFC,0xFE,0xCE,0x1C,0x7E,0x1F,0xC4,0x79,0xD0,0x00,
+  0x00,0x0B,0xFF,0x1D,0x17,0xFC,0x7E,0xCE,0x0C,0x7E,0x1F,0xCA,0x79,0xD0,0x00,
+  0x00,0x08,0x00,0x41,0x10,0x01,0x00,0x00,0xE1,0x00,0xC0,0x11,0x00,0x10,0x00,
+  0x00,0x07,0xFF,0xBE,0x0F,0xFE,0xFF,0xFF,0x1E,0xFF,0x3F,0xE0,0xFF,0xE0,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x04,0x04,0x10,0x03,0x8A,0x10,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x04,0x00,0x00,0x02,0x08,0x80,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0xF3,0x35,0x54,0xD7,0x63,0x1A,0xD7,0x60,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x46,0x54,0x95,0x52,0x2A,0x95,0x50,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x35,0x25,0x97,0x53,0x9A,0x57,0x50,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0xF0,0x06,0x04,0x00,0x04,0x00,0x38,0x00,0x0A,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x88,0x09,0x04,0x00,0x20,0x00,0x44,0x00,0x02,0x00,0x00,0x00,
+  0x00,0x00,0x00,0xF2,0x84,0x27,0x31,0xB5,0x98,0x40,0xC6,0x6A,0x80,0x00,0x00,
+  0x00,0x00,0x00,0x8A,0x82,0x54,0x8A,0x24,0x54,0x4D,0x28,0x8B,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x8A,0x89,0x44,0xA8,0xA5,0x54,0x45,0x22,0x8A,0x80,0x00,0x00,
+  0x00,0x00,0x00,0xF1,0x06,0x37,0x1B,0x14,0xD4,0x3C,0xCC,0x6A,0x80,0x00,0x00,
+  0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+const unsigned char fire[] =
+{
+  57,8,
+  0xF8,0x00,0x00,0x00,0x3D,0xEF,0x8F,0x80,
+  0xCC,0x00,0x00,0x00,0x60,0xCC,0xD8,0x00,
+  0xCC,0x00,0x00,0x00,0x60,0xCC,0xD8,0x00,
+  0xF9,0x67,0x1E,0x78,0x78,0xCF,0x9F,0x00,
+  0xC1,0x8C,0xA0,0x80,0x60,0xCC,0xD8,0x00,
+  0xC1,0x8F,0x1C,0x70,0x60,0xCC,0xD8,0x00,
+  0xC1,0x8C,0x02,0x08,0x60,0xCC,0xDF,0x80,
+  0xC1,0x87,0xBC,0xF0,0x61,0xEC,0xCF,0x80,
+};
+
+const unsigned char arrow[] =
+{
+  5,5,
+  0x20,
+  0x10,
+  0xF8,
+  0x10,
+  0x20,
+};
+
+
+#endif
\ No newline at end of file
--- a/main.cpp	Fri Jan 06 22:29:05 2017 +0000
+++ b/main.cpp	Sat Jan 07 12:43:36 2017 +0000
@@ -1,14 +1,13 @@
 #include "mbed.h"
 
-#include "helloworld.hpp"
+//#include "helloworld.hpp"
+#include "ardubreakout.hpp"
 
 DigitalOut led1(LED1);
 
 //DigitalOut led3(LED3);
 //DigitalOut led4(LED4);
 
-//DigitalIn   butt1(BUTTON1);
-
 Ticker ticker;
 
 void periodicCallback(void)
@@ -19,7 +18,6 @@
 // main() runs in its own thread in the OS
 // (note the calls to Thread::wait below for delays)
 int main() {
-    printf("start main");
     ticker.attach(periodicCallback, 1); /* Blink LED every second */
     
     setup();
--- a/mbedboy.hpp	Fri Jan 06 22:29:05 2017 +0000
+++ b/mbedboy.hpp	Sat Jan 07 12:43:36 2017 +0000
@@ -1,11 +1,25 @@
+#include "mbed.h"
 #include "abstractarduboy.h"
 
+Ticker timer;
 SPI _spi(p30, p31, p29); // mosi, miso, sclk
 
 DigitalOut _cs(p3);
 DigitalOut _dc(p28);
 DigitalOut _rst(p4);
 
+DigitalIn   _left(BUTTON1);
+DigitalIn   _right(BUTTON4);
+DigitalIn   _A(BUTTON2);
+DigitalIn   _B(BUTTON3);
+
+unsigned long  _millis;
+
+void gameTimerCallback(void)
+{
+    _millis++;
+}
+
 class MbedBoy : public AbstractArduboy, public Stream
 {
   public:
@@ -13,10 +27,19 @@
 
     void start()
     {
+        // init systime
+        timer.attach(gameTimerCallback, 0.001); /* Blink LED every second */
+        
         // init SPI
         _spi.format(8,3);
         _spi.frequency(1000000);
         
+        // init pin
+        _left.mode(PullUp);
+        _right.mode(PullUp);
+        _A.mode(PullUp);
+        _B.mode(PullUp);
+        
         // init pin LCD
         _dc = 0;
         _cs = 0;
@@ -31,7 +54,7 @@
     
     long getTime()
     {
-        return time(NULL);
+        return _millis;
     }
     
     void drawScreen(const unsigned char *image)
@@ -44,7 +67,7 @@
     
     uint8_t getInput()
     {
-    
+        return !_left + ((!_right) << 1) + ((!_A) << 4) + ((!_B) << 5);
     }
 
     void LCDCommandMode()
@@ -109,5 +132,4 @@
     // You would otherwise be forced to use writeChar()
     virtual int _putc(int value) { return writeChar(value); };
     virtual int _getc() { return -1; };
-
 };
\ No newline at end of file