Large refactoring. Also, reimplemented resource manager to use parsers. Changed from json to xml (it allows comments!!!).

This commit is contained in:
Tiberiu Chibici 2016-12-01 21:08:28 +02:00
parent 9c8cbf8518
commit 0b6a988184
71 changed files with 1608 additions and 923 deletions

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
<animationFps>60</animationFps>
</Configuration>

View File

@ -0,0 +1,15 @@
{
"name" : "Level 1 Sword",
"description" : "Most basic sword.",
"enemyDamage" : 3,
"attackDuration" : 10,
"criticalProbability" : 0.01,
"level" : 1,
"tool" : true,
"giftable" : false,
"sellable" : false,
"sprite" : "sprites/items/lvl1_sword.sprite"
}

View File

@ -0,0 +1,16 @@
{
"name" : "Stone pickaxe",
"description" : "The most basic type of pickaxe. It can break small stones.",
"enemyDamage" : 1,
"criticalProbability" : 0,
"level" : 1,
"tool" : true,
"giftable" : false,
"sellable" : false,
"sprite" : "sprites/items/stone_pickaxe.sprite",
"controller" : "PickaxeItem"
}

8
assets/levels/Farm.back Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<Background columns="380" rows="213">
<Layer name="Background"
cells="levels/Farm_Background.csv"
texture="tilesets/Ground.png" />
</Background>

View File

@ -1,17 +0,0 @@
{
"cellWidth": 16,
"cellHeight": 16,
"layerCount" : 1,
"width" : 380,
"height" : 213,
"layers":
[
{
"name" : "Background",
"cellsFile" : "levels/Farm_Background.csv",
"textureFile" : "tilesets/Ground.png"
}
]
}

29
assets/scenes/Game.scene Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<Scene cellWidth="16"
cellHeight="16">
<!-- Main camera -->
<GameObject name="Main Camera">
<Transform />
<Camera scale="4" mainCamera="true" />
</GameObject>
<!-- Background object -->
<GameObject name="Background">
<Background src="levels/Farm.back" />
<BackgroundRenderer />
</GameObject>
<!-- Player object -->
<GameObject name="Player">
<Transform x="120" y="100" />
<SpriteRenderer sprite="sprites/Player.sprite" />
<PlayerController />
</GameObject>
<!-- Debug object -->
<GameObject name="Debug">
<DebugController />
</GameObject>
</Scene>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" ?>
<Sprite name="Player"
anchorX="0.5" anchorY="1">
<State name="Idle right">
<Frame tileSet="tilesets/PlayerTiles.png" cell="0" w="1" h="2" duration="1" />
</State>
<State name="Idle up">
<Frame tileSet="tilesets/PlayerTiles.png" cell="2" w="1" h="2" duration="1" />
</State>
<State name="Idle left">
<Frame tileSet="tilesets/PlayerTiles.png" cell="4" w="1" h="2" duration="1" />
</State>
<State name="Idle down">
<Frame tileSet="tilesets/PlayerTiles.png" cell="6" w="1" h="2" duration="1" />
</State>
<State name="Walking right">
<Frame tileSet="tilesets/PlayerTiles.png" cell="0" w="1" h="2" duration="7" />
<Frame tileSet="tilesets/PlayerTiles.png" cell="1" w="1" h="2" duration="7" />
</State>
<State name="Walking up">
<Frame tileSet="tilesets/PlayerTiles.png" cell="2" w="1" h="2" duration="7" />
<Frame tileSet="tilesets/PlayerTiles.png" cell="3" w="1" h="2" duration="7" />
</State>
<State name="Walking left">
<Frame tileSet="tilesets/PlayerTiles.png" cell="4" w="1" h="2" duration="7" />
<Frame tileSet="tilesets/PlayerTiles.png" cell="5" w="1" h="2" duration="7" />
</State>
<State name="Walking down">
<Frame tileSet="tilesets/PlayerTiles.png" cell="6" w="1" h="2" duration="7" />
<Frame tileSet="tilesets/PlayerTiles.png" cell="7" w="1" h="2" duration="7" />
</State>
</Sprite>

View File

@ -0,0 +1,36 @@
{
"name" : "Level 1 sword",
"anchorX" : 0,
"anchorY" : 1,
"states" :
[
{
"name" : "Normal",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 0,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
},
{
"name" : " Attack",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 2,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
}
]
}

View File

@ -0,0 +1,36 @@
{
"name" : "Stone pickaxe",
"anchorX" : 0,
"anchorY" : 1,
"states" :
[
{
"name" : "Normal",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 0,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
},
{
"name" : "Attack",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 2,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
}
]
}

View File

@ -1,148 +0,0 @@
{
"name" : "Player",
"anchorX" : 0.5,
"anchorY" : 1,
"states" :
[
{
"name" : "Idle right",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 0,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
},
{
"name" : "Idle up",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 2,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
},
{
"name" : "Idle left",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 4,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
},
{
"name" : "Idle down",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 6,
"width" : 1,
"height" : 2,
"duration" : 1
}
]
},
{
"name" : "Walking right",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 0,
"width" : 1,
"height" : 2,
"duration" : 7
},
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 1,
"width" : 1,
"height" : 2,
"duration" : 7
}
]
},
{
"name" : "Walking up",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 2,
"width" : 1,
"height" : 2,
"duration" : 7
},
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 3,
"width" : 1,
"height" : 2,
"duration" : 7
}
]
},
{
"name" : "Walking left",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 4,
"width" : 1,
"height" : 2,
"duration" : 7
},
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 5,
"width" : 1,
"height" : 2,
"duration" : 7
}
]
},
{
"name" : "Walking down",
"frames" :
[
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 6,
"width" : 1,
"height" : 2,
"duration" : 7
},
{
"tileSet" : "tilesets/PlayerTiles.png",
"cell" : 7,
"width" : 1,
"height" : 2,
"duration" : 7
}
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

View File

@ -45,10 +45,13 @@ RINFO_FOOTER=" };\n"
# #
FILE_TYPES = [ FILE_TYPES = [
([".png", ".bmp"], "Texture"), ([".png", ".bmp"], "Texture"),
([".level"], "Level"),
([".csv"], "LevelLayer"),
([".ttf"], "Font"), ([".ttf"], "Font"),
([".sprite"], "Sprite"), ([".sprite"], "Sprite"),
([".config"], "Configuration"),
([".scene"], "Scene"),
([".back"], "Background"),
([".csv"], "BackgroundLayer"),
([".item"], "Item"),
] ]

View File

@ -10,6 +10,20 @@ namespace farmlands {
GameState GameState::s_current; GameState GameState::s_current;
GameState::GameState()
: renderContext(),
scene(nullptr),
config(nullptr),
elapsedTime(0)
{
}
GameState::~GameState()
{
if (scene) delete scene;
if (config) delete config;
}
GameState& farmlands::GameState::current() GameState& farmlands::GameState::current()
{ {
return s_current; return s_current;

View File

@ -10,8 +10,7 @@
#include <base/GameObject.h> #include <base/GameObject.h>
#include <base/RenderContext.h> #include <base/RenderContext.h>
#include <model/Level.h> #include <base/Scene.h>
#include <model/Player.h>
#include <model/Configuration.h> #include <model/Configuration.h>
#include <resources/ResourceManager.h> #include <resources/ResourceManager.h>
@ -19,30 +18,20 @@
namespace farmlands { namespace farmlands {
struct GuiState
{
};
class GameState class GameState
{ {
public: public:
GameState();
~GameState();
static GameState& current(); static GameState& current();
static void setCurrent(GameState& state); static void setCurrent(GameState& state);
// Render context // Render context
base::RenderContext renderContext; base::RenderContext renderContext;
base::Scene* scene;
model::Configuration* config;
// Gui // Misc
GuiState gui;
// Settings
model::Configuration config;
// Current game
model::Player player;
model::Level* currentLevel;
base::GameObject root;
float elapsedTime; float elapsedTime;
private: private:

View File

@ -17,4 +17,9 @@ int main()
std::cerr << typeid(ex).name() << " : " << ex.message() << "\n"; std::cerr << typeid(ex).name() << " : " << ex.message() << "\n";
std::cerr << "Source: file " << ex.file() << " line " << ex.line() << "\n"; std::cerr << "Source: file " << ex.file() << " line " << ex.line() << "\n";
} }
catch (std::exception& ex)
{
std::cerr << "Panic: Caught unhandled exception!\n";
std::cerr << typeid(ex).name() << " : " << ex.what() << "\n";
}
} }

35
src/base/Camera.cpp Normal file
View File

@ -0,0 +1,35 @@
/*
* Camera.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <GameState.h>
#include <base/Camera.h>
#include <base/Component.h>
namespace farmlands {
namespace base {
Camera::Camera()
: scale(1),
mainCamera(true)
{
}
Camera::~Camera()
{
}
void Camera::onCreate()
{
if (mainCamera)
{
GameState::current().renderContext.setCamera(gameObject);
}
}
}
}

View File

@ -13,9 +13,17 @@
namespace farmlands { namespace farmlands {
namespace base { namespace base {
struct Camera : public Component class Camera : public Component
{ {
public:
Camera();
virtual ~Camera();
virtual void onCreate();
float scale; float scale;
bool mainCamera;
}; };
} }

View File

@ -52,6 +52,9 @@ namespace base {
void onPostRender(); void onPostRender();
void onDestroy(); void onDestroy();
// Other properties
std::string name;
private: private:
std::unordered_map<std::type_index, Component*> m_components; std::unordered_map<std::type_index, Component*> m_components;

25
src/base/Scene.h Normal file
View File

@ -0,0 +1,25 @@
/*
* Scene.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef MODEL_SCENE_H_
#define MODEL_SCENE_H_
#include <base/GameObject.h>
namespace farmlands {
namespace base {
struct Scene
{
GameObject root;
uint32_t cellWidth, cellHeight;
};
} /* namespace model */
} /* namespace farmlands */
#endif /* MODEL_SCENE_H_ */

View File

@ -19,7 +19,8 @@ Sprite::Sprite()
m_states(), m_states(),
m_currentState(0), m_currentState(0),
m_currentFrame(0), m_currentFrame(0),
m_currentFrameTimeLeft(0) m_currentFrameTimeLeft(0),
m_animationVelocity(1)
{ {
} }
@ -53,7 +54,7 @@ void Sprite::setState(size_t stateId)
m_currentState = stateId; m_currentState = stateId;
m_currentFrame = 0; m_currentFrame = 0;
m_currentFrameTimeLeft = currentFrame().duration * 1; m_currentFrameTimeLeft = currentFrame().duration;
} }
void Sprite::setState(const std::string& name) void Sprite::setState(const std::string& name)
@ -62,28 +63,19 @@ void Sprite::setState(const std::string& name)
setState(m_stateNames.at(name)); setState(m_stateNames.at(name));
} }
void Sprite::advanceTime(uint32_t steps) void Sprite::advanceTime(float fractions)
{ {
Assert(m_states.size() > 0, "Sprite must have at least one state!"); Assert(m_states.size() > 0, "Sprite must have at least one state!");
while (steps > 0) m_currentFrameTimeLeft -= fractions * m_animationVelocity;
{
// There is time left in the current frame?
if (m_currentFrameTimeLeft > 0)
{
uint32_t sub = std::min(steps, m_currentFrameTimeLeft);
m_currentFrameTimeLeft -= sub;
steps -= sub;
}
if (m_currentFrameTimeLeft == 0) while (m_currentFrameTimeLeft <= 0)
{ {
// Move to the next frame // Move to the next frame
if (++m_currentFrame >= currentState().frames.size()) if (++m_currentFrame >= currentState().frames.size())
m_currentFrame = 0; m_currentFrame = 0;
m_currentFrameTimeLeft = currentFrame().duration * 1; m_currentFrameTimeLeft += currentFrame().duration;
}
} }
} }
@ -93,6 +85,11 @@ SpriteState& Sprite::currentState()
return m_states.at(m_currentState); return m_states.at(m_currentState);
} }
void Sprite::setAnimationVelocity(float velocity)
{
m_animationVelocity = velocity;
}
Frame& Sprite::currentFrame() Frame& Sprite::currentFrame()
{ {
Assert(currentState().frames.size() > 0, "State must have at least one frame!"); Assert(currentState().frames.size() > 0, "State must have at least one frame!");

View File

@ -63,8 +63,12 @@ namespace base {
/** /**
* Advances the current frame * Advances the current frame
*/ */
void advanceTime(uint32_t steps); void advanceTime(float fractions);
/**
* Sets the animation velocity. Using this property, animation can be slowed or accelerated.
*/
void setAnimationVelocity(float velocity);
// Getters // Getters
SpriteState& currentState(); SpriteState& currentState();
@ -80,7 +84,8 @@ namespace base {
size_t m_currentState; size_t m_currentState;
size_t m_currentFrame; size_t m_currentFrame;
uint32_t m_currentFrameTimeLeft; float m_currentFrameTimeLeft;
float m_animationVelocity;
}; };
} /* namespace model */ } /* namespace model */

