Reorganized classes & namespaces. Made sprite a component.
This commit is contained in:
80
src/components/Background.cpp
Normal file
80
src/components/Background.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Background.cpp
|
||||
*
|
||||
* Created on: Dec 1, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <components/Background.h>
|
||||
#include <utils/Assert.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
model::Component* Background::clone()
|
||||
{
|
||||
Background* clone = new Background(m_layers, m_rows, m_columns);
|
||||
memcpy(clone->m_cells, m_cells, sizeof(Cell) * m_layers * m_rows * m_columns);
|
||||
memcpy(clone->m_textures, m_textures, sizeof(resources::ResourceId) * m_layers);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Background::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Background\n";
|
||||
}
|
||||
|
||||
} /* namespace model */
|
||||
} /* namespace farmlands */
|
49
src/components/Background.h
Normal file
49
src/components/Background.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Background.h
|
||||
*
|
||||
* Created on: Dec 1, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef MODEL_BACKGROUND_H_
|
||||
#define MODEL_BACKGROUND_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
#include <resources/ResourceManager.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
|
||||
typedef int16_t Cell;
|
||||
|
||||
class Background: public model::Component
|
||||
{
|
||||
public:
|
||||
Background(size_t layerCount, size_t rowCount, size_t columnCount);
|
||||
virtual ~Background();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
inline size_t layerCount() const { return m_layers; }
|
||||
inline size_t rowCount() const { return m_rows; }
|
||||
inline size_t columnCount() const { return m_columns; }
|
||||
|
||||
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);
|
||||
|
||||
resources::ResourceId texture(size_t layer) const;
|
||||
void setTexture(size_t layer, resources::ResourceId textureId) const;
|
||||
|
||||
private:
|
||||
Cell* m_cells;
|
||||
resources::ResourceId* m_textures;
|
||||
size_t m_layers;
|
||||
size_t m_rows;
|
||||
size_t m_columns;
|
||||
};
|
||||
|
||||
} /* namespace model */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* MODEL_BACKGROUND_H_ */
|
69
src/components/DebugController.cpp
Normal file
69
src/components/DebugController.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* DebugController.cpp
|
||||
*
|
||||
* Created on: Nov 30, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/basic/Camera.h>
|
||||
#include <components/DebugController.h>
|
||||
#include <input/Input.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace farmlands::input;
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
|
||||
static const float ScaleVelocity = 0.5f;
|
||||
static const float ScaleShiftVelocity = 2.0f;
|
||||
|
||||
DebugController::DebugController()
|
||||
: m_camera(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DebugController::~DebugController()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* DebugController::clone()
|
||||
{
|
||||
return new DebugController();
|
||||
}
|
||||
|
||||
void DebugController::onInitialize()
|
||||
{
|
||||
m_camera = GameState::current().renderContext.camera();
|
||||
}
|
||||
|
||||
void DebugController::onUpdateLogic()
|
||||
{
|
||||
// Compute velocity
|
||||
float vel = ScaleVelocity;
|
||||
|
||||
if (Input::instance().pressed(GameKey::Run))
|
||||
vel = ScaleShiftVelocity;
|
||||
|
||||
// Time independent
|
||||
vel *= GameState::current().elapsedTime;
|
||||
|
||||
if (Input::instance().pressed(GameKey::Debug_ZoomIn))
|
||||
m_camera->scale *= 1 + vel;
|
||||
|
||||
if (Input::instance().pressed(GameKey::Debug_ZoomOut))
|
||||
m_camera->scale *= 1 - vel;
|
||||
}
|
||||
|
||||
void DebugController::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: DebugController\n";
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
} /* namespace farmlands */
|
36
src/components/DebugController.h
Normal file
36
src/components/DebugController.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* DebugController.h
|
||||
*
|
||||
* Created on: Nov 30, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_DEBUGCONTROLLER_H_
|
||||
#define CONTROLLER_DEBUGCONTROLLER_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
#include <components/basic/Camera.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
|
||||
class DebugController: public model::Component
|
||||
{
|
||||
public:
|
||||
DebugController();
|
||||
virtual ~DebugController();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onInitialize() override;
|
||||
virtual void onUpdateLogic() override;
|
||||
|
||||
private:
|
||||
basic::Camera* m_camera;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* CONTROLLER_DEBUGCONTROLLER_H_ */
|
86
src/components/GuiController.cpp
Normal file
86
src/components/GuiController.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* GuiController.cpp
|
||||
*
|
||||
* Created on: Nov 26, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/GuiController.h>
|
||||
#include <gui/widgets/TextArea.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
|
||||
GuiController::GuiController()
|
||||
: m_canvas()
|
||||
{
|
||||
}
|
||||
|
||||
GuiController::~GuiController()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* GuiController::clone()
|
||||
{
|
||||
return new GuiController();
|
||||
}
|
||||
|
||||
void GuiController::onInitialize()
|
||||
{
|
||||
m_context = &GameState::current().renderContext;
|
||||
|
||||
// Set up canvas
|
||||
m_canvas.setSize(m_context->viewport.width, m_context->viewport.height);
|
||||
|
||||
// Add a text element
|
||||
auto text = new gui::widgets::TextArea();
|
||||
text->setText("Hello world!");
|
||||
text->setSize(50, 5);
|
||||
text->setPosition(100, 10);
|
||||
text->setColor(0, 1, 0);
|
||||
text->setBackColor(0.5f, 0, 0, 0.5f);
|
||||
text->setTextSize(11);
|
||||
text->setHorizontalWrap(gui::widgets::TextHorizontalWrapping::Ellipsis);
|
||||
text->setVerticalWrap(gui::widgets::TextVerticalWrapping::Trim);
|
||||
text->setAlignment(gui::widgets::TextAlign::BottomRight);
|
||||
m_canvas.addChild(text);
|
||||
}
|
||||
|
||||
bool GuiController::onEvent(SDL_Event& event)
|
||||
{
|
||||
bool handled = m_canvas.handleEvent(event);
|
||||
|
||||
float currentW = m_canvas.child(0)->width();
|
||||
float currentH = m_canvas.child(0)->height();
|
||||
|
||||
if (event.type == SDL_EventType::SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_HOME)
|
||||
{
|
||||
m_canvas.child(0)->setSize(currentW + 5, currentH);
|
||||
}
|
||||
if (event.type == SDL_EventType::SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_END)
|
||||
{
|
||||
m_canvas.child(0)->setSize(currentW - 5, currentH);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void GuiController::onRender()
|
||||
{
|
||||
// Render
|
||||
m_canvas.render(m_context);
|
||||
}
|
||||
|
||||
void GuiController::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: DebugController\n";
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
} /* namespace farmlands */
|
44
src/components/GuiController.h
Normal file
44
src/components/GuiController.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* GuiController.h
|
||||
*
|
||||
* Created on: Nov 26, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_GUICONTROLLER_H_
|
||||
#define CONTROLLER_GUICONTROLLER_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
#include <graphics/RenderContext.h>
|
||||
#include <gui/layout/Canvas.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
|
||||
class GuiController : public model::Component
|
||||
{
|
||||
public:
|
||||
GuiController();
|
||||
virtual ~GuiController();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
/**
|
||||
* Initializes game renderer
|
||||
*/
|
||||
virtual void onInitialize() override;
|
||||
virtual bool onEvent(SDL_Event& event) override;
|
||||
virtual void onRender() override;
|
||||
|
||||
private:
|
||||
gui::layout::Canvas m_canvas;
|
||||
graphics::RenderContext* m_context;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* CONTROLLER_GUICONTROLLER_H_ */
|
60
src/components/basic/Camera.cpp
Normal file
60
src/components/basic/Camera.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Camera.cpp
|
||||
*
|
||||
* Created on: Dec 1, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/basic/Camera.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace farmlands::model;
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace basic {
|
||||
|
||||
Camera::Camera()
|
||||
: scale(1),
|
||||
mainCamera(true)
|
||||
{
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
}
|
||||
|
||||
Component* Camera::clone()
|
||||
{
|
||||
Camera* clone = new Camera();
|
||||
clone->mainCamera = mainCamera;
|
||||
clone->scale = scale;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void Camera::onCreate()
|
||||
{
|
||||
if (mainCamera)
|
||||
{
|
||||
GameState::current().renderContext.setCamera(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Camera ";
|
||||
std::cout << "main="<<mainCamera<<" ";
|
||||
std::cout << "scale="<<scale<<"\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
src/components/basic/Camera.h
Normal file
36
src/components/basic/Camera.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Camera.h
|
||||
*
|
||||
* Created on: Nov 30, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef MODEL_CAMERA_H_
|
||||
#define MODEL_CAMERA_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace basic {
|
||||
|
||||
class Camera : public model::Component
|
||||
{
|
||||
public:
|
||||
Camera();
|
||||
virtual ~Camera();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onCreate();
|
||||
|
||||
float scale;
|
||||
bool mainCamera;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MODEL_CAMERA_H_ */
|
134
src/components/basic/Sprite.cpp
Normal file
134
src/components/basic/Sprite.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Sprite.cpp
|
||||
*
|
||||
* Created on: Nov 29, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/basic/Sprite.h>
|
||||
#include <utils/Assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace basic {
|
||||
|
||||
Sprite::Sprite()
|
||||
: name(),
|
||||
anchorX(0), anchorY(0),
|
||||
animationVelocity(1.0f),
|
||||
m_states(),
|
||||
m_stateNames(),
|
||||
m_currentState(0),
|
||||
m_currentFrame(0),
|
||||
m_currentFrameTimeLeft(0)
|
||||
{
|
||||
}
|
||||
|
||||
Sprite::~Sprite()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* Sprite::clone()
|
||||
{
|
||||
Sprite* clone = new Sprite();
|
||||
|
||||
// Copy public fields
|
||||
clone->name = name;
|
||||
clone->anchorX = anchorX;
|
||||
clone->anchorY = anchorY;
|
||||
clone->animationVelocity = animationVelocity;
|
||||
|
||||
// Copy private memberes
|
||||
std::copy(m_states.begin(), m_states.end(), std::back_inserter(clone->m_states));
|
||||
std::copy(m_stateNames.begin(), m_stateNames.end(), std::inserter(clone->m_stateNames, clone->m_stateNames.end()));
|
||||
clone->m_currentState = m_currentState;
|
||||
clone->m_currentFrame = m_currentFrame;
|
||||
clone->m_currentFrameTimeLeft = m_currentFrameTimeLeft;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void Sprite::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Sprite ";
|
||||
std::cout << "name="<<name<<"\n";
|
||||
}
|
||||
|
||||
void Sprite::onPreRender()
|
||||
{
|
||||
advanceTime(GameState::current().elapsedTime);
|
||||
}
|
||||
|
||||
void Sprite::addState(const SpriteState& state)
|
||||
{
|
||||
Assert(state.frames.size() > 0, "State must have at least one frame!");
|
||||
#ifdef BUILD_DEBUG
|
||||
float totalDuration = 0;
|
||||
for (auto frame : state.frames)
|
||||
totalDuration += frame.duration;
|
||||
|
||||
Assert(totalDuration > 0, "State must have a frame which last at least one tick.");
|
||||
#endif
|
||||
Assert(m_stateNames.count(state.name) == 0, "A state with the same name already added!");
|
||||
|
||||
m_states.push_back(state);
|
||||
m_stateNames.emplace(state.name, m_states.size() - 1);
|
||||
}
|
||||
|
||||
void Sprite::setState(size_t stateId)
|
||||
{
|
||||
Assert(stateId < m_states.size(), "Inexistent state.");
|
||||
|
||||
// Avoid resetting state
|
||||
if (stateId == m_currentState)
|
||||
return;
|
||||
|
||||
m_currentState = stateId;
|
||||
m_currentFrame = 0;
|
||||
m_currentFrameTimeLeft = currentFrame().duration;
|
||||
}
|
||||
|
||||
void Sprite::setState(const std::string& name)
|
||||
{
|
||||
Assert(m_stateNames.count(name) > 0, "Inexistent state.");
|
||||
setState(m_stateNames.at(name));
|
||||
}
|
||||
|
||||
SpriteState& Sprite::currentState()
|
||||
{
|
||||
Assert(m_states.size() > 0, "Sprite must have at least one state!");
|
||||
return m_states.at(m_currentState);
|
||||
}
|
||||
|
||||
Frame& Sprite::currentFrame()
|
||||
{
|
||||
Assert(currentState().frames.size() > 0, "State must have at least one frame!");
|
||||
return currentState().frames.at(m_currentFrame);
|
||||
}
|
||||
|
||||
void Sprite::advanceTime(float fractions)
|
||||
{
|
||||
Assert(m_states.size() > 0, "Sprite must have at least one state!");
|
||||
|
||||
m_currentFrameTimeLeft -= fractions * animationVelocity;
|
||||
|
||||
while (m_currentFrameTimeLeft <= 0)
|
||||
{
|
||||
// Move to the next frame
|
||||
if (++m_currentFrame >= currentState().frames.size())
|
||||
m_currentFrame = 0;
|
||||
|
||||
m_currentFrameTimeLeft += currentFrame().duration;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} /* namespace farmlands */
|
94
src/components/basic/Sprite.h
Normal file
94
src/components/basic/Sprite.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Sprite.h
|
||||
*
|
||||
* Created on: Nov 29, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef MODEL_SPRITE_H_
|
||||
#define MODEL_SPRITE_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
#include <utils/Exceptions.h>
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace basic {
|
||||
|
||||
/**
|
||||
* Defines an animation frame
|
||||
*/
|
||||
struct Frame
|
||||
{
|
||||
uint32_t tileSetId;
|
||||
uint32_t tileSetCell;
|
||||
uint32_t width, height;
|
||||
float duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a sprite state (i.e. an animation).
|
||||
*/
|
||||
struct SpriteState
|
||||
{
|
||||
std::string name;
|
||||
std::vector<Frame> frames;
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a sprite
|
||||
*/
|
||||
class Sprite : public model::Component
|
||||
{
|
||||
public:
|
||||
Sprite();
|
||||
virtual ~Sprite();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onPreRender() override;
|
||||
|
||||
/**
|
||||
* Adds a state to the sprite.
|
||||
*/
|
||||
void addState(const SpriteState& state);
|
||||
|
||||
/**
|
||||
* Sets the current state.
|
||||
*/
|
||||
void setState(size_t stateId);
|
||||
|
||||
/**
|
||||
* Sets the current state.
|
||||
*/
|
||||
void setState(const std::string& name);
|
||||
|
||||
// Getters
|
||||
SpriteState& currentState();
|
||||
Frame& currentFrame();
|
||||
|
||||
// Public fields
|
||||
std::string name;
|
||||
float anchorX, anchorY;
|
||||
float animationVelocity;
|
||||
|
||||
private:
|
||||
void advanceTime(float fractions);
|
||||
|
||||
std::vector<SpriteState> m_states;
|
||||
std::unordered_map<std::string, size_t> m_stateNames;
|
||||
|
||||
size_t m_currentState;
|
||||
size_t m_currentFrame;
|
||||
float m_currentFrameTimeLeft;
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* MODEL_SPRITE_H_ */
|
80
src/components/basic/Transform.cpp
Normal file
80
src/components/basic/Transform.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Transform.cpp
|
||||
*
|
||||
* Created on: Dec 2, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <model/GameObject.h>
|
||||
#include <components/basic/Transform.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace basic {
|
||||
|
||||
Transform::Transform()
|
||||
: x(0), y(0),
|
||||
w(0), h(0),
|
||||
m_parent(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Transform::~Transform()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* Transform::clone()
|
||||
{
|
||||
Transform* clone = new Transform();
|
||||
clone->x = x;
|
||||
clone->y = y;
|
||||
clone->w = w;
|
||||
clone->h = h;
|
||||
return clone;
|
||||
}
|
||||
|
||||
void Transform::onCreate()
|
||||
{
|
||||
if (gameObject->parent() != nullptr)
|
||||
m_parent = gameObject->parent()->component<Transform>();
|
||||
}
|
||||
|
||||
float Transform::globalX() const
|
||||
{
|
||||
return (m_parent) ? m_parent->globalX() + x : x;
|
||||
}
|
||||
|
||||
float Transform::globalY() const
|
||||
{
|
||||
return (m_parent) ? m_parent->globalY() + y : y;
|
||||
}
|
||||
|
||||
void Transform::setGlobalX(float x)
|
||||
{
|
||||
this->x = (m_parent) ? x - m_parent->globalX() : x;
|
||||
}
|
||||
|
||||
void Transform::setGlobalY(float y)
|
||||
{
|
||||
this->y = (m_parent) ? y - m_parent->globalY() : y;
|
||||
}
|
||||
|
||||
void Transform::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Transform ";
|
||||
std::cout << "x="<<x<<" ";
|
||||
std::cout << "y="<<y<<" ";
|
||||
std::cout << "w="<<w<<" ";
|
||||
std::cout << "h="<<h<<"\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} /* namespace farmlands */
|
||||
|
||||
|
48
src/components/basic/Transform.h
Normal file
48
src/components/basic/Transform.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Transform.h
|
||||
*
|
||||
* Created on: Nov 30, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef BASE_TRANSFORM_H_
|
||||
#define BASE_TRANSFORM_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace basic {
|
||||
|
||||
class Transform: public model::Component
|
||||
{
|
||||
public:
|
||||
Transform();
|
||||
virtual ~Transform();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onCreate();
|
||||
|
||||
// Getters
|
||||
float globalX() const;
|
||||
float globalY() const;
|
||||
|
||||
// Setters
|
||||
void setGlobalX(float x);
|
||||
void setGlobalY(float y);
|
||||
|
||||
// Local coordinates (relative to parent)
|
||||
float x, y;
|
||||
float w, h;
|
||||
|
||||
private:
|
||||
Transform* m_parent;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* BASE_TRANSFORM_H_ */
|
50
src/components/items/Giftable.cpp
Normal file
50
src/components/items/Giftable.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Giftable.cpp
|
||||
*
|
||||
* Created on: Dec 2, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <components/items/Giftable.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
Giftable::Giftable()
|
||||
{
|
||||
}
|
||||
|
||||
Giftable::~Giftable()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* Giftable::clone()
|
||||
{
|
||||
return new Giftable();
|
||||
}
|
||||
|
||||
bool Giftable::canGift(float x, float y, model::Direction d)
|
||||
{
|
||||
// TODO: implement Giftable::canGift
|
||||
return false;
|
||||
}
|
||||
|
||||
void Giftable::offerGift(float x, float y, model::Direction d)
|
||||
{
|
||||
// TODO: implement Giftable::offerGift
|
||||
}
|
||||
|
||||
void Giftable::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Giftable\n";
|
||||
}
|
||||
|
||||
} /* namespace items */
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
35
src/components/items/Giftable.h
Normal file
35
src/components/items/Giftable.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Giftable.h
|
||||
*
|
||||
* Created on: Dec 2, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_ITEMS_GIFTABLE_H_
|
||||
#define CONTROLLER_ITEMS_GIFTABLE_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
#include <model/Direction.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Giftable: public model::Component
|
||||
{
|
||||
public:
|
||||
Giftable();
|
||||
virtual ~Giftable();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
bool canGift(float x, float y, model::Direction d);
|
||||
void offerGift(float x, float y, model::Direction d);
|
||||
};
|
||||
|
||||
} /* namespace items */
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* CONTROLLER_ITEMS_GIFTABLE_H_ */
|
67
src/components/items/Item.h
Normal file
67
src/components/items/Item.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Item.h
|
||||
*
|
||||
* Created on: Dec 2, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef MODEL_ITEM_H_
|
||||
#define MODEL_ITEM_H_
|
||||
|
||||
#include <model/Component.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Item: public model::Component
|
||||
{
|
||||
public:
|
||||
Item();
|
||||
virtual ~Item();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
std::string name;
|
||||
std::string description;
|
||||
uint8_t level;
|
||||
};
|
||||
|
||||
|
||||
/****** Implementation ******/
|
||||
|
||||
inline Item::Item()
|
||||
: name(), description(),
|
||||
level(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline Item::~Item()
|
||||
{
|
||||
}
|
||||
|
||||
inline model::Component* Item::clone()
|
||||
{
|
||||
Item* clone = new Item();
|
||||
clone->name = name;
|
||||
clone->description = description;
|
||||
clone->level = level;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
inline void Item::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Item\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* MODEL_ITEM_H_ */
|
83
src/components/items/Weapon.cpp
Normal file
83
src/components/items/Weapon.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Weapon.cpp
|
||||
*
|
||||
* Created on: Dec 2, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/items/Weapon.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
Weapon::Weapon()
|
||||
: damage(0),
|
||||
critProbability(0),
|
||||
critDamage(0),
|
||||
attackDuration(1.0f),
|
||||
m_sprite(nullptr),
|
||||
m_attackTimeLeft(0)
|
||||
{
|
||||
}
|
||||
|
||||
Weapon::~Weapon()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* Weapon::clone()
|
||||
{
|
||||
Weapon* clone = new Weapon();
|
||||
clone->damage = damage;
|
||||
clone->critProbability = critProbability;
|
||||
clone->critDamage = critDamage;
|
||||
clone->attackDuration = attackDuration;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void Weapon::onInitialize()
|
||||
{
|
||||
m_sprite = gameObject->component<basic::Sprite>();
|
||||
}
|
||||
|
||||
void Weapon::onPreRender()
|
||||
{
|
||||
m_sprite->setState(m_attackTimeLeft > 0);
|
||||
}
|
||||
|
||||
void Weapon::onUpdateLogic()
|
||||
{
|
||||
if (m_attackTimeLeft > 0)
|
||||
{
|
||||
m_attackTimeLeft -= GameState::current().elapsedTime;
|
||||
}
|
||||
}
|
||||
|
||||
void Weapon::performAttack(float x, float y, model::Direction d)
|
||||
{
|
||||
if (m_attackTimeLeft <= 0)
|
||||
{
|
||||
m_attackTimeLeft = attackDuration;
|
||||
}
|
||||
}
|
||||
|
||||
void Weapon::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: Transform ";
|
||||
std::cout << "damage="<<damage<<" ";
|
||||
std::cout << "critProbability="<<critProbability<<" ";
|
||||
std::cout << "critDamage="<<critDamage<<" ";
|
||||
std::cout << "attackDuration="<<attackDuration<<"\n";
|
||||
}
|
||||
|
||||
}
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
54
src/components/items/Weapon.h
Normal file
54
src/components/items/Weapon.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Weapon.h
|
||||
*
|
||||
* Created on: Dec 2, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_ITEMS_WEAPON_H_
|
||||
#define CONTROLLER_ITEMS_WEAPON_H_
|
||||
|
||||
#include <components/basic/Sprite.h>
|
||||
#include <graphics/SpriteRenderer.h>
|
||||
#include <model/Component.h>
|
||||
#include <model/Direction.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Weapon: public model::Component
|
||||
{
|
||||
public:
|
||||
Weapon();
|
||||
virtual ~Weapon();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onInitialize() override;
|
||||
virtual void onUpdateLogic() override;
|
||||
virtual void onPreRender() override;
|
||||
|
||||
/**
|
||||
* Performs everything required to attacking an enemy with a weapon. To be called from player controller.
|
||||
*/
|
||||
void performAttack(float x, float y, model::Direction d);
|
||||
|
||||
// Properties
|
||||
float damage;
|
||||
float critProbability;
|
||||
float critDamage;
|
||||
|
||||
float attackDuration; // In seconds
|
||||
|
||||
private:
|
||||
basic::Sprite* m_sprite;
|
||||
float m_attackTimeLeft;
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* CONTROLLER_ITEMS_WEAPON_H_ */
|
240
src/components/player/PlayerController.cpp
Normal file
240
src/components/player/PlayerController.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* PlayerController.cpp
|
||||
*
|
||||
* Created on: Nov 27, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#include <GameState.h>
|
||||
#include <components/items/Giftable.h>
|
||||
#include <components/items/Item.h>
|
||||
#include <components/items/Weapon.h>
|
||||
#include <components/player/PlayerController.h>
|
||||
#include <graphics/SpriteRenderer.h>
|
||||
#include <input/Input.h>
|
||||
#include <utils/Assert.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace farmlands::components::basic;
|
||||
using namespace farmlands::components::items;
|
||||
using namespace farmlands::graphics;
|
||||
using namespace farmlands::input;
|
||||
using namespace farmlands::model;
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace player {
|
||||
|
||||
static const float PlayerWalkVelocity = 2.0f; // 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.
|
||||
|
||||
/**
|
||||
* Direction enum based on sign of velocity on x and y
|
||||
*/
|
||||
static const Direction VelocitySignDirections[3][3] =
|
||||
{
|
||||
{ Direction::NorthWest, Direction::West, Direction::SouthWest },
|
||||
{ Direction::North, Direction::None, Direction::South },
|
||||
{ Direction::NorthEast, Direction::East, Direction::SouthEast },
|
||||
};
|
||||
|
||||
PlayerController::PlayerController()
|
||||
: m_transform(nullptr),
|
||||
m_facingDirection(Direction::South),
|
||||
m_walking(false),
|
||||
m_running(false),
|
||||
m_currentItem(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PlayerController::~PlayerController()
|
||||
{
|
||||
}
|
||||
|
||||
model::Component* PlayerController::clone()
|
||||
{
|
||||
return new PlayerController();
|
||||
}
|
||||
|
||||
void PlayerController::onInitialize()
|
||||
{
|
||||
m_transform = gameObject->component<components::basic::Transform>();
|
||||
}
|
||||
|
||||
bool PlayerController::onEvent(SDL_Event& event)
|
||||
{
|
||||
handleAttackEvents(event);
|
||||
handleInventoryEvents(event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlayerController::handleAttackEvents(SDL_Event& event)
|
||||
{
|
||||
bool attack = (Input::instance().down(GameKey::Action, event));
|
||||
if (attack && m_currentItem != nullptr)
|
||||
{
|
||||
// Weapon behavior
|
||||
Weapon* weapon = m_currentItem->component<Weapon>();
|
||||
if (weapon)
|
||||
weapon->performAttack(m_transform->x, m_transform->y, m_facingDirection);
|
||||
|
||||
// Gift behavior
|
||||
Giftable* giftable = m_currentItem->component<Giftable>();
|
||||
if (giftable)
|
||||
giftable->offerGift(m_transform->x, m_transform->y, m_facingDirection);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::handleInventoryEvents(SDL_Event& event)
|
||||
{
|
||||
// See what key was pressed
|
||||
int slot = -1;
|
||||
|
||||
if (Input::instance().down(GameKey::Inventory1, event)) slot = 1;
|
||||
if (Input::instance().down(GameKey::Inventory2, event)) slot = 2;
|
||||
if (Input::instance().down(GameKey::Inventory3, event)) slot = 3;
|
||||
if (Input::instance().down(GameKey::Inventory4, event)) slot = 4;
|
||||
if (Input::instance().down(GameKey::Inventory5, event)) slot = 5;
|
||||
if (Input::instance().down(GameKey::Inventory6, event)) slot = 6;
|
||||
if (Input::instance().down(GameKey::Inventory7, event)) slot = 7;
|
||||
if (Input::instance().down(GameKey::Inventory8, event)) slot = 8;
|
||||
if (Input::instance().down(GameKey::Inventory9, event)) slot = 9;
|
||||
if (Input::instance().down(GameKey::Inventory10, event)) slot = 10;
|
||||
|
||||
// For now we don't have an inventory, so just instantiate some object
|
||||
if (0 <= slot && slot <= GameState::current().itemPrefabs.size())
|
||||
{
|
||||
GameObject* itemPrefab = GameState::current().itemPrefabs[slot - 1];
|
||||
|
||||
// Get rid of old object
|
||||
if (m_currentItem != nullptr)
|
||||
gameObject->destroyChild(m_currentItem);
|
||||
|
||||
// Instantiate new object
|
||||
m_currentItem = GameObject::instantiate(itemPrefab, "Current item", gameObject);
|
||||
|
||||
// Print some information
|
||||
// Item* item = itemPrefab->component<Item>();
|
||||
// std::string name = (item == nullptr) ? "unknown" : item->name;
|
||||
// std::cout << "Instantiated object " << slot << " (" << name << ")\n";
|
||||
}
|
||||
else if (0 <= slot)
|
||||
{
|
||||
std::cout << "Slot " << slot << "empty\n";
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::onUpdateLogic()
|
||||
{
|
||||
m_running = false;
|
||||
m_walking = false;
|
||||
|
||||
// Compute movement velocity
|
||||
float velMultiplier = PlayerWalkVelocity;
|
||||
|
||||
// if (m_attackTimeLeft)
|
||||
// {
|
||||
// velMultiplier = PlayerAttackVelocity;
|
||||
// --m_attackTimeLeft;
|
||||
// } else
|
||||
|
||||
if (Input::instance().pressed(GameKey::Run))
|
||||
{
|
||||
velMultiplier = PlayerRunVelocity;
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
|
||||
// Make movement time independent
|
||||
velMultiplier *= GameState::current().elapsedTime;
|
||||
|
||||
// Get velocity of axes
|
||||
float vx = Input::instance().getX() * velMultiplier;
|
||||
float vy = Input::instance().getY() * velMultiplier;
|
||||
|
||||
// Check if we can move to the new position
|
||||
float newX = m_transform->x + vx;
|
||||
float newY = m_transform->y + vy;
|
||||
if ((vx || vy) && canMove(newX, newY))
|
||||
{
|
||||
m_walking = true;
|
||||
m_transform->x = newX;
|
||||
m_transform->y = newY;
|
||||
|
||||
m_facingDirection = getDirection(vx, vy);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::onPreRender()
|
||||
{
|
||||
// Get sprite
|
||||
Sprite* sprite = gameObject->component<Sprite>();
|
||||
|
||||
// Compute current state
|
||||
std::string stateName = (m_walking) ? "Walking " : "Idle ";
|
||||
|
||||
if (m_facingDirection & Direction::East)
|
||||
stateName += "right";
|
||||
else if (m_facingDirection & Direction::West)
|
||||
stateName += "left";
|
||||
else if (m_facingDirection & Direction::North)
|
||||
stateName += "up";
|
||||
else
|
||||
stateName += "down";
|
||||
|
||||
sprite->setState(stateName);
|
||||
|
||||
// Set animation velocity
|
||||
float animVelocity = (m_running) ? 1.0f : 0.7f;
|
||||
// if (m_attackTimeLeft)
|
||||
// animVelocity = 0.1f;
|
||||
|
||||
sprite->animationVelocity = animVelocity;
|
||||
|
||||
// Set weapon
|
||||
if (m_currentItem)
|
||||
{
|
||||
Transform* itemTransf = m_currentItem->component<Transform>();
|
||||
itemTransf->x = 0.2f;
|
||||
itemTransf->y = -0.8f;
|
||||
}
|
||||
|
||||
// Set camera
|
||||
components::basic::Transform* cam = GameState::current().renderContext.cameraTransform();
|
||||
cam->x = m_transform->x;
|
||||
cam->y = m_transform->y - 1;
|
||||
}
|
||||
|
||||
bool PlayerController::canMove(float x, float y)
|
||||
{
|
||||
// TODO: check collisions & stuff. For now, nothing
|
||||
return true;
|
||||
}
|
||||
|
||||
Direction PlayerController::getDirection(float vx, float vy)
|
||||
{
|
||||
int xx = (0 < vx) - (vx < 0);
|
||||
int yy = (0 < vy) - (vy < 0);
|
||||
|
||||
return VelocitySignDirections[xx + 1][yy + 1];
|
||||
}
|
||||
|
||||
void PlayerController::attack()
|
||||
{
|
||||
// For now - nothing
|
||||
}
|
||||
|
||||
void PlayerController::dump(unsigned level)
|
||||
{
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
std::cout<<" ";
|
||||
|
||||
std::cout << " .Component: PlayerController\n";
|
||||
}
|
||||
|
||||
}
|
||||
} /* namespace controller */
|
||||
} /* namespace farmlands */
|
55
src/components/player/PlayerController.h
Normal file
55
src/components/player/PlayerController.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* PlayerController.h
|
||||
*
|
||||
* Created on: Nov 27, 2016
|
||||
* Author: tibi
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_PLAYERCONTROLLER_H_
|
||||
#define CONTROLLER_PLAYERCONTROLLER_H_
|
||||
|
||||
#include <components/basic/Transform.h>
|
||||
#include <model/Component.h>
|
||||
#include <model/Direction.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace player {
|
||||
|
||||
class PlayerController : public model::Component
|
||||
{
|
||||
public:
|
||||
PlayerController();
|
||||
virtual ~PlayerController();
|
||||
|
||||
virtual model::Component* clone() override;
|
||||
virtual void dump(unsigned level) override;
|
||||
|
||||
virtual void onInitialize() override;
|
||||
virtual bool onEvent(SDL_Event& event) override;
|
||||
virtual void onUpdateLogic() override;
|
||||
virtual void onPreRender() override;
|
||||
|
||||
private:
|
||||
static model::Direction getDirection(float vx, float vy);
|
||||
|
||||
void handleAttackEvents(SDL_Event& event);
|
||||
void handleInventoryEvents(SDL_Event& event);
|
||||
|
||||
bool canMove(float x, float y);
|
||||
void attack();
|
||||
|
||||
basic::Transform* m_transform;
|
||||
model::Direction m_facingDirection;
|
||||
bool m_walking, m_running;
|
||||
|
||||
model::GameObject* m_currentItem;
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace components */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* CONTROLLER_PLAYERCONTROLLER_H_ */
|
Reference in New Issue
Block a user