Skip to content

Commit

Permalink
Basic Sprite Animation
Browse files Browse the repository at this point in the history
Create a system for animating sprites by manipulating their SpriteClip
components based on frame data. Replace the bespoke rendering systems
for the Ship and Wallop in the GracilisGame with the new Sprite and
SpriteAnimation systems.

Should AnimationFrames be a resource that is managed by the engine
itself?
  • Loading branch information
meisekimiu committed Jun 12, 2024
1 parent ad73350 commit c632330
Show file tree
Hide file tree
Showing 17 changed files with 307 additions and 115 deletions.
Binary file added assets/wallop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/game/components/PlayerShip.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef GL_ADAGIO_PLAYERSHIP_H
#define GL_ADAGIO_PLAYERSHIP_H

#include "raylib.h"
#include "SpriteAnimation.h"

struct PlayerShip {
/*
Expand All @@ -11,6 +11,7 @@ struct PlayerShip {
*/
Adagio::Vector2d velocity;
Adagio::Texture2D wallopTexture;
AnimationFrame* wallopFrames{nullptr};
};

#endif //GL_ADAGIO_PLAYERSHIP_H
12 changes: 0 additions & 12 deletions src/game/components/ShipRenderer.h

This file was deleted.

22 changes: 22 additions & 0 deletions src/game/components/SpriteAnimation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef GL_ADAGIO_SPRITEANIMATION_H
#define GL_ADAGIO_SPRITEANIMATION_H

#include "../../math/Rect.h"

typedef unsigned char FrameIndex;

struct AnimationFrame {
double duration{0.0};
Adagio::RectI clip;
};

struct SpriteAnimation {
FrameIndex currentFrame{0};
FrameIndex frameLength{0};
bool loop{false};
bool done{false};
double timeOnCurrentFrame{0.0};
AnimationFrame* frames{nullptr};
};

#endif //GL_ADAGIO_SPRITEANIMATION_H
12 changes: 0 additions & 12 deletions src/game/components/WallopRenderer.h

This file was deleted.

34 changes: 29 additions & 5 deletions src/game/states/GracilisGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
#include "raylib.h"
#include "../components/PlayerShip.h"
#include "../components/Position.h"
#include "../components/ShipRenderer.h"
#include "../components/Sprite.h"
#include "../components/SpriteAnimation.h"
#include "../components/SpriteClip.h"
#include "../systems/RemoveDead.h"
#include "../systems/ship.h"
#include "../systems/ShipRendererSystem.h"
#include "../systems/Wallop.h"
#include "../systems/WallopRendererSystem.h"
#include "../systems/AnimateSprite.h"
#include "../systems/RenderSprite.h"

