tely: Wire up the sprite up/down/left/right anims

This commit is contained in:
doyle 2023-09-24 16:24:51 +10:00
parent 3745b0c6bc
commit f95cb8ec9b
2 changed files with 54 additions and 13 deletions

View File

@ -595,7 +595,7 @@ void TELY_DLL_Init(void *user_data)
entity->flags |= FP_GameEntityFlag_MoveByMouse; entity->flags |= FP_GameEntityFlag_MoveByMouse;
entity->flags |= FP_GameEntityFlag_MoveByGamepad; entity->flags |= FP_GameEntityFlag_MoveByGamepad;
entity->flags |= FP_GameEntityFlag_NonTraversable; entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->facing_left = true; entity->direction = FP_GameDirection_Left;
game->clicked_entity = entity->handle; game->clicked_entity = entity->handle;
game->player = entity->handle; game->player = entity->handle;
} }
@ -731,7 +731,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
if (entity->flags & (FP_GameEntityFlag_MoveByKeyboard || FP_GameEntityFlag_MoveByGamepad)) { if (entity->flags & (FP_GameEntityFlag_MoveByKeyboard || FP_GameEntityFlag_MoveByGamepad)) {
acceleration = dir_vector * 10000000.f; acceleration = dir_vector * 10000000.f;
if (dir_vector.x) if (dir_vector.x)
entity->facing_left = dir_vector.x < 0.f; entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (dir_vector.y)
entity->direction = dir_vector.y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
} }
} }
@ -795,19 +797,33 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
#endif #endif
// NOTE: Core equations of motion ========================================================== // NOTE: Core equations of motion ==========================================================
bool has_collision = false;
{ {
// f"(t) = a // f"(t) = a
// f'(t) = at + v // f'(t) = at + v
// f (t) = 0.5f*a(t^2) + vt + p // f (t) = 0.5f*a(t^2) + vt + p
Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(input->delta_s); Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(input->delta_s);
Dqn_f32 t_squared = DQN_SQUARED(t); Dqn_f32 t_squared = DQN_SQUARED(t);
entity->velocity = (acceleration * t) + entity->velocity * 0.82f;
Dqn_f32 velocity_falloff_coefficient = 0.25f;
if (entity->handle == game->clicked_entity) {
if (dir_vector.x || dir_vector.y)
velocity_falloff_coefficient = 0.82f;
}
entity->velocity = (acceleration * t) + entity->velocity * velocity_falloff_coefficient;
// NOTE: Zero out velocity with epsilon
if (DQN_ABS(entity->velocity.x) < 5.f)
entity->velocity.x = 0.f;
if (DQN_ABS(entity->velocity.y) < 5.f)
entity->velocity.y = 0.f;
Dqn_V2 delta_pos = (acceleration * 0.5f * t_squared) + (entity->velocity * t); Dqn_V2 delta_pos = (acceleration * 0.5f * t_squared) + (entity->velocity * t);
Dqn_Rect entity_world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle); Dqn_Rect entity_world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
Dqn_V2 entity_pos = Dqn_Rect_Center(entity_world_hit_box); Dqn_V2 entity_pos = Dqn_Rect_Center(entity_world_hit_box);
Dqn_V2 entity_new_pos = entity_pos + delta_pos; Dqn_V2 entity_new_pos = entity_pos + delta_pos;
bool has_collision = false;
for (FP_GameEntityIterator collider_it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &collider_it, game->root_entity); ) { for (FP_GameEntityIterator collider_it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &collider_it, game->root_entity); ) {
FP_GameEntity *collider = collider_it.entity; FP_GameEntity *collider = collider_it.entity;
@ -975,11 +991,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
} }
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); switch (entity->direction) {
case FP_GameDirection_Up: action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkUp); break;
case FP_GameDirection_Down: action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkDown); break;
case FP_GameDirection_Left: action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkLeft); break;
case FP_GameDirection_Right: action_to_anim_mapping = FP_Game_GetActionAnimMappingForType(game, entity->handle, FP_ActionType_WalkRight); break;
}
if (action->flags & FP_GameEntityActionFlag_StateTransition) { if (we_are_clicked_entity) {
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) || if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) { TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
FP_Game_EntityActionSetState(action, FP_GameEntityState_AttackA); FP_Game_EntityActionSetState(action, FP_GameEntityState_AttackA);
@ -989,7 +1008,12 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
} }
} }
if ((action_has_finished && !entity_has_velocity) || (we_are_clicked_entity && dir_vector.x == 0.f && dir_vector.y == 0.f)) { // NOTE: Also handles state transition
if (action->mapping.action_type != action_to_anim_mapping.action_type) {
FP_Game_EntityActionReset(action, FP_GAME_ENTITY_ACTION_INFINITE_TIMER, action_to_anim_mapping);
}
if (!entity_has_velocity && !has_collision) {
FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle); FP_Game_EntityActionSetState(action, FP_GameEntityState_Idle);
} }
} }
@ -1000,7 +1024,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
if (action->flags & FP_GameEntityActionFlag_StateTransition) { if (action->flags & FP_GameEntityActionFlag_StateTransition) {
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, 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_dir = {};
switch (entity->direction) {
case FP_GameDirection_Up: dash_dir.y = -1.f; break;
case FP_GameDirection_Down: dash_dir.y = +1.f; break;
case FP_GameDirection_Left: dash_dir.x = -1.f; break;
case FP_GameDirection_Right: dash_dir.x = +1.f; break;
}
Dqn_V2 dash_acceleration = dash_dir * 400'000'000.f; Dqn_V2 dash_acceleration = dash_dir * 400'000'000.f;
Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(input->delta_s); Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(input->delta_s);
entity->velocity = (dash_acceleration * t) + entity->velocity * 2.0f; entity->velocity = (dash_acceleration * t) + entity->velocity * 2.0f;
@ -1026,7 +1057,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_Renderer *renderer,
entity->attack_box_size = entity->local_hit_box_size; entity->attack_box_size = entity->local_hit_box_size;
// NOTE: Position the attack box // NOTE: Position the attack box
if (entity->facing_left) { if (entity->direction == FP_GameDirection_Left) {
entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x - entity->attack_box_size.w, entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x - entity->attack_box_size.w,
entity->local_hit_box_offset.y); entity->local_hit_box_offset.y);
} else { } else {
@ -1173,8 +1204,10 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
dest_rect.size = src_rect.size * entity->size_scale; dest_rect.size = src_rect.size * entity->size_scale;
dest_rect.pos = world_pos - (dest_rect.size * .5f); dest_rect.pos = world_pos - (dest_rect.size * .5f);
if (entity->facing_left) #if 0
if (entity->direction == FP_GameDirection_Left)
dest_rect.size.w *= -1.f; // NOTE: Flip the texture horizontally dest_rect.size.w *= -1.f; // NOTE: Flip the texture horizontally
#endif
TELY_Render_TextureColourV4(renderer, sprite_sheet->tex_handle, src_rect, dest_rect, TELY_COLOUR_WHITE_V4); TELY_Render_TextureColourV4(renderer, sprite_sheet->tex_handle, src_rect, dest_rect, TELY_COLOUR_WHITE_V4);
} }

View File

@ -97,6 +97,14 @@ struct FP_GameEntityAction
Dqn_f32 end_at_s; Dqn_f32 end_at_s;
}; };
enum FP_GameDirection
{
FP_GameDirection_Up,
FP_GameDirection_Down,
FP_GameDirection_Left,
FP_GameDirection_Right,
};
struct FP_GameEntity struct FP_GameEntity
{ {
FP_GameEntity *next; FP_GameEntity *next;
@ -128,7 +136,7 @@ struct FP_GameEntity
uint64_t spawn_cap; uint64_t spawn_cap;
uint64_t flags; uint64_t flags;
bool facing_left; FP_GameDirection direction;
Dqn_V2 local_pos; Dqn_V2 local_pos;
Dqn_f64 alive_time_s; Dqn_f64 alive_time_s;
Dqn_FArray<FP_GameShape, 4> shapes; Dqn_FArray<FP_GameShape, 4> shapes;