"Lost treasure of mBedungu" 100 level puzzle game for RETRO
Dependencies: LCD_ST7735 RetroPlatform mbed
Diff: Game/GameScreen.cpp
- 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