View File

@ -34,63 +34,6 @@ FarmlandsGame::FarmlandsGame() :
{ {
} }
void FarmlandsGame::createScene()
{
// Create camera
Transform* cameraTransform = new Transform();
cameraTransform->x = 120;
cameraTransform->y = 100 - 1;
Camera* camera = new Camera();
camera->scale = 4.0f;
GameObject* cameraObj = new GameObject();
cameraObj->addComponent(cameraTransform);
cameraObj->addComponent(camera);
GameState::current().root.addChild(cameraObj);
GameState::current().renderContext.setCamera(cameraObj);
cameraObj->onCreate();
// Create background
BackgroundRenderer* backRenderer = new BackgroundRenderer();
backRenderer->level = GameState::current().currentLevel;
GameObject* backObj = new GameObject();
backObj->addComponent(backRenderer);
GameState::current().root.addChild(backObj);
backObj->onCreate();
// Create player
Transform* playerTransform = new Transform();
playerTransform->x = 120;
playerTransform->y = 100;
SpriteRenderer* playerRender = new SpriteRenderer();
playerRender->sprite = ResourceManager::instance().sprite(R::Sprites::Player);
PlayerController* playerCtrl = new PlayerController();
GameObject* playerObj = new GameObject();
playerObj->addComponent(playerTransform);
playerObj->addComponent(playerRender);
playerObj->addComponent(playerCtrl);
GameState::current().root.addChild(playerObj);
playerObj->onCreate();
// Create debug object
DebugController* dbgController = new DebugController();
GameObject* dbgObj = new GameObject();
dbgObj->addComponent(dbgController);
GameState::current().root.addChild(dbgObj);
dbgObj->onCreate();
}
bool FarmlandsGame::initialize() bool FarmlandsGame::initialize()
{ {
bool ok = true; bool ok = true;
@ -102,41 +45,36 @@ bool FarmlandsGame::initialize()
// Initialize & load resources // Initialize & load resources
ResourceManager::instance().initialize(); ResourceManager::instance().initialize();
ResourceManager::instance().loadGameAssets(); ResourceManager::instance().loadGame();
ResourceManager::instance().loadLevel(resources::R::Levels::Farm); GameState::current().renderContext.viewport.pixelsPerUnitX = GameState::current().scene->cellWidth;
GameState::current().currentLevel = ResourceManager::instance().level(resources::R::Levels::Farm); GameState::current().renderContext.viewport.pixelsPerUnitY = GameState::current().scene->cellHeight;
GameState::current().renderContext.viewport.pixelsPerUnitX = GameState::current().currentLevel->m_cellWidth;
GameState::current().renderContext.viewport.pixelsPerUnitY = GameState::current().currentLevel->m_cellHeight;
// Set up scene
createScene();
// Finish initialization // Finish initialization
GameState::current().root.onInitialize(); GameState::current().scene->root.onInitialize();
return true; return true;
} }
void FarmlandsGame::onUpdateLogic() void FarmlandsGame::onUpdateLogic()
{ {
GameState::current().root.onUpdateLogic(); GameState::current().scene->root.onUpdateLogic();
} }
void FarmlandsGame::onPreRender() void FarmlandsGame::onPreRender()
{ {
GameState::current().root.onPreRender(); GameState::current().scene->root.onPreRender();
SdlRenderer::instance().renderBegin(); SdlRenderer::instance().renderBegin();
} }
void FarmlandsGame::onRender() void FarmlandsGame::onRender()
{ {
GameState::current().root.onRender(); GameState::current().scene->root.onRender();
} }
void FarmlandsGame::onEvent(SDL_Event& event) void FarmlandsGame::onEvent(SDL_Event& event)
{ {
// Let controllers handle event // Let controllers handle event
if (GameState::current().root.onEvent(event)) if (GameState::current().scene->root.onEvent(event))
return; return;
// Nobody? Handle global events // Nobody? Handle global events
@ -159,13 +97,13 @@ void FarmlandsGame::onEvent(SDL_Event& event)
void FarmlandsGame::onPostRender() void FarmlandsGame::onPostRender()
{ {
SdlRenderer::instance().renderEnd(); SdlRenderer::instance().renderEnd();
GameState::current().root.onPostRender(); GameState::current().scene->root.onPostRender();
} }
void FarmlandsGame::stop() void FarmlandsGame::stop()
{ {
m_running = false; m_running = false;
GameState::current().root.onDestroy(); GameState::current().scene->root.onDestroy();
} }
int FarmlandsGame::run() int FarmlandsGame::run()

View File

@ -9,8 +9,6 @@
#define FARMLANDSGAME_H_ #define FARMLANDSGAME_H_
#include <GameState.h> #include <GameState.h>
#include <controller/GuiController.h>
#include <controller/PlayerController.h>
#include <resources/ResourceManager.h> #include <resources/ResourceManager.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
@ -36,7 +34,6 @@ namespace controller {
void stop(); void stop();
private: private:
void createScene();
bool m_running; bool m_running;
Uint32 m_time; Uint32 m_time;

View File

@ -0,0 +1,30 @@
/*
* ItemController.cpp
*
* Created on: Nov 30, 2016
* Author: tibi
*/
#include <controller/items/ItemController.h>
namespace farmlands
{
namespace controller
{
namespace items
{
ItemController::ItemController()
{
// TODO Auto-generated constructor stub
}
ItemController::~ItemController()
{
// TODO Auto-generated destructor stub
}
} /* namespace items */
} /* namespace controller */
} /* namespace farmlands */

View File

@ -0,0 +1,30 @@
/*
* ItemController.h
*
* Created on: Nov 30, 2016
* Author: tibi
*/
#ifndef CONTROLLER_ITEMS_ITEMCONTROLLER_H_
#define CONTROLLER_ITEMS_ITEMCONTROLLER_H_
#include <base/Component.h>
namespace farmlands {
namespace controller {
namespace items {
class ItemController: public base::Component
{
public:
ItemController();
virtual ~ItemController();
float enemyDamage;
};
} /* namespace items */
} /* namespace controller */
} /* namespace farmlands */
#endif /* CONTROLLER_ITEMS_ITEMCONTROLLER_H_ */

View File

@ -6,7 +6,7 @@
*/ */
#include <GameState.h> #include <GameState.h>
#include <controller/PlayerController.h> #include <controller/player/PlayerController.h>
#include <graphics/SpriteRenderer.h> #include <graphics/SpriteRenderer.h>
#include <input/Input.h> #include <input/Input.h>
#include <utils/Assert.h> #include <utils/Assert.h>
@ -17,21 +17,11 @@ using namespace farmlands::model;
namespace farmlands { namespace farmlands {
namespace controller { namespace controller {
namespace player {
/** static const float PlayerWalkVelocity = 2.0f; // The default velocity of the player when walking (units/sec).
* The default velocity of the player when walking (units/sec). static const float PlayerRunVelocity = 4.0f; // The default velocity of the player when running (units/sec).
*/ static const float PlayerAttackVelocity = 0.1f; // Movement speed when attacking.
static const float PlayerWalkVelocity = 2.0f;
/**
* The default velocity of the player when running (units/sec).
*/
static const float PlayerRunVelocity = 4.0f;
/*
* Movement speed when attacking.
*/
static const float PlayerAttackVelocity = 0.1f;
/** /**
* Direction enum based on sign of velocity on x and y * Direction enum based on sign of velocity on x and y
@ -43,12 +33,12 @@ static const Direction VelocitySignDirections[3][3] =
{ Direction::NorthEast, Direction::East, Direction::SouthEast }, { Direction::NorthEast, Direction::East, Direction::SouthEast },
}; };
PlayerController::PlayerController() PlayerController::PlayerController()
: m_transform(nullptr), : m_transform(nullptr),
m_attackTimeLeft(0), m_attackTimeLeft(0),
m_vx(0), m_vy(0), m_facingDirection(Direction::South),
m_facingDirection(Direction::South) m_walking(false),
m_running(false)
{ {
} }
@ -77,18 +67,25 @@ bool PlayerController::onEvent(SDL_Event& event)
void PlayerController::onUpdateLogic() void PlayerController::onUpdateLogic()
{ {
m_running = false;
m_walking = false;
// Compute movement velocity // Compute movement velocity
float velMultiplier = PlayerWalkVelocity; float velMultiplier = PlayerWalkVelocity;
if (Input::instance().pressed(GameKey::Run))
velMultiplier = PlayerRunVelocity;
if (m_attackTimeLeft) if (m_attackTimeLeft)
{ {
velMultiplier = PlayerAttackVelocity; velMultiplier = PlayerAttackVelocity;
--m_attackTimeLeft; --m_attackTimeLeft;
} }
else if (Input::instance().pressed(GameKey::Run))
{
velMultiplier = PlayerRunVelocity;
m_running = true;
}
// Make movement time independent // Make movement time independent
velMultiplier *= GameState::current().elapsedTime; velMultiplier *= GameState::current().elapsedTime;
@ -97,25 +94,15 @@ void PlayerController::onUpdateLogic()
float vy = Input::instance().getY() * velMultiplier; float vy = Input::instance().getY() * velMultiplier;
// Check if we can move to the new position // Check if we can move to the new position
float newX = m_transform->x + m_vx; float newX = m_transform->x + vx;
float newY = m_transform->y + m_vy; float newY = m_transform->y + vy;
if ((vx || vy) && canMove(newX, newY)) if ((vx || vy) && canMove(newX, newY))
{ {
m_vx = vx; m_walking = true;
m_vy = vy;
m_transform->x = newX; m_transform->x = newX;
m_transform->y = newY; m_transform->y = newY;
m_facingDirection = getDirection(vx, vy); m_facingDirection = getDirection(vx, vy);
base::Transform* cam = GameState::current().renderContext.cameraTransform();
cam->x = newX;
cam->y = newY - 1;
}
else
{
m_vx = 0;
m_vy = 0;
} }
} }
@ -125,8 +112,7 @@ void PlayerController::onPreRender()
SpriteRenderer* spriteRenderer = gameObject->component<SpriteRenderer>(); SpriteRenderer* spriteRenderer = gameObject->component<SpriteRenderer>();
// Compute current state // Compute current state
bool idle = (m_vx == 0 && m_vy == 0); std::string stateName = (m_walking) ? "Walking " : "Idle ";
std::string stateName = (idle) ? "Idle " : "Walking ";
if (m_facingDirection & Direction::East) if (m_facingDirection & Direction::East)
stateName += "right"; stateName += "right";
@ -138,6 +124,18 @@ void PlayerController::onPreRender()
stateName += "down"; stateName += "down";
spriteRenderer->sprite->setState(stateName); spriteRenderer->sprite->setState(stateName);
// Set animation velocity
float animVelocity = (m_running) ? 1.0f : 0.7f;
if (m_attackTimeLeft)
animVelocity = 0.1f;
spriteRenderer->sprite->setAnimationVelocity(animVelocity);
// Set camera
base::Transform* cam = GameState::current().renderContext.cameraTransform();
cam->x = m_transform->x;
cam->y = m_transform->y - 1;
} }
bool PlayerController::canMove(float x, float y) bool PlayerController::canMove(float x, float y)
@ -159,5 +157,6 @@ void PlayerController::attack()
// For now - nothing // For now - nothing
} }
}
} /* namespace controller */ } /* namespace controller */
} /* namespace farmlands */ } /* namespace farmlands */

View File

@ -10,14 +10,13 @@
#include <base/Component.h> #include <base/Component.h>
#include <base/Transform.h> #include <base/Transform.h>
#include <model/Direction.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
namespace farmlands { namespace farmlands {
// Forward declarations
struct GameState;
namespace controller { namespace controller {
namespace player {
class PlayerController : public base::Component class PlayerController : public base::Component
{ {
@ -38,10 +37,12 @@ namespace controller {
base::Transform* m_transform; base::Transform* m_transform;
uint32_t m_attackTimeLeft; uint32_t m_attackTimeLeft;
float m_vx, m_vy;
model::Direction m_facingDirection; model::Direction m_facingDirection;
bool m_walking, m_running;
}; };
}
} /* namespace controller */ } /* namespace controller */
} /* namespace farmlands */ } /* namespace farmlands */

View File

@ -22,8 +22,8 @@ namespace farmlands {
namespace graphics { namespace graphics {
BackgroundRenderer::BackgroundRenderer() BackgroundRenderer::BackgroundRenderer()
: level(nullptr), : m_context(nullptr),
m_context(nullptr) m_back(nullptr)
{ {
} }
@ -36,6 +36,7 @@ void BackgroundRenderer::onInitialize()
Assert(gameObject != nullptr, "Component not properly initialized!"); Assert(gameObject != nullptr, "Component not properly initialized!");
m_context = &GameState::current().renderContext; m_context = &GameState::current().renderContext;
m_back = gameObject->component<model::Background>();
} }
void BackgroundRenderer::onRender() void BackgroundRenderer::onRender()
@ -53,21 +54,21 @@ void BackgroundRenderer::onRender()
int maxCellY = ceilf(m_context->cameraTransform()->y + cellsOnScreenY / 2); int maxCellY = ceilf(m_context->cameraTransform()->y + cellsOnScreenY / 2);
// Clamp cell positions // Clamp cell positions
minCellX = clamp(minCellX, 0, (int)level->columnCount() - 1); minCellX = clamp(minCellX, 0, (int)m_back->columnCount() - 1);
maxCellX = clamp(maxCellX, 0, (int)level->columnCount() - 1); maxCellX = clamp(maxCellX, 0, (int)m_back->columnCount() - 1);
minCellY = clamp(minCellY, 0, (int)level->rowCount() - 1); minCellY = clamp(minCellY, 0, (int)m_back->rowCount() - 1);
maxCellY = clamp(maxCellY, 0, (int)level->rowCount() - 1); maxCellY = clamp(maxCellY, 0, (int)m_back->rowCount() - 1);
// Draw each layer // Draw each layer
for (size_t i = 0; i < level->layerCount(); i++) for (size_t i = 0; i < m_back->layerCount(); i++)
{ {
int textureId = level->texture(i); resources::ResourceId textureId = m_back->texture(i);
// Render only visible tiles // Render only visible tiles
for (int y = minCellY; y <= maxCellY; y++) for (int y = minCellY; y <= maxCellY; y++)
for (int x = minCellX; x <= maxCellX; x++) for (int x = minCellX; x <= maxCellX; x++)
{ {
int cellId = level->cell(i, y, x); int cellId = m_back->cell(i, y, x);
// Obtain texture // Obtain texture
SDL_Texture* texture = ResourceManager::instance().texture(textureId); SDL_Texture* texture = ResourceManager::instance().texture(textureId);

View File

@ -11,7 +11,8 @@
#include <base/Component.h> #include <base/Component.h>
#include <base/Camera.h> #include <base/Camera.h>
#include <base/Transform.h> #include <base/Transform.h>
#include <model/Level.h> #include <base/RenderContext.h>
#include <model/Background.h>
namespace farmlands { namespace farmlands {
namespace graphics { namespace graphics {
@ -25,14 +26,12 @@ public:
virtual void onInitialize() override; virtual void onInitialize() override;
virtual void onRender() override; virtual void onRender() override;
// Public fields
model::Level* level;
private: private:
void getCell(SDL_Texture* texture, uint32_t cell, int* outX, int* outY); void getCell(SDL_Texture* texture, uint32_t cell, int* outX, int* outY);
// Private fields // Private fields
base::RenderContext* m_context; base::RenderContext* m_context;
model::Background* m_back;
}; };
} /* namespace graphics */ } /* namespace graphics */

View File

@ -13,6 +13,7 @@
#include <utils/Assert.h> #include <utils/Assert.h>
using namespace farmlands::graphics::backend; using namespace farmlands::graphics::backend;
using namespace farmlands::resources;
namespace farmlands { namespace farmlands {
namespace graphics { namespace graphics {
@ -66,7 +67,10 @@ void SpriteRenderer::onRender()
void SpriteRenderer::onPostRender() void SpriteRenderer::onPostRender()
{ {
sprite->advanceTime(1); float animFps = GameState::current().config->animationFps;
float deltaTime = GameState::current().elapsedTime;
sprite->advanceTime(animFps * deltaTime);
} }
void SpriteRenderer::getCell(SDL_Texture* texture, uint32_t cell, int* outX, int* outY) void SpriteRenderer::getCell(SDL_Texture* texture, uint32_t cell, int* outX, int* outY)

View File

@ -171,7 +171,7 @@ void TextArea::wrapText(TTF_Font* font)
m_wrappedText = m_text + " "; m_wrappedText = m_text + " ";
// Process characters // Process characters
for (int i = 0; i < m_wrappedText.size(); i++) for (int i = 0; i < (int)m_wrappedText.size(); i++)
{ {
// Remove unwanted character // Remove unwanted character
if (m_wrappedText[i] == '\r') if (m_wrappedText[i] == '\r')

View File

@ -13,20 +13,37 @@ namespace input {
enum GameKey enum GameKey
{ {
// Movement
Right, Right,
Up, Up,
Left, Left,
Down, Down,
Action,
Action2,
Run, Run,
// Actions
Action,
Action2,
// Alternative move keys
AltRight, AltRight,
AltUp, AltUp,
AltLeft, AltLeft,
AltDown, AltDown,
// Inventory
InventoryToggle,
Inventory1,
Inventory2,
Inventory3,
Inventory4,
Inventory5,
Inventory6,
Inventory7,
Inventory8,
Inventory9,
Inventory10,
// Debug keys
Debug_ZoomIn, Debug_ZoomIn,
Debug_ZoomOut, Debug_ZoomOut,

View File

@ -17,20 +17,37 @@ namespace input {
{ {
.keys = .keys =
{ {
// Movement
SDL_SCANCODE_RIGHT, // Right SDL_SCANCODE_RIGHT, // Right
SDL_SCANCODE_UP, // Up SDL_SCANCODE_UP, // Up
SDL_SCANCODE_LEFT, // Left SDL_SCANCODE_LEFT, // Left
SDL_SCANCODE_DOWN, // Down SDL_SCANCODE_DOWN, // Down
SDL_SCANCODE_SPACE, // Action
SDL_SCANCODE_LCTRL, // Action2
SDL_SCANCODE_LSHIFT, // Run SDL_SCANCODE_LSHIFT, // Run
// Action keys
SDL_SCANCODE_SPACE, // Action
SDL_SCANCODE_LCTRL, // Action2
// Alternative movement
SDL_SCANCODE_D, // AltRight SDL_SCANCODE_D, // AltRight
SDL_SCANCODE_W, // AltUp SDL_SCANCODE_W, // AltUp
SDL_SCANCODE_A, // AltLeft SDL_SCANCODE_A, // AltLeft
SDL_SCANCODE_S, // AltRight SDL_SCANCODE_S, // AltRight
// Inventory
SDL_SCANCODE_I, // InventoryToggle
SDL_SCANCODE_1, // Inventory1
SDL_SCANCODE_2, // Inventory2
SDL_SCANCODE_3, // Inventory3
SDL_SCANCODE_4, // Inventory4
SDL_SCANCODE_5, // Inventory5
SDL_SCANCODE_6, // Inventory6
SDL_SCANCODE_7, // Inventory7
SDL_SCANCODE_8, // Inventory8
SDL_SCANCODE_9, // Inventory9
SDL_SCANCODE_0, // Inventory10
// Debug
SDL_SCANCODE_KP_PLUS, // Debug_ZoomIn, SDL_SCANCODE_KP_PLUS, // Debug_ZoomIn,
SDL_SCANCODE_KP_MINUS, // Debug_ZoomOut, SDL_SCANCODE_KP_MINUS, // Debug_ZoomOut,
} }

61
src/model/Background.cpp Normal file
View File

@ -0,0 +1,61 @@
/*
* Background.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <model/Background.h>
#include <utils/Assert.h>
namespace farmlands {
namespace model {
Background::Background(size_t layerCount, size_t rowCount, size_t columnCount)
: m_cells(new Cell[layerCount * rowCount * columnCount]),
m_textures(new resources::ResourceId[layerCount]),
m_layers(layerCount),
m_rows(rowCount),
m_columns(columnCount)
{
}
Background::~Background()
{
delete[] m_cells;
delete[] m_textures;
}
Cell Background::cell(size_t layer, size_t row, size_t col) const
{
Assert(layer < m_layers, "Layer out of bounds.");
Assert(row < m_rows, "Row out of bounds.");
Assert(col < m_columns, "Column out of bounds.");
return m_cells[layer * m_rows * m_columns + row * m_columns + col];
}
void Background::setCell(size_t layer, size_t row, size_t col, Cell value)
{
Assert(layer < m_layers, "Layer out of bounds.");
Assert(row < m_rows, "Row out of bounds.");
Assert(col < m_columns, "Column out of bounds.");
m_cells[layer * m_rows * m_columns + row * m_columns + col] = value;
}
resources::ResourceId Background::texture(size_t layer) const
{
Assert(layer < m_layers, "Layer out of bounds.");
return m_textures[layer];
}
void Background::setTexture(size_t layer, resources::ResourceId textureId) const
{
Assert(layer < m_layers, "Layer out of bounds.");
m_textures[layer] = textureId;
}
} /* namespace model */
} /* namespace farmlands */

View File

@ -1,29 +1,26 @@
/* /*
* Level.h * Background.h
* *
* Created on: Nov 11, 2016 * Created on: Dec 1, 2016
* Author: tibi * Author: tibi
*/ */
#ifndef MODEL_LEVEL_H_ #ifndef MODEL_BACKGROUND_H_
#define MODEL_LEVEL_H_ #define MODEL_BACKGROUND_H_
#include <cstdint> #include <base/Component.h>
#include <cstddef> #include <resources/ResourceManager.h>
namespace farmlands { namespace farmlands {
namespace model { namespace model {
typedef int16_t Cell; typedef int16_t Cell;
class Level class Background: public base::Component
{ {
public: public:
Level(size_t layerCount, size_t rowCount, size_t columnCount); Background(size_t layerCount, size_t rowCount, size_t columnCount);
Level(const Level&) = delete; virtual ~Background();
Level& operator= (const Level&) = delete;
virtual ~Level();
inline size_t layerCount() const { return m_layers; } inline size_t layerCount() const { return m_layers; }
inline size_t rowCount() const { return m_rows; } inline size_t rowCount() const { return m_rows; }
@ -32,14 +29,12 @@ namespace model {
Cell cell(size_t layer, size_t row, size_t col) const; Cell cell(size_t layer, size_t row, size_t col) const;
void setCell(size_t layer, size_t row, size_t col, Cell value); void setCell(size_t layer, size_t row, size_t col, Cell value);
int texture(size_t layer) const; resources::ResourceId texture(size_t layer) const;
void setTexture(size_t layer, int textureId) const; void setTexture(size_t layer, resources::ResourceId textureId) const;
size_t m_cellWidth, m_cellHeight;
private: private:
Cell* m_cells; Cell* m_cells;
int* m_textures; resources::ResourceId* m_textures;
size_t m_layers; size_t m_layers;
size_t m_rows; size_t m_rows;
size_t m_columns; size_t m_columns;
@ -48,4 +43,4 @@ namespace model {
} /* namespace model */ } /* namespace model */
} /* namespace farmlands */ } /* namespace farmlands */
#endif /* MODEL_LEVEL_H_ */ #endif /* MODEL_BACKGROUND_H_ */

View File

@ -4,37 +4,20 @@
* Created on: Nov 13, 2016 * Created on: Nov 13, 2016
* Author: tibi * Author: tibi
*/ */
#ifndef MODEL_CONFIGURATION_H_
#define MODEL_CONFIGURATION_H_
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
namespace farmlands { namespace farmlands {
namespace model { namespace model {
struct KeyConfiguration
{
SDL_Scancode Right = SDL_SCANCODE_RIGHT;
SDL_Scancode Up = SDL_SCANCODE_UP;
SDL_Scancode Left = SDL_SCANCODE_LEFT;
SDL_Scancode Down = SDL_SCANCODE_DOWN;
SDL_Scancode AltRight = SDL_SCANCODE_D;
SDL_Scancode AltUp = SDL_SCANCODE_W;
SDL_Scancode AltLeft = SDL_SCANCODE_A;
SDL_Scancode AltDown = SDL_SCANCODE_S;
SDL_Scancode Action = SDL_SCANCODE_SPACE;
SDL_Scancode Action2 = SDL_SCANCODE_LCTRL;
SDL_Scancode Run = SDL_SCANCODE_LSHIFT;
SDL_Scancode Debug_ZoomIn = SDL_SCANCODE_KP_PLUS;
SDL_Scancode Debug_ZoomOut = SDL_SCANCODE_KP_MINUS;
};
struct Configuration struct Configuration
{ {
KeyConfiguration keys; float animationFps = 60.0f;
}; };
} }
} }
#endif

View File

@ -1,62 +0,0 @@
/*
* Level.cpp
*
* Created on: Nov 11, 2016
* Author: tibi
*/
#include "Level.h"
#include <cassert>
namespace farmlands {
namespace model {
Level::Level(size_t layerCount, size_t rowCount, size_t columnCount)
: m_cellWidth(0),
m_cellHeight(0),
m_cells(new Cell[layerCount * rowCount * columnCount]),
m_textures(new int[layerCount]),
m_layers(layerCount),
m_rows(rowCount),
m_columns(columnCount)
{
}
Level::~Level()
{
delete[] m_cells;
delete[] m_textures;
}
Cell Level::cell(size_t layer, size_t row, size_t col) const
{
assert(layer < m_layers);
assert(row < m_rows);
assert(col < m_columns);
return m_cells[layer * m_rows * m_columns + row * m_columns + col];
}
void Level::setCell(size_t layer, size_t row, size_t col, Cell value)
{
assert(layer < m_layers);
assert(row < m_rows);
assert(col < m_columns);
m_cells[layer * m_rows * m_columns + row * m_columns + col] = value;
}
int Level::texture(size_t layer) const
{
return m_textures[layer];
}
void Level::setTexture(size_t layer, int textureId) const
{
m_textures[layer] = textureId;
}
} /* namespace model */
} /* namespace farmlands */

View File

@ -1,36 +0,0 @@
/*
* Player.h
*
* Created on: Nov 26, 2016
* Author: tibi
*/
#ifndef MODEL_PLAYER_H_
#define MODEL_PLAYER_H_
#include <model/Direction.h>
namespace farmlands {
namespace model {
#define PLAYER_INVENTORY_SIZE 3*12
struct Player
{
float posX, posY;
float lastDeltaX, lastDeltaY;
Direction direction;
bool attacking;
uint32_t attackTimeLeft;
int inventorySelection = -1;
int inventory[PLAYER_INVENTORY_SIZE];
};
}
}
#endif /* MODEL_PLAYER_H_ */

View File

@ -15,10 +15,13 @@ namespace resources {
{ {
None, None,
Texture, Texture,
Sprite,
Level,
LevelLayer,
Font, Font,
Sprite,
Configuration,
Scene,
Background,
BackgroundLayer,
Item,
}; };
struct ResourceInfo struct ResourceInfo

View File

@ -0,0 +1,162 @@
/*
* ResourceManager.cpp
*
* Created on: Nov 7, 2016
* Author: tibi
*/
#include <GameState.h>
#include <graphics/backend/SdlRenderer.h>
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#include <storage/Parsers.h>
#include <utils/Assert.h>
#include <iostream>
#include <boost/filesystem.hpp>
#define FONTID(id,size) (id * 1000 + size)
#define FONTID_SIZE(fontid) (fontid % 1000)
#define FONTID_ID(fontid) (fontid / 1000)
using namespace farmlands::graphics::backend;
namespace farmlands {
namespace resources {
ResourceManager ResourceManager::s_instance;
ResourceManager& ResourceManager::instance()
{
return s_instance;
}
ResourceManager::ResourceManager()
: m_loadedResources(new LoadedResource[sizeof(RInfo) / sizeof(RInfo[0])])
{
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
m_loadedResources[i].loaded = false;
}
ResourceManager::~ResourceManager()
{
// Unload resources
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
{
if (m_loadedResources[i].loaded)
{
switch(RInfo[i].type)
{
case ResourceType::Texture:
SDL_DestroyTexture(m_loadedResources[i].texture.texture);
SDL_FreeSurface(m_loadedResources[i].texture.surface);
break;
default:
std::cerr << "Warning: Cannot free resource " << i << " of type " << (int)RInfo[i].type << "\n";
break;
}
}
}
delete[] m_loadedResources;
// Unload fonts
for (auto pair : m_fontCache)
{
TTF_CloseFont(pair.second);
}
}
void ResourceManager::initialize()
{
}
void ResourceManager::loadMainMenu()
{
}
void ResourceManager::loadGame()
{
GameState::current().config = storage::parse<model::Configuration>(R::Config::Default);
GameState::current().scene = storage::parse<base::Scene>(R::Scenes::Game);
GameState::current().scene->root.onCreate();
}
std::string ResourceManager::getPath(ResourceId resourceId)
{
Assert(resourceId >= 0 && resourceId < sizeof(RInfo) / sizeof(RInfo[0]), "Resource id out of bounds.");
boost::filesystem::path resPath(ASSETS_DIR);
resPath.append(RInfo[resourceId].path);
return resPath.native();
}
ResourceId ResourceManager::getId(std::string resPathStr)
{
boost::filesystem::path resPath(resPathStr);
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
{
boost::filesystem::path iPath (RInfo[i].path);
if (resPath == iPath)
return i;
}
return (ResourceId)-1;
}
TTF_Font* ResourceManager::font(ResourceId fontId, int pointSize)
{
Assert(RInfo[fontId].type == ResourceType::Font, "Resource must be a font");
// Do not load if already loaded
auto it = m_fontCache.find(FONTID(fontId, pointSize));
if (it != m_fontCache.end())
return it->second;
// Open font
std::string fontPath = getPath(fontId);
TTF_Font* font = TTF_OpenFont(fontPath.c_str(), pointSize);
if (!font)
THROW(utils::ResourceLoadException, "Could not load font " + fontPath);
// Cache font
m_fontCache.emplace(FONTID(fontId, pointSize), font);
return font;
}
SDL_Texture* ResourceManager::texture(ResourceId textureId)
{
Assert(RInfo[textureId].type == ResourceType::Texture, "Resource must be a texture");
// See if already loaded
if (!m_loadedResources[textureId].loaded)
{
// Open file
std::string texturePath = getPath(textureId);
SDL_Surface* surface = IMG_Load(texturePath.c_str());
if (surface == NULL)
THROW(utils::ResourceLoadException, "Failed to load texture " + texturePath);
SDL_Texture* texture = SDL_CreateTextureFromSurface(SdlRenderer::instance().internalRenderer(), surface);
if (texture == NULL)
THROW(utils::ResourceLoadException, "Failed to create texture " + texturePath);
// Add to loaded resources
m_loadedResources[textureId].texture.surface = surface;
m_loadedResources[textureId].texture.texture = texture;
m_loadedResources[textureId].loaded = true;
}
return m_loadedResources[textureId].texture.texture;
}
} /* namespace storage */
} /* namespace farmlands */

View File

@ -9,7 +9,6 @@
#define STORAGE_RESOURCEMANAGER_H_ #define STORAGE_RESOURCEMANAGER_H_
#include <base/Sprite.h> #include <base/Sprite.h>
#include <model/Level.h>
#include <vector> #include <vector>
#include <map> #include <map>
@ -30,7 +29,6 @@ namespace resources {
struct LoadedResource struct LoadedResource
{ {
bool loaded; bool loaded;
union union
{ {
struct struct
@ -38,9 +36,6 @@ namespace resources {
SDL_Surface* surface; SDL_Surface* surface;
SDL_Texture* texture; SDL_Texture* texture;
} texture; } texture;
model::Level* level;
base::Sprite* sprite;
}; };
}; };
@ -52,20 +47,12 @@ namespace resources {
static ResourceManager& instance(); static ResourceManager& instance();
~ResourceManager(); ~ResourceManager();
void initialize();
// Loading routines // Loading routines
void initialize();
void loadMainMenu(); void loadMainMenu();
void loadGameAssets(); void loadGame();
void loadLevel(ResourceId levelId);
TTF_Font* font(ResourceId id, int pointSize); // Getters
SDL_Texture* texture(ResourceId id);
model::Level* level(ResourceId id);
base::Sprite* sprite(ResourceId id);
private:
ResourceManager();
/** /**
* Obtains the path of the resource in native format. * Obtains the path of the resource in native format.
@ -76,20 +63,22 @@ namespace resources {
* Obtains the id of a resource based on its path. * Obtains the id of a resource based on its path.
* Returns: the resource id, or -1 if resource not found. * Returns: the resource id, or -1 if resource not found.
*/ */
int getId(std::string resourcePath); ResourceId getId(std::string resourcePath);
void loadFont(ResourceId fontId, int pointSize); // Resource getters
void loadTexture(ResourceId textureId); TTF_Font* font(ResourceId id, int pointSize);
void loadSprite(ResourceId spriteId); SDL_Texture* texture(ResourceId id);
void loadLevelLayer(model::Level* level, size_t layerNumber, ResourceId resourceId);
private:
ResourceManager();
typedef int FontId;
// Instance
static ResourceManager s_instance; static ResourceManager s_instance;
// Loaded resources // Loaded resources
LoadedResource* m_loadedResources; LoadedResource* m_loadedResources;
typedef int FontId;
std::map<FontId, TTF_Font*> m_fontCache; std::map<FontId, TTF_Font*> m_fontCache;
}; };

View File

@ -1,102 +0,0 @@
/*
* ResourceManager.cpp
*
* Created on: Nov 7, 2016
* Author: tibi
*/
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#include <utils/Assert.h>
#include <boost/filesystem.hpp>
namespace farmlands {
namespace resources {
ResourceManager ResourceManager::s_instance;
ResourceManager& ResourceManager::instance()
{
return s_instance;
}
ResourceManager::ResourceManager()
: m_loadedResources(new LoadedResource[sizeof(RInfo) / sizeof(RInfo[0])])
{
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
m_loadedResources[i].loaded = false;
}
ResourceManager::~ResourceManager()
{
// Unload resources
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
{
if (m_loadedResources[i].loaded)
{
switch(RInfo[i].type)
{
case ResourceType::Level:
delete m_loadedResources[i].level;
break;
case ResourceType::Texture:
SDL_DestroyTexture(m_loadedResources[i].texture.texture);
SDL_FreeSurface(m_loadedResources[i].texture.surface);
break;
case ResourceType::Sprite:
delete m_loadedResources[i].sprite;
default:
Assert(false, "Cannot free resources!");
break;
}
}
}
delete[] m_loadedResources;
}
void ResourceManager::initialize()
{
}
void ResourceManager::loadMainMenu()
{
}
void ResourceManager::loadGameAssets()
{
loadSprite(R::Sprites::Player);
}
std::string ResourceManager::getPath(ResourceId resourceId)
{
Assert(resourceId >= 0 && resourceId < sizeof(RInfo) / sizeof(RInfo[0]), "Resource id out of bounds.");
boost::filesystem::path resPath(ASSETS_DIR);
resPath.append(RInfo[resourceId].path);
return resPath.native();
}
int ResourceManager::getId(std::string resPathStr)
{
boost::filesystem::path resPath(resPathStr);
for(size_t i = 0; i < sizeof(RInfo) / sizeof(RInfo[0]); i++)
{
boost::filesystem::path iPath (RInfo[i].path);
if (resPath == iPath)
return (int)i;
}
return -1;
}
} /* namespace storage */
} /* namespace farmlands */

View File

@ -1,37 +0,0 @@
/*
* ResourceManager_Fonts.cpp
*
* Created on: Nov 29, 2016
* Author: tibi
*/
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#define FONTID(id,size) (id * 1000 + size)
#define FONTID_SIZE(fontid) (fontid % 1000)
#define FONTID_ID(fontid) (fontid / 1000)
namespace farmlands {
namespace resources {
TTF_Font* ResourceManager::font(ResourceId id, int pointSize)
{
// Open from cache
auto it = m_fontCache.find(FONTID(id, pointSize));
if (it != m_fontCache.end())
return it->second;
// Open font
std::string fontPath = getPath(id);
TTF_Font* font = TTF_OpenFont(fontPath.c_str(), pointSize);
if (!font)
THROW(utils::ResourceLoadException, "Could not load font " + fontPath);
// Cache it
m_fontCache.emplace(FONTID(id, pointSize), font);
return font;
}
}
}

View File

@ -1,114 +0,0 @@
/*
* ResourceManager_Levels.cpp
*
* Created on: Nov 11, 2016
* Author: tibi
*/
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#include <utils/Assert.h>
#include <fstream>
#include <string>
#include <json.hpp>
using namespace nlohmann;
namespace farmlands {
namespace resources {
void ResourceManager::loadLevelLayer(model::Level* level, size_t layer, ResourceId resourceId)
{
Assert(RInfo[resourceId].type == ResourceType::LevelLayer, "Resource must be a level layer.");
char buffer[1024 * 10];
// Open file
std::string pathIn = getPath(resourceId);
std::ifstream in(pathIn);
if (!in)
THROW(utils::ResourceLoadException, "Could not load level layer " + pathIn);
// Read CSV file line by line
for (size_t row = 0; row < level->rowCount(); row++)
{
in.getline(buffer, sizeof(buffer));
if (in.eof())
THROW(utils::ResourceLoadException, "Unexpected end of file " + pathIn);
// Separated by comma (or maybe semicolon)
char* nextNum = strtok(buffer, ",;");
for (size_t col = 0; col < level->columnCount() && nextNum != NULL; col++)
{
model::Cell cell = (model::Cell)strtol(nextNum, NULL, 10);
level->setCell(layer, row, col, cell);
nextNum = strtok(NULL, ",;");
}
}
in.close();
}
void ResourceManager::loadLevel(ResourceId levelId)
{
// Sanity checks
Assert(RInfo[levelId].type == ResourceType::Level, "Resource must be a level!");
if (m_loadedResources[levelId].loaded)
return;
// Open file
std::string levelPath = getPath(levelId);
std::ifstream levelIn(getPath(levelId));
if (!levelIn)
THROW(utils::ResourceLoadException, "Failed to load level " + levelPath);
// Parse file
json levelJs;
levelIn>>levelJs;
size_t layerCount = levelJs.value("layerCount", 0u);
size_t rowCount = levelJs.value("height", 0u);
size_t colCount = levelJs.value("width", 0u);
assert(layerCount > 0 && rowCount > 0 && colCount > 0);
model::Level* level = new model::Level(layerCount, rowCount, colCount);
level->m_cellWidth = levelJs.value("cellWidth", 0u);
level->m_cellHeight = levelJs.value("cellHeight", 0u);
// Read layers
json layersJs = levelJs["layers"];
size_t layer = 0;
for (auto it = layersJs.begin(); it != layersJs.end(); it++, layer++)
{
std::string cellsFileName = it->value("cellsFile", std::string());
loadLevelLayer(level, layer, getId(cellsFileName));
std::string textureFileName = it->value("textureFile", std::string());
int textureId = getId(textureFileName);
level->setTexture(layer, textureId);
loadTexture(textureId);
}
m_loadedResources[levelId].loaded = true;
m_loadedResources[levelId].level = level;
}
model::Level* ResourceManager::level(ResourceId id)
{
Assert(RInfo[id].type == ResourceType::Level, "Resource must be a level!");
return m_loadedResources[id].level;
}
}
}

View File

@ -1,92 +0,0 @@
/*
* ResourceManager_Sprites.cpp
*
* Created on: Nov 29, 2016
* Author: tibi
*/
#include <base/Sprite.h>
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#include <utils/Assert.h>
#include <fstream>
#include <string>
#include <json.hpp>
using namespace nlohmann;
using namespace farmlands::base;
namespace farmlands {
namespace resources {
void ResourceManager::loadSprite(ResourceId spriteId)
{
Assert(RInfo[spriteId].type == ResourceType::Sprite, "Resource must be a sprite!");
if (m_loadedResources[spriteId].loaded)
return;
// Open file
std::string spritePath = getPath(spriteId);
std::ifstream spriteIn(spritePath);
if (!spriteIn)
THROW(utils::ResourceLoadException, "Could not load " + spritePath);
// Parse file
json spriteJs;
spriteIn >> spriteJs;
Sprite* sprite = new Sprite();
sprite->anchorX = spriteJs.value("anchorX", 0.0f);
sprite->anchorY = spriteJs.value("anchorY", 0.0f);
json statesJs = spriteJs.at("states");
for (auto state : statesJs)
{
SpriteState spriteState;
spriteState.name = state.value("name", std::string());
// Obtain frames
json framesJs = state.at("frames");
for (auto frame : framesJs)
{
Frame spriteFrame;
spriteFrame.tileSetCell = frame.value("cell", 0u);
spriteFrame.width = frame.value("width", 0u);
spriteFrame.height = frame.value("height", 0u);
spriteFrame.duration = frame.value("duration", 0u);
// Obtain tile set id
std::string tileSetPath = frame.value("tileSet", std::string());
spriteFrame.tileSetId = getId(tileSetPath);
loadTexture(spriteFrame.tileSetId);
// Add frame
spriteState.frames.push_back(spriteFrame);
}
// Add state
sprite->addState(spriteState);
}
m_loadedResources[spriteId].loaded = true;
m_loadedResources[spriteId].sprite = sprite;
}
Sprite* ResourceManager::sprite(ResourceId id)
{
Assert(RInfo[id].type == ResourceType::Sprite, "Resource must be a sprite!");
return m_loadedResources[id].sprite;
}
}
}

View File

@ -1,55 +0,0 @@
/*
* ResourceManager_Textures.cpp
*
* Created on: Nov 12, 2016
* Author: tibi
*/
#include <graphics/backend/SdlRenderer.h>
#include <resources/ResourceManager.h>
#include <resources/Resources.h>
#include <utils/Assert.h>
using namespace farmlands::graphics::backend;
namespace farmlands {
namespace resources {
void ResourceManager::loadTexture(ResourceId resourceId)
{
Assert(RInfo[resourceId].type == ResourceType::Texture, "Resource must be a texture!");
if (m_loadedResources[resourceId].loaded)
return;
// Open file
std::string texturePath = getPath(resourceId);
SDL_Surface* surface = IMG_Load(texturePath.c_str());
if (surface == NULL)
THROW(utils::ResourceLoadException, "Failed to load texture " + texturePath);
SDL_Texture* texture = SDL_CreateTextureFromSurface(SdlRenderer::instance().internalRenderer(), surface);
if (texture == NULL)
THROW(utils::ResourceLoadException, "Failed to create texture " + texturePath);
// Add to loaded resources
m_loadedResources[resourceId].loaded = true;
m_loadedResources[resourceId].texture.surface = surface;
m_loadedResources[resourceId].texture.texture = texture;
}
SDL_Texture* ResourceManager::texture(ResourceId id)
{
Assert(RInfo[id].type == ResourceType::Texture, "Resource must be a texture!");
return m_loadedResources[id].texture.texture;
}
}
}

View File

@ -15,44 +15,70 @@ namespace resources {
enum Sprites enum Sprites
{ {
Player = 0, Player = 0,
items_Lvl1_sword = 1,
items_Stone_pickaxe = 2,
};
enum Scenes
{
Game = 3,
}; };
enum Fonts enum Fonts
{ {
DejaVuSans = 1, DejaVuSans = 4,
}; };
enum Tilesets enum Tilesets
{ {
PlayerTiles = 2, PlayerTiles = 5,
Ground = 3, Ground = 6,
}; };
enum Ui enum Ui
{ {
Cursor = 4, Mini_inventory = 7,
Cursor = 8,
}; };
enum Levels enum Levels
{ {
Farm_Background = 5, Farm_Background = 9,
Farm = 6, Farm = 10,
};
enum Config
{
Default = 11,
};
enum Items
{
Stone_pickaxe = 12,
Lvl1_sword = 13,
}; };
} }
const int RInfo_Sprites_Begin = 0; const int RInfo_Sprites_Begin = 0;
const int RInfo_Fonts_Begin = 1; const int RInfo_Scenes_Begin = 3;
const int RInfo_Tilesets_Begin = 2; const int RInfo_Fonts_Begin = 4;
const int RInfo_Ui_Begin = 4; const int RInfo_Tilesets_Begin = 5;
const int RInfo_Levels_Begin = 5; const int RInfo_Ui_Begin = 7;
const int RInfo_Levels_Begin = 9;
const int RInfo_Config_Begin = 11;
const int RInfo_Items_Begin = 12;
/** /**
* This array contains the names of all the files, and the corresponding file type. * This array contains the names of all the files, and the corresponding file type.
*/ */
const ResourceInfo RInfo[] = { const ResourceInfo RInfo[] = {
{ "sprites/player.sprite", ResourceType::Sprite }, { "sprites/Player.sprite", ResourceType::Sprite },
{ "sprites/items/lvl1_sword.sprite", ResourceType::Sprite },
{ "sprites/items/stone_pickaxe.sprite", ResourceType::Sprite },
{ "scenes/Game.scene", ResourceType::Scene },
{ "fonts/DejaVuSans.ttf", ResourceType::Font }, { "fonts/DejaVuSans.ttf", ResourceType::Font },
{ "tilesets/PlayerTiles.png", ResourceType::Texture }, { "tilesets/PlayerTiles.png", ResourceType::Texture },
{ "tilesets/Ground.png", ResourceType::Texture }, { "tilesets/Ground.png", ResourceType::Texture },
{ "ui/mini_inventory.png", ResourceType::Texture },
{ "ui/cursor.png", ResourceType::Texture }, { "ui/cursor.png", ResourceType::Texture },
{ "levels/Farm_Background.csv", ResourceType::LevelLayer }, { "levels/Farm_Background.csv", ResourceType::BackgroundLayer },
{ "levels/Farm.level", ResourceType::Level }, { "levels/Farm.back", ResourceType::Background },
{ "config/Default.config", ResourceType::Configuration },
{ "items/stone_pickaxe.item", ResourceType::Item },
{ "items/lvl1_sword.item", ResourceType::Item },
}; };
} }

10
src/storage/Parse.cpp Normal file
View File

@ -0,0 +1,10 @@
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
DEFINE_EXCEPTION_CPP(ParserException, utils::Exception);
}
}

87
src/storage/Parse.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Parsers.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSE_H_
#define STORAGE_PARSE_H_
#include <resources/ResourceManager.h>
#include <utils/Assert.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
namespace farmlands {
namespace storage {
/****** Declarations ******/
DEFINE_EXCEPTION_CLASS(ParserException, utils::Exception);
/**
* Parses a resource using a resource ID.
*/
template <typename T>
T* parse(resources::ResourceId resourceId);
/**
* Parses a resource using a file path.
*/
template <typename T>
T* parse(std::string filePath);
/**
* Parses a resource from a property tree.
*/
template <typename T>
T* parse(boost::property_tree::ptree& root);
/****** Implementations ******/
template <typename T>
T* parse(resources::ResourceId resourceId)
{
// Get resource file
std::string path = resources::ResourceManager::instance().getPath(resourceId);
// Parse the tree
return parse<T>(path);
}
template <typename T>
T* parse(std::string path)
{
// Open file
std::ifstream resourceIn(path);
if (!resourceIn)
THROW(utils::ResourceLoadException, "Failed to load resource " + path);
// Read property tree
boost::property_tree::ptree tree;
boost::property_tree::read_xml(resourceIn, tree);
resourceIn.close();
// Parse the tree (give root element)
return parse<T>(tree);
}
template <typename T>
T* parse(boost::property_tree::ptree& root)
{
std::string typeName = typeid(T).name();
// Throw not implemented exception
THROW(utils::NotImplementedException, "No parser implemented for type " + typeName);
}
}
}
#endif /* STORAGE_PARSE_H_ */

22
src/storage/Parsers.h Normal file
View File

@ -0,0 +1,22 @@
/*
* Parsers.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSERS_H_
#define STORAGE_PARSERS_PARSERS_H_
#include <storage/Parse.h>
#include <storage/parsers/ParseComponents_base.h>
#include <storage/parsers/ParseComponents_controller.h>
#include <storage/parsers/ParseComponents_graphics.h>
#include <storage/parsers/ParseComponents_model.h>
#include <storage/parsers/ParseConfiguration.h>
#include <storage/parsers/ParseSprite.h>
#include <storage/parsers/ParseGameObject.h>
#include <storage/parsers/ParseScene.h>
#endif /* STORAGE_PARSERS_PARSERS_H_ */

View File

@ -0,0 +1,39 @@
/*
* ParseComponents_base.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseComponents_base.h>
namespace farmlands {
namespace storage {
template <>
base::Transform* parse<base::Transform> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "Transform")
root = root.front().second;
base::Transform* transform = new base::Transform();
transform->x = root.get<float>("<xmlattr>.x", 0.0f);
transform->y = root.get<float>("<xmlattr>.y", 0.0f);
return transform;
}
template <>
base::Camera* parse<base::Camera> (boost::property_tree::ptree& root)
{
if (root.front().first == "Camera")
root = root.front().second;
base::Camera* camera = new base::Camera();
camera->scale = root.get<float>("<xmlattr>.scale", 1.0f);
camera->mainCamera = root.get<bool>("<xmlattr>.mainCamera", false);
return camera;
}
}
}

View File

@ -0,0 +1,27 @@
/*
* ParseGameObject.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSECOMPONENTS_BASE_H_
#define STORAGE_PARSERS_PARSECOMPONENTS_BASE_H_
#include <base/GameObject.h>
#include <base/Camera.h>
#include <base/Transform.h>
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
template <>
base::Transform* parse<base::Transform> (boost::property_tree::ptree& root);
template <>
base::Camera* parse<base::Camera> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSERS_PARSEGAMEOBJECT_H_ */

View File

@ -0,0 +1,36 @@
/*
* ParseComponents_controller.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseComponents_controller.h>
namespace farmlands {
namespace storage {
template <>
controller::player::PlayerController* parse<controller::player::PlayerController> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "PlayerController")
root = root.front().second;
controller::player::PlayerController* controller = new controller::player::PlayerController();
return controller;
}
template <>
controller::DebugController* parse<controller::DebugController> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "DebugController")
root = root.front().second;
controller::DebugController* controller = new controller::DebugController();
return controller;
}
}
}

View File

@ -0,0 +1,27 @@
/*
* ParseComponents_controller.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSECOMPONENTS_CONTROLLER_H_
#define STORAGE_PARSERS_PARSECOMPONENTS_CONTROLLER_H_
#include <controller/player/PlayerController.h>
#include <controller/DebugController.h>
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
template <>
controller::player::PlayerController* parse<controller::player::PlayerController> (boost::property_tree::ptree& root);
template <>
controller::DebugController* parse<controller::DebugController> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSERS_PARSECOMPONENTS_CONTROLLER_H_ */

View File

@ -0,0 +1,42 @@
/*
* ParseComponents_graphics.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseComponents_graphics.h>
namespace farmlands {
namespace storage {
template <>
graphics::BackgroundRenderer* parse<graphics::BackgroundRenderer> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "BackgroundRenderer")
root = root.front().second;
graphics::BackgroundRenderer* renderer = new graphics::BackgroundRenderer();
return renderer;
}
template <>
graphics::SpriteRenderer* parse<graphics::SpriteRenderer> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "SpriteRenderer")
root = root.front().second;
graphics::SpriteRenderer* renderer = new graphics::SpriteRenderer();
// Load sprite
std::string spritePath = root.get<std::string>("<xmlattr>.sprite");
resources::ResourceId spriteId = resources::ResourceManager::instance().getId(spritePath);
renderer->sprite = parse<base::Sprite>(spriteId);
return renderer;
}
}
}

View File

@ -0,0 +1,27 @@
/*
* ParseComponents_graphics.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSECOMPONENTS_GRAPHICS_H_
#define STORAGE_PARSERS_PARSECOMPONENTS_GRAPHICS_H_
#include <graphics/BackgroundRenderer.h>
#include <graphics/SpriteRenderer.h>
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
template <>
graphics::BackgroundRenderer* parse<graphics::BackgroundRenderer> (boost::property_tree::ptree& root);
template <>
graphics::SpriteRenderer* parse<graphics::SpriteRenderer> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSERS_PARSECOMPONENTS_GRAPHICS_H_ */

View File

@ -0,0 +1,92 @@
/*
* ParseComponents_model.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseComponents_model.h>
#include <resources/Resources.h>
using namespace farmlands::resources;
namespace farmlands {
namespace storage {
void parseBackgroundCells(resources::ResourceId cellsResource, model::Background* back, size_t layer)
{
Assert(RInfo[cellsResource].type == ResourceType::BackgroundLayer, "Resource must be a level layer.");
char buffer[1024 * 10];
// Open file
std::string pathIn = ResourceManager::instance().getPath(cellsResource);
std::ifstream in(pathIn);
if (!in)
THROW(utils::ResourceLoadException, "Could not load level layer " + pathIn);
// Read CSV file line by line
for (size_t row = 0; row < back->rowCount(); row++)
{
in.getline(buffer, sizeof(buffer));
if (in.eof())
THROW(utils::ResourceLoadException, "Unexpected end of file " + pathIn);
// Separated by comma (or maybe semicolon)
char* nextNum = strtok(buffer, ",;");
for (size_t col = 0; col < back->columnCount() && nextNum != NULL; col++)
{
model::Cell cell = (model::Cell)strtol(nextNum, NULL, 10);
back->setCell(layer, row, col, cell);
nextNum = strtok(NULL, ",;");
}
}
in.close();
}
template <>
model::Background* parse<model::Background> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "Background")
root = root.front().second;
// Read sizes
uint32_t layers = root.count("Layer");
uint32_t rows = root.get<uint32_t>("<xmlattr>.rows");
uint32_t cols = root.get<uint32_t>("<xmlattr>.columns");
// Create background object
model::Background* back = new model::Background(layers, rows, cols);
// Read layers
size_t layerNum = 0;
for (auto layer : root)
{
if (layer.first == "Layer")
{
// Read cells
std::string cellsPath = layer.second.get<std::string>("<xmlattr>.cells");
resources::ResourceId cellsId = resources::ResourceManager::instance().getId(cellsPath);
parseBackgroundCells(cellsId, back, layerNum);
// Read texture name
std::string texPath = layer.second.get<std::string>("<xmlattr>.texture");
resources::ResourceId tex = resources::ResourceManager::instance().getId(texPath);
back->setTexture(layerNum, tex);
++layerNum;
}
}
return back;
}
}
}

View File

@ -0,0 +1,27 @@
/*
* ParseComponents_model.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSECOMPONENTS_MODEL_H_
#define STORAGE_PARSERS_PARSECOMPONENTS_MODEL_H_
#include <model/Background.h>
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
void parseBackgroundCells(resources::ResourceId cellsResource, model::Background* back, size_t layer);
template <>
model::Background* parse<model::Background> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSERS_PARSECOMPONENTS_MODEL_H_ */

View File

@ -0,0 +1,30 @@
/*
* ParseConfiguration.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseConfiguration.h>
#include <resources/Resources.h>
using namespace farmlands::resources;
namespace farmlands {
namespace storage {
template <>
model::Configuration* parse<model::Configuration> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "Configuration")
root = root.front().second;
model::Configuration* config = new model::Configuration();
config->animationFps = root.get<float>("animationFps");
return config;
}
} /* namespace storage */
} /* namespace farmlands */

View File

@ -0,0 +1,23 @@
/*
* ParseConfiguration.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSECONFIGURATION_H_
#define STORAGE_PARSERS_PARSECONFIGURATION_H_
#include <model/Configuration.h>
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
template <>
model::Configuration* parse<model::Configuration> (boost::property_tree::ptree& root);
} /* namespace storage */
} /* namespace farmlands */
#endif /* STORAGE_PARSERS_PARSECONFIGURATION_H_ */

View File

@ -0,0 +1,61 @@
/*
* ParseGameObject.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <model/Background.h>
#include <storage/parsers/ParseGameObject.h>
namespace farmlands {
namespace storage {
template <>
base::GameObject* parse<base::GameObject> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "GameObject")
root = root.front().second;
base::GameObject* gameObj = new base::GameObject();
gameObj->name = root.get<std::string>("<xmlattr>.name");
for (auto child : root)
{
// Base objects
if (child.first == "Transform")
gameObj->addComponent(parse<base::Transform>(child.second));
else if (child.first == "Camera")
gameObj->addComponent(parse<base::Camera>(child.second));
// Model
else if (child.first == "Background")
{
std::string path = child.second.get<std::string>("<xmlattr>.src");
resources::ResourceId id = resources::ResourceManager::instance().getId(path);
gameObj->addComponent(parse<model::Background>(id));
}
// Graphics
else if (child.first == "BackgroundRenderer")
gameObj->addComponent(parse<graphics::BackgroundRenderer>(child.second));
else if (child.first == "SpriteRenderer")
gameObj->addComponent(parse<graphics::SpriteRenderer>(child.second));
// Controllers
else if (child.first == "PlayerController")
gameObj->addComponent(parse<controller::player::PlayerController>(child.second));
else if (child.first == "DebugController")
gameObj->addComponent(parse<controller::DebugController>(child.second));
// !!! Add additional types here !!!
}
return gameObj;
}
}
}

View File

@ -0,0 +1,30 @@
/*
* ParseGameObject.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSEGAMEOBJECT_H_
#define STORAGE_PARSERS_PARSEGAMEOBJECT_H_
#include <base/GameObject.h>
#include <base/Camera.h>
#include <base/Transform.h>
#include <controller/player/PlayerController.h>
#include <controller/DebugController.h>
#include <graphics/BackgroundRenderer.h>
#include <graphics/SpriteRenderer.h>
#include <storage/Parse.h>
#include <resources/Resources.h>
namespace farmlands {
namespace storage {
template <>
base::GameObject* parse<base::GameObject> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSERS_PARSEGAMEOBJECT_H_ */

View File

@ -0,0 +1,39 @@
/*
* ParseScene.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseScene.h>
namespace farmlands {
namespace storage {
template <>
base::Scene* parse<base::Scene> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "Scene")
root = root.front().second;
base::Scene* scene = new base::Scene();
scene->cellWidth = root.get<uint32_t>("<xmlattr>.cellWidth");
scene->cellHeight = root.get<uint32_t>("<xmlattr>.cellHeight");
for (auto child : root)
{
if (child.first == "GameObject")
{
base::GameObject* obj = parse<base::GameObject>(child.second);
scene->root.addChild(obj);
}
}
return scene;
}
}
}

View File

@ -0,0 +1,27 @@
/*
* ParseScene.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSE_SCENE_H_
#define STORAGE_PARSERS_PARSE_SCENE_H_
#include <base/GameObject.h>
#include <base/Scene.h>
#include <storage/Parse.h>
#include <resources/Resources.h>
namespace farmlands {
namespace storage {
template <>
base::Scene* parse<base::Scene> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSE_H_ */

View File

@ -0,0 +1,84 @@
/*
* ParseSprite.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <storage/parsers/ParseSprite.h>
#include <resources/Resources.h>
namespace farmlands {
namespace storage {
template <>
base::Frame* parse<base::Frame> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "Frame")
root = root.front().second;
base::Frame* frame = new base::Frame();
// Obtine tile set id
std::string tileSetPath = root.get<std::string>("<xmlattr>.tileSet");
frame->tileSetId = resources::ResourceManager::instance().getId(tileSetPath);
// Set properties
frame->tileSetCell = root.get<int>("<xmlattr>.cell");
frame->width = root.get<uint32_t>("<xmlattr>.w", 1u);
frame->height = root.get<uint32_t>("<xmlattr>.h", 1u);
frame->duration = root.get<uint32_t>("<xmlattr>.duration");
return frame;
}
template <>
base::SpriteState* parse<base::SpriteState> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "SpriteState")
root = root.front().second;
base::SpriteState* spriteState = new base::SpriteState();
spriteState->name = root.get<std::string>("<xmlattr>.name");
for (auto child : root)
{
if (child.first == "Frame")
{
base::Frame* frame = parse<base::Frame>(child.second);
spriteState->frames.push_back(*frame);
delete frame;
}
}
return spriteState;
}
template <>
base::Sprite* parse<base::Sprite> (boost::property_tree::ptree& root)
{
// Ensure we are on the scene node (property tree seems to add root of its own)
if (root.front().first == "Sprite")
root = root.front().second;
base::Sprite* sprite = new base::Sprite();
sprite->anchorX = root.get<float>("<xmlattr>.anchorX");
sprite->anchorY = root.get<float>("<xmlattr>.anchorY");
for (auto child : root)
{
if (child.first == "State")
{
base::SpriteState* state = parse<base::SpriteState>(child.second);
sprite->addState(*state);
delete state;
}
}
return sprite;
}
}
}

View File

@ -0,0 +1,29 @@
/*
* ParseSprite.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef STORAGE_PARSERS_PARSESPRITE_H_
#define STORAGE_PARSERS_PARSESPRITE_H_
#include <base/Sprite.h>
#include <storage/Parse.h>
namespace farmlands {
namespace storage {
template <>
base::Frame* parse<base::Frame> (boost::property_tree::ptree& root);
template <>
base::SpriteState* parse<base::SpriteState> (boost::property_tree::ptree& root);
template <>
base::Sprite* parse<base::Sprite> (boost::property_tree::ptree& root);
}
}
#endif /* STORAGE_PARSERS_PARSESPRITE_H_ */

View File

@ -0,0 +1,43 @@
/*
* S.cpp
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#include <utils/DumpPropertyTree.h>
#include <iostream>
#include <boost/algorithm/string.hpp>
namespace farmlands {
namespace utils {
void dumpPropertyTreeInternal(boost::property_tree::ptree& tree, unsigned level)
{
for (auto child : tree)
{
for (unsigned i = 0; i < level; i++)
std::cout << " ";
std::string data = child.second.data();
boost::trim(data);
std::cout<< "* " << child.first <<" = " << data << "\n";
dumpPropertyTreeInternal(child.second, level + 1);
}
}
void dumpPropertyTree(boost::property_tree::ptree& tree)
{
std::string data = tree.data();
boost::trim(data);
std::cout << "[root] = " << data << "\n";
dumpPropertyTreeInternal(tree, 1);
}
} /* namespace utils */
} /* namespace farmlands */

View File

@ -0,0 +1,21 @@
/*
* S.h
*
* Created on: Dec 1, 2016
* Author: tibi
*/
#ifndef UTILS_DUMPPROPERTYTREE_H_
#define UTILS_DUMPPROPERTYTREE_H_
#include <boost/property_tree/ptree.hpp>
namespace farmlands {
namespace utils {
void dumpPropertyTree(boost::property_tree::ptree& tree);
} /* namespace utils */
} /* namespace farmlands */
#endif /* UTILS_DUMPPROPERTYTREE_H_ */

View File

@ -36,7 +36,9 @@ Exception::~Exception()
} }
DEFINE_EXCEPTION_CPP(InvalidArgumentException, Exception) DEFINE_EXCEPTION_CPP(InvalidArgumentException, Exception);
DEFINE_EXCEPTION_CPP(NotImplementedException, Exception);
DEFINE_EXCEPTION_CPP(IOException, Exception); DEFINE_EXCEPTION_CPP(IOException, Exception);
DEFINE_EXCEPTION_CPP(ResourceLoadException, IOException); DEFINE_EXCEPTION_CPP(ResourceLoadException, IOException);

View File

@ -65,8 +65,10 @@ namespace utils {
// Common exceptions // Common exceptions
DEFINE_EXCEPTION_CLASS(InvalidArgumentException, Exception); DEFINE_EXCEPTION_CLASS(InvalidArgumentException, Exception);
DEFINE_EXCEPTION_CLASS(NotImplementedException, Exception);
// IO Exceptions
DEFINE_EXCEPTION_CLASS(IOException, Exception); DEFINE_EXCEPTION_CLASS(IOException, Exception);
DEFINE_EXCEPTION_CLASS(ResourceLoadException, IOException); DEFINE_EXCEPTION_CLASS(ResourceLoadException, IOException);