Skip to content

Commit fffb811

Browse files
Merge pull request #13 from ThePythonator/feature/add-animation-support
Feature: Add support for animations
2 parents 3042c22 + 33dfe3e commit fffb811

5 files changed

Lines changed: 164 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ set(FRAMEWORK_SOURCES
5050
"Font.cpp"
5151
"Image.cpp"
5252
"Spritesheet.cpp"
53+
"Animation.cpp"
5354

5455
"Colour.cpp"
5556

include/framework/Animation.hpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#pragma once
2+
3+
#include <utility>
4+
#include <vector>
5+
#include <map>
6+
7+
#include "Maths.hpp"
8+
#include "Spritesheet.hpp"
9+
10+
namespace Framework {
11+
struct AnimationFrame {
12+
uint16_t index;
13+
float duration;
14+
Framework::SpriteTransform transform;
15+
};
16+
17+
// Multiple frames make an animation
18+
typedef std::vector<AnimationFrame> Animation;
19+
20+
// Basic interface class
21+
class AnimationInterface {
22+
public:
23+
virtual void update(float dt) = 0;
24+
virtual void render(Framework::vec2 position) = 0;
25+
};
26+
27+
class AnimationHandler : public AnimationInterface {
28+
public:
29+
AnimationHandler(const Framework::Spritesheet& _spritesheet, Animation _animation, float time_offset = 0.0f, Framework::vec2 _position_offset = Framework::VEC_NULL);
30+
31+
void update(float dt);
32+
void render(Framework::vec2 position);
33+
34+
private:
35+
const Framework::Spritesheet& spritesheet;
36+
Animation animation;
37+
Framework::vec2 position_offset;
38+
39+
float current_time = 0.0f;
40+
41+
uint16_t current_index = 0;
42+
};
43+
44+
typedef std::map<Framework::vec2, Animation> MultiTileAnimation;
45+
46+
class MultiTileAnimationHandler : public AnimationInterface {
47+
public:
48+
MultiTileAnimationHandler(const Framework::Spritesheet& _spritesheet, MultiTileAnimation _animation, float time_offset = 0.0f, Framework::vec2 _position_offset = Framework::VEC_NULL);
49+
50+
void update(float dt);
51+
void render(Framework::vec2 position);
52+
53+
private:
54+
std::vector<AnimationHandler> animations;
55+
};
56+
}

include/game/GameStages.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@
66

77
#include "MenuStages.hpp"
88

9+
#include "Animation.hpp"
10+
911
class GameStage : public Framework::BaseStage {
1012
public:
1113
void start();
1214

1315
bool update(float dt);
1416
void render();
17+
18+
private:
19+
std::unique_ptr<Framework::AnimationInterface> spinning_sword;
20+
std::unique_ptr<Framework::AnimationInterface> big_animation;
1521
};
1622

1723
class PausedStage : public Framework::BaseStage {

src/framework/Animation.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "Animation.hpp"
2+
3+
namespace Framework {
4+
AnimationHandler::AnimationHandler(const Framework::Spritesheet& _spritesheet, Animation _animation, float time_offset, Framework::vec2 _position_offset) : spritesheet(_spritesheet) {
5+
animation = _animation;
6+
current_time = time_offset;
7+
position_offset = _position_offset;
8+
}
9+
10+
void AnimationHandler::update(float dt) {
11+
current_time += dt;
12+
float t = animation.at(current_index).duration;
13+
while (current_time >= t) {
14+
current_time -= t;
15+
current_index++;
16+
current_index %= animation.size();
17+
t = animation.at(current_index).duration;
18+
}
19+
}
20+
21+
void AnimationHandler::render(Framework::vec2 position) {
22+
const AnimationFrame& current_frame = animation.at(current_index);
23+
spritesheet.sprite(current_frame.index, position + position_offset, current_frame.transform);
24+
}
25+
26+
MultiTileAnimationHandler::MultiTileAnimationHandler(const Framework::Spritesheet& _spritesheet, MultiTileAnimation _animation, float time_offset, Framework::vec2 _position_offset) {
27+
for (const auto& [position, animation] : _animation) {
28+
animations.push_back(AnimationHandler(_spritesheet, animation, time_offset, position + _position_offset));
29+
}
30+
}
31+
32+
void MultiTileAnimationHandler::update(float dt) {
33+
for (AnimationHandler& animation_handler : animations) {
34+
animation_handler.update(dt);
35+
}
36+
}
37+
38+
void MultiTileAnimationHandler::render(Framework::vec2 position) {
39+
for (AnimationHandler& animation_handler : animations) {
40+
animation_handler.render(position);
41+
}
42+
}
43+
}

src/game/GameStages.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,66 @@ void GameStage::start() {
88

99
// Start transition
1010
transition->open();
11+
12+
// Create animation
13+
Framework::Animation demo_animation = {
14+
{0, 0.5f, Framework::SpriteTransform::NONE},
15+
{0, 0.5f, Framework::SpriteTransform::ROTATE_90_CW},
16+
{0, 0.5f, Framework::SpriteTransform::ROTATE_180_CW},
17+
{0, 0.5f, Framework::SpriteTransform::ROTATE_270_CW}
18+
};
19+
// Create animation handler
20+
spinning_sword = std::make_unique<Framework::AnimationHandler>(graphics_objects->spritesheets[GRAPHICS_OBJECTS::SPRITESHEETS::MAIN_SPRITESHEET], demo_animation);
21+
22+
// Create big animation
23+
Framework::MultiTileAnimation big_multi_animation = {
24+
{
25+
{0, 0},
26+
{
27+
{4, 1.0f, Framework::SpriteTransform::NONE},
28+
{8, 0.4f, Framework::SpriteTransform::NONE},
29+
{12, 0.2f, Framework::SpriteTransform::NONE},
30+
{8, 0.4f, Framework::SpriteTransform::NONE},
31+
}
32+
},
33+
{
34+
{16, 0},
35+
{
36+
{5, 1.0f, Framework::SpriteTransform::NONE},
37+
{9, 0.4f, Framework::SpriteTransform::NONE},
38+
{13, 0.2f, Framework::SpriteTransform::NONE},
39+
{9, 0.4f, Framework::SpriteTransform::NONE},
40+
}
41+
},
42+
{
43+
{32, 0},
44+
{
45+
{6, 1.0f, Framework::SpriteTransform::NONE},
46+
{10, 0.4f, Framework::SpriteTransform::NONE},
47+
{14, 0.2f, Framework::SpriteTransform::NONE},
48+
{10, 0.4f, Framework::SpriteTransform::NONE},
49+
}
50+
},
51+
{
52+
{48, 0},
53+
{
54+
{7, 1.0f, Framework::SpriteTransform::NONE},
55+
{11, 0.4f, Framework::SpriteTransform::NONE},
56+
{15, 0.2f, Framework::SpriteTransform::NONE},
57+
{11, 0.4f, Framework::SpriteTransform::NONE},
58+
}
59+
},
60+
};
61+
// Create animation handler
62+
big_animation = std::make_unique<Framework::MultiTileAnimationHandler>(graphics_objects->spritesheets[GRAPHICS_OBJECTS::SPRITESHEETS::MAIN_SPRITESHEET], big_multi_animation);
1163
}
1264

1365
bool GameStage::update(float dt) {
1466
transition->update(dt);
1567

68+
spinning_sword->update(dt);
69+
big_animation->update(dt);
70+
1671
if (input->just_down(Framework::KeyHandler::Key::ESCAPE) || input->just_down(Framework::KeyHandler::Key::P)) {
1772
finish(new PausedStage(this), false);
1873
}
@@ -25,6 +80,9 @@ void GameStage::render() {
2580

2681
graphics_objects->spritesheets[GRAPHICS_OBJECTS::SPRITESHEETS::MAIN_SPRITESHEET].sprite(0, Framework::Vec(128, 64));
2782

83+
spinning_sword->render({ 64, 64 });
84+
big_animation->render({ 64, 96 });
85+
2886
transition->render();
2987
}
3088

0 commit comments

Comments
 (0)