fp: Add rudimentary build mode
This commit is contained in:
parent
20da505f2e
commit
3efa397d1d
2
External/tely
vendored
2
External/tely
vendored
@ -1 +1 @@
|
|||||||
Subproject commit d58010b431d3ed7ee0076f3195f1d2a8ccc4a220
|
Subproject commit 26f6dd7d348c5a732ddfb929bd2d9b01e644ac48
|
259
feely_pona.cpp
259
feely_pona.cpp
@ -5,6 +5,42 @@
|
|||||||
|
|
||||||
Dqn_f32 const PHYSICS_STEP = 1 / 60.f;
|
Dqn_f32 const PHYSICS_STEP = 1 / 60.f;
|
||||||
|
|
||||||
|
Dqn_Rect FP_Game_GetBuildingPlacementRectForEntity(FP_Game *game, FP_GameEntityHandle handle)
|
||||||
|
{
|
||||||
|
Dqn_Rect result = {};
|
||||||
|
FP_GameEntity *entity = FP_Game_GetEntity(game, handle);
|
||||||
|
if (FP_Game_IsNilEntity(entity))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
FP_EntityRenderData club_terry_render_data = FP_Entity_GetRenderData(game, FP_EntityType_ClubTerry, FP_EntityClubTerryState_Idle, entity->direction);
|
||||||
|
|
||||||
|
Dqn_Rect box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
|
||||||
|
Dqn_V2 build_p = {};
|
||||||
|
switch (entity->direction) {
|
||||||
|
case FP_GameDirection_Up: {
|
||||||
|
build_p = Dqn_Rect_InterpolatedPoint(box, Dqn_V2_InitNx2(0.5f, 0.f)) - Dqn_V2_InitNx2(0.f, club_terry_render_data.render_size.h * .5f + 10.f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Down: {
|
||||||
|
build_p = Dqn_Rect_InterpolatedPoint(box, Dqn_V2_InitNx2(0.5f, 1.f)) + Dqn_V2_InitNx2(0.f, club_terry_render_data.render_size.h * .5f + 10.f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Left: {
|
||||||
|
build_p = Dqn_Rect_InterpolatedPoint(box, Dqn_V2_InitNx2(0.0f, 0.5f)) - Dqn_V2_InitNx2(club_terry_render_data.render_size.w * .5f + 10.f, 0);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Right: {
|
||||||
|
build_p = Dqn_Rect_InterpolatedPoint(box, Dqn_V2_InitNx2(1.f, 0.5f)) + Dqn_V2_InitNx2(club_terry_render_data.render_size.w * .5f + 10.f, 0);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.size = club_terry_render_data.render_size;
|
||||||
|
result.pos = build_p - (club_terry_render_data.render_size * .5f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name)
|
TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name)
|
||||||
{
|
{
|
||||||
TELY_AssetSpriteSheet result = {};
|
TELY_AssetSpriteSheet result = {};
|
||||||
@ -230,6 +266,7 @@ void TELY_DLL_Reload(void *user_data)
|
|||||||
{
|
{
|
||||||
TELY_Platform *platform = DQN_CAST(TELY_Platform *)user_data;
|
TELY_Platform *platform = DQN_CAST(TELY_Platform *)user_data;
|
||||||
Dqn_Library_SetPointer(platform->core.dqn_lib);
|
Dqn_Library_SetPointer(platform->core.dqn_lib);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" __declspec(dllexport)
|
extern "C" __declspec(dllexport)
|
||||||
@ -296,10 +333,10 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.map);
|
TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.map);
|
||||||
Dqn_Rect sprite_rect = game->atlas_sprite_sheet.rects.data[sprite_anim->index];
|
Dqn_Rect sprite_rect = game->atlas_sprite_sheet.rects.data[sprite_anim->index];
|
||||||
|
|
||||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Map");
|
FP_GameEntity *entity = FP_Game_MakeEntityPointerF(game, "Map");
|
||||||
entity->type = FP_EntityType_Map;
|
entity->type = FP_EntityType_Map;
|
||||||
entity->sprite_height.meters = 41.9f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
entity->local_pos = {};
|
entity->local_pos = {};
|
||||||
|
|
||||||
Dqn_f32 size_scale = FP_Entity_CalcSpriteScaleForDesiredHeight(game, entity->sprite_height, sprite_rect);
|
Dqn_f32 size_scale = FP_Entity_CalcSpriteScaleForDesiredHeight(game, entity->sprite_height, sprite_rect);
|
||||||
Dqn_V2 sprite_rect_scaled = sprite_rect.size * size_scale;
|
Dqn_V2 sprite_rect_scaled = sprite_rect.size * size_scale;
|
||||||
@ -368,7 +405,7 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
// NOTE: Mid lane mob spawner ==================================================================
|
// NOTE: Mid lane mob spawner ==================================================================
|
||||||
Dqn_V2 base_mid_p = Dqn_V2_InitNx2(1580, 0.f);
|
Dqn_V2 base_mid_p = Dqn_V2_InitNx2(1580, 0.f);
|
||||||
Dqn_V2 mid_lane_mob_spawner_pos = Dqn_V2_InitNx2(game->map->local_hit_box_size.w * -0.5f, 0.f);
|
Dqn_V2 mid_lane_mob_spawner_pos = Dqn_V2_InitNx2(game->map->local_hit_box_size.w * -0.5f, 0.f);
|
||||||
Dqn_usize spawn_cap = 128;
|
Dqn_usize spawn_cap = 16;
|
||||||
{
|
{
|
||||||
FP_GameEntityHandle mob_spawner = FP_Entity_CreateMobSpawner(game, mid_lane_mob_spawner_pos, spawn_cap, "Mob spawner");
|
FP_GameEntityHandle mob_spawner = FP_Entity_CreateMobSpawner(game, mid_lane_mob_spawner_pos, spawn_cap, "Mob spawner");
|
||||||
FP_Game_PushParentEntity(game, mob_spawner);
|
FP_Game_PushParentEntity(game, mob_spawner);
|
||||||
@ -419,10 +456,18 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
bool const action_has_finished = !entering_new_state && game->clock_ms >= action->end_at_clock_ms;
|
bool const action_has_finished = !entering_new_state && game->clock_ms >= action->end_at_clock_ms;
|
||||||
action->state = action->next_state;
|
action->state = action->next_state;
|
||||||
|
|
||||||
switch (entity->type) {
|
// NOTE: Left-shift lets us strafe in the same direction
|
||||||
|
if (!TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_LeftShift)) {
|
||||||
|
if (acceleration_meters_per_s->x)
|
||||||
|
entity->direction = acceleration_meters_per_s->x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
|
||||||
|
else if (acceleration_meters_per_s->y)
|
||||||
|
entity->direction = acceleration_meters_per_s->y > 0.f ? FP_GameDirection_Down : FP_GameDirection_Up;
|
||||||
|
}
|
||||||
|
|
||||||
|
FP_EntityRenderData render_data = FP_Entity_GetRenderData(game, entity->type, entity->action.state, entity->direction);
|
||||||
|
switch (entity->type) {
|
||||||
case FP_EntityType_Terry: {
|
case FP_EntityType_Terry: {
|
||||||
FP_EntityTerryState *state = DQN_CAST(FP_EntityTerryState *) & action->state;
|
FP_EntityTerryState *state = DQN_CAST(FP_EntityTerryState *) & action->state;
|
||||||
|
|
||||||
switch (*state) {
|
switch (*state) {
|
||||||
case FP_EntityTerryState_Nil: {
|
case FP_EntityTerryState_Nil: {
|
||||||
@ -431,9 +476,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityTerryState_Idle: {
|
case FP_EntityTerryState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.terry_walk_idle, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (we_are_clicked_entity) {
|
if (we_are_clicked_entity) {
|
||||||
@ -448,19 +492,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityTerryState_Attack: {
|
case FP_EntityTerryState_Attack: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
uint32_t asset_flip = {};
|
uint64_t duration_ms = render_data.sprite.anim->count * render_data.sprite.anim->ms_per_frame;
|
||||||
Dqn_String8 desired_action_name = {};
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
switch (entity->direction) {
|
|
||||||
case FP_GameDirection_Up: desired_action_name = g_anim_names.terry_attack_up; break;
|
|
||||||
case FP_GameDirection_Down: desired_action_name = g_anim_names.terry_attack_down; break;
|
|
||||||
case FP_GameDirection_Left: desired_action_name = g_anim_names.terry_attack_side; break;
|
|
||||||
case FP_GameDirection_Right: desired_action_name = g_anim_names.terry_attack_side; asset_flip |= TELY_AssetFlip_X; break;
|
|
||||||
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, desired_action_name, DQN_CAST(TELY_AssetFlip)asset_flip);
|
|
||||||
uint64_t duration_ms = sprite.anim->count * sprite.anim->ms_per_frame;
|
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action_has_finished) {
|
if (action_has_finished) {
|
||||||
@ -469,26 +502,16 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntityTerryState_Run: {
|
case FP_EntityTerryState_Run: {
|
||||||
Dqn_String8 desired_action_name = {};
|
if (entering_new_state || action->sprite.anim->label != render_data.anim_name) {
|
||||||
switch (entity->direction) {
|
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
||||||
case FP_GameDirection_Up: desired_action_name = g_anim_names.terry_walk_up; break;
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
case FP_GameDirection_Down: desired_action_name = g_anim_names.terry_walk_down; break;
|
|
||||||
case FP_GameDirection_Left: desired_action_name = g_anim_names.terry_walk_left; break;
|
|
||||||
case FP_GameDirection_Right: desired_action_name = g_anim_names.terry_walk_right; break;
|
|
||||||
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entering_new_state || action->sprite.anim->label != desired_action_name) {
|
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, desired_action_name, TELY_AssetFlip_No);
|
|
||||||
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (we_are_clicked_entity) {
|
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_EntityTransitionState(game, entity, FP_EntityTerryState_Attack);
|
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Attack);
|
||||||
} else if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_LeftShift) ||
|
} else if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_LeftControl) ||
|
||||||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_A)) {
|
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_A)) {
|
||||||
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Dash);
|
FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Dash);
|
||||||
}
|
}
|
||||||
@ -502,7 +525,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
case FP_EntityTerryState_Dash: {
|
case FP_EntityTerryState_Dash: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
uint64_t duration_ms = 250;
|
uint64_t duration_ms = 250;
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, entity->action.sprite);
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
*acceleration_meters_per_s *= 35.f;
|
*acceleration_meters_per_s *= 35.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,11 +588,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntitySmoochieState_Idle: {
|
case FP_EntitySmoochieState_Idle: {
|
||||||
|
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.smoochie_walk_down, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (we_are_clicked_entity) {
|
if (we_are_clicked_entity) {
|
||||||
@ -588,9 +609,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntitySmoochieState_Attack: {
|
case FP_EntitySmoochieState_Attack: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.smoochie_attack_down, TELY_AssetFlip_No);
|
uint64_t duration_ms = render_data.sprite.anim->count * render_data.sprite.anim->ms_per_frame;
|
||||||
uint64_t duration_ms = sprite.anim->count * sprite.anim->ms_per_frame;
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
// NOTE: Deal with this further down with the gameplay attack code.
|
// NOTE: Deal with this further down with the gameplay attack code.
|
||||||
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Smooch], 1.f);
|
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Smooch], 1.f);
|
||||||
}
|
}
|
||||||
@ -639,24 +660,18 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntitySmoochieState_HurtSide: {
|
case FP_EntitySmoochieState_HurtSide: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetFlip flip = entity->direction == FP_GameDirection_Right ? TELY_AssetFlip_X : TELY_AssetFlip_No;
|
uint64_t duration_ms = render_data.sprite.anim->count * render_data.sprite.anim->ms_per_frame;
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.smoochie_hurt_side, flip);
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
uint64_t duration_ms = sprite.anim->count * sprite.anim->ms_per_frame;
|
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action_has_finished)
|
if (action_has_finished)
|
||||||
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Idle);
|
FP_Game_EntityTransitionState(game, entity, FP_EntitySmoochieState_Idle);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntitySmoochieState_AttackHeart: {
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case FP_EntitySmoochieState_Death: {
|
case FP_EntitySmoochieState_Death: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.smoochie_death, TELY_AssetFlip_No);
|
uint64_t duration_ms = render_data.sprite.anim->count * render_data.sprite.anim->ms_per_frame;
|
||||||
uint64_t duration_ms = sprite.anim->count * sprite.anim->ms_per_frame;
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action_has_finished)
|
if (action_has_finished)
|
||||||
@ -665,17 +680,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
|
|
||||||
case FP_EntitySmoochieState_Run: {
|
case FP_EntitySmoochieState_Run: {
|
||||||
Dqn_String8 desired_action_name = {};
|
if (entering_new_state || action->sprite.anim->label != render_data.anim_name) {
|
||||||
switch (entity->direction) {
|
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, render_data.anim_name, render_data.flip);
|
||||||
case FP_GameDirection_Up: desired_action_name = g_anim_names.smoochie_walk_up; break;
|
|
||||||
case FP_GameDirection_Down: desired_action_name = g_anim_names.smoochie_walk_down; break;
|
|
||||||
case FP_GameDirection_Left: desired_action_name = g_anim_names.smoochie_walk_left; break;
|
|
||||||
case FP_GameDirection_Right: desired_action_name = g_anim_names.smoochie_walk_right; break;
|
|
||||||
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entering_new_state || action->sprite.anim->label != desired_action_name) {
|
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, desired_action_name, TELY_AssetFlip_No);
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -737,9 +743,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityClingerState_Idle: {
|
case FP_EntityClingerState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.clinger_walk_down, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (we_are_clicked_entity) {
|
if (we_are_clicked_entity) {
|
||||||
@ -757,21 +762,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntityClingerState_Attack: {
|
case FP_EntityClingerState_Attack: {
|
||||||
|
|
||||||
uint32_t asset_flip = {};
|
|
||||||
Dqn_String8 desired_action_name = {};
|
|
||||||
switch (entity->direction) {
|
|
||||||
case FP_GameDirection_Up: desired_action_name = g_anim_names.clinger_attack_up; break;
|
|
||||||
case FP_GameDirection_Down: desired_action_name = g_anim_names.clinger_attack_down; break;
|
|
||||||
case FP_GameDirection_Left: desired_action_name = g_anim_names.clinger_attack_side; asset_flip |= TELY_AssetFlip_X; break;
|
|
||||||
case FP_GameDirection_Right: desired_action_name = g_anim_names.clinger_attack_side; break;
|
|
||||||
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, desired_action_name, DQN_CAST(TELY_AssetFlip)asset_flip);
|
uint64_t duration_ms = render_data.sprite.anim->count * render_data.sprite.anim->ms_per_frame;
|
||||||
uint64_t duration_ms = sprite.anim->count * sprite.anim->ms_per_frame;
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action_has_finished)
|
if (action_has_finished)
|
||||||
@ -791,19 +784,9 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntityClingerState_Run: {
|
case FP_EntityClingerState_Run: {
|
||||||
Dqn_String8 desired_action_name = {};
|
if (entering_new_state || action->sprite.anim->label != render_data.anim_name) {
|
||||||
switch (entity->direction) {
|
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
||||||
case FP_GameDirection_Up: desired_action_name = g_anim_names.clinger_walk_up; break;
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
case FP_GameDirection_Down: desired_action_name = g_anim_names.clinger_walk_down; break;
|
|
||||||
case FP_GameDirection_Left: desired_action_name = g_anim_names.clinger_walk_down; break;
|
|
||||||
case FP_GameDirection_Right: desired_action_name = g_anim_names.clinger_walk_down; break;
|
|
||||||
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entering_new_state || action->sprite.anim->label != desired_action_name) {
|
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, desired_action_name, TELY_AssetFlip_No);
|
|
||||||
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (we_are_clicked_entity) {
|
if (we_are_clicked_entity) {
|
||||||
@ -862,9 +845,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityMerchantTerryState_Idle: {
|
case FP_EntityMerchantTerryState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.merchant_terry, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@ -880,9 +862,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityMerchantPhoneCompanyState_Idle: {
|
case FP_EntityMerchantPhoneCompanyState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.merchant_phone_company, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -897,9 +878,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityMerchantGymState_Idle: {
|
case FP_EntityMerchantGymState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.merchant_gym, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@ -915,9 +895,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityMerchantGraveyardState_Idle: {
|
case FP_EntityMerchantGraveyardState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.merchant_graveyard, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@ -933,17 +912,15 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityClubTerryState_Idle: {
|
case FP_EntityClubTerryState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.club_terry_dark, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntityClubTerryState_PartyTime: {
|
case FP_EntityClubTerryState_PartyTime: {
|
||||||
if (entering_new_state) {
|
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;
|
||||||
uint64_t duration_ms = 5000;
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action_has_finished) {
|
if (action_has_finished) {
|
||||||
@ -970,9 +947,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityMapState_Idle: {
|
case FP_EntityMapState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.map, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -988,9 +964,8 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
|
|
||||||
case FP_EntityHeartState_Idle: {
|
case FP_EntityHeartState_Idle: {
|
||||||
if (entering_new_state) {
|
if (entering_new_state) {
|
||||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.heart, TELY_AssetFlip_No);
|
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, render_data.sprite);
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -1088,15 +1063,11 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
case FP_EntityType_MerchantGraveyard: break;
|
case FP_EntityType_MerchantGraveyard: break;
|
||||||
case FP_EntityType_MerchantPhoneCompany: break;
|
case FP_EntityType_MerchantPhoneCompany: break;
|
||||||
case FP_EntityType_Heart: break;
|
case FP_EntityType_Heart: break;
|
||||||
|
case FP_EntityType_MerchantGym: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move_entity) {
|
if (move_entity) {
|
||||||
acceleration_meters_per_s = dir_vector * entity->base_acceleration_per_s.meters;
|
acceleration_meters_per_s = dir_vector * entity->base_acceleration_per_s.meters;
|
||||||
if (dir_vector.x)
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_Space))
|
if (TELY_Platform_InputScanCodeIsDown(input, TELY_PlatformInputScanCode_Space))
|
||||||
acceleration_meters_per_s *= 2.5f;
|
acceleration_meters_per_s *= 2.5f;
|
||||||
}
|
}
|
||||||
@ -1357,6 +1328,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (game->clicked_entity == entity->handle) {
|
if (game->clicked_entity == entity->handle) {
|
||||||
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F))
|
||||||
|
game->build_mode = !game->build_mode;
|
||||||
|
|
||||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F1)) {
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F1)) {
|
||||||
entity->sprite_height.meters += 1;
|
entity->sprite_height.meters += 1;
|
||||||
Dqn_Log_InfoF("Height: %.1f", entity->sprite_height.meters);
|
Dqn_Log_InfoF("Height: %.1f", entity->sprite_height.meters);
|
||||||
@ -1368,6 +1342,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
|
|
||||||
if (entity->flags & FP_GameEntityFlag_CameraTracking)
|
if (entity->flags & FP_GameEntityFlag_CameraTracking)
|
||||||
game->camera.world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle) - Dqn_V2_InitV2I(platform->core.window_size) * .5f;
|
game->camera.world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle) - Dqn_V2_InitV2I(platform->core.window_size) * .5f;
|
||||||
|
|
||||||
|
if (game->build_mode) {
|
||||||
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_E)) {
|
||||||
|
Dqn_Rect dest_rect = FP_Game_GetBuildingPlacementRectForEntity(game, entity->handle);
|
||||||
|
Dqn_V2 placement_pos = Dqn_Rect_Center(dest_rect);
|
||||||
|
FP_Entity_CreateClubTerry(game, placement_pos, "Club Terry");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Tick the state machine
|
// NOTE: Tick the state machine
|
||||||
@ -1451,7 +1433,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
waypoint->data.arrive = FP_GameWaypointArrive_WhenWithinEntitySize;
|
waypoint->data.arrive = FP_GameWaypointArrive_WhenWithinEntitySize;
|
||||||
waypoint->data.value = 1.5f;
|
waypoint->data.value = 1.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity->enemies_spawned_this_wave++;
|
entity->enemies_spawned_this_wave++;
|
||||||
|
|
||||||
// NOTE: If all enemies for the current wave have been spawned
|
// NOTE: If all enemies for the current wave have been spawned
|
||||||
@ -1741,6 +1722,27 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
|
|||||||
// NOTE: Render world position =============================================================
|
// NOTE: Render world position =============================================================
|
||||||
TELY_Render_CircleColourV4(renderer, world_pos, 4.f, TELY_RenderShapeMode_Fill, TELY_COLOUR_RED_TOMATO_V4);
|
TELY_Render_CircleColourV4(renderer, world_pos, 4.f, TELY_RenderShapeMode_Fill, TELY_COLOUR_RED_TOMATO_V4);
|
||||||
|
|
||||||
|
// NOTE: Render building blueprint =========================================================
|
||||||
|
if (game->clicked_entity == entity->handle && game->build_mode) {
|
||||||
|
|
||||||
|
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
|
||||||
|
Dqn_V2 label_p = Dqn_V2_InitNx2(platform->core.window_size.x * .5f, platform->core.window_size.y * .1f);
|
||||||
|
TELY_Render_Text(renderer, label_p, Dqn_V2_InitNx2(0.5f, 0.5f), DQN_STRING8("Build Mode"));
|
||||||
|
TELY_Render_PopTransform(renderer);
|
||||||
|
|
||||||
|
FP_EntityRenderData club_terry_render_data = FP_Entity_GetRenderData(game, FP_EntityType_ClubTerry, FP_EntityClubTerryState_Idle, entity->direction);
|
||||||
|
Dqn_Rect dest_rect = FP_Game_GetBuildingPlacementRectForEntity(game, entity->handle);
|
||||||
|
|
||||||
|
TELY_Render_RectColourV4(renderer, dest_rect, TELY_RenderShapeMode_Fill, TELY_Colour_V4Alpha(TELY_COLOUR_BLUE_CADET_V4, 0.5f));
|
||||||
|
TELY_Render_TextureColourV4(renderer,
|
||||||
|
club_terry_render_data.sheet->tex_handle,
|
||||||
|
club_terry_render_data.sheet_rect,
|
||||||
|
dest_rect,
|
||||||
|
Dqn_V2_Zero /*rotate origin*/,
|
||||||
|
0.f /*rotation*/,
|
||||||
|
TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Render hot/active entity ==========================================================
|
// NOTE: Render hot/active entity ==========================================================
|
||||||
if (game->clicked_entity == entity->handle) {
|
if (game->clicked_entity == entity->handle) {
|
||||||
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4);
|
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4);
|
||||||
@ -1847,10 +1849,9 @@ void TELY_DLL_FrameUpdate(void *user_data)
|
|||||||
FP_Render(game, platform, renderer);
|
FP_Render(game, platform, renderer);
|
||||||
|
|
||||||
// NOTE: UI ====================================================================================
|
// NOTE: UI ====================================================================================
|
||||||
|
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
|
||||||
|
DQN_DEFER { TELY_Render_PopTransform(renderer); };
|
||||||
{
|
{
|
||||||
TELY_Render_PushTransform(renderer, Dqn_M2x3_Identity());
|
|
||||||
DQN_DEFER { TELY_Render_PopTransform(renderer); };
|
|
||||||
|
|
||||||
// NOTE: Info bar ==========================================================================
|
// NOTE: Info bar ==========================================================================
|
||||||
{
|
{
|
||||||
TELY_RFuiResult info_bar = TELY_RFui_Row(rfui, DQN_STRING8("Info Bar"));
|
TELY_RFuiResult info_bar = TELY_RFui_Row(rfui, DQN_STRING8("Info Bar"));
|
||||||
|
@ -34,7 +34,6 @@ enum FP_EntitySmoochieState
|
|||||||
FP_EntitySmoochieState_Idle,
|
FP_EntitySmoochieState_Idle,
|
||||||
FP_EntitySmoochieState_Attack,
|
FP_EntitySmoochieState_Attack,
|
||||||
FP_EntitySmoochieState_HurtSide,
|
FP_EntitySmoochieState_HurtSide,
|
||||||
FP_EntitySmoochieState_AttackHeart,
|
|
||||||
FP_EntitySmoochieState_Death,
|
FP_EntitySmoochieState_Death,
|
||||||
FP_EntitySmoochieState_Run,
|
FP_EntitySmoochieState_Run,
|
||||||
};
|
};
|
||||||
@ -90,3 +89,14 @@ enum FP_EntityHeartState
|
|||||||
FP_EntityHeartState_Nil,
|
FP_EntityHeartState_Nil,
|
||||||
FP_EntityHeartState_Idle,
|
FP_EntityHeartState_Idle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FP_EntityRenderData
|
||||||
|
{
|
||||||
|
FP_Meters height;
|
||||||
|
TELY_AssetFlip flip;
|
||||||
|
Dqn_String8 anim_name;
|
||||||
|
TELY_AssetSpriteSheet *sheet;
|
||||||
|
Dqn_Rect sheet_rect;
|
||||||
|
Dqn_V2 render_size;
|
||||||
|
TELY_AssetAnimatedSprite sprite;
|
||||||
|
};
|
||||||
|
@ -3,6 +3,178 @@
|
|||||||
#include "feely_pona_unity.h"
|
#include "feely_pona_unity.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static Dqn_f32 FP_Entity_CalcSpriteScaleForDesiredHeight(FP_Game *game, FP_Meters height, Dqn_Rect sprite_rect)
|
||||||
|
{
|
||||||
|
Dqn_f32 sprite_in_meters = FP_Game_PixelsToMetersNx1(game, sprite_rect.size.y);
|
||||||
|
Dqn_f32 result = height.meters / sprite_in_meters;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, uint32_t raw_state, FP_GameDirection direction)
|
||||||
|
{
|
||||||
|
FP_EntityRenderData result = {};
|
||||||
|
switch (type) {
|
||||||
|
case FP_EntityType_Nil: {
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_Map: {
|
||||||
|
result.height.meters = 41.9f;
|
||||||
|
result.anim_name = g_anim_names.map;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_Terry: {
|
||||||
|
result.height.meters = 1.8f;
|
||||||
|
FP_EntityTerryState state = DQN_CAST(FP_EntityTerryState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityTerryState_Nil: break;
|
||||||
|
case FP_EntityTerryState_Idle: result.anim_name = g_anim_names.terry_walk_idle; break;
|
||||||
|
|
||||||
|
case FP_EntityTerryState_Attack: {
|
||||||
|
switch (direction) {
|
||||||
|
case FP_GameDirection_Up: result.anim_name = g_anim_names.terry_attack_up; break;
|
||||||
|
case FP_GameDirection_Down: result.anim_name = g_anim_names.terry_attack_down; break;
|
||||||
|
case FP_GameDirection_Left: result.anim_name = g_anim_names.terry_attack_side; break;
|
||||||
|
case FP_GameDirection_Right: result.anim_name = g_anim_names.terry_attack_side; result.flip = TELY_AssetFlip_X; break;
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityTerryState_Run: /*FALLTHRU*/
|
||||||
|
case FP_EntityTerryState_Dash: {
|
||||||
|
switch (direction) {
|
||||||
|
case FP_GameDirection_Up: result.anim_name = g_anim_names.terry_walk_up; break;
|
||||||
|
case FP_GameDirection_Down: result.anim_name = g_anim_names.terry_walk_down; break;
|
||||||
|
case FP_GameDirection_Left: result.anim_name = g_anim_names.terry_walk_left; break;
|
||||||
|
case FP_GameDirection_Right: result.anim_name = g_anim_names.terry_walk_right; break;
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_Smoochie: {
|
||||||
|
result.height.meters = 1.6f;
|
||||||
|
FP_EntitySmoochieState state = DQN_CAST(FP_EntitySmoochieState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntitySmoochieState_Nil: break;
|
||||||
|
case FP_EntitySmoochieState_Idle: result.anim_name = g_anim_names.smoochie_walk_down; break;
|
||||||
|
case FP_EntitySmoochieState_Attack: result.anim_name = g_anim_names.smoochie_attack_down; break;
|
||||||
|
case FP_EntitySmoochieState_HurtSide: result.anim_name = g_anim_names.smoochie_hurt_side; result.flip = direction == FP_GameDirection_Right ? TELY_AssetFlip_X : TELY_AssetFlip_No; break;
|
||||||
|
case FP_EntitySmoochieState_Death: result.anim_name = g_anim_names.smoochie_death; break;
|
||||||
|
case FP_EntitySmoochieState_Run: {
|
||||||
|
switch (direction) {
|
||||||
|
case FP_GameDirection_Up: result.anim_name = g_anim_names.smoochie_walk_up; break;
|
||||||
|
case FP_GameDirection_Down: result.anim_name = g_anim_names.smoochie_walk_down; break;
|
||||||
|
case FP_GameDirection_Left: result.anim_name = g_anim_names.smoochie_walk_left; break;
|
||||||
|
case FP_GameDirection_Right: result.anim_name = g_anim_names.smoochie_walk_right; break;
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_MerchantTerry: {
|
||||||
|
result.height.meters = 3.66f;
|
||||||
|
FP_EntityMerchantTerryState state = DQN_CAST(FP_EntityMerchantTerryState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityMerchantTerryState_Nil: break;
|
||||||
|
case FP_EntityMerchantTerryState_Idle: result.anim_name = g_anim_names.merchant_terry; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_MerchantGraveyard: {
|
||||||
|
result.height.meters = 3.66f;
|
||||||
|
FP_EntityMerchantGraveyardState state = DQN_CAST(FP_EntityMerchantGraveyardState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityMerchantGraveyardState_Nil: break;
|
||||||
|
case FP_EntityMerchantGraveyardState_Idle: result.anim_name = g_anim_names.merchant_graveyard; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_MerchantGym: {
|
||||||
|
result.height.meters = 3.66f;
|
||||||
|
result.anim_name = g_anim_names.merchant_gym;
|
||||||
|
FP_EntityMerchantGymState state = DQN_CAST(FP_EntityMerchantGymState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityMerchantGymState_Nil: break;
|
||||||
|
case FP_EntityMerchantGymState_Idle: result.anim_name = g_anim_names.merchant_gym; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_MerchantPhoneCompany: {
|
||||||
|
result.height.meters = 3.66f;
|
||||||
|
FP_EntityMerchantPhoneCompanyState state = DQN_CAST(FP_EntityMerchantPhoneCompanyState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityMerchantPhoneCompanyState_Nil: break;
|
||||||
|
case FP_EntityMerchantPhoneCompanyState_Idle: result.anim_name = g_anim_names.merchant_phone_company; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_ClubTerry: {
|
||||||
|
result.height.meters = 4.f;
|
||||||
|
FP_EntityClubTerryState state = DQN_CAST(FP_EntityClubTerryState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityClubTerryState_Nil: break;
|
||||||
|
case FP_EntityClubTerryState_Idle: result.anim_name = g_anim_names.club_terry_dark; break;
|
||||||
|
case FP_EntityClubTerryState_PartyTime: result.anim_name = g_anim_names.club_terry_alive; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_Clinger: {
|
||||||
|
result.height.meters = 1.6f;
|
||||||
|
FP_EntityClingerState state = DQN_CAST(FP_EntityClingerState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityClingerState_Nil: break;
|
||||||
|
case FP_EntityClingerState_Idle: result.anim_name = g_anim_names.clinger_walk_down; break;
|
||||||
|
|
||||||
|
case FP_EntityClingerState_Attack: {
|
||||||
|
switch (direction) {
|
||||||
|
case FP_GameDirection_Up: result.anim_name = g_anim_names.clinger_attack_up; break;
|
||||||
|
case FP_GameDirection_Down: result.anim_name = g_anim_names.clinger_attack_down; break;
|
||||||
|
case FP_GameDirection_Left: result.anim_name = g_anim_names.clinger_attack_side; result.flip = TELY_AssetFlip_X; break;
|
||||||
|
case FP_GameDirection_Right: result.anim_name = g_anim_names.clinger_attack_side; break;
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityClingerState_Death: result.anim_name = g_anim_names.clinger_death; break;
|
||||||
|
|
||||||
|
case FP_EntityClingerState_Run: {
|
||||||
|
switch (direction) {
|
||||||
|
case FP_GameDirection_Up: result.anim_name = g_anim_names.clinger_walk_up; break;
|
||||||
|
case FP_GameDirection_Down: result.anim_name = g_anim_names.clinger_walk_down; break;
|
||||||
|
case FP_GameDirection_Left: result.anim_name = g_anim_names.clinger_walk_down; break;
|
||||||
|
case FP_GameDirection_Right: result.anim_name = g_anim_names.clinger_walk_down; break;
|
||||||
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_Heart: {
|
||||||
|
result.height.meters = 4.f;
|
||||||
|
FP_EntityHeartState state = DQN_CAST(FP_EntityHeartState)raw_state;
|
||||||
|
switch (state) {
|
||||||
|
case FP_EntityHeartState_Nil: break;
|
||||||
|
case FP_EntityHeartState_Idle: result.anim_name = g_anim_names.heart; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sheet = &game->atlas_sprite_sheet;
|
||||||
|
TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name);
|
||||||
|
if (sprite_anim) {
|
||||||
|
result.sheet_rect = result.sheet->rects.data[sprite_anim->index];
|
||||||
|
Dqn_f32 size_scale = FP_Entity_CalcSpriteScaleForDesiredHeight(game, result.height, result.sheet_rect);
|
||||||
|
result.render_size = result.sheet_rect.size * size_scale;
|
||||||
|
result.sprite = TELY_Asset_MakeAnimatedSprite(result.sheet, result.anim_name, result.flip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void FP_Entity_AddDebugEditorFlags(FP_Game *game, FP_GameEntityHandle handle)
|
static void FP_Entity_AddDebugEditorFlags(FP_Game *game, FP_GameEntityHandle handle)
|
||||||
{
|
{
|
||||||
FP_GameEntity *entity = FP_Game_GetEntity(game, handle);
|
FP_GameEntity *entity = FP_Game_GetEntity(game, handle);
|
||||||
@ -14,13 +186,6 @@ static void FP_Entity_AddDebugEditorFlags(FP_Game *game, FP_GameEntityHandle han
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dqn_f32 FP_Entity_CalcSpriteScaleForDesiredHeight(FP_Game *game, FP_Meters height, Dqn_Rect sprite_rect)
|
|
||||||
{
|
|
||||||
Dqn_f32 sprite_in_meters = FP_Game_PixelsToMetersNx1(game, sprite_rect.size.y);
|
|
||||||
Dqn_f32 result = height.meters / sprite_in_meters;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FP_GameEntityHandle FP_Entity_CreateWaypointF(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
static FP_GameEntityHandle FP_Entity_CreateWaypointF(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -55,7 +220,7 @@ static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQ
|
|||||||
entity->is_dying = false;
|
entity->is_dying = false;
|
||||||
entity->base_acceleration_per_s.meters = 8.f;
|
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 = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
entity->attack_cooldown_ms = 1000;
|
entity->attack_cooldown_ms = 1000;
|
||||||
|
|
||||||
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);
|
||||||
@ -78,7 +243,7 @@ static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, D
|
|||||||
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 = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
entity->attack_cooldown_ms = 1000;
|
entity->attack_cooldown_ms = 1000;
|
||||||
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);
|
||||||
@ -144,7 +309,7 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
|
|||||||
entity->type = FP_EntityType_Terry;
|
entity->type = FP_EntityType_Terry;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->base_acceleration_per_s.meters = 16.f;
|
entity->base_acceleration_per_s.meters = 16.f;
|
||||||
entity->sprite_height.meters = 1.8f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
entity->attack_cooldown_ms = 500;
|
entity->attack_cooldown_ms = 500;
|
||||||
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);
|
||||||
@ -164,7 +329,7 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantTerry(FP_Game *game, Dqn_V2 p
|
|||||||
|
|
||||||
entity->type = FP_EntityType_MerchantTerry;
|
entity->type = FP_EntityType_MerchantTerry;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 3.66f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
@ -188,7 +353,7 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantGraveyard(FP_Game *game, Dqn_
|
|||||||
|
|
||||||
entity->type = FP_EntityType_MerchantGraveyard;
|
entity->type = FP_EntityType_MerchantGraveyard;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 3.66f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
@ -211,11 +376,11 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantGym(FP_Game *game, Dqn_V2 pos
|
|||||||
FP_GameEntityHandle result = entity->handle;
|
FP_GameEntityHandle result = entity->handle;
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
entity->type = FP_EntityType_MerchantGym;
|
entity->type = FP_EntityType_MerchantGym;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 3.66f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.merchant_gym);
|
TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(&game->atlas_sprite_sheet, g_anim_names.merchant_gym);
|
||||||
Dqn_Rect sprite_rect = game->atlas_sprite_sheet.rects.data[sprite_anim->index];
|
Dqn_Rect sprite_rect = game->atlas_sprite_sheet.rects.data[sprite_anim->index];
|
||||||
@ -237,7 +402,7 @@ static FP_GameEntityHandle FP_Entity_CreateMerchantPhoneCompany(FP_Game *game, D
|
|||||||
|
|
||||||
entity->type = FP_EntityType_MerchantPhoneCompany;
|
entity->type = FP_EntityType_MerchantPhoneCompany;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 3.66f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
@ -261,7 +426,7 @@ static FP_GameEntityHandle FP_Entity_CreateClubTerry(FP_Game *game, Dqn_V2 pos,
|
|||||||
|
|
||||||
entity->type = FP_EntityType_ClubTerry;
|
entity->type = FP_EntityType_ClubTerry;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 4.f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
@ -285,7 +450,7 @@ static FP_GameEntityHandle FP_Entity_CreateHeart(FP_Game *game, Dqn_V2 pos, DQN_
|
|||||||
|
|
||||||
entity->type = FP_EntityType_Heart;
|
entity->type = FP_EntityType_Heart;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 4.f;
|
entity->sprite_height = FP_Entity_GetRenderData(game, entity->type, 0 /*state*/, FP_GameDirection_Down).height;
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
|
@ -254,6 +254,8 @@ struct FP_Game
|
|||||||
Dqn_f32 meters_to_pixels;
|
Dqn_f32 meters_to_pixels;
|
||||||
uint64_t clock_ms;
|
uint64_t clock_ms;
|
||||||
Dqn_PCG32 rng;
|
Dqn_PCG32 rng;
|
||||||
|
|
||||||
|
bool build_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FP_GameAStarNode
|
struct FP_GameAStarNode
|
||||||
|
Loading…
Reference in New Issue
Block a user