Compare commits

..

No commits in common. "1c6037bbaaa4570cbeb0d4c62270c0e18fe0a105" and "e467abf922b259e85e3f361a20f30aadcd5cd6ee" have entirely different histories.

5 changed files with 24 additions and 103 deletions

2
External/tely vendored

@ -1 +1 @@
Subproject commit f4390f0a385345efc07297317539d5eb6e8c9c09 Subproject commit 949f5e16338c7f981b38f03fc406dca3a499ab9a

View File

@ -854,28 +854,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_PlatformInput *input, FP_Ga
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER; uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite); FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
} }
} break;
case FP_EntityClubTerryState_PartyTime: {
if (entering_new_state) {
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.club_terry_alive, TELY_AssetFlip_No);
uint64_t duration_ms = 5000;
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
}
if (action_has_finished) {
if (!FP_Game_IsNilEntityHandle(game, entity->club_terry_patron)) {
FP_GameEntity *patron = FP_Game_GetEntity(game, entity->club_terry_patron);
patron->flags |= FP_GameEntityFlag_ExperiencedClubTerry;
patron->flags &= ~FP_GameEntityFlag_PartyingAtClubTerry;
patron->base_acceleration_per_s.meters *= .5f;
entity->club_terry_patron = {};
}
action->next_state = FP_EntityClubTerryState_Idle;
}
} break; } break;
} }
} break; } break;
case FP_EntityType_Nil: break; case FP_EntityType_Nil: break;
@ -942,9 +923,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
FP_GameEntity *entity = it.entity; FP_GameEntity *entity = it.entity;
entity->alive_time_s += PHYSICS_STEP; entity->alive_time_s += PHYSICS_STEP;
if (entity->flags & FP_GameEntityFlag_PartyingAtClubTerry)
continue;
// NOTE: Move entity by keyboard and gamepad =============================================== // NOTE: Move entity by keyboard and gamepad ===============================================
Dqn_V2 acceleration_meters_per_s = {}; Dqn_V2 acceleration_meters_per_s = {};
if (game->clicked_entity == entity->handle) { if (game->clicked_entity == entity->handle) {
@ -973,7 +951,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
} }
if (move_entity) { if (move_entity) {
acceleration_meters_per_s = dir_vector * entity->base_acceleration_per_s.meters; acceleration_meters_per_s = dir_vector * 8;
if (dir_vector.x) if (dir_vector.x)
entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left; entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (dir_vector.y) else if (dir_vector.y)
@ -1028,7 +1006,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
} }
} }
if (entity->flags & FP_GameEntityFlag_RespondsToClubTerry && (entity->flags & FP_GameEntityFlag_ExperiencedClubTerry) == 0) { if (entity->flags & FP_GameEntityFlag_RespondsToClubTerry) {
FP_GameFindClosestEntityResult closest_club = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_ClubTerry); FP_GameFindClosestEntityResult closest_club = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_ClubTerry);
if (closest_club.dist_squared < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4.f))) { if (closest_club.dist_squared < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4.f))) {
@ -1091,33 +1069,15 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
// NOTE: We haven't arrived yet, calculate an acceleration vector to the waypoint // NOTE: We haven't arrived yet, calculate an acceleration vector to the waypoint
if (dist_to_waypoint_sq > DQN_SQUARED(arrival_threshold)) { if (dist_to_waypoint_sq > DQN_SQUARED(arrival_threshold)) {
Dqn_V2 entity_to_waypoint_norm = Dqn_V2_Normalise(entity_to_waypoint); Dqn_V2 entity_to_waypoint_norm = Dqn_V2_Normalise(entity_to_waypoint);
acceleration_meters_per_s = entity_to_waypoint_norm * (entity->base_acceleration_per_s.meters * 0.25f); acceleration_meters_per_s = entity_to_waypoint_norm * 2.f;
break; break;
} }
// NOTE: We have arrived at the waypoint // NOTE: We have arrived at the waypoint
bool aggro_on_terry = (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint_entity->type == FP_EntityType_Terry; bool aggro_on_terry = (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint_entity->type == FP_EntityType_Terry;
bool club_terry_response = (entity->flags & FP_GameEntityFlag_RespondsToClubTerry) && bool club_terry_response = (entity->flags & FP_GameEntityFlag_RespondsToClubTerry) && waypoint_entity->type == FP_EntityType_ClubTerry;
((entity->flags & FP_GameEntityFlag_ExperiencedClubTerry) == 0) &&
waypoint_entity->type == FP_EntityType_ClubTerry;
if (((waypoint->flags & FP_GameWaypointFlag_NonInterruptible) == 0) && (aggro_on_terry || club_terry_response)) { if (((waypoint->flags & FP_GameWaypointFlag_NonInterruptible) == 0) && (aggro_on_terry || club_terry_response)) {
bool can_attack = !entity->is_dying; // TODO(doyle): State transition needs to check if it's valid to move to making this not necessary bool can_attack = !entity->is_dying; // TODO(doyle): State transition needs to check if it's valid to move to making this not necessary
if (club_terry_response) {
FP_GameEntity *club = waypoint_entity;
if (FP_Game_IsNilEntityHandle(game, club->club_terry_patron)) {
club->club_terry_patron = entity->handle;
club->action.next_state = FP_EntityClubTerryState_PartyTime;
entity->flags |= FP_GameEntityFlag_PartyingAtClubTerry;
Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, club->handle);
Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.5f, 1.1f));
entity->local_pos = exit_pos; // TODO(doyle): Only works when parent world pos is 0,0
can_attack = false;
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->chunk_pool);
}
}
if (can_attack) { if (can_attack) {
Dqn_V2 attack_dir_vectors[FP_GameDirection_Count] = {}; Dqn_V2 attack_dir_vectors[FP_GameDirection_Count] = {};
attack_dir_vectors[FP_GameDirection_Up] = Dqn_V2_InitNx2(+0, -1); attack_dir_vectors[FP_GameDirection_Up] = Dqn_V2_InitNx2(+0, -1);
@ -1351,12 +1311,8 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) { for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
FP_GameEntity *entity = it.entity; FP_GameEntity *entity = it.entity;
if (entity->flags & FP_GameEntityFlag_PartyingAtClubTerry)
continue;
// NOTE: Render shapes in entity =========================================================== // NOTE: Render shapes in entity ===========================================================
Dqn_Rect world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle); Dqn_V2 world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
Dqn_V2 world_pos = Dqn_Rect_Center(world_hit_box);
for (FP_GameShape const &shape_ : entity->shapes) { for (FP_GameShape const &shape_ : entity->shapes) {
FP_GameShape const *shape = &shape_; FP_GameShape const *shape = &shape_;
Dqn_V2 local_to_world_p1 = world_pos + shape->p1; Dqn_V2 local_to_world_p1 = world_pos + shape->p1;
@ -1420,14 +1376,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
if (sprite.flip & TELY_AssetFlip_Y) if (sprite.flip & TELY_AssetFlip_Y)
dest_rect.size.h *= -1.f; // NOTE: Flip the texture vertically dest_rect.size.h *= -1.f; // NOTE: Flip the texture vertically
Dqn_f32 rotate_radians = Dqn_PCG32_NextF32(&game->rng) * DQN_PI * 0.5f; 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,
Dqn_V2_Zero /*rotate origin*/,
rotate_radians,
TELY_COLOUR_WHITE_V4);
} }
DQN_FOR_UINDEX(anim_index, entity->extra_cosmetic_anims.size) { DQN_FOR_UINDEX(anim_index, entity->extra_cosmetic_anims.size) {
@ -1471,27 +1420,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
if (sprite->asset.flip & TELY_AssetFlip_Y) if (sprite->asset.flip & TELY_AssetFlip_Y)
dest_rect.size.h *= -1.f; // NOTE: Flip the texture vertically dest_rect.size.h *= -1.f; // NOTE: Flip the texture vertically
TELY_Render_TextureColourV4(renderer, TELY_Render_TextureColourV4(renderer, sprite->asset.sheet->tex_handle, src_rect, dest_rect, TELY_COLOUR_WHITE_V4);
sprite->asset.sheet->tex_handle,
src_rect,
dest_rect,
Dqn_V2_Zero /*rotate origin*/,
0.f /*rotation*/,
TELY_COLOUR_WHITE_V4);
}
if (entity->type == FP_EntityType_ClubTerry) {
FP_EntityClubTerryState *state = DQN_CAST(FP_EntityClubTerryState *)&entity->action.state;
if (*state == FP_EntityClubTerryState_PartyTime) {
Dqn_f32 duration = entity->action.end_at_clock_ms - DQN_CAST(Dqn_f32)entity->action.started_at_clock_ms;
Dqn_f32 elapsed = DQN_CAST(Dqn_f32)(game->clock_ms - entity->action.started_at_clock_ms);
Dqn_f32 t01 = DQN_MIN(1.f, elapsed / duration);
Dqn_Rect rect = {};
rect.pos = Dqn_Rect_InterpolatedPoint(world_hit_box, Dqn_V2_InitNx2(0, -0.3f));
rect.size = Dqn_V2_InitNx2(world_hit_box.size.w * t01, 16.f);
TELY_Render_RectColourV4(renderer, rect, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_RED_TOMATO_V4, 1.0f));
}
} }
// NOTE: Render waypoint entities ========================================================== // NOTE: Render waypoint entities ==========================================================
@ -1508,6 +1437,7 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
} }
// NOTE: Render attack box ================================================================= // NOTE: Render attack box =================================================================
Dqn_Rect world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
{ {
Dqn_Rect attack_box = FP_Game_CalcEntityAttackWorldHitBox(game, entity->handle); Dqn_Rect attack_box = FP_Game_CalcEntityAttackWorldHitBox(game, entity->handle);
TELY_Render_RectColourV4(renderer, attack_box, TELY_RenderShapeMode_Line, TELY_COLOUR_RED_TOMATO_V4); TELY_Render_RectColourV4(renderer, attack_box, TELY_RenderShapeMode_Line, TELY_COLOUR_RED_TOMATO_V4);

View File

@ -53,5 +53,4 @@ enum FP_EntityClubTerryState
{ {
FP_EntityClubTerryState_Nil, FP_EntityClubTerryState_Nil,
FP_EntityClubTerryState_Idle, FP_EntityClubTerryState_Idle,
FP_EntityClubTerryState_PartyTime,
}; };

View File

@ -50,12 +50,11 @@ static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQ
FP_GameEntityHandle result = entity->handle; FP_GameEntityHandle result = entity->handle;
va_end(args); va_end(args);
entity->type = FP_EntityType_Clinger; entity->type = FP_EntityType_Clinger;
entity->hp = 1; entity->hp = 1;
entity->is_dying = false; entity->is_dying = false;
entity->base_acceleration_per_s.meters = 8.f; entity->local_pos = pos;
entity->local_pos = pos; entity->sprite_height.meters = 1.6f;
entity->sprite_height.meters = 1.6f;
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, entity->sprite_height.meters * .5f); entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, entity->sprite_height.meters * .5f);
FP_Entity_AddDebugEditorFlags(game, entity->handle); FP_Entity_AddDebugEditorFlags(game, entity->handle);
@ -72,13 +71,12 @@ static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, D
FP_GameEntityHandle result = entity->handle; FP_GameEntityHandle result = entity->handle;
va_end(args); va_end(args);
entity->type = FP_EntityType_Smoochie; entity->type = FP_EntityType_Smoochie;
entity->base_acceleration_per_s.meters = 8.f; entity->hp = 1;
entity->hp = 1; entity->is_dying = false;
entity->is_dying = false; entity->local_pos = pos;
entity->local_pos = pos; entity->sprite_height.meters = 1.6f;
entity->sprite_height.meters = 1.6f; entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, entity->sprite_height.meters * .6f);
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, entity->sprite_height.meters * .6f);
FP_Entity_AddDebugEditorFlags(game, entity->handle); FP_Entity_AddDebugEditorFlags(game, entity->handle);
entity->flags |= FP_GameEntityFlag_NonTraversable; entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable; entity->flags |= FP_GameEntityFlag_Attackable;
@ -138,11 +136,10 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
FP_GameEntityHandle result = entity->handle; FP_GameEntityHandle result = entity->handle;
va_end(args); va_end(args);
entity->type = FP_EntityType_Terry; entity->type = FP_EntityType_Terry;
entity->local_pos = pos; entity->local_pos = pos;
entity->base_acceleration_per_s.meters = 8.f; entity->sprite_height.meters = 1.8f;
entity->sprite_height.meters = 1.8f; entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.5f, entity->sprite_height.meters * .6f);
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.5f, entity->sprite_height.meters * .6f);
FP_Entity_AddDebugEditorFlags(game, result); FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable; entity->flags |= FP_GameEntityFlag_NonTraversable;
entity->flags |= FP_GameEntityFlag_Attackable; entity->flags |= FP_GameEntityFlag_Attackable;

