farmlands/src/components/basic/Sprite.cpp

173 lines
3.7 KiB
C++

/*
* 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()
: w(1), h(1),
anchorX(0), anchorY(0),
animationSpeed(1.0f),
m_states(),
m_stateNames(),
m_currentState((size_t)-1),
m_currentFrame(0),
m_currentFrameTimeLeft(0)
{
}
Sprite::~Sprite()
{
}
model::Component* Sprite::clone()
{
Sprite* clone = new Sprite();
// Copy public fields
clone->w = w;
clone->h = h;
clone->anchorX = anchorX;
clone->anchorY = anchorY;
clone->animationSpeed = animationSpeed;
// Copy private members
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 << "state="<<m_currentState<<"\n";
}
void Sprite::onPreRender()
{
advanceTime(GameState::current().deltaTime);
}
utils::RectF Sprite::boundaries() const
{
const float sX = gameObject->transform.globalScaleX();
const float sY = gameObject->transform.globalScaleY();
return utils::RectF(
gameObject->transform.globalX() - sX * anchorX * w,
gameObject->transform.globalY() - sY * anchorY * h,
sX * w, sY * h);
}
void Sprite::addState(const SpriteState& state)
{
Assert(m_stateNames.count(state.name) == 0, "A state with the same name already exists!");
m_states.push_back(state);
m_stateNames.emplace(state.name, m_states.size() - 1);
// First added state?
if (m_states.size() == 1)
{
m_currentState = 0;
}
}
SpriteState& Sprite::createState(const std::string& name)
{
SpriteState state = { .name = name };
addState(state);
return m_states.back();
}
SpriteState& Sprite::state(const std::string& name)
{
Assert(m_stateNames.count(name) != 0, "State doesn't exist.");
size_t index = m_stateNames.at(name);
return m_states.at(index);
}
SpriteState& Sprite::state(size_t stateId)
{
Assert(stateId < m_states.size(), "State ID doesn't exist.");
return m_states.at(stateId);
}
size_t Sprite::stateCount() const
{
return m_states.size();
}
void Sprite::setState(size_t stateId)
{
Assert(stateId < m_states.size(), "Inexistent state.");
// Avoid restarting the animation at every function call
if (stateId != m_currentState)
{
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_currentState != (size_t)-1, "No states have been added!!!");
Assert(m_states.size() > 0, "Sprite must have at least one state!");
return m_states.at(m_currentState);
}
Frame& Sprite::currentFrame()
{
Assert(m_currentFrame < currentState().frames.size(), "State must have at least one frame!");
return currentState().frames.at(m_currentFrame);
}
void Sprite::advanceTime(float fractions)
{
Assert(m_currentState != (size_t)-1, "No states have been added!");
m_currentFrameTimeLeft -= fractions * animationSpeed;
while (m_currentFrameTimeLeft <= 0)
{
// Move to the next frame
if (++m_currentFrame >= currentState().frames.size())
m_currentFrame = 0;
m_currentFrameTimeLeft += currentFrame().duration;
}
}
}
}
} /* namespace farmlands */