tely: Decouple entity from sprite sheet
This commit is contained in:
parent
481da3a6dd
commit
8568996914
2
External/tely
vendored
2
External/tely
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f874ab4d3d127c7caa9ccdffebdb9ba1edfa5067
|
Subproject commit b135bb46769657e730b49c173db7476160855984
|
147
feely_pona.cpp
147
feely_pona.cpp
@ -3,20 +3,12 @@
|
|||||||
#include "feely_pona_unity.h"
|
#include "feely_pona_unity.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct FP_LoadSpriteSheetFromSpecResult
|
TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name)
|
||||||
{
|
{
|
||||||
TELY_AssetSpriteSheet sheet;
|
TELY_AssetSpriteSheet result = {};
|
||||||
Dqn_Slice<TELY_AssetSpriteAnimation> anims;
|
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(arena);
|
||||||
};
|
result.sprite_size = Dqn_V2I_InitNx2(185, 170);
|
||||||
|
result.type = TELY_AssetSpriteSheetType_Rects;
|
||||||
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 =========================================================
|
// 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_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.txt", DQN_STRING_FMT(assets->textures_dir), DQN_STRING_FMT(sheet_name));
|
||||||
@ -35,13 +27,13 @@ FP_LoadSpriteSheetFromSpecResult FP_LoadSpriteSheetFromSpec(TELY_Platform *platf
|
|||||||
|
|
||||||
// NOTE: Sprite sheet path
|
// 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]));
|
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);
|
result.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));
|
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
|
// NOTE: Total sprite frame count
|
||||||
Dqn_String8ToU64Result total_frame_count = Dqn_String8_ToU64(line_splits.data[2], 0);
|
Dqn_String8ToU64Result total_frame_count = Dqn_String8_ToU64(line_splits.data[2], 0);
|
||||||
DQN_ASSERT(total_frame_count.success);
|
DQN_ASSERT(total_frame_count.success);
|
||||||
sheet->rects = Dqn_Slice_Alloc<Dqn_Rect>(arena, total_frame_count.value, Dqn_ZeroMem_No);
|
result.rects = Dqn_Slice_Alloc<Dqn_Rect>(arena, total_frame_count.value, Dqn_ZeroMem_No);
|
||||||
|
|
||||||
// NOTE: Total animation count
|
// NOTE: Total animation count
|
||||||
Dqn_String8ToU64Result total_anim_count = Dqn_String8_ToU64(line_splits.data[3], 0);
|
Dqn_String8ToU64Result total_anim_count = Dqn_String8_ToU64(line_splits.data[3], 0);
|
||||||
@ -82,7 +74,7 @@ FP_LoadSpriteSheetFromSpecResult FP_LoadSpriteSheetFromSpec(TELY_Platform *platf
|
|||||||
DQN_ASSERT(w.success);
|
DQN_ASSERT(w.success);
|
||||||
DQN_ASSERT(h.success);
|
DQN_ASSERT(h.success);
|
||||||
|
|
||||||
sheet->rects.data[sprite_rect_index++] =
|
result.rects.data[sprite_rect_index++] =
|
||||||
Dqn_Rect_InitNx4(DQN_CAST(Dqn_f32) x.value,
|
Dqn_Rect_InitNx4(DQN_CAST(Dqn_f32) x.value,
|
||||||
DQN_CAST(Dqn_f32) y.value,
|
DQN_CAST(Dqn_f32) y.value,
|
||||||
DQN_CAST(Dqn_f32) w.value,
|
DQN_CAST(Dqn_f32) w.value,
|
||||||
@ -90,7 +82,7 @@ FP_LoadSpriteSheetFromSpecResult FP_LoadSpriteSheetFromSpec(TELY_Platform *platf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DQN_ASSERT(sheet->rects.size == sprite_rect_index);
|
DQN_ASSERT(result.rects.size == sprite_rect_index);
|
||||||
DQN_ASSERT(result.anims.size == sprite_anim_index);
|
DQN_ASSERT(result.anims.size == sprite_anim_index);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -492,17 +484,24 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
|
|
||||||
// NOTE: Load sprite sheets ====================================================================
|
// NOTE: Load sprite sheets ====================================================================
|
||||||
{
|
{
|
||||||
{
|
game->terry_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("terry_walk_resized_25%"));
|
||||||
FP_LoadSpriteSheetFromSpecResult terry = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("terry_walk_resized_25%"));
|
game->terry_action_mappings = Dqn_Slice_CopyArray<FP_ActionToAnimationMapping>(&platform->arena, {
|
||||||
game->terry_sprite_sheet = terry.sheet;
|
{FP_ActionType_Idle, &game->terry_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->terry_sprite_sheet, DQN_STRING8("terry_walk_idle"))},
|
||||||
game->terry_sprite_anims = terry.anims;
|
{FP_ActionType_WalkUp, &game->terry_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->terry_sprite_sheet, DQN_STRING8("terry_walk_up"))},
|
||||||
}
|
{FP_ActionType_WalkDown, &game->terry_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->terry_sprite_sheet, DQN_STRING8("terry_walk_down"))},
|
||||||
|
{FP_ActionType_WalkLeft, &game->terry_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->terry_sprite_sheet, DQN_STRING8("terry_walk_left"))},
|
||||||
|
{FP_ActionType_WalkRight, &game->terry_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->terry_sprite_sheet, DQN_STRING8("terry_walk_right"))},
|
||||||
|
});
|
||||||
|
|
||||||
{
|
game->smoochie_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("smoochie_resized_25%"));
|
||||||
FP_LoadSpriteSheetFromSpecResult smoochie = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("smoochie_resized_25%"));
|
game->smoochie_action_mappings = Dqn_Slice_CopyArray<FP_ActionToAnimationMapping>(&platform->arena, {
|
||||||
game->smoochie_sprite_sheet = smoochie.sheet;
|
{FP_ActionType_Idle, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_walk_down"))},
|
||||||
game->smoochie_sprite_anims = smoochie.anims;
|
{FP_ActionType_WalkUp, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_walk_up"))},
|
||||||
}
|
{FP_ActionType_WalkDown, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_walk_down"))},
|
||||||
|
{FP_ActionType_WalkLeft, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_walk_left"))},
|
||||||
|
{FP_ActionType_WalkRight, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_walk_right"))},
|
||||||
|
{FP_ActionType_Death, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_death"))},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
game->entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
|
game->entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
|
||||||
@ -585,22 +584,19 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
|
|
||||||
// NOTE: Hero
|
// NOTE: Hero
|
||||||
{
|
{
|
||||||
TELY_AssetSpriteSheet *sheet = &game->terry_sprite_sheet;
|
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);
|
||||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Terry");
|
entity->action_to_anim_mapping = game->terry_action_mappings;
|
||||||
entity->local_pos = Dqn_V2_InitNx2(1334, 396);
|
entity->size_scale = Dqn_V2_InitNx1(0.25f);
|
||||||
entity->sprite_sheet = sheet;
|
entity->local_hit_box_size = Dqn_V2_InitV2I(sheet->sprite_size);
|
||||||
entity->sprite_anims = anims;
|
entity->flags |= FP_GameEntityFlag_Clickable;
|
||||||
entity->size_scale = Dqn_V2_InitNx1(0.5f);
|
entity->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
||||||
entity->local_hit_box_size = Dqn_V2_InitV2I(sheet->sprite_size);
|
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
||||||
entity->flags |= FP_GameEntityFlag_Clickable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
entity->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
entity->facing_left = true;
|
||||||
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
game->clicked_entity = entity->handle;
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
game->player = entity->handle;
|
||||||
entity->facing_left = true;
|
|
||||||
game->clicked_entity = entity->handle;
|
|
||||||
game->player = entity->handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
game->tile_size = 37;
|
game->tile_size = 37;
|
||||||
@ -668,6 +664,19 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
game->test_audio = platform->func_load_audio(assets, DQN_STRING8("Test Audio"), DQN_STRING8("Data/Audio/Purrple Cat - Moonwinds.qoa"));
|
game->test_audio = platform->func_load_audio(assets, DQN_STRING8("Test Audio"), DQN_STRING8("Data/Audio/Purrple Cat - Moonwinds.qoa"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FP_ActionToAnimationMapping FP_Game_GetActionAnimMappingForType(FP_Game *game, FP_GameEntityHandle entity_handle, FP_ActionType type)
|
||||||
|
{
|
||||||
|
FP_GameEntity *entity = FP_Game_GetEntity(game, entity_handle);
|
||||||
|
FP_ActionToAnimationMapping result = {};
|
||||||
|
for (FP_ActionToAnimationMapping const &mapping : entity->action_to_anim_mapping) {
|
||||||
|
if (mapping.action_type == type) {
|
||||||
|
result = mapping;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer, TELY_PlatformInput *input)
|
void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer, TELY_PlatformInput *input)
|
||||||
{
|
{
|
||||||
Dqn_Profiler_ZoneScopeWithIndex("FP_Update", FP_ProfileZone_FPUpdate);
|
Dqn_Profiler_ZoneScopeWithIndex("FP_Update", FP_ProfileZone_FPUpdate);
|
||||||
@ -695,7 +704,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (dir_vector.x && dir_vector.y) {
|
if (dir_vector.x && dir_vector.y) {
|
||||||
dir_vector.x *= 0.7071067811865475244f;
|
dir_vector.x *= 0.7071067811865475244f;
|
||||||
dir_vector.y *= 0.7071067811865475244f;
|
dir_vector.y *= 0.7071067811865475244f;
|
||||||
@ -726,6 +734,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
|
|
||||||
// NOTE: Stalk entity ======================================================================
|
// NOTE: Stalk entity ======================================================================
|
||||||
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
FP_GameEntity *stalk_entity = FP_Game_GetEntity(game, entity->stalk_entity);
|
FP_GameEntity *stalk_entity = FP_Game_GetEntity(game, entity->stalk_entity);
|
||||||
if (stalk_entity->handle.id) {
|
if (stalk_entity->handle.id) {
|
||||||
@ -774,10 +783,13 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
TELY_ChunkPool_Dealloc(game->chunk_pool, waypoint);
|
TELY_ChunkPool_Dealloc(game->chunk_pool, waypoint);
|
||||||
} else {
|
} else {
|
||||||
Dqn_V2 entity_to_target_pos_norm = Dqn_V2_Normalise(entity_to_target_pos);
|
Dqn_V2 entity_to_target_pos_norm = Dqn_V2_Normalise(entity_to_target_pos);
|
||||||
entity->local_pos += entity_to_target_pos_norm * (entity->local_hit_box_size.x * .05f);
|
if (acceleration.x == 0 && acceleration.y == 0) {
|
||||||
|
acceleration = entity_to_target_pos_norm * 700'000.f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: Core equations of motion ==========================================================
|
// NOTE: Core equations of motion ==========================================================
|
||||||
{
|
{
|
||||||
@ -886,7 +898,8 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Handle input on entity ============================================================
|
// NOTE: Handle input on entity ============================================================
|
||||||
FP_GameEntityAction *action = &entity->action;
|
FP_GameEntityAction *action = &entity->action;
|
||||||
|
FP_ActionToAnimationMapping action_to_anim_mapping = {};
|
||||||
{
|
{
|
||||||
bool we_are_clicked_entity = entity->handle == game->clicked_entity;
|
bool we_are_clicked_entity = entity->handle == game->clicked_entity;
|
||||||
bool action_has_finished = action->timer_s != FP_GAME_ENTITY_ACTION_INFINITE_TIMER && action->timer_s >= action->end_at_s;
|
bool action_has_finished = action->timer_s != FP_GAME_ENTITY_ACTION_INFINITE_TIMER && action->timer_s >= action->end_at_s;
|
||||||
@ -896,9 +909,10 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
||||||
|
|
||||||
if (action->state == FP_GameEntityState_Idle) {
|
if (action->state == FP_GameEntityState_Idle) {
|
||||||
|
action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Idle);
|
||||||
|
|
||||||
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
||||||
TELY_AssetSpriteAnimation *anim = entity->sprite_anims.data + TELY_Asset_GetSpriteAnimation(entity->sprite_anims, DQN_STRING8("terry_walk_idle")).index;
|
FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, action_to_anim_mapping);
|
||||||
FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, anim);
|
|
||||||
} else if (we_are_clicked_entity) {
|
} else if (we_are_clicked_entity) {
|
||||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
||||||
FP_Game_EntityActionSetState(action, FP_GameEntityState_AttackA);
|
FP_Game_EntityActionSetState(action, FP_GameEntityState_AttackA);
|
||||||
@ -909,9 +923,10 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action->state == FP_GameEntityState_AttackA) {
|
if (action->state == FP_GameEntityState_AttackA) {
|
||||||
|
action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Attack);
|
||||||
|
|
||||||
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
||||||
TELY_AssetSpriteAnimation *anim = entity->sprite_anims.data + TELY_Asset_GetSpriteAnimation(entity->sprite_anims, DQN_STRING8("Attack A")).index;
|
FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping);
|
||||||
FP_Game_EntityActionReset(action, anim->count * anim->seconds_per_frame, anim);
|
|
||||||
} else if (action_has_finished) {
|
} else if (action_has_finished) {
|
||||||
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
||||||
} else if (!FP_Game_EntityActionHasFailed(action) && we_are_clicked_entity) {
|
} else if (!FP_Game_EntityActionHasFailed(action) && we_are_clicked_entity) {
|
||||||
@ -926,9 +941,10 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action->state == FP_GameEntityState_AttackB) {
|
if (action->state == FP_GameEntityState_AttackB) {
|
||||||
|
action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Attack);
|
||||||
|
|
||||||
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
||||||
TELY_AssetSpriteAnimation *anim = entity->sprite_anims.data + TELY_Asset_GetSpriteAnimation(entity->sprite_anims, DQN_STRING8("Attack B")).index;
|
FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping);
|
||||||
FP_Game_EntityActionReset(action, anim->count * anim->seconds_per_frame, anim);
|
|
||||||
} else if (action_has_finished) {
|
} else if (action_has_finished) {
|
||||||
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
||||||
} else if (!FP_Game_EntityActionHasFailed(action) && we_are_clicked_entity) {
|
} else if (!FP_Game_EntityActionHasFailed(action) && we_are_clicked_entity) {
|
||||||
@ -943,18 +959,20 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action->state == FP_GameEntityState_AttackC) {
|
if (action->state == FP_GameEntityState_AttackC) {
|
||||||
|
action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Attack);
|
||||||
|
|
||||||
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
||||||
TELY_AssetSpriteAnimation *anim = entity->sprite_anims.data + TELY_Asset_GetSpriteAnimation(entity->sprite_anims, DQN_STRING8("Attack C")).index;
|
FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping);
|
||||||
FP_Game_EntityActionReset(action, anim->count * anim->seconds_per_frame, anim);
|
|
||||||
} else if (action_has_finished) {
|
} else if (action_has_finished) {
|
||||||
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action->state == FP_GameEntityState_Run) {
|
if (action->state == FP_GameEntityState_Run) {
|
||||||
|
action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkRight);
|
||||||
|
|
||||||
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
||||||
TELY_AssetSpriteAnimation *anim = entity->sprite_anims.data + TELY_Asset_GetSpriteAnimation(entity->sprite_anims, DQN_STRING8("terry_walk_right")).index;
|
FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, action_to_anim_mapping);
|
||||||
FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, anim);
|
|
||||||
} else if (we_are_clicked_entity) {
|
} else if (we_are_clicked_entity) {
|
||||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
||||||
FP_Game_EntityActionSetState(action, FP_GameEntityState_AttackA);
|
FP_Game_EntityActionSetState(action, FP_GameEntityState_AttackA);
|
||||||
@ -969,9 +987,10 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action->state == FP_GameEntityState_Dash) {
|
if (action->state == FP_GameEntityState_Dash) {
|
||||||
|
action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkRight);
|
||||||
|
|
||||||
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
if (action->flags & FP_GameEntityActionFlag_StateTransition) {
|
||||||
TELY_AssetSpriteAnimation *anim = entity->sprite_anims.data + TELY_Asset_GetSpriteAnimation(entity->sprite_anims, DQN_STRING8("Floor slide")).index;
|
FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping);
|
||||||
FP_Game_EntityActionReset(action, anim->count * anim->seconds_per_frame, anim);
|
|
||||||
|
|
||||||
Dqn_V2 dash_dir = {entity->facing_left ? -1.f : 1.f, 0.f};
|
Dqn_V2 dash_dir = {entity->facing_left ? -1.f : 1.f, 0.f};
|
||||||
Dqn_V2 dash_acceleration = dash_dir * 400'000'000.f;
|
Dqn_V2 dash_acceleration = dash_dir * 400'000'000.f;
|
||||||
@ -996,11 +1015,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
|
|||||||
if (action->state == FP_GameEntityState_AttackA ||
|
if (action->state == FP_GameEntityState_AttackA ||
|
||||||
action->state == FP_GameEntityState_AttackB ||
|
action->state == FP_GameEntityState_AttackB ||
|
||||||
action->state == FP_GameEntityState_AttackC) {
|
action->state == FP_GameEntityState_AttackC) {
|
||||||
entity->attack_box_size = entity->local_hit_box_size;
|
entity->attack_box_size = entity->local_hit_box_size;
|
||||||
TELY_AssetSpriteSheet const *sprite_sheet = entity->sprite_sheet;
|
|
||||||
if (sprite_sheet) {
|
|
||||||
entity->attack_box_size = Dqn_V2_InitV2I(sprite_sheet->sprite_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Position the attack box
|
// NOTE: Position the attack box
|
||||||
if (entity->facing_left) {
|
if (entity->facing_left) {
|
||||||
@ -1122,10 +1137,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Render entity sprites =============================================================
|
// NOTE: Render entity sprites =============================================================
|
||||||
if (entity->sprite_sheet && entity->action.anim) {
|
if (entity->action.mapping.anim.label.size) {
|
||||||
TELY_AssetSpriteSheet const *sprite_sheet = entity->sprite_sheet;
|
|
||||||
FP_GameEntityAction const *action = &entity->action;
|
FP_GameEntityAction const *action = &entity->action;
|
||||||
TELY_AssetSpriteAnimation const *sprite_anim = action->anim;
|
TELY_AssetSpriteSheet const *sprite_sheet = action->mapping.sheet;
|
||||||
|
TELY_AssetSpriteAnimation const *sprite_anim = &action->mapping.anim;
|
||||||
uint16_t anim_frame = DQN_CAST(uint16_t)(action->timer_s / sprite_anim->seconds_per_frame) % sprite_anim->count;
|
uint16_t anim_frame = DQN_CAST(uint16_t)(action->timer_s / sprite_anim->seconds_per_frame) % sprite_anim->count;
|
||||||
|
|
||||||
Dqn_usize sprite_index = sprite_anim->index + anim_frame;
|
Dqn_usize sprite_index = sprite_anim->index + anim_frame;
|
||||||
|
@ -434,11 +434,11 @@ static void FP_Game_EntityActionSetState(FP_GameEntityAction *action, FP_GameEnt
|
|||||||
|
|
||||||
// Reset the timers and animation for the current action and set the duration
|
// Reset the timers and animation for the current action and set the duration
|
||||||
// for the new action.
|
// for the new action.
|
||||||
static void FP_Game_EntityActionReset(FP_GameEntityAction *action, Dqn_f32 new_action_duration, TELY_AssetSpriteAnimation *anim)
|
static void FP_Game_EntityActionReset(FP_GameEntityAction *action, Dqn_f32 new_action_duration, FP_ActionToAnimationMapping mapping)
|
||||||
{
|
{
|
||||||
if (!action)
|
if (!action)
|
||||||
return;
|
return;
|
||||||
action->anim = anim;
|
action->mapping = mapping;
|
||||||
action->timer_s = 0.f;
|
action->timer_s = 0.f;
|
||||||
action->end_at_s = new_action_duration;
|
action->end_at_s = new_action_duration;
|
||||||
action->flags = 0;
|
action->flags = 0;
|
||||||
@ -667,17 +667,16 @@ static FP_GameEntityHandle FP_Game_EntityAddWallAtTile(FP_Game *game, Dqn_String
|
|||||||
|
|
||||||
static FP_GameEntityHandle FP_Game_EntityAddMob(FP_Game *game, Dqn_V2 pos)
|
static FP_GameEntityHandle FP_Game_EntityAddMob(FP_Game *game, Dqn_V2 pos)
|
||||||
{
|
{
|
||||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Mob");
|
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Mob");
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->size_scale = Dqn_V2_InitNx1(.5f);
|
entity->size_scale = Dqn_V2_InitNx1(.25f);
|
||||||
entity->sprite_sheet = &game->smoochie_sprite_sheet;
|
entity->action_to_anim_mapping = game->smoochie_action_mappings;
|
||||||
entity->sprite_anims = game->smoochie_sprite_anims;
|
entity->local_hit_box_size = Dqn_V2_InitV2I(game->smoochie_sprite_sheet.sprite_size);
|
||||||
entity->local_hit_box_size = Dqn_V2_InitV2I(game->smoochie_sprite_sheet.sprite_size);
|
entity->flags |= FP_GameEntityFlag_Clickable;
|
||||||
entity->flags |= FP_GameEntityFlag_Clickable;
|
entity->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
||||||
entity->flags |= FP_GameEntityFlag_MoveByKeyboard;
|
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
||||||
entity->flags |= FP_GameEntityFlag_MoveByMouse;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->stalk_entity = game->player;
|
||||||
entity->stalk_entity = game->player;
|
|
||||||
|
|
||||||
FP_GameEntityHandle result = entity->handle;
|
FP_GameEntityHandle result = entity->handle;
|
||||||
return result;
|
return result;
|
||||||
|
@ -68,14 +68,32 @@ enum FP_GameEntityActionFlag
|
|||||||
FP_GameEntityActionFlag_Failed = 1 << 1,
|
FP_GameEntityActionFlag_Failed = 1 << 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FP_ActionType
|
||||||
|
{
|
||||||
|
FP_ActionType_Idle,
|
||||||
|
FP_ActionType_Attack,
|
||||||
|
FP_ActionType_WalkUp,
|
||||||
|
FP_ActionType_WalkDown,
|
||||||
|
FP_ActionType_WalkLeft,
|
||||||
|
FP_ActionType_WalkRight,
|
||||||
|
FP_ActionType_Death,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FP_ActionToAnimationMapping
|
||||||
|
{
|
||||||
|
FP_ActionType action_type;
|
||||||
|
TELY_AssetSpriteSheet *sheet;
|
||||||
|
TELY_AssetSpriteAnimation anim;
|
||||||
|
};
|
||||||
|
|
||||||
Dqn_f32 const FP_GAME_ENTITY_ACTION_INFINITE_TIMER = -1.f;
|
Dqn_f32 const FP_GAME_ENTITY_ACTION_INFINITE_TIMER = -1.f;
|
||||||
struct FP_GameEntityAction
|
struct FP_GameEntityAction
|
||||||
{
|
{
|
||||||
FP_GameEntityState state;
|
FP_GameEntityState state;
|
||||||
uint32_t flags; // Bit flags corresponding with `FP_GameEntityActionFlag`
|
uint32_t flags; // Bit flags corresponding with `FP_GameEntityActionFlag`
|
||||||
TELY_AssetSpriteAnimation *anim;
|
FP_ActionToAnimationMapping mapping;
|
||||||
Dqn_f32 timer_s;
|
Dqn_f32 timer_s;
|
||||||
Dqn_f32 end_at_s;
|
Dqn_f32 end_at_s;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FP_GameEntity
|
struct FP_GameEntity
|
||||||
@ -88,8 +106,7 @@ struct FP_GameEntity
|
|||||||
|
|
||||||
Dqn_String8 name;
|
Dqn_String8 name;
|
||||||
FP_GameEntityHandle handle;
|
FP_GameEntityHandle handle;
|
||||||
TELY_AssetSpriteSheet *sprite_sheet;
|
Dqn_Slice<FP_ActionToAnimationMapping> action_to_anim_mapping;
|
||||||
Dqn_Slice<TELY_AssetSpriteAnimation> sprite_anims;
|
|
||||||
Dqn_V2 size_scale;
|
Dqn_V2 size_scale;
|
||||||
FP_GameEntityAction action;
|
FP_GameEntityAction action;
|
||||||
Dqn_V2 velocity;
|
Dqn_V2 velocity;
|
||||||
@ -150,26 +167,26 @@ struct FP_Game
|
|||||||
Dqn_FArray<FP_GameEntityHandle, 8> parent_entity_stack;
|
Dqn_FArray<FP_GameEntityHandle, 8> parent_entity_stack;
|
||||||
Dqn_VArray<FP_GameEntity> entities;
|
Dqn_VArray<FP_GameEntity> entities;
|
||||||
|
|
||||||
TELY_AssetSpriteSheet terry_sprite_sheet;
|
TELY_AssetSpriteSheet terry_sprite_sheet;
|
||||||
Dqn_Slice<TELY_AssetSpriteAnimation> terry_sprite_anims;
|
Dqn_Slice<FP_ActionToAnimationMapping> terry_action_mappings;
|
||||||
|
|
||||||
TELY_AssetSpriteSheet smoochie_sprite_sheet;
|
TELY_AssetSpriteSheet smoochie_sprite_sheet;
|
||||||
Dqn_Slice<TELY_AssetSpriteAnimation> smoochie_sprite_anims;
|
Dqn_Slice<FP_ActionToAnimationMapping> smoochie_action_mappings;
|
||||||
|
|
||||||
FP_GameEntity *root_entity;
|
FP_GameEntity *root_entity;
|
||||||
FP_GameEntity *entity_free_list;
|
FP_GameEntity *entity_free_list;
|
||||||
|
|
||||||
FP_GameEntityHandle player;
|
FP_GameEntityHandle player;
|
||||||
|
|
||||||
FP_GameEntityHandle clicked_entity;
|
FP_GameEntityHandle clicked_entity;
|
||||||
FP_GameEntityHandle hot_entity;
|
FP_GameEntityHandle hot_entity;
|
||||||
FP_GameEntityHandle active_entity;
|
FP_GameEntityHandle active_entity;
|
||||||
FP_GameEntityHandle prev_clicked_entity;
|
FP_GameEntityHandle prev_clicked_entity;
|
||||||
FP_GameEntityHandle prev_hot_entity;
|
FP_GameEntityHandle prev_hot_entity;
|
||||||
FP_GameEntityHandle prev_active_entity;
|
FP_GameEntityHandle prev_active_entity;
|
||||||
|
|
||||||
FP_GameCamera camera;
|
FP_GameCamera camera;
|
||||||
TELY_RFui rfui;
|
TELY_RFui rfui;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FP_GameAStarNode
|
struct FP_GameAStarNode
|
||||||
|
Loading…
Reference in New Issue
Block a user