tely/asset: Fix sprite packer emitting wrong anim rect count
This commit is contained in:
+116
-87
@@ -3,6 +3,98 @@
|
||||
#include "feely_pona_unity.h"
|
||||
#endif
|
||||
|
||||
struct FP_LoadSpriteSheetFromSpecResult
|
||||
{
|
||||
TELY_AssetSpriteSheet sheet;
|
||||
Dqn_Slice<TELY_AssetSpriteAnimation> anims;
|
||||
};
|
||||
|
||||
FP_LoadSpriteSheetFromSpecResult FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name)
|
||||
{
|
||||
FP_LoadSpriteSheetFromSpecResult result = {};
|
||||
|
||||
TELY_AssetSpriteSheet *sheet = &result.sheet;
|
||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(arena);
|
||||
sheet->sprite_size = Dqn_V2I_InitNx2(185, 170);
|
||||
sheet->type = TELY_AssetSpriteSheetType_Rects;
|
||||
|
||||
// NOTE: Load the sprite meta file =========================================================
|
||||
Dqn_String8 sprite_spec_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.txt", DQN_STRING_FMT(assets->textures_dir), DQN_STRING_FMT(sheet_name));
|
||||
Dqn_String8 sprite_spec_buffer = platform->func_load_file(scratch.arena, sprite_spec_path);
|
||||
Dqn_String8SplitAllocResult lines = Dqn_String8_SplitAlloc(scratch.allocator, sprite_spec_buffer, DQN_STRING8("\n"));
|
||||
Dqn_usize sprite_rect_index = 0;
|
||||
Dqn_usize sprite_anim_index = 0;
|
||||
|
||||
DQN_FOR_UINDEX(line_index, lines.size) {
|
||||
Dqn_String8 line = lines.data[line_index];
|
||||
Dqn_String8SplitAllocResult line_splits = Dqn_String8_SplitAlloc(scratch.allocator, line, DQN_STRING8(";"));
|
||||
|
||||
if (line_index == 0) {
|
||||
DQN_ASSERTF(line_splits.size == 4, "Expected 4 splits for @file lines");
|
||||
DQN_ASSERT(Dqn_String8_StartsWith(line_splits.data[0], DQN_STRING8("@file"), Dqn_String8EqCase_Sensitive));
|
||||
|
||||
// NOTE: Sprite sheet path
|
||||
Dqn_String8 sprite_sheet_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STRING_FMT(assets->textures_dir), DQN_STRING_FMT(line_splits.data[1]));
|
||||
sheet->tex_handle = platform->func_load_texture(assets, sheet_name, sprite_sheet_path);
|
||||
DQN_ASSERTF(Dqn_Fs_Exists(sprite_sheet_path), "Required file does not exist '%.*s'", DQN_STRING_FMT(sprite_sheet_path));
|
||||
|
||||
// NOTE: Total sprite frame count
|
||||
Dqn_String8ToU64Result total_frame_count = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||
DQN_ASSERT(total_frame_count.success);
|
||||
sheet->rects = Dqn_Slice_Alloc<Dqn_Rect>(arena, total_frame_count.value, Dqn_ZeroMem_No);
|
||||
|
||||
// NOTE: Total animation count
|
||||
Dqn_String8ToU64Result total_anim_count = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||
DQN_ASSERT(total_anim_count.success);
|
||||
result.anims = Dqn_Slice_Alloc<TELY_AssetSpriteAnimation>(arena, total_anim_count.value, Dqn_ZeroMem_No);
|
||||
|
||||
// TODO: Sprite size?
|
||||
|
||||
// TODO: Texture name?
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Dqn_String8_StartsWith(line, DQN_STRING8("@anim"))) {
|
||||
DQN_ASSERTF(line_splits.size == 4, "Expected 4 splits for @anim lines");
|
||||
Dqn_String8 anim_name = line_splits.data[1];
|
||||
Dqn_String8ToU64Result frames_per_second = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||
Dqn_String8ToU64Result frame_count = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||
|
||||
DQN_ASSERT(anim_name.size);
|
||||
DQN_ASSERT(frame_count.success);
|
||||
DQN_ASSERT(frames_per_second.success);
|
||||
|
||||
Dqn_Allocator allocator = Dqn_Arena_Allocator(arena);
|
||||
TELY_AssetSpriteAnimation *anim = result.anims.data + sprite_anim_index++;
|
||||
anim->label = Dqn_String8_Copy(allocator, anim_name);
|
||||
anim->index = DQN_CAST(uint16_t)sprite_rect_index;
|
||||
anim->count = DQN_CAST(uint16_t)frame_count.value;
|
||||
anim->seconds_per_frame = 1.f / frames_per_second.value;
|
||||
} else {
|
||||
DQN_ASSERTF(line_splits.size == 4, "Expected 4 splits for sprite frame lines");
|
||||
Dqn_String8ToU64Result x = Dqn_String8_ToU64(line_splits.data[0], 0);
|
||||
Dqn_String8ToU64Result y = Dqn_String8_ToU64(line_splits.data[1], 0);
|
||||
Dqn_String8ToU64Result w = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||
Dqn_String8ToU64Result h = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||
|
||||
DQN_ASSERT(x.success);
|
||||
DQN_ASSERT(y.success);
|
||||
DQN_ASSERT(w.success);
|
||||
DQN_ASSERT(h.success);
|
||||
|
||||
sheet->rects.data[sprite_rect_index++] =
|
||||
Dqn_Rect_InitNx4(DQN_CAST(Dqn_f32) x.value,
|
||||
DQN_CAST(Dqn_f32) y.value,
|
||||
DQN_CAST(Dqn_f32) w.value,
|
||||
DQN_CAST(Dqn_f32) h.value);
|
||||
}
|
||||
}
|
||||
|
||||
DQN_ASSERT(sheet->rects.size == sprite_rect_index);
|
||||
DQN_ASSERT(result.anims.size == sprite_anim_index);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport)
|
||||
void TELY_DLL_Reload(void *user_data)
|
||||
{
|
||||
@@ -398,89 +490,19 @@ void TELY_DLL_Init(void *user_data)
|
||||
DQN_MEMCPY(game->hero_sprite_anims.data, &hero_anims, sizeof(hero_anims[0]) * DQN_ARRAY_UCOUNT(hero_anims));
|
||||
}
|
||||
|
||||
// NOTE: Load sprite sheets ====================================================================
|
||||
{
|
||||
TELY_AssetSpriteSheet *sheet = &game->protag_walk_sprite_sheet;
|
||||
Dqn_Slice<TELY_AssetSpriteAnimation> *anims = &game->protag_walk_sprite_anims;
|
||||
|
||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
||||
sheet->sprite_size = Dqn_V2I_InitNx2(185, 170);
|
||||
sheet->type = TELY_AssetSpriteSheetType_Rects;
|
||||
|
||||
// NOTE: Load the sprite meta file =========================================================
|
||||
Dqn_String8 sheet_name = DQN_STRING8("terry_walk_resized_25%");
|
||||
|
||||
Dqn_String8 sprite_spec_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.txt", DQN_STRING_FMT(assets->textures_dir), DQN_STRING_FMT(sheet_name));
|
||||
Dqn_String8 sprite_spec_buffer = platform->func_load_file(scratch.arena, sprite_spec_path);
|
||||
Dqn_String8SplitAllocResult lines = Dqn_String8_SplitAlloc(scratch.allocator, sprite_spec_buffer, DQN_STRING8("\n"));
|
||||
Dqn_usize sprite_rect_index = 0;
|
||||
Dqn_usize sprite_anim_index = 0;
|
||||
|
||||
DQN_FOR_UINDEX(line_index, lines.size) {
|
||||
Dqn_String8 line = lines.data[line_index];
|
||||
Dqn_String8SplitAllocResult line_splits = Dqn_String8_SplitAlloc(scratch.allocator, line, DQN_STRING8(";"));
|
||||
|
||||
if (line_index == 0) {
|
||||
DQN_ASSERTF(line_splits.size == 4, "Expected 4 splits for @file lines");
|
||||
DQN_ASSERT(Dqn_String8_StartsWith(line_splits.data[0], DQN_STRING8("@file"), Dqn_String8EqCase_Sensitive));
|
||||
|
||||
// NOTE: Sprite sheet path
|
||||
Dqn_String8 sprite_sheet_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STRING_FMT(assets->textures_dir), DQN_STRING_FMT(line_splits.data[1]));
|
||||
sheet->tex_handle = platform->func_load_texture(assets, sheet_name, sprite_sheet_path);
|
||||
DQN_ASSERTF(Dqn_Fs_Exists(sprite_sheet_path), "Required file does not exist '%.*s'", DQN_STRING_FMT(sprite_sheet_path));
|
||||
|
||||
// NOTE: Total sprite frame count
|
||||
Dqn_String8ToU64Result total_frame_count = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||
DQN_ASSERT(total_frame_count.success);
|
||||
sheet->rects = Dqn_Slice_Alloc<Dqn_Rect>(&platform->arena, total_frame_count.value, Dqn_ZeroMem_No);
|
||||
|
||||
// NOTE: Total animation count
|
||||
Dqn_String8ToU64Result total_anim_count = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||
DQN_ASSERT(total_anim_count.success);
|
||||
*anims = Dqn_Slice_Alloc<TELY_AssetSpriteAnimation>(&platform->arena, total_anim_count.value, Dqn_ZeroMem_No);
|
||||
|
||||
// TODO: Sprite size?
|
||||
|
||||
// TODO: Texture name?
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Dqn_String8_StartsWith(line, DQN_STRING8("@anim"))) {
|
||||
DQN_ASSERTF(line_splits.size == 4, "Expected 4 splits for @anim lines");
|
||||
Dqn_String8 anim_name = line_splits.data[1];
|
||||
Dqn_String8ToU64Result frames_per_second = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||
Dqn_String8ToU64Result frame_count = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||
|
||||
DQN_ASSERT(anim_name.size);
|
||||
DQN_ASSERT(frame_count.success);
|
||||
DQN_ASSERT(frames_per_second.success);
|
||||
|
||||
TELY_AssetSpriteAnimation *anim = anims->data + sprite_anim_index++;
|
||||
anim->label = Dqn_String8_Copy(platform->allocator, anim_name);
|
||||
anim->index = DQN_CAST(uint16_t)sprite_rect_index;
|
||||
anim->count = DQN_CAST(uint16_t)frame_count.value;
|
||||
anim->seconds_per_frame = 1.f / frames_per_second.value;
|
||||
} else {
|
||||
DQN_ASSERTF(line_splits.size == 4, "Expected 4 splits for sprite frame lines");
|
||||
Dqn_String8ToU64Result x = Dqn_String8_ToU64(line_splits.data[0], 0);
|
||||
Dqn_String8ToU64Result y = Dqn_String8_ToU64(line_splits.data[1], 0);
|
||||
Dqn_String8ToU64Result w = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||
Dqn_String8ToU64Result h = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||
|
||||
DQN_ASSERT(x.success);
|
||||
DQN_ASSERT(y.success);
|
||||
DQN_ASSERT(w.success);
|
||||
DQN_ASSERT(h.success);
|
||||
|
||||
sheet->rects.data[sprite_rect_index++] =
|
||||
Dqn_Rect_InitNx4(DQN_CAST(Dqn_f32) x.value,
|
||||
DQN_CAST(Dqn_f32) y.value,
|
||||
DQN_CAST(Dqn_f32) w.value,
|
||||
DQN_CAST(Dqn_f32) h.value);
|
||||
}
|
||||
{
|
||||
FP_LoadSpriteSheetFromSpecResult terry = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("terry_walk_resized_25%"));
|
||||
game->terry_sprite_sheet = terry.sheet;
|
||||
game->terry_sprite_anims = terry.anims;
|
||||
}
|
||||
|
||||
DQN_ASSERT(sheet->rects.size == sprite_rect_index);
|
||||
DQN_ASSERT(anims->size == sprite_anim_index);
|
||||
{
|
||||
FP_LoadSpriteSheetFromSpecResult smoochie = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("smoochie_resized_25%"));
|
||||
game->smoochie_sprite_sheet = smoochie.sheet;
|
||||
game->smoochie_sprite_anims = smoochie.anims;
|
||||
}
|
||||
}
|
||||
|
||||
game->entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
|
||||
@@ -563,8 +585,8 @@ void TELY_DLL_Init(void *user_data)
|
||||
|
||||
// NOTE: Hero
|
||||
{
|
||||
TELY_AssetSpriteSheet *sheet = &game->protag_walk_sprite_sheet;
|
||||
Dqn_Slice<TELY_AssetSpriteAnimation> anims = game->protag_walk_sprite_anims;
|
||||
TELY_AssetSpriteSheet *sheet = &game->terry_sprite_sheet;
|
||||
Dqn_Slice<TELY_AssetSpriteAnimation> anims = game->terry_sprite_anims;
|
||||
|
||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Terry");
|
||||
entity->local_pos = Dqn_V2_InitNx2(1334, 396);
|
||||
@@ -628,8 +650,8 @@ void TELY_DLL_Init(void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Mob spawner
|
||||
if (0) {
|
||||
// NOTE: Mob spawner ===========================================================================
|
||||
{
|
||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Mob spawner");
|
||||
entity->local_pos = Dqn_V2_InitNx2(0, platform->core.window_size.y * .5f);
|
||||
entity->flags |= FP_GameEntityFlag_Clickable;
|
||||
@@ -637,6 +659,7 @@ void TELY_DLL_Init(void *user_data)
|
||||
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
||||
entity->flags |= FP_GameEntityFlag_MoveByGamepad;
|
||||
entity->flags |= FP_GameEntityFlag_MobSpawner;
|
||||
entity->spawn_cap = 1;
|
||||
}
|
||||
|
||||
uint16_t font_size = 18;
|
||||
@@ -1000,9 +1023,15 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
||||
}
|
||||
|
||||
// NOTE: Mob spawner =======================================================================
|
||||
if ((entity->flags & FP_GameEntityFlag_MobSpawner) && input->timer_s >= entity->next_spawn_timestamp_s) {
|
||||
entity->next_spawn_timestamp_s = DQN_CAST(uint64_t)(input->timer_s + 5.f);
|
||||
FP_Game_EntityAddMob(game, entity_world_pos);
|
||||
if (entity->flags & FP_GameEntityFlag_MobSpawner) {
|
||||
if (entity->spawn_count < entity->spawn_cap) {
|
||||
if (input->timer_s >= entity->next_spawn_timestamp_s) {
|
||||
entity->next_spawn_timestamp_s = DQN_CAST(uint64_t)(input->timer_s + 5.f);
|
||||
entity->spawn_count++;
|
||||
|
||||
FP_Game_EntityAddMob(game, entity_world_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Dqn_Profiler_EndZone(update_zone);
|
||||
|
||||
Reference in New Issue
Block a user