void GracilisGame::init() {
std::cout << "GracilisGame init" << std::endl;
registerSystem(AnimateSprite);
registerRenderer(RenderSprite);
registerSystem(ShipSystem);
registerRenderer(ShipRendererSystem);
registerSystem(WallopSystem);
registerRenderer(WallopRendererSystem);
registerSystem(RemoveDead);
Expand All @@ -23,14 +27,34 @@ void GracilisGame::loadContent(Adagio::SpriteBatch &spriteBatch, Adagio::Renderi
spriteBatch.setClearColor({0, 0, 0, 255});
shipTex = services.textureManager->load("assets/ship.png");
wallopTex = services.textureManager->load("assets/wallop.png");
wallopFrames = new AnimationFrame[4]{
{0.083333, Adagio::RectI{0, 0, 64, 56}},
{0.083333, Adagio::RectI{64, 0, 64, 56}},
{0.083333, Adagio::RectI{64 * 2, 0, 64, 56}},
{0.083333, Adagio::RectI{64 * 3, 0, 64, 56}},
};

const auto ship = registry.create();
registry.emplace<PlayerShip>(ship, Adagio::Vector2d{0, 0}, wallopTex);
registry.emplace<PlayerShip>(ship, Adagio::Vector2d{0, 0}, wallopTex, wallopFrames);
registry.emplace<Position>(ship, Adagio::Vector2d{320, 240});
registry.emplace<ShipRenderer>(ship, shipTex, 0, 0);
registry.emplace<Sprite>(ship, shipTex, Adagio::Vector2d{0, 0}, 0);
registry.emplace<SpriteClip>(ship);
SpriteAnimation &animation = registry.emplace<SpriteAnimation>(ship);
animation.frameLength = 4;
animation.loop = true;
shipFrames = new AnimationFrame[4]{
{0.083333, Adagio::RectI{0, 0, 56, 89}},
{0.083333, Adagio::RectI{56, 0, 56, 89}},
{0.083333, Adagio::RectI{56 * 2, 0, 56, 89}},
{0.083333, Adagio::RectI{56 * 3, 0, 56, 89}},
};
animation.frames = shipFrames;
}

void GracilisGame::unloadContent(Adagio::RenderingServices &services) {
std::cout << "GracilisGame quit" << std::endl;
services.textureManager->unload(shipTex);
services.textureManager->unload(wallopTex);
delete shipFrames;
delete wallopFrames;
}
3 changes: 3 additions & 0 deletions src/game/states/GracilisGame.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef GL_ADAGIO_GRACILISGAME_H
#define GL_ADAGIO_GRACILISGAME_H

#include "../components/SpriteAnimation.h"
#include "../../state/EntityGameState.h"

class GracilisGame : public Adagio::EntityGameState {
Expand All @@ -14,6 +15,8 @@ class GracilisGame : public Adagio::EntityGameState {
private:
Adagio::Texture2D shipTex;
Adagio::Texture2D wallopTex;
AnimationFrame* shipFrames{nullptr};
AnimationFrame* wallopFrames{nullptr};
};


Expand Down
31 changes: 31 additions & 0 deletions src/game/systems/AnimateSprite.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "AnimateSprite.h"
#include "../components/SpriteClip.h"
#include "../components/SpriteAnimation.h"

void AnimateSprite(entt::registry &registry, Adagio::GameStats &stats, Adagio::StateMachine *state) {
auto view = registry.view<SpriteClip, SpriteAnimation>();
for (auto [entity, clip, animation] : view.each()) {
if (animation.frameLength > 0 && !animation.done) {
animation.timeOnCurrentFrame += stats.getFrameDelta();
while (animation.timeOnCurrentFrame > animation.frames[animation.currentFrame].duration) {
animation.timeOnCurrentFrame -= animation.frames[animation.currentFrame].duration;
animation.currentFrame++;
if (animation.currentFrame > animation.frameLength - 1) {
if (animation.loop) {
animation.currentFrame = 0;
} else {
animation.currentFrame = animation.frameLength - 1;
animation.done = true;
break;
}
}
}
Adagio::RectI &frameClip = animation.frames[animation.currentFrame].clip;
clip.source.position.x = static_cast<float>(frameClip.position.x);
clip.source.position.y = static_cast<float>(frameClip.position.y);
clip.source.size.x = static_cast<float>(frameClip.size.x);
clip.source.size.y = static_cast<float>(frameClip.size.y);
}
}

}
10 changes: 10 additions & 0 deletions src/game/systems/AnimateSprite.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef GL_ADAGIO_ANIMATESPRITE_H
#define GL_ADAGIO_ANIMATESPRITE_H

#include "entt/entt.hpp"
#include "../../graphics/SpriteBatch.h"
#include "../../state/GameState.h"

void AnimateSprite(entt::registry &registry, Adagio::GameStats &stats, Adagio::StateMachine *state);

#endif //GL_ADAGIO_ANIMATESPRITE_H
32 changes: 0 additions & 32 deletions src/game/systems/ShipRendererSystem.cpp

This file was deleted.

11 changes: 0 additions & 11 deletions src/game/systems/ShipRendererSystem.h

This file was deleted.

29 changes: 0 additions & 29 deletions src/game/systems/WallopRendererSystem.cpp

This file was deleted.

11 changes: 0 additions & 11 deletions src/game/systems/WallopRendererSystem.h

This file was deleted.

13 changes: 11 additions & 2 deletions src/game/systems/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#include "../components/Position.h"
#include "../components/PlayerShip.h"
#include "../components/UserProjectile.h"
#include "../components/WallopRenderer.h"
#include "../components/Sprite.h"
#include "../components/SpriteClip.h"
#include "../components/SpriteScale.h"
#include "../components/SpriteAnimation.h"
#include <iostream>

float lowerVelocity(float v);
Expand Down Expand Up @@ -33,8 +36,14 @@ void ShipSystem(entt::registry &registry, Adagio::GameStats &stats, Adagio::Stat
if (IsKeyPressed(KEY_SPACE)) {
const auto wallop = registry.create();
registry.emplace<UserProjectile>(wallop, 6);
registry.emplace<WallopRenderer>(wallop, ship.wallopTexture, 0, 0);
registry.emplace<Position>(wallop, Adagio::Vector2{pos.position.x + 27 - 16, pos.position.y});
registry.emplace<Sprite>(wallop, ship.wallopTexture, Adagio::Vector2d{0, 0}, 0);
registry.emplace<SpriteClip>(wallop);
registry.emplace<SpriteScale>(wallop, Adagio::Vector2f{0.5, 0.5});
SpriteAnimation& anim = registry.emplace<SpriteAnimation>(wallop);
anim.frameLength = 4;
anim.loop = true;
anim.frames = ship.wallopFrames;
}
ship.velocity = normalizeVelocity(ship.velocity, speed);
pos.position.x += ship.velocity.x;
Expand Down
5 changes: 5 additions & 0 deletions test/game/EcsTestingHarness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

EcsTestingHarness::EcsTestingHarness() {
renderingServices = {&spriteBatch, graphicsDevice.getTextureManager(), &stats};
stateMachine = new Adagio::StateMachine(&spriteBatch, &renderingServices);
}

void EcsTestingHarness::reset() {
Expand All @@ -16,3 +17,7 @@ void EcsTestingHarness::testRendererFrame(Adagio::RendererFn renderer) {
renderer(registry, spriteBatch, renderingServices);
spriteBatch.end();
}

void EcsTestingHarness::testSystemFrame(Adagio::SystemFn system) {
system(registry, stats, stateMachine);
}
3 changes: 3 additions & 0 deletions test/game/EcsTestingHarness.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "harness/MockGameStats.h"
#include "entt/entt.hpp"
#include "../../src/state/EntityGameState.h"
#include "../../src/state/StateMachine.h"

class EcsTestingHarness {
public:
Expand All @@ -15,12 +16,14 @@ class EcsTestingHarness {
MockGameStats stats;
entt::registry registry;
Adagio::RenderingServices renderingServices{};
Adagio::StateMachine *stateMachine;

EcsTestingHarness();

void reset();

void testRendererFrame(Adagio::RendererFn renderer);
void testSystemFrame(Adagio::SystemFn system);
};


Expand Down
Loading

0 comments on commit c632330

Please sign in to comment.