Started to write my own RL, and already fell into analysis (paralysis?) when implementing map class.
My TILE class looks like:
class CMapTile
{
public:
enum eMapTileType
{
E_UNKNOWN = 0,
E_FREE,
E_WALL,
E_ALL
};
CMapTile();
virtual ~CMapTile();
uint8_t GetType();
uint8_t IsBlocking();
uint8_t GetSymbol();
protected:
uint8_t m_uiType;
uint8_t m_uiBlocking;
uint8_t m_uiSymbol;
};
Then i wrote a class for the map itself
#include "CMapTile.hpp"
class CMap
{
public:
CMap();
void Init(const uint8_t& ruiWidth, const uint8_t& ruiHeight);
void Generate();
void Print();
CMapTile GetTile(const uint8_t& ruiX, const uint8_t& ruiY) const;
private:
uint8_t m_uiWidth;
uint8_t m_uiHeight;
std::vector<CMapTile> m_vTiles;
};
And here is me thinking. With the design above, Map has no idea about entities. Entities have no idea about map.
So when i want to move Player RIGHT given above i will have to make two checks (totally separated). A check for map if tile is blocking and a check in a vector of entities if there is any entity on that position (X+1).
// Obtain tile to the right
CMapTile *pTile = m_Map->GetTile(pPlayer->GetPosX()+1, pPlayer->GetPosY());
// Obtain entity to the right
CEntity *pEntityToRight = m_EntitiesManager.GetEntity(pPlayer->GetPosX()+1, pPlayer->GetPosY());
// Check if blocking
if(pTile != NULL && pTile->IsBlocking() == false)
{
// Check if any entity there and blocking
if(pEntityToRight != NULL && pEntityToRight->IsBlocking == false)
{
// Update Player Pos to Tile position
pPlayer->SetPosition(pTile->GetPosX(), pTile->GetPosY());
// Update Map Entity Id for this Tile
_Tile->SetEntityId(pPlayer->GetID());
}
}
Maybe instead i should have an integer in the CMapTile storing an id of an entity, like below:
class CMapTile
{
public:
enum eMapTileType
{
E_UNKNOWN = 0,
E_FREE,
E_WALL,
E_ALL
};
CMapTile();
virtual ~CMapTile();
uint8_t GetType();
uint8_t IsBlocking();
uint8_t GetSymbol();
int GetEntityID();
protected:
uint8_t m_uiType;
uint8_t m_uiBlocking;
uint8_t m_uiSymbol;
int m_iEntityID; // <<<<<<<-----
};
Thanks to which i can make a simple call to CMap like this to check if i can move player Right:
// Obtain tile to the right
CMapTile *pTile = m_Map->GetTile(pPlayer->GetPosX()+1, pPlayer->GetPosY());
// Check if blocking
if(pTile->IsBlocking() == false)
{
// Update Player Pos to Tile position
pPlayer->SetPosition(pTile->GetPosX(), pTile->GetPosY());
// Update Map Entity Id for this Tile
_Tile->SetEntityId(pPlayer->GetID());
}
With the above CMapTile::IsBlocking would have to know about Entity class, to figure out if entity is a blocking type or not.
Questions This sounds simple but that initial design has an effect on later development. Examples:
What happens later when for an example NPC would have to attack player?
How from the NPC class the logic knows where is the player located or if he (NPC) can move right ? - having no idea about the map.
Should i pass the MAP pointer to the AI logic ?
Which is the proper way to go to separate the logic and make all of the above simple in future stages of development ?