From 84766a7d49d3c1e233e13191c86d4ada2bbe2ddc Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Fri, 20 Apr 2018 14:18:16 +0200 Subject: Refactor and improve the hivemind + better AI debugging. --- src/common.hpp | 1 + src/game/assets.cpp | 6 +++--- src/game/effects.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/game/game.hpp | 26 +++++++++++++++++++------- src/game/unit_nest.cpp | 6 +++--- src/game/unit_soldier.cpp | 2 ++ src/game/unit_spider.cpp | 8 ++++---- src/game/units.cpp | 26 +++++++++++++++++++------- 8 files changed, 89 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/common.hpp b/src/common.hpp index 620580e..2e89142 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -321,6 +321,7 @@ namespace game { void resume(void); void explosion(v2f_t x); + void hivemind_alert(v2f_t x, float r, bool do_move, v2f_t move_to); // These are called by the interface. void select(rectf_t rect, int type); diff --git a/src/game/assets.cpp b/src/game/assets.cpp index d7ba653..68d94dd 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -108,9 +108,9 @@ void load(void) move_marker.load("assets/units/move_marker_", 8); aim_marker.load("assets/units/aim_marker_", 5); - world::register_tile(TILE_DIRT, 0); + world::register_tile(TILE_DIRT, CF_SURFACE); render::register_tile(TILE_DIRT, "assets/tiles/dirt.png", NULL, 0.0f, render::LAYER_FLAT); - world::register_tile(TILE_DIRT_RED, 0); + world::register_tile(TILE_DIRT_RED, CF_SURFACE); render::register_tile(TILE_DIRT_RED, "assets/tiles/dirt_red.png", NULL, 0.0f, render::LAYER_FLAT); world::register_tile(TILE_STONE, CF_SOLID); render::register_tile(TILE_STONE, "assets/tiles/stone.png", "assets/tiles/stone_side.png", 1.0f, render::LAYER_NORMAL); @@ -118,7 +118,7 @@ void load(void) render::register_tile(TILE_STONE_RED, "assets/tiles/stone_red.png", "assets/tiles/stone_red_side.png", 1.4f, render::LAYER_NORMAL); world::register_tile(TILE_WATER, CF_WATER); render::register_tile(TILE_WATER, "assets/tiles/water.png", NULL, 0.0f, render::LAYER_FLAT); - world::register_tile(TILE_GRAVEL, 0); + world::register_tile(TILE_GRAVEL, CF_SURFACE); render::register_tile(TILE_GRAVEL, "assets/tiles/gravel.png", NULL, 0.0f, render::LAYER_FLAT); ambients[AMBIENT_NEXUS].load("assets/ambience/nexus.ogg"); diff --git a/src/game/effects.cpp b/src/game/effects.cpp index daa2770..b69647c 100644 --- a/src/game/effects.cpp +++ b/src/game/effects.cpp @@ -174,6 +174,8 @@ fx_explosion_t::fx_explosion_t(state_t *game_, v2f_t x_) : effect_t(game_) flash = new fx_flash_t(game, x, 5.0f, sf::Color(255, 255, 170, 255)); flash->place(&game->world); + + game->hivemind_alert(x, 20.0f, false, v2f_t(0, 0)); } void fx_explosion_t::render_to(render::state_t *render) @@ -202,6 +204,8 @@ fx_bullet_miss_t::fx_bullet_miss_t(state_t *game_, v2f_t x_, bool water_) : effe assets::fx.water_splash_sound.play_3d(x); else assets::fx.ricochet_sound.play_3d(x); + + game->hivemind_alert(x, 6.0f, false, v2f_t(0, 0)); } void fx_bullet_miss_t::render_to(render::state_t *render) @@ -210,4 +214,38 @@ void fx_bullet_miss_t::render_to(render::state_t *render) render->render(phase, (water ? &assets::fx.water_splash : &assets::fx.ricochet), render_bounds, sf::Color::White); } +fx_debug_hivemind_t::fx_debug_hivemind_t(state_t *game_, v2f_t x_, float r_, bool do_move_, v2f_t move_to_) : effect_t(game_) +{ + ttl = game->now + 1.0; + + x = x_; + r = r_; + do_move = do_move_; + move_to = move_to_; + + render_bounds[0] = x - v2f_t(r, r); + render_bounds[1] = x + v2f_t(r, r); + render_bounds = render_bounds.norm(); + cmodel.bounds = render_bounds; + cmodel.cflags = 0; + + ignore_waking = true; + wake(); +} + +void fx_debug_hivemind_t::render_to(render::state_t *render) +{ + static const sf::Color color(0, 255, 0, 50); + + if (debug_AI) { + render->render_circle(x, r, color); + + if (do_move) { + render->render_line(x, move_to, sf::Color::Red); + render->render_circle(x, 0.1f, sf::Color::Red); + } + } +} + + } // namespace game diff --git a/src/game/game.hpp b/src/game/game.hpp index 8d13b17..27fc69b 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -36,12 +36,13 @@ namespace game { }; enum { - CF_BACKGROUND = 1, - CF_SOLID = 2, - CF_BODY = 4, - CF_BODY_SMALL = 8, - CF_WATER = 16, - CF_DECOS = 32 + CF_SURFACE = 1, + CF_BACKGROUND = 2, + CF_SOLID = 4, + CF_BODY = 8, + CF_BODY_SMALL = 16, + CF_WATER = 32, + CF_DECOS = 64 }; enum { @@ -169,7 +170,6 @@ namespace game { class fx_aim_marker_t; unit_t *find_target(world::world_t *world, v2f_t x, float r, bool friendly); - void hivemind_attack(unit_t *source, bool have_target, v2f_t target); class unit_t : public entity_t { protected: @@ -403,6 +403,18 @@ namespace game { void render_to(render::state_t *render); }; + class fx_debug_hivemind_t : public effect_t { + v2f_t x, move_to; + float r; + bool do_move; + + public: + fx_debug_hivemind_t(game::state_t *game_, v2f_t x_, float r_, bool do_move_, v2f_t move_to_); + ~fx_debug_hivemind_t(void) {}; + + void render_to(render::state_t *render); + }; + typedef enum { DECO_STONE, DECO_STONE_CRACKED, diff --git a/src/game/unit_nest.cpp b/src/game/unit_nest.cpp index 89846c2..a52574a 100644 --- a/src/game/unit_nest.cpp +++ b/src/game/unit_nest.cpp @@ -82,16 +82,16 @@ void unit_nest_t::on_spawn(void) void unit_nest_t::on_damage(unit_t *attacker) { if (attacker) - hivemind_attack(this, true, attacker->x); + game->hivemind_alert(x, 12.0f, true, attacker->x); else - hivemind_attack(this, false, v2f_t(0, 0)); + game->hivemind_alert(x, 12.0f, false, v2f_t(0, 0)); assets::nest.pain.play_3d(x); } void unit_nest_t::on_death(void) { - hivemind_attack(this, false, v2f_t(0, 0)); + game->hivemind_alert(x, 16.0f, false, v2f_t(0, 0)); render_layer = render::LAYER_FLAT; cmodel.cflags = CF_BACKGROUND; diff --git a/src/game/unit_soldier.cpp b/src/game/unit_soldier.cpp index 2131493..a10e014 100644 --- a/src/game/unit_soldier.cpp +++ b/src/game/unit_soldier.cpp @@ -131,6 +131,8 @@ void unit_soldier_t::fire_shotgun(v2f_t aim) flash->place(&game->world); last_attack = game->now; assets::soldier.fire.play_3d(x); + + game->hivemind_alert(x, 14.0f, true, x); } diff --git a/src/game/unit_spider.cpp b/src/game/unit_spider.cpp index 7d4d0a1..2838a8b 100644 --- a/src/game/unit_spider.cpp +++ b/src/game/unit_spider.cpp @@ -53,7 +53,7 @@ void unit_spider_t::target_and_attack(void) // Tell everyone about a new target. if (!have_target) - hivemind_attack(this, true, target->x); + game->hivemind_alert(x, 12.0f, true, target->x); have_target = true; wake_time = game->time; @@ -104,14 +104,14 @@ void unit_spider_t::on_damage(unit_t *attacker) assets::spider.sounds.play_3d(x); if (attacker) - hivemind_attack(this, true, attacker->x); + game->hivemind_alert(x, 12.0f, true, attacker->x); else - hivemind_attack(this, false, v2f_t(0, 0)); + game->hivemind_alert(x, 12.0f, false, v2f_t(0, 0)); } void unit_spider_t::on_death(void) { - hivemind_attack(this, false, v2f_t(0, 0)); + game->hivemind_alert(x, 16.0f, false, v2f_t(0, 0)); if (health < -5) { assets::soldier.gib_sound.play_3d(x); diff --git a/src/game/units.cpp b/src/game/units.cpp index 20e74a7..a342a09 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -272,15 +272,17 @@ void unit_t::random_walk(void) move.random_walk_time = game->time; } -void hivemind_attack(unit_t *source, bool have_target, v2f_t target) +void state_t::hivemind_alert(v2f_t x, float r, bool do_move, v2f_t move_to) { rectf_t search; std::list ents; - search[0] = source->x - v2f_t(12, 12); - search[1] = source->x + v2f_t(12, 12); + search[0] = x - v2f_t(r, r); + search[1] = x + v2f_t(r, r); - ents = source->game->world.get_entities(search, CF_BODY_SMALL); + ents = world.get_entities(search, CF_BODY_SMALL); + + printf("alert with r=%f\n", r); for (world::entity_t *ent : ents) { unit_t *unit; @@ -290,6 +292,9 @@ void hivemind_attack(unit_t *source, bool have_target, v2f_t target) unit = dynamic_cast(ent); + if ((unit->x - x).len() > r) + continue; + if (unit->type != unit_t::UNIT_SPIDER) continue; @@ -298,15 +303,22 @@ void hivemind_attack(unit_t *source, bool have_target, v2f_t target) unit->wake(); - if (!have_target) + if (!do_move) continue; // Move towards the target if it's close, otherwise walk // randomly to avoid fire. - if ((unit->x - target).len() > 25.0f) + if ((unit->x - move_to).len() > 25.0f) continue; - unit->start_moving(target); + unit->start_moving(move_to); + } + + if (debug_AI) { + fx_debug_hivemind_t *debug; + + debug = new fx_debug_hivemind_t(this, x, r, do_move, move_to); + debug->place(&world); } } -- cgit