Skip to content

Commit

Permalink
fix draw rect and update animation controller
Browse files Browse the repository at this point in the history
  • Loading branch information
durkisneer1 committed Nov 10, 2024
1 parent dac1523 commit 875aa7e
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 52 deletions.
11 changes: 1 addition & 10 deletions example/include/Player.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
#pragma once

#include <KrakenEngine.hpp>
#include <unordered_map>

enum AnimState
{
IDLE,
WALK
};

class Player final
{
Expand All @@ -22,12 +15,10 @@ class Player final

kn::AnimationController animController;
bool facingRight = true;
AnimState animState = IDLE;
std::unordered_map<AnimState, kn::Texture> animMap;

kn::Rect rect;
kn::math::Vec2 velocity;
const kn::Layer* collisionLayer;
bool onGround = false;
float moveSpeed = 45.0f;
};
};
2 changes: 1 addition & 1 deletion example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main()
for (const auto& event : kn::window::getEvents())
{
if (event.type == kn::QUIT ||
event.type == kn::KEYDOWN && event.key.keysym.sym == kn::K_ESCAPE)
(event.type == kn::KEYDOWN && event.key.keysym.sym == kn::K_ESCAPE))
done = true;
}

Expand Down
20 changes: 7 additions & 13 deletions example/src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,8 @@
Player::Player(const kn::Layer* collisionLayer)
: animController(5), rect(48, 120, 13, 16), collisionLayer(collisionLayer)
{
animMap[IDLE] = kn::Texture();
animMap[WALK] = kn::Texture();

if (!animMap.at(IDLE).loadFromFile("../example/assets/player_idle.png") ||
!animMap.at(WALK).loadFromFile("../example/assets/player_walk.png"))
ERROR("Failed to load texture");

if (!animController.setup(animMap.at(IDLE).getSize(), 13, 16))
ERROR("Failed to set up animation");
animController.addAnim("../example/assets/player_idle.png", "idle", 13, 16);
animController.addAnim("../example/assets/player_walk.png", "walk", 13, 16);
}

void Player::update(const double dt)
Expand All @@ -34,15 +27,15 @@ void Player::update(const double dt)
const auto dirVec = kn::input::getVector({kn::S_a}, {kn::S_d});
if (dirVec.x != 0.0)
{
animState = WALK;
animController.setAnim("walk");

if (dirVec.x > 0.0)
facingRight = true;
else if (dirVec.x < 0.0)
facingRight = false;
}
else
animState = IDLE;
animController.setAnim("idle");

velocity.x = dirVec.x * moveSpeed;

Expand All @@ -51,10 +44,11 @@ void Player::update(const double dt)
rect.y += static_cast<float>(velocity.y * dt);
handleCollision(AxisY);

const kn::Frame frame = animController.nextFrame(dt);
if (facingRight)
kn::window::blit(animMap.at(animState), rect, animController.update(dt));
kn::window::blit(*frame.tex, rect, frame.rect);
else
kn::window::blitEx(animMap.at(animState), rect, animController.update(dt), 0, true);
kn::window::blitEx(*frame.tex, rect, frame.rect, 0, true);
}

void Player::handleCollision(const int axis)
Expand Down
39 changes: 32 additions & 7 deletions include/AnimationController.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
#pragma once

#include "Rect.hpp"
#include "Texture.hpp"
#include <memory>
#include <unordered_map>
#include <vector>

namespace kn
{

/**
* @brief Container for a texture pointer and rect
*/
struct Frame
{
std::shared_ptr<Texture> tex;
Rect rect;
};

/**
* @brief Handler for sprite sheet animations.
*/
Expand All @@ -22,22 +35,33 @@ class AnimationController final
/**
* @brief Set up the animation controller.
*
* @param size The size of the sprite sheet.
* @param filePath The path to the sprite sheet image file.
* @param name The name of the animation.
* @param frameWidth The width of each frame.
* @param frameHeight The height of each frame.
*
* @return true if the setup was successful, false otherwise.
*/
[[maybe_unused]] bool setup(const math::Vec2& size, int frameWidth, int frameHeight);
[[maybe_unused]] bool addAnim(const std::string& filePath, const std::string& name,
int frameWidth, int frameHeight);

/**
* @brief Change the active animation.
*
* @param name The name of an added animation.
*
* @return true if the animation was successfully changed, false otherwise.
*/
[[maybe_unused]] bool setAnim(const std::string& name);

/**
* @brief Update the animation.
* @brief Get the next frame of the animation.
*
* @param deltaTime The time since the last frame.
* @param deltaTime The time since the last time this function was called.
*
* @return The srcRect area of the current frame. Use when blitting.
* @return The next frame's texture and area to render from.
*/
[[nodiscard]] const Rect& update(double deltaTime);
[[nodiscard]] const Frame& nextFrame(double deltaTime);

/**
* @brief Set the frame rate of the animation.
Expand All @@ -64,10 +88,11 @@ class AnimationController final
int m_fps;
int m_index = 0;
bool m_paused = false;
std::string m_currAnim;

double m_frameTime_ms;
double m_timeLeftInFrame_ms = 0.0;

std::vector<Rect> m_frameRects;
std::unordered_map<std::string, std::vector<Frame>> m_animMap;
};
} // namespace kn
2 changes: 1 addition & 1 deletion include/Draw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ namespace draw
*
* @note If thickness remains 0, the rectangle will be filled.
*/
void rect(Rect& rect, const Color& color, float thickness = 0.0f);
void rect(const Rect& rect, const Color& color, int thickness = 0);
} // namespace draw
} // namespace kn
4 changes: 2 additions & 2 deletions include/Rect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ struct Rect : SDL_FRect
*
* @return The position of the rectangle.
*/
math::Vec2 getPos() const;
[[nodiscard]] math::Vec2 getPos() const;

