Refactored sprite & transform. Replaced distance with collider when picking objects up.

This commit is contained in:
2016-12-15 22:52:36 +02:00
parent ddae4934ef
commit 42f0d4125b
20 changed files with 273 additions and 208 deletions

View File

@ -60,17 +60,14 @@ void Grid::onInitialize()
GameObject* obj = *it;
// Compute grid position(s)
Rect<int> bounds(obj->transform.x, obj->transform.y, roundf(obj->transform.w), roundf(obj->transform.h));
if (!bounds.intersects(m_bounds))
if (!m_bounds.contains(obj->transform.x, obj->transform.y))
{
std::cerr << "Grid: ignoring object " << obj->name << ": object outside allowed bounds.";
continue;
}
// Set
for (int y = bounds.y; y < bounds.y + bounds.h; y++)
for (int x = bounds.x; x < bounds.x + bounds.w; x++)
set(obj, x, y, false);
set(obj, (int)obj->transform.x, (int)obj->transform.y, false);
}
}

View File

@ -17,12 +17,12 @@ namespace components {
namespace basic {
Sprite::Sprite()
: name(),
: w(1), h(1),
anchorX(0), anchorY(0),
animationVelocity(1.0f),
animationSpeed(1.0f),
m_states(),
m_stateNames(),
m_currentState(0),
m_currentState((size_t)-1),
m_currentFrame(0),
m_currentFrameTimeLeft(0)
{
@ -37,12 +37,13 @@ model::Component* Sprite::clone()
Sprite* clone = new Sprite();
// Copy public fields
clone->name = name;
clone->w = w;
clone->h = h;
clone->anchorX = anchorX;
clone->anchorY = anchorY;
clone->animationVelocity = animationVelocity;
clone->animationSpeed = animationSpeed;
// Copy private memberes
// 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;
@ -58,7 +59,7 @@ void Sprite::dump(unsigned level)
std::cout<<" ";
std::cout << " .Component: Sprite ";
std::cout << "name="<<name<<"\n";
std::cout << "state="<<m_currentState<<"\n";
}
void Sprite::onPreRender()
@ -66,33 +67,69 @@ 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(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!");
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 resetting state
if (stateId == m_currentState)
return;
m_currentState = stateId;
m_currentFrame = 0;
m_currentFrameTimeLeft = currentFrame().duration;
// 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)
@ -103,21 +140,22 @@ void Sprite::setState(const std::string& 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(currentState().frames.size() > 0, "State must have at least one frame!");
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_states.size() > 0, "Sprite must have at least one state!");
Assert(m_currentState != (size_t)-1, "No states have been added!");
m_currentFrameTimeLeft -= fractions * animationVelocity;
m_currentFrameTimeLeft -= fractions * animationSpeed;
while (m_currentFrameTimeLeft <= 0)
{

View File

@ -10,6 +10,7 @@
#include <model/Component.h>
#include <utils/Exceptions.h>
#include <utils/Rect.h>
#include <vector>
#include <unordered_map>
@ -25,7 +26,6 @@ namespace basic {
{
uint32_t tileSetId;
uint32_t tileSetCell;
uint32_t width, height;
float duration;
};
@ -53,28 +53,31 @@ namespace basic {
virtual void onPreRender() override;
/**
* Adds a state to the sprite.
* Computes the boundaries of the sprite, considering all the elements:
* - global coordinates and scale
* - width and height
* - anchor point
*/
utils::RectF boundaries() const;
// State management
void addState(const SpriteState& state);
SpriteState& createState(const std::string& name);
SpriteState& state(const std::string& name);
SpriteState& state(size_t stateId);
size_t stateCount() const;
/**
* Sets the current state.
*/
// Current state & frame
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 w, h;
float anchorX, anchorY;
float animationVelocity;
float animationSpeed;
private:
void advanceTime(float fractions);