fp: Integrate clinger as a spawnable mob
This commit is contained in:
parent
ffb2ec3ea3
commit
d85fbe95fa
BIN
Data/Textures/clinger_resized_25%.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%.txt
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%.txt
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_down_1.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_down_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_down_2.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_down_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_down_3.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_down_3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_side_1.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_side_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_side_2.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_side_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_side_3.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_side_3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_up_1.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_up_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_up_2.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_up_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_attack_up_3.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_attack_up_3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_death_1.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_death_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_death_2.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_death_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_death_3.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_death_3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_death_4.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_death_4.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_death_5.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_death_5.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_walk_down_1.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_walk_down_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_walk_down_2.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_walk_down_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_walk_up_1.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_walk_up_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/clinger_resized_25%/clinger_walk_up_2.png
(Stored with Git LFS)
Normal file
BIN
Data/Textures/clinger_resized_25%/clinger_walk_up_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Data/Textures/sprite_spec.txt
(Stored with Git LFS)
BIN
Data/Textures/sprite_spec.txt
(Stored with Git LFS)
Binary file not shown.
@ -13,3 +13,4 @@ if not exist "%sprite_packer%" (
|
||||
%sprite_packer% 4096x4096 %script_dir%\Data\Textures\sprite_spec.txt %script_dir%\Data\Textures\terry_resized_25%% || exit /b 1
|
||||
%sprite_packer% 4096x2048 %script_dir%\Data\Textures\sprite_spec.txt %script_dir%\Data\Textures\terry_merchant_resized_25%% || exit /b 1
|
||||
%sprite_packer% 4096x2048 %script_dir%\Data\Textures\sprite_spec.txt %script_dir%\Data\Textures\smoochie_resized_25%% || exit /b 1
|
||||
%sprite_packer% 4096x2048 %script_dir%\Data\Textures\sprite_spec.txt %script_dir%\Data\Textures\clinger_resized_25%% || exit /b 1
|
||||
|
132
feely_pona.cpp
132
feely_pona.cpp
@ -15,6 +15,7 @@ struct FP_GlobalAnimations
|
||||
Dqn_String8 terry_attack_side = DQN_STRING8("terry_attack_side");
|
||||
Dqn_String8 terry_attack_down = DQN_STRING8("terry_attack_down");
|
||||
Dqn_String8 terry_merchant = DQN_STRING8("terry_merchant");
|
||||
|
||||
Dqn_String8 smoochie_walk_up = DQN_STRING8("smoochie_walk_up");
|
||||
Dqn_String8 smoochie_walk_down = DQN_STRING8("smoochie_walk_down");
|
||||
Dqn_String8 smoochie_walk_left = DQN_STRING8("smoochie_walk_left");
|
||||
@ -23,6 +24,13 @@ struct FP_GlobalAnimations
|
||||
Dqn_String8 smoochie_hurt_side = DQN_STRING8("smoochie_hurt_side");
|
||||
Dqn_String8 smoochie_attack_heart = DQN_STRING8("smoochie_attack_heart");
|
||||
Dqn_String8 smoochie_death = DQN_STRING8("smoochie_death");
|
||||
|
||||
Dqn_String8 clinger_attack_down = DQN_STRING8("clinger_attack_down");
|
||||
Dqn_String8 clinger_attack_side = DQN_STRING8("clinger_attack_side");
|
||||
Dqn_String8 clinger_attack_up = DQN_STRING8("clinger_attack_up");
|
||||
Dqn_String8 clinger_death = DQN_STRING8("clinger_death");
|
||||
Dqn_String8 clinger_walk_up = DQN_STRING8("clinger_walk_up");
|
||||
Dqn_String8 clinger_walk_down = DQN_STRING8("clinger_walk_down");
|
||||
}
|
||||
g_anim_names;
|
||||
|
||||
@ -176,6 +184,7 @@ void TELY_DLL_Init(void *user_data)
|
||||
game->terry_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("terry_resized_25%"));
|
||||
game->terry_merchant_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("terry_merchant_resized_25%"));
|
||||
game->smoochie_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("smoochie_resized_25%"));
|
||||
game->clinger_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("clinger_resized_25%"));
|
||||
}
|
||||
|
||||
game->entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
|
||||
@ -589,6 +598,116 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_PlatformInput *input, FP_Ga
|
||||
}
|
||||
} break;
|
||||
|
||||
case FP_EntityType_Clinger: {
|
||||
FP_EntityClingerState *state = DQN_CAST(FP_EntityClingerState *)&action->state;
|
||||
TELY_AssetSpriteSheet *sheet = &game->clinger_sprite_sheet;
|
||||
|
||||
switch (*state) {
|
||||
case FP_EntityClingerState_Nil: {
|
||||
action->next_state = FP_EntityClingerState_Idle;
|
||||
} break;
|
||||
|
||||
case FP_EntityClingerState_Idle: {
|
||||
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;
|
||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
||||
}
|
||||
|
||||
if (we_are_clicked_entity) {
|
||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
|
||||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
|
||||
action->next_state = FP_EntityClingerState_Attack;
|
||||
} else if (dir_vector.x || dir_vector.y) {
|
||||
action->next_state = FP_EntityClingerState_Run;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity_has_velocity) {
|
||||
action->next_state = FP_EntityClingerState_Run;
|
||||
}
|
||||
} break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (entering_new_state) {
|
||||
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)
|
||||
action->next_state = FP_EntityClingerState_Idle;
|
||||
} break;
|
||||
|
||||
case FP_EntityClingerState_Death: {
|
||||
// TODO(doyle): Implement
|
||||
} break;
|
||||
|
||||
case FP_EntityClingerState_Run: {
|
||||
Dqn_String8 desired_action_name = {};
|
||||
switch (entity->direction) {
|
||||
case FP_GameDirection_Up: desired_action_name = g_anim_names.clinger_walk_up; break;
|
||||
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;
|
||||
}
|
||||
|
||||
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 (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J) ||
|
||||
TELY_Platform_InputGamepadButtonCodeIsPressed(input, 0, TELY_PlatformInputGamepadButtonCode_X)) {
|
||||
action->next_state = FP_EntityClingerState_Attack;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entity_has_velocity) {
|
||||
action->next_state = FP_EntityClingerState_Idle;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (*state == FP_EntityClingerState_Attack) { // NOTE: Position the attack box
|
||||
entity->attack_box_size = entity->local_hit_box_size;
|
||||
switch (entity->direction) {
|
||||
case FP_GameDirection_Left: {
|
||||
entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x - entity->attack_box_size.w,
|
||||
entity->local_hit_box_offset.y);
|
||||
} break;
|
||||
|
||||
case FP_GameDirection_Right: {
|
||||
entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x + entity->attack_box_size.w,
|
||||
entity->local_hit_box_offset.y);
|
||||
} break;
|
||||
|
||||
case FP_GameDirection_Up: {
|
||||
entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x,
|
||||
entity->local_hit_box_offset.y - entity->attack_box_size.h);
|
||||
} break;
|
||||
|
||||
case FP_GameDirection_Down: {
|
||||
entity->attack_box_offset = Dqn_V2_InitNx2(entity->local_hit_box_offset.x,
|
||||
entity->local_hit_box_offset.y + entity->attack_box_size.h);
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
entity->attack_box_size = {};
|
||||
}
|
||||
} break;
|
||||
|
||||
case FP_EntityType_Merchant: {
|
||||
FP_EntityTerryMerchantState *state = DQN_CAST(FP_EntityTerryMerchantState *)&action->state;
|
||||
TELY_AssetSpriteSheet *sheet = &game->terry_merchant_sprite_sheet;
|
||||
@ -776,7 +895,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
// from the entity's current state
|
||||
entity->action.next_state = FP_EntitySmoochieState_AttackDown;
|
||||
} break;
|
||||
|
||||
case FP_EntityType_Clinger: {
|
||||
entity->action.next_state = FP_EntityClingerState_Attack;
|
||||
} break;
|
||||
}
|
||||
|
||||
// NOTE: Aggro makes the entity attack Terry, we will
|
||||
// exit here preserving the waypoint in the entity.
|
||||
break;
|
||||
} else {
|
||||
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->chunk_pool);
|
||||
@ -952,7 +1078,11 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
|
||||
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||
FP_SentinelListLink<FP_GameEntityHandle> *link = FP_SentinelList_Make(&entity->spawn_list, game->chunk_pool);
|
||||
link->data = FP_Entity_CreateSmoochie(game, entity_world_pos, "Smoochie");
|
||||
|
||||
if (Dqn_PCG32_NextF32(&game->rng) >= 0.5f)
|
||||
link->data = FP_Entity_CreateClinger(game, entity_world_pos, "Clinger");
|
||||
else
|
||||
link->data = FP_Entity_CreateSmoochie(game, entity_world_pos, "Smoochie");
|
||||
|
||||
// NOTE: Setup the mob with waypoints
|
||||
FP_GameEntity *mob = FP_Game_GetEntity(game, link->data);
|
||||
|
@ -35,6 +35,25 @@ static FP_GameEntityHandle FP_Entity_CreateWaypointF(FP_Game *game, Dqn_V2 pos,
|
||||
return result;
|
||||
}
|
||||
|
||||
static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
FP_GameEntity *entity = FP_Game_MakeEntityPointerFV(game, fmt, args);
|
||||
FP_GameEntityHandle result = entity->handle;
|
||||
va_end(args);
|
||||
|
||||
entity->type = FP_EntityType_Clinger;
|
||||
entity->hp = 3;
|
||||
entity->local_pos = pos;
|
||||
entity->sprite_height.meters = 1.6f;
|
||||
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, 1.7f);
|
||||
FP_Entity_AddDebugEditorFlags(game, entity->handle);
|
||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||
entity->flags |= FP_GameEntityFlag_Attackable;
|
||||
return result;
|
||||
}
|
||||
|
||||
static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
@ -9,6 +9,7 @@ enum FP_EntityType
|
||||
FP_EntityType_Terry,
|
||||
FP_EntityType_Smoochie,
|
||||
FP_EntityType_Merchant,
|
||||
FP_EntityType_Clinger,
|
||||
};
|
||||
|
||||
enum FP_EntityTerryState
|
||||
@ -32,6 +33,15 @@ enum FP_EntitySmoochieState
|
||||
FP_EntitySmoochieState_Run,
|
||||
};
|
||||
|
||||
enum FP_EntityClingerState
|
||||
{
|
||||
FP_EntityClingerState_Nil,
|
||||
FP_EntityClingerState_Idle,
|
||||
FP_EntityClingerState_Attack,
|
||||
FP_EntityClingerState_Death,
|
||||
FP_EntityClingerState_Run,
|
||||
};
|
||||
|
||||
enum FP_EntityTerryMerchantState
|
||||
{
|
||||
FP_EntityTerryMerchantState_Nil,
|
||||
|
@ -192,6 +192,7 @@ struct FP_Game
|
||||
TELY_AssetSpriteSheet terry_sprite_sheet;
|
||||
TELY_AssetSpriteSheet smoochie_sprite_sheet;
|
||||
TELY_AssetSpriteSheet terry_merchant_sprite_sheet;
|
||||
TELY_AssetSpriteSheet clinger_sprite_sheet;
|
||||
|
||||
FP_GameEntity *root_entity;
|
||||
FP_GameEntity *entity_free_list;
|
||||
|
Loading…
Reference in New Issue
Block a user