/**
* @brief Get the size of the rectangle.
*
* @return The size of the rectangle.
*/
math::Vec2 getSize() const;
[[nodiscard]] math::Vec2 getSize() const;

/**
* @brief Set the size of the rectangle.
Expand Down
46 changes: 36 additions & 10 deletions src/animation_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,23 @@ AnimationController::AnimationController(const int fps) : m_fps(fps)
m_frameTime_ms = (fps == 0) ? 0.0 : MILLISECONDS_PER_SECOND / fps;
}

bool AnimationController::setup(const math::Vec2& size, int frameWidth, int frameHeight)
bool AnimationController::addAnim(const std::string& filePath, const std::string& name,
const int frameWidth, const int frameHeight)
{
if (!m_frameRects.empty())
std::shared_ptr<Texture> texPtr(new Texture());
if (!texPtr->loadFromFile(filePath))
return false;

if (m_animMap.find(name) != m_animMap.end()) // if animation name already exists
{
m_frameRects.clear();
m_animMap.at(name).clear();
m_timeLeftInFrame_ms = (m_fps == 0) ? 0.0 : m_frameTime_ms;
m_index = 0;
}

m_animMap[name] = {};
const math::Vec2 size = texPtr->getSize();

if (static_cast<int>(size.x) % frameWidth || static_cast<int>(size.y) % frameHeight)
{
ERROR("Sprite sheet dimensions are not divisible by frame dimensions");
Expand All @@ -29,20 +37,37 @@ bool AnimationController::setup(const math::Vec2& size, int frameWidth, int fram

for (int x = 0; x < size.x; x += frameWidth)
for (int y = 0; y < size.y; y += frameHeight)
m_frameRects.emplace_back(x, y, frameWidth, frameHeight);
{
const Frame frame{texPtr, {x, y, frameWidth, frameHeight}};
m_animMap.at(name).emplace_back(frame);
}

m_currAnim = name;

return true;
}

bool AnimationController::setAnim(const std::string& name)
{
if (m_animMap.find(name) == m_animMap.end())
{
ERROR(name + " does not exist in animation controller.")
return false;
}

m_currAnim = name;
return true;
}

const Rect& AnimationController::update(const double deltaTime)
const Frame& AnimationController::nextFrame(const double deltaTime)
{
if (m_paused)
return m_frameRects.at(m_index);
return m_animMap.at(m_currAnim).at(m_index);

if (!isProductValid(static_cast<double>(MILLISECONDS_PER_SECOND), deltaTime))
{
ERROR("Cannot multiply values");
return m_frameRects.at(m_index);
return m_animMap.at(m_currAnim).at(m_index);
}

if (const double msTakenLastFrame = MILLISECONDS_PER_SECOND * deltaTime;
Expand All @@ -51,19 +76,20 @@ const Rect& AnimationController::update(const double deltaTime)
const int numberOfFramesPassed =
static_cast<int>((msTakenLastFrame - m_timeLeftInFrame_ms) / m_frameTime_ms) + 1;
m_timeLeftInFrame_ms = m_frameTime_ms;
m_index = (m_index + numberOfFramesPassed) % static_cast<int>(m_frameRects.size());
m_index =
(m_index + numberOfFramesPassed) % static_cast<int>(m_animMap.at(m_currAnim).size());
}
else
{
if (!isSumValid(m_timeLeftInFrame_ms, -msTakenLastFrame))
{
ERROR("Cannot subtract values");
return m_frameRects.at(m_index);
return m_animMap.at(m_currAnim).at(m_index);
}
m_timeLeftInFrame_ms -= msTakenLastFrame;
}

return m_frameRects.at(m_index);
return m_animMap.at(m_currAnim).at(m_index);
}

void AnimationController::pause() { m_paused = true; }
Expand Down
21 changes: 13 additions & 8 deletions src/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,30 @@

namespace kn::draw
{
void rect(const Rect& rect, const Color& color, float thickness)
void rect(const Rect& rect, const Color& color, int thickness)
{
SDL_SetRenderDrawColor(window::getRenderer(), color.r, color.g, color.b, color.a);

if (thickness == 0)
{
SDL_RenderFillRectF(window::getRenderer(), &rect);
Rect offsetRect = rect;
offsetRect.setTopLeft(offsetRect.getTopLeft() - camera);
SDL_RenderFillRectF(window::getRenderer(), &offsetRect);
return;
}

if (thickness > rect.w / 2 || thickness > rect.h / 2)
thickness = std::min(rect.w / 2, rect.h / 2);
const int halfWidth = static_cast<int>(rect.w / 2.0);
const int halfHeight = static_cast<int>(rect.h / 2.0);

for (int i = 0; static_cast<float>(i) < thickness; i++)
if (thickness > halfWidth || thickness > halfHeight)
thickness = std::min(halfWidth, halfHeight);

for (int i = 0; i < thickness; i++)
{
const auto offset = static_cast<float>(i);
Rect layerRect = {
rect.x + offset, rect.y + offset, rect.w - offset * 2, rect.h - offset * 2
};
Rect layerRect = {static_cast<float>(rect.x + offset - camera.x),
static_cast<float>(rect.y + offset - camera.y), rect.w - offset * 2,
rect.h - offset * 2};
SDL_RenderDrawRectF(window::getRenderer(), &layerRect);
}
}
Expand Down

0 comments on commit 875aa7e

Please sign in to comment.