Skip to content

Commit

Permalink
lazy load animation sprites
Browse files Browse the repository at this point in the history
  • Loading branch information
afwbkbc committed Jun 9, 2024
1 parent af054e4 commit 23a7642
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 116 deletions.
66 changes: 36 additions & 30 deletions src/game/animation/FramesRow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,39 @@ FramesRow::FramesRow(
const std::string& sound_file
)
: Def( id, AT_FRAMES_ROW, duration_ms, scale_x, scale_y, sound_file )
, m_file( file )
, m_row_x( row_x )
, m_row_y( row_y )
, m_frame_width( frame_width )
, m_frame_height( frame_height )
, m_frame_center_x( frame_center_x )
, m_frame_center_y( frame_center_y )
, m_frame_padding( frame_padding )
, m_frames_count( frames_count )
, m_frames_per_row( frames_per_row ) {
, m_render(
{
file,
row_x,
row_y,
frame_width,
frame_height,
frame_padding,
frame_center_x,
frame_center_y,
frames_count,
frames_per_row,
scale_x,
scale_y
}
) {
//
}

const std::string FramesRow::ToString( const std::string& prefix ) const {
return (std::string)
TS_OBJ_BEGIN( "FramesRow" ) +
TS_OBJ_PROP_STR( "id", m_id ) +
TS_OBJ_PROP_STR( "file", m_file ) +
TS_OBJ_PROP_NUM( "row_x", m_row_x ) +
TS_OBJ_PROP_NUM( "row_y", m_row_y ) +
TS_OBJ_PROP_NUM( "frame_width", m_frame_width ) +
TS_OBJ_PROP_NUM( "frame_height", m_frame_height ) +
TS_OBJ_PROP_NUM( "frame_center_x", m_frame_center_x ) +
TS_OBJ_PROP_NUM( "frame_center_y", m_frame_center_y ) +
TS_OBJ_PROP_NUM( "frame_padding", m_frame_padding ) +
TS_OBJ_PROP_NUM( "frames_count", m_frames_count ) +
TS_OBJ_PROP_NUM( "frames_per_row", m_frames_per_row ) +
TS_OBJ_PROP_STR( "file", m_render.file ) +
TS_OBJ_PROP_NUM( "row_x", m_render.row_x ) +
TS_OBJ_PROP_NUM( "row_y", m_render.row_y ) +
TS_OBJ_PROP_NUM( "frame_width", m_render.frame_width ) +
TS_OBJ_PROP_NUM( "frame_height", m_render.frame_height ) +
TS_OBJ_PROP_NUM( "frame_center_x", m_render.frame_center_x ) +
TS_OBJ_PROP_NUM( "frame_center_y", m_render.frame_center_y ) +
TS_OBJ_PROP_NUM( "frame_padding", m_render.frame_padding ) +
TS_OBJ_PROP_NUM( "frames_count", m_render.frames_count ) +
TS_OBJ_PROP_NUM( "frames_per_row", m_render.frames_per_row ) +
TS_OBJ_PROP_NUM( "scale_x", m_scale_x ) +
TS_OBJ_PROP_NUM( "scale_y", m_scale_y ) +
TS_OBJ_PROP_NUM( "duration_ms", m_duration_ms ) +
Expand All @@ -56,16 +62,16 @@ const std::string FramesRow::ToString( const std::string& prefix ) const {
}

void FramesRow::Serialize( types::Buffer& buf, const FramesRow* def ) {
buf.WriteString( def->m_file );
buf.WriteInt( def->m_row_x );
buf.WriteInt( def->m_row_y );
buf.WriteInt( def->m_frame_width );
buf.WriteInt( def->m_frame_height );
buf.WriteInt( def->m_frame_center_x );
buf.WriteInt( def->m_frame_center_y );
buf.WriteInt( def->m_frame_padding );
buf.WriteInt( def->m_frames_count );
buf.WriteInt( def->m_frames_per_row );
buf.WriteString( def->m_render.file );
buf.WriteInt( def->m_render.row_x );
buf.WriteInt( def->m_render.row_y );
buf.WriteInt( def->m_render.frame_width );
buf.WriteInt( def->m_render.frame_height );
buf.WriteInt( def->m_render.frame_center_x );
buf.WriteInt( def->m_render.frame_center_y );
buf.WriteInt( def->m_render.frame_padding );
buf.WriteInt( def->m_render.frames_count );
buf.WriteInt( def->m_render.frames_per_row );
}

FramesRow* FramesRow::Unserialize(
Expand Down
13 changes: 3 additions & 10 deletions src/game/animation/FramesRow.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <cstdint>

#include "Types.h"

#include "Def.h"

namespace game {
Expand All @@ -28,16 +30,7 @@ class FramesRow : public Def {
const std::string& sound_file
);

const std::string m_file;
const uint16_t m_row_x;
const uint16_t m_row_y;
const uint16_t m_frame_width;
const uint16_t m_frame_height;
const uint16_t m_frame_padding;
const uint16_t m_frame_center_x;
const uint16_t m_frame_center_y;
const uint8_t m_frames_count;
const uint8_t m_frames_per_row;
sprite_render_info_t m_render = {};

const std::string ToString( const std::string& prefix ) const override;

Expand Down
18 changes: 18 additions & 0 deletions src/game/animation/Types.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include <string>
#include <cstdint>

namespace game {
namespace animation {

Expand All @@ -8,5 +11,20 @@ enum animation_type_t {
AT_FRAMES_ROW,
};

struct sprite_render_info_t {
std::string file;
uint16_t row_x;
uint16_t row_y;
uint16_t frame_width;
uint16_t frame_height;
uint16_t frame_padding;
uint16_t frame_center_x;
uint16_t frame_center_y;
uint8_t frames_count;
uint8_t frames_per_row;
float scale_x;
float scale_y;
};

}
}
1 change: 1 addition & 0 deletions src/loader/texture/TextureLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ static const std::unordered_map< resource::resource_t, TextureLoader::transparen
resource::PCX_XI,
{
types::Color::RGB( 0, 67, 255 ),
types::Color::RGB( 155, 27, 231 ), // label
types::Color::RGB( 27, 187, 231 ), // borders
}
},
Expand Down
31 changes: 18 additions & 13 deletions src/task/game/Animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Animation::Animation( const size_t animation_id, AnimationDef* def, const types:
m_sound = new scene::actor::Sound( "Animation_Sound_" + std::to_string( animation_id ), def->GetSound() );
g_engine->GetAudio()->AddActor( m_sound );
m_timer.SetInterval( m_def->GetDurationMs() / m_frames.size() );
ShowNextFrame();
m_sound->Play();
}

Expand All @@ -36,19 +37,23 @@ const bool Animation::IsFinished() const {

void Animation::Iterate() {
while ( m_timer.HasTicked() ) {
if ( m_frame_index ) {
// clear previous frame
m_frames.at( m_frame_index - 1 )->actor->RemoveInstance( m_instance_id );
}
if ( m_frame_index++ < m_frames.size() ) {
// show next frame
m_instance_id = m_frames.at( m_frame_index - 1 )->actor->AddInstance( m_render_coords );
}
else {
// no frames left
m_instance_id = 0;
m_timer.Stop();
}
ShowNextFrame();
}
}

void Animation::ShowNextFrame() {
if ( m_frame_index ) {
// clear previous frame
m_frames.at( m_frame_index - 1 )->actor->RemoveInstance( m_instance_id );
}
if ( m_frame_index++ < m_frames.size() ) {
// show next frame
m_instance_id = m_frames.at( m_frame_index - 1 )->actor->AddInstance( m_render_coords );
}
else {
// no frames left
m_instance_id = 0;
m_timer.Stop();
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/task/game/Animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Animation {

private:

void ShowNextFrame();

util::Timer m_timer;
scene::actor::Sound* m_sound = nullptr;
AnimationDef* m_def = nullptr;
Expand Down
92 changes: 48 additions & 44 deletions src/task/game/AnimationDef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,66 +13,70 @@ AnimationDef::AnimationDef( InstancedSpriteManager* ism, const ::game::animation
, m_id( def->m_id )
, m_type( def->m_type )
, m_duration_ms( def->m_duration_ms )
, m_sound( g_engine->GetSoundLoader()->LoadCustomSound( def->m_sound_file ) ) {
, m_sound_file( def->m_sound_file ) {

ASSERT_NOLOG( def->m_type == ::game::animation::animation_type_t::AT_FRAMES_ROW, "only frames row animations are supported for now" );
const auto* d = (::game::animation::FramesRow*)def;

auto* texture = g_engine->GetTextureLoader()->LoadCustomTexture( d->m_file );
m_sprites = {};
const uint32_t w = d->m_frame_width;
const uint32_t h = d->m_frame_height;
const uint32_t p = d->m_frame_padding;
const types::Vec2< uint32_t > src_wh = {
w,
h
};
const types::Vec2< float > dst_wh = {
d->m_scale_x,
d->m_scale_y / 0.8f
};
const types::Vec2< uint32_t > cxy = {
d->m_frame_center_x,//(uint32_t)( (float)d->m_frame_center_x * d->m_scale_x ),
d->m_frame_center_y,//(uint32_t)( (float)d->m_frame_center_y * d->m_scale_y * 0.8f ),
};
for ( size_t i = 0 ; i < d->m_frames_count ; i++ ) {
const uint32_t x = d->m_row_x + ( i % d->m_frames_per_row ) * ( w + p );
const uint32_t y = d->m_row_y + ( i / d->m_frames_per_row ) * ( h + p );

m_sprites.push_back(
m_ism->GetInstancedSprite(
"Animation_" + d->m_id,
texture,
{
x,
y
},
src_wh,
{
x + cxy.x,
y + cxy.y
},
dst_wh,
0.5f // ?
)
);
}

const auto* d = (::game::animation::FramesRow*)def;
m_render = d->m_render;
ASSERT_NOLOG( m_render.frames_count > 0, "animation has no frames defined" );
}

AnimationDef::~AnimationDef() {
//
}

const instanced_sprites_t& AnimationDef::GetSprites() const {
const instanced_sprites_t& AnimationDef::GetSprites() {
if ( m_sprites.empty() ) {
auto* texture = g_engine->GetTextureLoader()->LoadCustomTexture( m_render.file );
const uint32_t w = m_render.frame_width;
const uint32_t h = m_render.frame_height;
const uint32_t p = m_render.frame_padding;
const types::Vec2< uint32_t > src_wh = {
w,
h
};
const types::Vec2< float > dst_wh = {
m_render.scale_x,
m_render.scale_y / 0.8f
};
const types::Vec2< uint32_t > cxy = {
m_render.frame_center_x,
m_render.frame_center_y,
};
for ( size_t i = 0 ; i < m_render.frames_count ; i++ ) {
const uint32_t x = m_render.row_x + ( i % m_render.frames_per_row ) * ( w + p );
const uint32_t y = m_render.row_y + ( i / m_render.frames_per_row ) * ( h + p );
m_sprites.push_back(
m_ism->GetInstancedSprite(
"Animation_" + m_id,
texture,
{
x,
y
},
src_wh,
{
x + cxy.x,
y + cxy.y
},
dst_wh,
0.5f // ?
)
);
}
}
return m_sprites;
}

const size_t AnimationDef::GetDurationMs() const {
return m_duration_ms;
}

const types::Sound* AnimationDef::GetSound() const {
const types::Sound* AnimationDef::GetSound() {
if ( !m_sound ) {
m_sound = g_engine->GetSoundLoader()->LoadCustomSound( m_sound_file );
}
return m_sound;
}

Expand Down
15 changes: 9 additions & 6 deletions src/task/game/AnimationDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,24 @@ class AnimationDef {
AnimationDef( InstancedSpriteManager* ism, const ::game::animation::Def* def );
~AnimationDef();

const instanced_sprites_t& GetSprites() const;
const instanced_sprites_t& GetSprites();
const size_t GetDurationMs() const;
const types::Sound* GetSound() const;
const types::Sound* GetSound();

private:

InstancedSpriteManager* const m_ism;
InstancedSpriteManager* const m_ism = nullptr;

std::string m_id;
::game::animation::sprite_render_info_t m_render = {};

std::string m_id = "";
::game::animation::animation_type_t m_type;

types::Sound* m_sound;
types::Sound* m_sound = nullptr;

instanced_sprites_t m_sprites = {};
const size_t m_duration_ms;
const size_t m_duration_ms = 0;
const std::string m_sound_file = "";
};

}
Expand Down
23 changes: 10 additions & 13 deletions src/task/game/unit/UnitDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,17 @@ class UnitDef {

typedef std::unordered_map< ::game::unit::morale_t, Sprite > morale_based_sprites_t;

// TODO: get rid of union
union {
struct {
::game::unit::movement_type_t movement_type;
::game::unit::movement_t movement_per_turn;
struct {
::game::unit::movement_type_t movement_type;
::game::unit::movement_t movement_per_turn;
struct {
bool is_sprite = false;
uint32_t morale_based_xshift = 0;
types::texture::Texture* texture = nullptr;
Sprite sprite = {};
morale_based_sprites_t* morale_based_sprites = nullptr;
} render;
} static_;
};
bool is_sprite = false;
uint32_t morale_based_xshift = 0;
types::texture::Texture* texture = nullptr;
Sprite sprite = {};
morale_based_sprites_t* morale_based_sprites = nullptr;
} render = {};
} static_ = {};

types::texture::Texture* GetSpriteTexture();
};
Expand Down

0 comments on commit 23a7642

Please sign in to comment.