View File

@ -17,8 +17,6 @@ enum FP_GameEntityFlag
FP_GameEntityFlag_AggrosWhenNearTerry = 1 << 9, FP_GameEntityFlag_AggrosWhenNearTerry = 1 << 9,
FP_GameEntityFlag_Attackable = 1 << 10, FP_GameEntityFlag_Attackable = 1 << 10,
FP_GameEntityFlag_RespondsToClubTerry = 1 << 11, FP_GameEntityFlag_RespondsToClubTerry = 1 << 11,
FP_GameEntityFlag_PartyingAtClubTerry = 1 << 12,
FP_GameEntityFlag_ExperiencedClubTerry = 1 << 13,
}; };
enum FP_GameShapeType enum FP_GameShapeType
@ -146,7 +144,6 @@ struct FP_GameEntity
// is scaled uniformly with respect to the height. // is scaled uniformly with respect to the height.
FP_Meters sprite_height; FP_Meters sprite_height;
FP_GameEntityAction action; FP_GameEntityAction action;
FP_Meters base_acceleration_per_s;
Dqn_V2 velocity; Dqn_V2 velocity;
// Extra animations that are to be executed, but, don't affect the state // Extra animations that are to be executed, but, don't affect the state
@ -157,8 +154,6 @@ struct FP_GameEntity
FP_SentinelList<FP_GameWaypoint> waypoints; FP_SentinelList<FP_GameWaypoint> waypoints;
FP_GameEntityHandle aggro_slot[FP_GameDirection_Count]; FP_GameEntityHandle aggro_slot[FP_GameDirection_Count];
FP_GameEntityHandle club_terry_patron;
// NOTE: The entity hit box is positioned at the center of the entity. // NOTE: The entity hit box is positioned at the center of the entity.
Dqn_V2 local_hit_box_size; Dqn_V2 local_hit_box_size;
Dqn_V2 local_hit_box_offset; Dqn_V2 local_hit_box_offset;