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

Dependencies:   LCD_ST7735 RetroPlatform mbed

Into Level 0 Menu Level 99

Revision:
0:f5f961973d01
Child:
1:dcea5500a32d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game/GameScreen.cpp	Sat Feb 21 06:19:29 2015 +0000
@@ -0,0 +1,415 @@
+#include "GameScreen.h"
+#include "Retro.h"
+#include "Sprites.h"
+#include "Levels.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
+};
+
+GameScreen::GameScreen()
+{
+    _level = 0;
+    _state = 0;
+    _pocket[0] = 0;
+    _pocket[1] = 0;
+    _rickDirection = 0;
+}
+
+bool GameScreen::isPocketFull()
+{
+    return (_pocket[0] != 0 && _pocket[1] != 0);
+}
+
+bool GameScreen::isPocketEmpty()
+{
+    return (_pocket[0] == 0 && _pocket[1] == 0);
+}
+
+bool GameScreen::putInPocket( int item )
+{
+    if( item != CELL_BARREL && item != CELL_KEY )
+        return false;
+
+    bool bRet = true;
+
+    if( _pocket[0] == 0 )
+        _pocket[0] = item;
+    else if( _pocket[1] == 0 )
+        _pocket[1] = item;
+    else
+        bRet = false;
+
+    return bRet;
+}
+
+bool GameScreen::getKeyFromPocket()
+{
+    bool bRet = true;
+
+    if( _pocket[0] == CELL_KEY )
+        _pocket[0] = 0;
+    else if( _pocket[1] == CELL_KEY )
+        _pocket[1] = 0;
+    else
+        bRet = false;
+
+    return bRet;
+}
+
+bool GameScreen::getBarrelFromPocket()
+{
+    bool bRet = true;
+
+    if( _pocket[0] == CELL_BARREL )
+        _pocket[0] = 0;
+    else if( _pocket[1] == CELL_BARREL )
+        _pocket[1] = 0;
+    else
+        bRet = false;
+
+    return bRet;
+}
+
+void GameScreen::moveleft()
+{
+    if( _rickDirection == 0 )
+    {
+        _rickDirection = 1;
+        drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+    }
+    
+    if( _rickX == 0 )
+        return;
+
+    uint8_t cell = _maze[(_rickY<<3)+_rickX-1];
+
+
+    if( cell == CELL_KEY || cell == CELL_BARREL ) {
+        if( putInPocket(cell) ) {
+            _maze[(_rickY<<3)+_rickX-1] = CELL_EMPTY;
+            drawSprite((_rickX-1),_rickY, CELL_EMPTY);
+            drawPocket();
+        }
+        return;
+    }
+
+    if( cell == CELL_CRATE && (_rickX-1)>0 )
+    {
+        if( moveto(_rickX-1,_rickY, _rickX-2,_rickY) )
+            fall(_rickX-2,_rickY);
+        return;
+    }
+
+
+    if( moveto(_rickX,_rickY,_rickX-1,_rickY) )
+        fall(_rickX,_rickY);
+
+}
+
+void GameScreen::moveright()
+{
+    if( _rickDirection == 1 )
+    {
+        _rickDirection = 0;
+        drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+    }
+    
+    if( _rickX == 7 )
+        return;
+
+    uint8_t cell = _maze[(_rickY<<3)+_rickX+1];
+
+    if( cell == CELL_KEY || cell == CELL_BARREL ) {
+        if( putInPocket(cell) ) {
+            _maze[(_rickY<<3)+_rickX+1] = CELL_EMPTY;
+            drawSprite((_rickX+1),_rickY, CELL_EMPTY);
+            drawPocket();
+        }
+        return;
+    }
+    
+    if( cell == CELL_CRATE && (_rickX+1)<7 )
+    {
+        if( moveto(_rickX+1,_rickY, _rickX+2,_rickY) )
+            fall(_rickX+2,_rickY);
+        return;
+    }
+
+    if( moveto(_rickX,_rickY,_rickX+1,_rickY) )
+        fall(_rickX,_rickY);
+
+}
+
+void GameScreen::moveup()
+{
+    if( _rickY == 0 )
+        return;
+
+    uint8_t currentCell = _maze[((_rickY)<<3)+_rickX];
+    uint8_t aboveCell = _maze[((_rickY-1)<<3)+_rickX];
+
+    //if already on ladder
+    if( currentCell == CELL_LADDER )
+        moveto(_rickX,_rickY,_rickX,_rickY-1);
+    else if( currentCell == CELL_EMPTY && !isPocketEmpty()) {
+        uint8_t x = _rickX;
+        uint8_t y = _rickY;
+        if( moveto(_rickX,_rickY,_rickX,_rickY-1) ) {
+            if( getBarrelFromPocket() ) {
+                _maze[(y<<3)+x] = CELL_BARREL;
+                drawSprite(x,y,CELL_BARREL);
+            } else if( getKeyFromPocket() ) {
+                _maze[(y<<3)+x] = CELL_KEY;
+                drawSprite(x,y,CELL_KEY);
+            }
+
+            drawPocket();
+        }
+    }
+}
+
+void GameScreen::movedown()
+{
+    if( _rickY == 0 )
+        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( _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 )
+        isRick = true;
+
+    uint8_t fromCell = _maze[((fromY)<<3)+fromX];
+    uint8_t toCell = _maze[((toY)<<3)+toX];
+
+    if( isRick ) {
+        if( toCell == CELL_EMPTY || toCell == CELL_LADDER || toCell == CELL_TOTEM ) {
+            drawSprite(fromX,fromY, fromCell);
+            _rickX = toX;
+            _rickY = toY;
+            drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+            return true;
+        }
+        if( toCell == CELL_DOOR ) {
+            if( getKeyFromPocket() ) {
+                drawSprite(fromX,fromY, fromCell);
+                _maze[((toY)<<3)+toX] = CELL_EMPTY;
+                _rickX = toX;
+                _rickY = toY;
+                drawSprite(_rickX,_rickY, CELL_RICK, _rickDirection == 1);
+                drawPocket();
+                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;
+    }
+
+    return false;
+}
+
+bool GameScreen::fall(uint8_t fromX, uint8_t fromY)
+{
+    if( fromY == 7 )
+        return false;
+
+    uint8_t curCell = _maze[(fromY<<3)+fromX];
+
+    if( curCell == CELL_LADDER )
+        return false;
+
+    uint8_t cell = _maze[((fromY+1)<<3)+fromX];
+
+
+
+    while( cell == CELL_EMPTY || cell == CELL_TOTEM ) {
+        if( moveto(fromX,fromY,fromX,fromY+1) ) {
+            fromY++;
+
+            if( fromY == 7 )
+                break;
+
+            cell = _maze[((fromY+1)<<3)+fromX];
+        } else {
+            break;
+        }
+    }
+
+    return true;
+}
+
+
+
+
+void GameScreen::unpackLevel( int level )
+{
+    if( level < 0 || level > 99 )
+        level = 0;
+
+    _level = level;
+
+    const uint32_t * pLevel = &levels[level*8];
+
+    for( int y = 0; y < 8; y++ )
+        for( int x = 0; x < 8; x++ ) {
+            _maze[(y<<3) + x] = (pLevel[y]>>(28-(x<<2))) & 0x0F;
+
+            switch( _maze[(y<<3) + x] ) {
+                case CELL_RICK:
+                    //The level data has specialy marked cell for Rick
+                    //During the game Rick position is tracked separately
+                    //This allows us to put Rick on none EMPTY cells
+                    _maze[(y<<3) + x] = CELL_EMPTY;
+                    _rickX = x;
+                    _rickY = y;
+                    break;
+                case CELL_TOTEM:
+                    _totemX = x;
+                    _totemY = y;
+                    break;
+                default:
+                    break;
+            }
+        }
+}
+
+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()
+{
+    if( _pocket[0] == 0 )
+        retro.display.fillRect(136,80,151,95,0);
+    else
+        retro.display.drawBitmapIndexed(136,80, 16,16,sprites[_pocket[0]], 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);
+}
+
+
+void GameScreen::drawLevel()
+{
+    //Draw the maze
+    for( int y = 0; y < 8; y++ )
+        for( int x = 0; x < 8; x++ ) {
+            drawSprite(x, y, _maze[(y<<3)+x]);
+        }
+
+    //Put Rick on the map
+    drawSprite(_rickX, _rickY, CELL_RICK, _rickDirection == 1);
+
+    //Draw the statistics and "pocket" area
+    for( int y = 0; y < 8; y++ ) {
+        retro.display.drawBitmapIndexed(128,y<<4, 16,16,wall, palette);
+        retro.display.drawBitmapIndexed(144,y<<4, 16,16, wall, palette);
+    }
+    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);
+
+    drawPocket();
+}
+
+
+Screen GameScreen::Update()
+{
+    if( _state == 0 ) {
+        drawLevel();
+        _state = 1;
+    }
+
+    if(retro.buttons.pressed(BTN_LEFT)) {
+        moveleft();
+    }
+    if(retro.buttons.pressed(BTN_RIGHT)) {
+        moveright();
+    }
+    if(retro.buttons.pressed(BTN_UP)) {
+        moveup();
+    }
+    if(retro.buttons.pressed(BTN_DOWN)) {
+        movedown();
+    }
+    if(retro.buttons.pressed(BTN_ROBOT)) {
+        _state = 0;
+        return Menu;
+    }
+
+    return Game;
+}
\ No newline at end of file