fp: Vary the spawn and waypoints

This commit is contained in:
doyle 2023-10-08 19:48:17 +11:00
parent 179a683e25
commit ab61a482c7
2 changed files with 65 additions and 42 deletions

View File

@ -1977,45 +1977,61 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
link = FP_SentinelList_Erase(&entity->spawn_list, link, game->play.chunk_pool);
}
if (game->play.enemies_spawned_this_wave < game->play.enemies_per_wave && entity->spawn_list.size < entity->spawn_cap) { // NOTE: Spawn new entities
if (entity->action.state != FP_EntityMobSpawnerState_Shutdown && input->timer_s >= entity->next_spawn_timestamp_s) {
uint16_t hp_adjustment = DQN_CAST(uint16_t)game->play.current_wave;
entity->next_spawn_timestamp_s = DQN_CAST(uint64_t)(input->timer_s + 5.f);
if (entity->action.state != FP_EntityMobSpawnerState_Shutdown &&
game->play.enemies_spawned_this_wave < game->play.enemies_per_wave && entity->spawn_list.size < entity->spawn_cap) { // NOTE: Spawn new entities
if (input->timer_s >= entity->next_spawn_timestamp_s) {
Dqn_usize spawn_count = DQN_MIN(game->play.current_wave + 1, 8);
for (Dqn_usize spawn_index = 0; spawn_index < spawn_count; spawn_index++) {
uint16_t hp_adjustment = DQN_CAST(uint16_t)game->play.current_wave;
entity->next_spawn_timestamp_s = DQN_CAST(uint64_t)(input->timer_s + 5.f);
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
FP_SentinelListLink<FP_GameEntityHandle> *link = FP_SentinelList_Make(&entity->spawn_list, game->play.chunk_pool);
FP_SentinelListLink<FP_GameEntityHandle> *link = FP_SentinelList_Make(&entity->spawn_list, game->play.chunk_pool);
Dqn_f32 mob_choice = Dqn_PCG32_NextF32(&game->play.rng);
if (mob_choice <= 0.33f)
link->data = FP_Entity_CreateClinger(game, entity_world_pos, "Clinger");
else if (mob_choice <= 0.66f)
link->data = FP_Entity_CreateSmoochie(game, entity_world_pos, "Smoochie");
else
link->data = FP_Entity_CreateCatfish(game, entity_world_pos, "Catfish");
Dqn_f32 one_meter = FP_Game_MetersToPixelsNx1(game->play, 1.f);
Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
Dqn_Rect entity_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
// NOTE: Setup the mob with waypoints
FP_GameEntity *mob = FP_Game_GetEntity(game, link->data);
mob->waypoints = FP_SentinelList_Init<FP_GameWaypoint>(game->play.chunk_pool);
mob->flags |= FP_GameEntityFlag_Aggros;
mob->flags |= FP_GameEntityFlag_RespondsToBuildings;
mob->hp_cap += hp_adjustment;
mob->hp = mob->hp_cap;
Dqn_f32 step_y = (entity_hit_box.size.h / spawn_count) * 1.5f;
Dqn_V2 mob_world_pos = Dqn_V2_InitNx2(entity_world_pos.x,
entity_hit_box.pos.y + (Dqn_PCG32_NextF32(&game->play.rng) * step_y) + (step_y * spawn_index));
Dqn_f32 mob_choice = Dqn_PCG32_NextF32(&game->play.rng);
if (mob_choice <= 0.33f)
link->data = FP_Entity_CreateClinger(game, mob_world_pos, "Clinger");
else if (mob_choice <= 0.66f)
link->data = FP_Entity_CreateSmoochie(game, mob_world_pos, "Smoochie");
else
link->data = FP_Entity_CreateCatfish(game, mob_world_pos, "Catfish");
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0)
continue;
// NOTE: Setup the mob with waypoints
FP_GameEntity *mob = FP_Game_GetEntity(game, link->data);
mob->waypoints = FP_SentinelList_Init<FP_GameWaypoint>(game->play.chunk_pool);
mob->flags |= FP_GameEntityFlag_Aggros;
mob->flags |= FP_GameEntityFlag_RespondsToBuildings;
mob->hp_cap += hp_adjustment;
mob->hp = mob->hp_cap;
// NOTE: Add the waypoint
FP_SentinelListLink<FP_GameWaypoint> *waypoint = FP_SentinelList_Make(&mob->waypoints, game->play.chunk_pool);
waypoint->data.entity = waypoint_entity->handle;
waypoint->data.arrive = FP_GameWaypointArrive_WhenWithinEntitySize;
waypoint->data.value = 1.5f;
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0)
continue;
// NOTE: Add the waypoint
FP_SentinelListLink<FP_GameWaypoint> *waypoint = FP_SentinelList_Make(&mob->waypoints, game->play.chunk_pool);
waypoint->data.entity = waypoint_entity->handle;
waypoint->data.arrive = FP_GameWaypointArrive_WhenWithinEntitySize;
waypoint->data.value = 1.5f;
uint32_t min_vary = DQN_CAST(uint32_t)(one_meter * .5f);
uint32_t max_vary = DQN_CAST(uint32_t)(one_meter * 2.f);
waypoint->data.offset += Dqn_V2_InitNx2(DQN_CAST(Dqn_f32)Dqn_PCG32_Range(&game->play.rng, min_vary, max_vary),
DQN_CAST(Dqn_f32)Dqn_PCG32_Range(&game->play.rng, min_vary, max_vary));
}
game->play.enemies_spawned_this_wave++;
if (game->play.enemies_spawned_this_wave >= game->play.enemies_per_wave)
game->play.wave_cooldown_timestamp_ms = game->play.clock_ms + 30'000;
}
game->play.enemies_spawned_this_wave++;
if (game->play.enemies_spawned_this_wave >= game->play.enemies_per_wave)
game->play.wave_cooldown_timestamp_ms = game->play.clock_ms + 30'000;
}
}
}
@ -2362,6 +2378,14 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, TELY_COLOUR_BLUE_CADET_V4);
}
// NOTE: Draw the waypoints that the entity is moving along
Dqn_V2 start = world_pos;
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr; FP_SentinelList_Iterate(&entity->waypoints, &link); ) {
Dqn_V2 end = FP_Game_CalcWaypointWorldPos(game, entity->handle, &link->data);
TELY_Render_LineColourV4(renderer, start, end, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4, 2.f);
start = end;
}
if (entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint)
TELY_Render_CircleColourV4(renderer, world_pos, 16.f /*radius*/, TELY_RenderShapeMode_Line, TELY_COLOUR_BLUE_CADET_V4);
@ -2392,13 +2416,6 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
if (game->play.clicked_entity == entity->handle) {
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4);
// NOTE: Draw the waypoints that the entity is moving along
Dqn_V2 start = world_pos;
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr; FP_SentinelList_Iterate(&entity->waypoints, &link); ) {
Dqn_V2 end = FP_Game_CalcWaypointWorldPos(game, entity->handle, &link->data);
TELY_Render_LineColourV4(renderer, start, end, TELY_COLOUR_WHITE_PALE_GOLDENROD_V4, 2.f);
start = end;
}
} else if (game->play.hot_entity == entity->handle || (entity->flags & FP_GameEntityFlag_DrawHitBox)) {
Dqn_V4 hot_colour = game->play.hot_entity == entity->handle ? TELY_COLOUR_RED_TOMATO_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_YELLOW_SANDY_V4, .5f);
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, hot_colour);
@ -3231,16 +3248,21 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F5)) {
if (!FP_Game_IsNilEntity(player))
player->hp_cap += FP_DEFAULT_DAMAGE;
player->hp = player->hp_cap;
}
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F6)) {
if (!FP_Game_IsNilEntity(player))
if (!FP_Game_IsNilEntity(player)) {
player->stamina_cap += DQN_CAST(uint16_t)(FP_TERRY_DASH_STAMINA_COST * .5f);
player->stamina = player->stamina_cap;
}
}
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F7)) {
if (!FP_Game_IsNilEntity(player))
if (!FP_Game_IsNilEntity(player)) {
player->terry_mobile_data_plan_cap += DQN_KILOBYTES(1);
player->terry_mobile_data_plan = player->terry_mobile_data_plan_cap;
}
}
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F8))

View File

@ -757,10 +757,11 @@ static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameEntityHandle sr
} break;
case FP_GameWaypointType_Offset: {
result = FP_Game_CalcEntityWorldPos(game, waypoint_entity->handle) + waypoint->offset;
result = FP_Game_CalcEntityWorldPos(game, waypoint_entity->handle);
} break;
}
result += waypoint->offset;
return result;
}