"Lost treasure of mBedungu" 100 level puzzle game for RETRO

Dependencies:   LCD_ST7735 RetroPlatform mbed

Into Level 0 Menu Level 99

Revision:
1:dcea5500a32d
Parent:
0:f5f961973d01
--- a/Game/GameScreen.cpp	Sat Feb 21 06:19:29 2015 +0000
+++ b/Game/GameScreen.cpp	Sun Mar 01 05:32:06 2015 +0000
@@ -1,26 +1,68 @@
+/*
+ * (C) Copyright 2015 Valentin Ivanov. All rights reserved.
+ *
+ * This file is part of the "Lost treasure of mBedungu" game application for Retro
+ *
+ * The "Lost treasure of mBedungu" application 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+ 
 #include "GameScreen.h"
 #include "Retro.h"
 #include "Sprites.h"
 #include "Levels.h"
 
+#include "Utils.h"
+
 extern Retro retro;
 
-#ifdef FULL_COLOR
-const uint16_t * sprites[] = {
-#else
-const uint8_t * sprites[] = {
-#endif
-    NULL,
-    wall,
-    barrel,
-    ladder,
-    key,
-    door,
-    left,
-    right,
-    crate,
-    totem,
-    rick
+
+const int soundfx[][8] = {
+    {0,24,1,1,1,4,4,9}, // gameover
+    {0,27,53,1,1,1,4,5}, // pickup
+    {0,23,60,1,1,1,4,5} // drop
+};
+
+void sfx(int fxno, int channel)
+{
+    sfx(soundfx[fxno], channel);
+};
+
+void sfx( const int * effect, int channel)
+{
+    retro.sound.command(0, effect[6], 0, channel); // set volume
+    retro.sound.command(1, effect[0], 0, channel); // set waveform
+    retro.sound.command(2, effect[5], -effect[4], channel); // set volume slide
+    retro.sound.command(3, effect[3], effect[2] - 58, channel); // set pitch slide
+    retro.sound.playNote(effect[1], effect[7], channel); // play note
+    
+}
+
+Image sprites[] = {
+    {false, false, NULL},
+    {false, false, wall},
+    {false, false, barrel},
+    {false, false, ladder},
+    {false, false, key},
+    {false, false, door},
+    {false, false, left},
+    {true, false, left},
+    {false, false, crate},
+    {false, false, totem},
+    {false, true, rick},
+    {false, false, rick_top},
+    {false, false, rick_happy}
 };
 
 GameScreen::GameScreen()
@@ -30,6 +72,28 @@
     _pocket[0] = 0;
     _pocket[1] = 0;
     _rickDirection = 0;
+    _gameOver = false;
+    
+    //for some reason writing to eeprom sometime hangs the program                
+//    _gameData[0] = 0;
+//    _gameData[1] = 0;
+//    _gameData[2] = 0;
+//    _gameData[3] = 0;
+//    _gameData[4] = 0;
+//    _gameData[5] = 0;
+//    
+//    read_eeprom((char *)64, _gameData, 8);
+//    if( _gameData[0]=='R' && _gameData[1]=='I' && _gameData[2]=='C' && _gameData[3]=='K' )
+//    {
+//        _level = _gameData[4];
+//        _gameComplete = _gameData[5];
+//    }
+//    
+//    _gameData[0]='R';
+//    _gameData[1]='I';
+//    _gameData[2]='C';
+//    _gameData[3]='K';
+
 }
 
 bool GameScreen::isPocketFull()
@@ -89,12 +153,12 @@
 
 void GameScreen::moveleft()
 {
-    if( _rickDirection == 0 )
-    {
+    if( _rickDirection == 0 ) {
         _rickDirection = 1;
-        drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+        sprites[CELL_RICK].Mirrored = true;//(_rickDirection == 1);
+        drawSprite(_rickX,_rickY, CELL_RICK);
     }
-    
+
     if( _rickX == 0 )
         return;
 
@@ -103,17 +167,32 @@
 
     if( cell == CELL_KEY || cell == CELL_BARREL ) {
         if( putInPocket(cell) ) {
+            sfx(1,0);
             _maze[(_rickY<<3)+_rickX-1] = CELL_EMPTY;
             drawSprite((_rickX-1),_rickY, CELL_EMPTY);
             drawPocket();
+            
+            //Fall any crates on top of that key or barrel
+            int y = _rickY;
+            while( y >= 0 ) {
+                fall(_rickX-1,y--);
+            }
+
         }
         return;
     }
 
-    if( cell == CELL_CRATE && (_rickX-1)>0 )
-    {
-        if( moveto(_rickX-1,_rickY, _rickX-2,_rickY) )
+    if( (cell == CELL_CRATE) && ((_rickX-1)>0) ) {
+        if( moveto(_rickX-1,_rickY, _rickX-2,_rickY) ) {
             fall(_rickX-2,_rickY);
+
+            int y = _rickY;
+            while( y >= 0 ) {
+                fall(_rickX-1,y--);
+            }
+
+        }
+
         return;
     }
 
@@ -125,12 +204,12 @@
 
 void GameScreen::moveright()
 {
-    if( _rickDirection == 1 )
-    {
+    if( _rickDirection == 1 ) {
         _rickDirection = 0;
-        drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+        sprites[CELL_RICK].Mirrored = false;
+        drawSprite(_rickX,_rickY, CELL_RICK);
     }
-    
+
     if( _rickX == 7 )
         return;
 
@@ -138,17 +217,29 @@
 
     if( cell == CELL_KEY || cell == CELL_BARREL ) {
         if( putInPocket(cell) ) {
+            sfx(1,0);
             _maze[(_rickY<<3)+_rickX+1] = CELL_EMPTY;
             drawSprite((_rickX+1),_rickY, CELL_EMPTY);
             drawPocket();
+            
+            //Fall any crates on top of that key or barrel
+            int y = _rickY;
+            while( y >= 0 ) {
+                fall(_rickX+1,y--);
+            }
         }
         return;
     }
-    
-    if( cell == CELL_CRATE && (_rickX+1)<7 )
-    {
-        if( moveto(_rickX+1,_rickY, _rickX+2,_rickY) )
+
+    if( (cell == CELL_CRATE) && ((_rickX+1)<7) ) {
+        if( moveto(_rickX+1,_rickY, _rickX+2,_rickY) ) {
             fall(_rickX+2,_rickY);
+
+            int y = _rickY;
+            while( y >= 0 ) {
+                fall(_rickX+1,y--);
+            }
+        }
         return;
     }
 
@@ -173,13 +264,14 @@
         uint8_t y = _rickY;
         if( moveto(_rickX,_rickY,_rickX,_rickY-1) ) {
             if( getBarrelFromPocket() ) {
+                sfx(2,0);
                 _maze[(y<<3)+x] = CELL_BARREL;
                 drawSprite(x,y,CELL_BARREL);
             } else if( getKeyFromPocket() ) {
+                sfx(2,0);
                 _maze[(y<<3)+x] = CELL_KEY;
                 drawSprite(x,y,CELL_KEY);
             }
-
             drawPocket();
         }
     }
@@ -187,37 +279,20 @@
 
 void GameScreen::movedown()
 {
-    if( _rickY == 0 )
+    if( _rickY == 7 )
         return;
 
-//    uint8_t currentCell = _maze[((_rickY)<<3)+_rickX];
-//    uint8_t belowCell = _maze[((_rickY+1)<<3)+_rickX];
 
-        
-    if( moveto(_rickX,_rickY,_rickX,_rickY+1) )
-    {
-         fall(_rickX,_rickY);
+    if( moveto(_rickX,_rickY,_rickX,_rickY+1) ) {
+        fall(_rickX,_rickY);
     }
-//    if( _rickY > 0 ) {
-//        uint8_t cellAbove = _maze[((_rickY-1)<<3)+_rickX];
-//        if(cellAbove == CELL_EMPTY && !isPocketEmpty()) {
-//            if( getKeyFromPocket() ) {
-//                _maze[(_rickY<<3)+_rickX] = CELL_KEY;
-//            } else if( getBarrelFromPocket() )
-//                _maze[(_rickY<<3)+_rickX] = CELL_BARREL;
-//
-//            _rickY--;
-//            drawSprite(_rickX,_rickY+1, _maze[((_rickY+1)<<3)+_rickX]);
-//            drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
-//            drawPocket();
-//        }
-//    }
+
 }
 
 
 bool GameScreen::moveto(uint8_t fromX, uint8_t fromY, uint8_t toX, uint8_t toY)
 {
-    
+
     bool isRick = false;
 
     if( fromX == _rickX && fromY == _rickY )
@@ -227,11 +302,21 @@
     uint8_t toCell = _maze[((toY)<<3)+toX];
 
     if( isRick ) {
-        if( toCell == CELL_EMPTY || toCell == CELL_LADDER || toCell == CELL_TOTEM ) {
+        if( toCell == CELL_EMPTY || toCell == CELL_LADDER ) {
             drawSprite(fromX,fromY, fromCell);
             _rickX = toX;
             _rickY = toY;
-            drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+            drawSprite(_rickX,_rickY, CELL_RICK);
+            return true;
+        }
+        if( toCell == CELL_TOTEM )
+        {
+            sfx(0,0);
+            _gameOver = true;
+            drawSprite(fromX,fromY, fromCell);
+            _rickX = toX;
+            _rickY = toY;
+            drawSprite(_rickX,_rickY, CELL_RICK);
             return true;
         }
         if( toCell == CELL_DOOR ) {
@@ -240,16 +325,22 @@
                 _maze[((toY)<<3)+toX] = CELL_EMPTY;
                 _rickX = toX;
                 _rickY = toY;
-                drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+                drawSprite(_rickX,_rickY, CELL_RICK);
                 drawPocket();
                 return true;
             }
         }
-    }else if( fromCell == CELL_CRATE && toCell == CELL_EMPTY )
-    {
+        if( (toCell == CELL_RIGHT && fromX < toX) || (toCell == CELL_LEFT && fromX > toX)) {
+            drawSprite(fromX,fromY, fromCell);
+            _rickX = toX;
+            _rickY = toY;
+            drawSprite(_rickX,_rickY, CELL_RICK);
+            return true;
+        }
+    } else if( fromCell == CELL_CRATE && toCell == CELL_EMPTY ) {
         _maze[((toY)<<3)+toX] = CELL_CRATE;
         _maze[((fromY)<<3)+fromX] = CELL_EMPTY;
-        
+
         drawSprite(fromX,fromY, toCell);
         drawSprite(toX,toY, fromCell);
         return true;
@@ -321,28 +412,21 @@
                     break;
             }
         }
+
+    _state = 0;
+    _pocket[0] = 0;
+    _pocket[1] = 0;    
+    _rickDirection = 0;
+    _gameOver = false;
+        
+    sprites[CELL_RICK].Mirrored = false;
+    
+    frame = 0;    
 }
 
 void GameScreen::resetLevel()
 {
     unpackLevel(_level);
-    
-    _state = 0;
-    _pocket[0] = 0;
-    _pocket[1] = 0;
-    _rickDirection = 0;    
-}
-
-void GameScreen::drawSprite(int x, int y, int sprite, bool mirrored)
-{
-    int screenx = x<<4;
-    int screeny = y<<4;
-    if( sprite == 0 )
-        retro.display.fillRect(screenx,screeny, screenx+15,screeny+15,0);
-    else
-    {
-        retro.display.drawBitmapIndexed(screenx,screeny, 16,16,sprites[sprite],palette, mirrored);
-    }
 }
 
 void GameScreen::drawPocket()
@@ -350,12 +434,12 @@
     if( _pocket[0] == 0 )
         retro.display.fillRect(136,80,151,95,0);
     else
-        retro.display.drawBitmapIndexed(136,80, 16,16,sprites[_pocket[0]], palette);
+        retro.display.drawBitmapIndexed(136,80, 16,16,sprites[_pocket[0]].Sprite, palette);
 
     if( _pocket[1] == 0 )
         retro.display.fillRect(136,96,151,111,0);
     else
-        retro.display.drawBitmapIndexed(136,96, 16,16,sprites[_pocket[1]], palette);
+        retro.display.drawBitmapIndexed(136,96, 16,16,sprites[_pocket[1]].Sprite, palette);
 }
 
 
@@ -368,7 +452,7 @@
         }
 
     //Put Rick on the map
-    drawSprite(_rickX, _rickY, CELL_RICK, _rickDirection == 1);
+    drawSprite(_rickX, _rickY, CELL_RICK);
 
     //Draw the statistics and "pocket" area
     for( int y = 0; y < 8; y++ ) {
@@ -378,38 +462,94 @@
     retro.display.drawBitmapIndexed(136,16, 16,16,totem,palette);
     retro.display.fillRect(132,32,155,39,0);
 
-    char buff[4];
-    sprintf(buff,"%d",_level);
-
-    drawString(132,32,buff);
+    drawLevelNumber(136,32,_level);
 
     drawPocket();
 }
 
 
+
 Screen GameScreen::Update()
 {
+    frame++;
+    
     if( _state == 0 ) {
         drawLevel();
         _state = 1;
     }
+    
+    if( _gameOver )
+    {
+        if( (frame % 3) == 0 )
+        {
+            sprites[12].Mirrored = !sprites[12].Mirrored;
+            drawSprite(_rickX,_rickY,12);
+        }        
+    }
 
-    if(retro.buttons.pressed(BTN_LEFT)) {
-        moveleft();
+    if(retro.pressed(BTN_LEFT)) {
+        //sfx(0,0);
+        if( !_gameOver )
+            moveleft();
     }
-    if(retro.buttons.pressed(BTN_RIGHT)) {
+    if(retro.pressed(BTN_RIGHT)) {
+        //sfx(1,0);
+        if( !_gameOver )
         moveright();
     }
-    if(retro.buttons.pressed(BTN_UP)) {
-        moveup();
+    if(retro.pressed(BTN_UP)) {
+        //sfx(2,0);
+        if( !_gameOver )
+            moveup();
     }
-    if(retro.buttons.pressed(BTN_DOWN)) {
+    if(retro.pressed(BTN_DOWN)) {
+        //sfx(3,0);
+        if( !_gameOver )
         movedown();
     }
-    if(retro.buttons.pressed(BTN_ROBOT)) {
+    if(retro.pressed(BTN_ROBOT)) {
         _state = 0;
         return Menu;
     }
+    
+    if(retro.pressed(BTN_SHIP)) {
+        if( _gameOver )
+        {
+            if( _level < 99 )
+            {
+                _level++;
+                resetLevel();
+
+//for some reason writing to eeprom sometime hangs the program                
+//                _gameData[4]= _level;
+//                _gameData[5] = _gameComplete;
+//    
+//                write_eeprom(_gameData, (char *)64, 8 );
+            }
+        }
+    }
 
     return Game;
+}
+
+
+void drawSprite(int x, int y, int sprite)
+{
+    int screenx = x<<4;
+    int screeny = y<<4;
+    if( sprite == 0 )
+        retro.display.fillRect(screenx,screeny, screenx+15,screeny+15,0);
+    else {
+        retro.display.drawBitmapIndexed(screenx,screeny, 16,16,sprites[sprite].Sprite, palette, sprites[sprite].Mirrored);
+    }
+}
+
+void drawLevelNumber(int x, int y, int level)
+{
+    char buf[3];
+    if( (level/10) > 0 )
+        sprintf(buf,"%d",level);
+    else
+        sprintf(buf,"@%d",level);
+    drawString(x,y,buf, palette_orange);
 }
\ No newline at end of file