Platform game written for the GHI/OutrageousCircuits RETRO game device. Navigate the caves collecting all the pickups and avoiding the creatures and haunted mine carts that patrol the caves. Oh and remember to watch out for the poisonous plants... This game demonstrates the ability to have multiple animated sprites where the sprites can overlap the background environment. See how the player moves past the fence and climbs the wall in the 3rd screen.

Dependencies:   mbed

Revision:
9:34008d8b1cdf
Child:
11:9ae9a88a1da8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RetroGameEngine/GameObject.cpp	Sun Jan 11 02:53:03 2015 +0000
@@ -0,0 +1,248 @@
+#include "mbed.h"
+#include "GameEngine.h"
+#include "GameObject.h"
+
+GameObject::GameObject() : 
+    _spriteId(0),
+    _position(0,0),    
+    _dx(0),
+    _dy(0),
+    _lastdx(0),
+    _lastdy(0),
+    _speed(2),
+    _animationCounter(0),
+    _collisionRect(0, 0, 16, 16),
+    _flipSprite(false)
+{
+    
+}
+
+void GameObject::setStartPosition(Point position)
+{
+    _position = position;
+}
+
+void GameObject::setSpriteId(uint8_t spriteId)
+{
+    _spriteId = spriteId;
+}
+
+void GameObject::setSpeed(uint8_t speed)
+{
+    _speed = speed;
+}
+
+void GameObject::setCollisionRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
+{
+    _collisionRect = Rect(x, y, w, h);
+}
+
+void GameObject::animate()
+{
+    if (_animationCounter++ % 2)
+    {
+        _pScene->animate(_spriteId);
+    }
+}
+
+bool GameObject::moveLeft()
+{    
+    if ((abs(_dx) == _speed) || !canGoLeft(_position.X, _position.Y)) return false;    
+    _dx -= _speed;        
+    _position.X -= _speed; 
+    _flipSprite = false;
+    return true;
+}
+
+bool GameObject::moveRight()
+{    
+    if ((abs(_dx) == _speed) || !canGoRight(_position.X, _position.Y)) return false;
+    _dx += _speed;
+    _position.X += _speed; 
+    _flipSprite = true;   
+    return true;
+}
+
+bool GameObject::moveUp()
+{    
+    if ((abs(_dy) == _speed) || !canGoUp(_position.X, _position.Y)) return false;
+    _dy -= _speed;
+    _position.Y -= _speed;    
+    return true;
+}
+
+bool GameObject::moveDown()
+{    
+    if ((abs(_dy) == _speed) || !canGoDown(_position.X, _position.Y, 0)) return false;
+    _dy += _speed;
+    _position.Y += _speed;    
+    return true;
+}
+
+bool GameObject::fall()
+{    
+    if ((abs(_dy) == _speed) || !canGoDown(_position.X, _position.Y, 4)) return false;
+    
+    const Block& left = _pScene->getBlock(_position.X + 4, _position.Y + 16);
+    const Block& right = _pScene->getBlock(_position.X + 12, _position.Y + 16);    
+    if (left.getType() == Block::Ladder || right.getType() == Block::Ladder) return false;
+ 
+    _dy += _speed;       
+    _position.Y += _speed;    
+    
+    return true;
+}
+
+const GameObject* GameObject::detectCollision()
+{
+    return _pScene->detectCollision(this);
+}
+
+const Block* GameObject::detectBlock()
+{
+    return _pScene->detectBlock(this);
+}
+
+Rect GameObject::getCollisionRect()
+{
+    return Rect(_position.X + _collisionRect.left, _position.Y + _collisionRect.top, _collisionRect.getWidth(), _collisionRect.getHeight());    
+}
+
+bool GameObject::pickupObject()
+{    
+    uint8_t cellX = _position.X / 8;
+    uint8_t cellY = _position.Y / 8;
+    for (uint8_t cx = 0; cx < 2; ++cx)
+    {
+        for (uint8_t cy = 0; cy < 2; ++cy)
+        {    
+            if (_pScene->pickupObject(cellX + cx, cellY + cy)) return true;
+        }
+    }
+    
+    return false;
+}
+
+bool GameObject::canGoLeft(uint8_t x, uint8_t y)
+{
+    int16_t tx = x - _speed;
+    if (tx < 0) return false;
+        
+    if (!_pScene->canEnter(tx, y + 0)) return false;
+    if (!_pScene->canEnter(tx, y + 7)) return false;
+    if (!_pScene->canEnter(tx, y + 8)) return false;
+    if (!_pScene->canEnter(tx, y + 15)) return false;
+    
+    return true;
+}
+
+bool GameObject::canGoRight(uint8_t x, uint8_t y)
+{
+    int tx = x + 15 + _speed;
+
+    if ((tx / 8) == _pScene->getMapXCells()) return false;
+    
+    if (!_pScene->canEnter(tx, y + 0)) return false;
+    if (!_pScene->canEnter(tx, y + 7)) return false;
+    if (!_pScene->canEnter(tx, y + 8)) return false;
+    if (!_pScene->canEnter(tx, y + 15)) return false;
+    
+    return true;
+}
+
+bool GameObject::canGoUp(uint8_t x, uint8_t y)
+{
+    int16_t ty = y - _speed;
+    if (ty < 0) return false;
+    
+    if (!_pScene->canEnter(x + 4, ty)) return false;
+    if (!_pScene->canEnter(x + 7, ty)) return false;
+    if (!_pScene->canEnter(x + 8, ty)) return false;
+    if (!_pScene->canEnter(x + 11, ty)) return false;
+    
+    return true;
+}
+
+bool GameObject::canGoDown(uint8_t x, uint8_t y, uint8_t collisionBorder)
+{   
+    uint8_t by =  y + 15;
+    uint8_t ty = by + _speed;   
+    
+    // If not moving to a new cell then no need to test
+    if ((by / 8) == (ty / 8)) return true;
+    
+    if ((ty / 8) >= (_pScene->getMapYCells() - 1)) return false;
+    
+    if (!_pScene->canEnterFromTop(x + collisionBorder, ty)) return false;
+    if (!_pScene->canEnterFromTop(x + 7, ty)) return false;
+    if (!_pScene->canEnterFromTop(x + 8, ty)) return false;
+    if (!_pScene->canEnterFromTop(x + 15 - collisionBorder, ty)) return false;
+    
+    return true;
+}
+
+bool GameObject::isOpenBelow()
+{
+    return isOpenBelow(4) && isOpenBelow(12);
+}
+
+bool GameObject::isOpenBelow(int8_t dx)
+{
+    return _pScene->canEnterFromTop(_position.X + dx, _position.Y + 20);    
+}
+
+bool GameObject::isOverLadder()
+{
+    const Block& left = _pScene->getBlock(_position.X + 4, _position.Y + 12);
+    const Block& right = _pScene->getBlock(_position.X + 12, _position.Y + 15);    
+    return left.getType() == Block::Ladder || right.getType() == Block::Ladder;
+}
+
+bool GameObject::isLadderAbove()
+{
+    const Block& left = _pScene->getBlock(_position.X + 4, _position.Y + 2);
+    const Block& right = _pScene->getBlock(_position.X + 12, _position.Y + 2);
+    return left.getType() == Block::Ladder && right.getType() == Block::Ladder;
+}
+
+bool GameObject::isLadderBelow()
+{
+    const Block& left = _pScene->getBlock(_position.X + 4, _position.Y + 16);
+    const Block& right = _pScene->getBlock(_position.X + 12, _position.Y + 16);
+    return left.getType() == Block::Ladder && right.getType() == Block::Ladder;
+}
+
+bool GameObject::isLadderLeft()
+{
+    const Block& left = _pScene->getBlock(_position.X - 4, _position.Y + 2);    
+    return left.getType() == Block::Ladder;
+}
+
+bool GameObject::isLadderRight()
+{    
+    const Block& right = _pScene->getBlock(_position.X + 20, _position.Y + 2);
+    return right.getType() == Block::Ladder;
+}
+
+const Block& GameObject::getBlockAbove()
+{
+    return _pScene->getBlock(_position.X + 8, _position.Y - 4);
+}
+
+const Block& GameObject::getBlockBelow()
+{
+    return _pScene->getBlock(_position.X + 8, _position.Y + 16);
+}
+        
+void GameObject::update()
+{    
+}
+
+void GameObject::draw()
+{
+    _pScene->drawSprite(_spriteId, _position.X, _position.Y, _dx, _dy, _flipSprite);
+    _lastdx = _dx;
+    _lastdy = _dy;
+    _dx = 0;
+    _dy = 0;
+}