diff --git a/External/tely b/External/tely index f874ab4..b135bb4 160000 --- a/External/tely +++ b/External/tely @@ -1 +1 @@ -Subproject commit f874ab4d3d127c7caa9ccdffebdb9ba1edfa5067 +Subproject commit b135bb46769657e730b49c173db7476160855984 diff --git a/feely_pona.cpp b/feely_pona.cpp index 943a3e9..0cd46ea 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -3,20 +3,12 @@ #include "feely_pona_unity.h" #endif -struct FP_LoadSpriteSheetFromSpecResult +TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name) { - TELY_AssetSpriteSheet sheet; - Dqn_Slice 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; + TELY_AssetSpriteSheet result = {}; + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(arena); + result.sprite_size = Dqn_V2I_InitNx2(185, 170); + result.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)); @@ -35,13 +27,13 @@ FP_LoadSpriteSheetFromSpecResult FP_LoadSpriteSheetFromSpec(TELY_Platform *platf // 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); + 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)); // 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(arena, total_frame_count.value, Dqn_ZeroMem_No); + result.rects = Dqn_Slice_Alloc(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); @@ -82,7 +74,7 @@ FP_LoadSpriteSheetFromSpecResult FP_LoadSpriteSheetFromSpec(TELY_Platform *platf DQN_ASSERT(w.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_CAST(Dqn_f32) y.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); return result; } @@ -492,17 +484,24 @@ void TELY_DLL_Init(void *user_data) // NOTE: Load sprite sheets ==================================================================== { - { - 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; - } + game->terry_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("terry_walk_resized_25%")); + game->terry_action_mappings = Dqn_Slice_CopyArray(&platform->arena, { + {FP_ActionType_Idle, &game->terry_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->terry_sprite_sheet, DQN_STRING8("terry_walk_idle"))}, + {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"))}, + }); - { - 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->smoochie_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("smoochie_resized_25%")); + game->smoochie_action_mappings = Dqn_Slice_CopyArray(&platform->arena, { + {FP_ActionType_Idle, &game->smoochie_sprite_sheet, TELY_Asset_GetSpriteAnimation(&game->smoochie_sprite_sheet, DQN_STRING8("smoochie_walk_down"))}, + {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(&platform->arena, 1024 * 8); @@ -585,22 +584,19 @@ void TELY_DLL_Init(void *user_data) // NOTE: Hero { - TELY_AssetSpriteSheet *sheet = &game->terry_sprite_sheet; - Dqn_Slice anims = game->terry_sprite_anims; - - FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Terry"); - entity->local_pos = Dqn_V2_InitNx2(1334, 396); - entity->sprite_sheet = sheet; - entity->sprite_anims = anims; - entity->size_scale = Dqn_V2_InitNx1(0.5f); - entity->local_hit_box_size = Dqn_V2_InitV2I(sheet->sprite_size); - entity->flags |= FP_GameEntityFlag_Clickable; - entity->flags |= FP_GameEntityFlag_MoveByKeyboard; - entity->flags |= FP_GameEntityFlag_MoveByMouse; - entity->flags |= FP_GameEntityFlag_NonTraversable; - entity->facing_left = true; - game->clicked_entity = entity->handle; - game->player = entity->handle; + TELY_AssetSpriteSheet *sheet = &game->terry_sprite_sheet; + FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Terry"); + entity->local_pos = Dqn_V2_InitNx2(1334, 396); + entity->action_to_anim_mapping = game->terry_action_mappings; + entity->size_scale = Dqn_V2_InitNx1(0.25f); + entity->local_hit_box_size = Dqn_V2_InitV2I(sheet->sprite_size); + entity->flags |= FP_GameEntityFlag_Clickable; + entity->flags |= FP_GameEntityFlag_MoveByKeyboard; + entity->flags |= FP_GameEntityFlag_MoveByMouse; + entity->flags |= FP_GameEntityFlag_NonTraversable; + entity->facing_left = true; + game->clicked_entity = entity->handle; + game->player = entity->handle; } 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")); } +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) { 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) { dir_vector.x *= 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 ====================================================================== Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle); + #if 0 { FP_GameEntity *stalk_entity = FP_Game_GetEntity(game, entity->stalk_entity); 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); } else { 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 ========================================================== { @@ -886,7 +898,8 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer, } // 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 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); 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) { - 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, anim); + FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, action_to_anim_mapping); } else if (we_are_clicked_entity) { if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) { 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) { + action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Attack); + 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, anim->count * anim->seconds_per_frame, anim); + FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping); } else if (action_has_finished) { FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle); } 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) { + action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Attack); + 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, anim->count * anim->seconds_per_frame, anim); + FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping); } else if (action_has_finished) { FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle); } 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) { + action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_Attack); + 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, anim->count * anim->seconds_per_frame, anim); + FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping); } else if (action_has_finished) { FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle); } } 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) { - 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, anim); + FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, action_to_anim_mapping); } else if (we_are_clicked_entity) { if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) { 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) { + action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkRight); + 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, anim->count * anim->seconds_per_frame, anim); + FP_Game_EntityActionReset(action, action_to_anim_mapping.anim.count * action_to_anim_mapping.anim.seconds_per_frame, action_to_anim_mapping); Dqn_V2 dash_dir = {entity->facing_left ? -1.f : 1.f, 0.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 || action->state == FP_GameEntityState_AttackB || action->state == FP_GameEntityState_AttackC) { - 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); - } + entity->attack_box_size = entity->local_hit_box_size; // NOTE: Position the attack box if (entity->facing_left) { @@ -1122,10 +1137,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer) } // NOTE: Render entity sprites ============================================================= - if (entity->sprite_sheet && entity->action.anim) { - TELY_AssetSpriteSheet const *sprite_sheet = entity->sprite_sheet; + if (entity->action.mapping.anim.label.size) { 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; Dqn_usize sprite_index = sprite_anim->index + anim_frame; diff --git a/feely_pona_game.cpp b/feely_pona_game.cpp index e795ef8..af332fc 100644 --- a/feely_pona_game.cpp +++ b/feely_pona_game.cpp @@ -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 // 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) return; - action->anim = anim; + action->mapping = mapping; action->timer_s = 0.f; action->end_at_s = new_action_duration; 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) { - FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Mob"); - entity->local_pos = pos; - entity->size_scale = Dqn_V2_InitNx1(.5f); - entity->sprite_sheet = &game->smoochie_sprite_sheet; - entity->sprite_anims = game->smoochie_sprite_anims; - entity->local_hit_box_size = Dqn_V2_InitV2I(game->smoochie_sprite_sheet.sprite_size); - entity->flags |= FP_GameEntityFlag_Clickable; - entity->flags |= FP_GameEntityFlag_MoveByKeyboard; - entity->flags |= FP_GameEntityFlag_MoveByMouse; - entity->flags |= FP_GameEntityFlag_NonTraversable; - entity->stalk_entity = game->player; + FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Mob"); + entity->local_pos = pos; + entity->size_scale = Dqn_V2_InitNx1(.25f); + entity->action_to_anim_mapping = game->smoochie_action_mappings; + entity->local_hit_box_size = Dqn_V2_InitV2I(game->smoochie_sprite_sheet.sprite_size); + entity->flags |= FP_GameEntityFlag_Clickable; + entity->flags |= FP_GameEntityFlag_MoveByKeyboard; + entity->flags |= FP_GameEntityFlag_MoveByMouse; + entity->flags |= FP_GameEntityFlag_NonTraversable; + entity->stalk_entity = game->player; FP_GameEntityHandle result = entity->handle; return result; diff --git a/feely_pona_game.h b/feely_pona_game.h index bac8fad..98f763e 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -68,14 +68,32 @@ enum FP_GameEntityActionFlag 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; struct FP_GameEntityAction { - FP_GameEntityState state; - uint32_t flags; // Bit flags corresponding with `FP_GameEntityActionFlag` - TELY_AssetSpriteAnimation *anim; - Dqn_f32 timer_s; - Dqn_f32 end_at_s; + FP_GameEntityState state; + uint32_t flags; // Bit flags corresponding with `FP_GameEntityActionFlag` + FP_ActionToAnimationMapping mapping; + Dqn_f32 timer_s; + Dqn_f32 end_at_s; }; struct FP_GameEntity @@ -88,8 +106,7 @@ struct FP_GameEntity Dqn_String8 name; FP_GameEntityHandle handle; - TELY_AssetSpriteSheet *sprite_sheet; - Dqn_Slice sprite_anims; + Dqn_Slice action_to_anim_mapping; Dqn_V2 size_scale; FP_GameEntityAction action; Dqn_V2 velocity; @@ -150,26 +167,26 @@ struct FP_Game Dqn_FArray parent_entity_stack; Dqn_VArray entities; - TELY_AssetSpriteSheet terry_sprite_sheet; - Dqn_Slice terry_sprite_anims; + TELY_AssetSpriteSheet terry_sprite_sheet; + Dqn_Slice terry_action_mappings; - TELY_AssetSpriteSheet smoochie_sprite_sheet; - Dqn_Slice smoochie_sprite_anims; + TELY_AssetSpriteSheet smoochie_sprite_sheet; + Dqn_Slice smoochie_action_mappings; - FP_GameEntity *root_entity; - FP_GameEntity *entity_free_list; + FP_GameEntity *root_entity; + FP_GameEntity *entity_free_list; - FP_GameEntityHandle player; + FP_GameEntityHandle player; - FP_GameEntityHandle clicked_entity; - FP_GameEntityHandle hot_entity; - FP_GameEntityHandle active_entity; - FP_GameEntityHandle prev_clicked_entity; - FP_GameEntityHandle prev_hot_entity; - FP_GameEntityHandle prev_active_entity; + FP_GameEntityHandle clicked_entity; + FP_GameEntityHandle hot_entity; + FP_GameEntityHandle active_entity; + FP_GameEntityHandle prev_clicked_entity; + FP_GameEntityHandle prev_hot_entity; + FP_GameEntityHandle prev_active_entity; - FP_GameCamera camera; - TELY_RFui rfui; + FP_GameCamera camera; + TELY_RFui rfui; }; struct FP_GameAStarNode