From b3b30521e50f1ed0046091b316b19daec646b4ac Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Wed, 13 Dec 2017 16:27:34 +0100 Subject: Basic alien AI. --- src/common.hpp | 1 + src/game/game.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++---- src/game/game.hpp | 29 ++++++++++++++++++++++++++--- src/game/units.cpp | 40 +++++++++++++++++++++++++++++++++------- src/path_finder.cpp | 2 +- src/world.cpp | 6 ++---- 6 files changed, 107 insertions(+), 19 deletions(-) diff --git a/src/common.hpp b/src/common.hpp index 20c5a12..948e829 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -186,6 +186,7 @@ namespace game { std::unordered_set units; std::unordered_set selected_units; + std::unordered_set awake_units; public: world::world_t world; diff --git a/src/game/game.cpp b/src/game/game.cpp index 71d24ac..b9a46db 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -16,8 +16,7 @@ void state_t::start(void) units.insert(human); alien = new alien_t; - alien->place(&world, v2f_t(5.5, 5.5)); - units.insert(alien); + alien->place(&world, v2f_t(15.5, -2.5)); } void state_t::stop(void) @@ -41,6 +40,10 @@ void state_t::select(rectf_t x) continue; unit = (unit_t*)ent; + + if (unit->type != unit_t::UNIT_HUMAN) + continue; + unit->selected = selection_cookie; selected_units.insert(unit); } @@ -62,8 +65,45 @@ void state_t::tick(double now_, double dt_) now = now_; dt = dt_; - for (unit_t *unit : units) - unit->keep_moving(now, dt); + for (unit_t *unit : units) { + rectf_t wake_range; + + wake_range[0] = unit->x - v2f_t(10, 10); + wake_range[1] = unit->x + v2f_t(10, 10); + + for (world::entity_t *ent : world.get_entities(wake_range, -1)) { + unit_t *enemy; + + if (ent->type != ET_UNIT) + continue; + + enemy = (unit_t*)ent; + enemy->wake_time = now; + + if (enemy->awake) + continue; + + if (enemy->type == unit_t::UNIT_HUMAN) + continue; + + enemy->awake = true; + awake_units.insert(enemy); + enemy->wake(now, unit); + } + + unit->think(now, dt); + } + + for (auto i = std::begin(awake_units); i != std::end(awake_units);) { + if (now - (*i)->wake_time >= 5.0) { + (*i)->awake = false; + (*i)->sleep(now); + i = awake_units.erase(i); + } else { + (*i)->think(now, dt); + i++; + } + } } bool load_assets(void) diff --git a/src/game/game.hpp b/src/game/game.hpp index f45aecf..f141e85 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -45,7 +45,14 @@ namespace game { world::cflags_t cflags; size_t selected = 0; - unit_t(); + typedef enum { + UNIT_HUMAN, + UNIT_ALIEN + } type_t; + + type_t type; + + unit_t(type_t type_); struct { bool moving = false; @@ -62,23 +69,39 @@ namespace game { const wchar_t *say_text; double say_time = -INFINITY; + bool awake = false; + double wake_time = -INFINITY; + void render_to(render::state_t *render); void say(const wchar_t *wstr, double now); void place(world::world_t *world_, v2f_t x_); - bool keep_moving(double now, double dt); + bool keep_moving(double now, double dt, double speed); bool start_moving(v2f_t dst_, double now); + + virtual void wake(double now, unit_t *by_whom) = 0; + virtual void sleep(double now) = 0; + virtual void think(double now, double dt) = 0; }; class human_t : public unit_t { public: human_t(); void render_to(render::state_t *render); - bool keep_moving(double now, double dt); + + void wake(double now, unit_t *by_whom); + void sleep(double now); + void think(double now, double dt); }; class alien_t : public unit_t { + unit_t *target; + public: alien_t(); void render_to(render::state_t *render); + + void wake(double now, unit_t *by_whom); + void sleep(double now); + void think(double now, double dt); }; }; diff --git a/src/game/units.cpp b/src/game/units.cpp index d695050..4c4e828 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -20,8 +20,9 @@ void unit_t::compute_bounds() } -unit_t::unit_t() : entity_t(ET_UNIT) +unit_t::unit_t(unit_t::type_t type_) : entity_t(ET_UNIT) { + type = type_; } void unit_t::render_to(render::state_t *render) @@ -53,7 +54,7 @@ void unit_t::place(world::world_t *world_, v2f_t x_) link(world); } -bool unit_t::keep_moving(double now, double dt) +bool unit_t::keep_moving(double now, double dt, double speed) { float time; @@ -63,7 +64,7 @@ bool unit_t::keep_moving(double now, double dt) if (move.blocked && now < move.next_attempt) return false; - time = dt * 10; + time = dt * speed; while (time > 0.0f) { v2f_t delta, next, x_new; @@ -137,7 +138,7 @@ bool unit_t::start_moving(v2f_t dst_, double now) return true; } -human_t::human_t() +human_t::human_t() : unit_t(UNIT_HUMAN) { size[0] = v2f_t(-0.4f, -0.4f); size[1] = v2f_t(+0.4f, +0.4f); @@ -145,9 +146,17 @@ human_t::human_t() render_size[1] = v2f_t(+0.5f, +0.5f); } -bool human_t::keep_moving(double now, double dt) +void human_t::wake(double now, unit_t *by_whom) { - unit_t::keep_moving(now, dt); +} + +void human_t::sleep(double now) +{ +} + +void human_t::think(double now, double dt) +{ + keep_moving(now, dt, 4.0); } void human_t::render_to(render::state_t *render) @@ -175,7 +184,7 @@ void human_t::render_to(render::state_t *render) unit_t::render_to(render); } -alien_t::alien_t() +alien_t::alien_t() : unit_t(UNIT_ALIEN) { size[0] = v2f_t(-0.2f, -0.2f); size[1] = v2f_t(+0.2f, +0.2f); @@ -183,6 +192,23 @@ alien_t::alien_t() render_size[1] = v2f_t(+0.3f, +0.3f); } +void alien_t::wake(double now, unit_t *by_whom) +{ + target = by_whom; + printf("the alien is now awake\n"); +} + +void alien_t::sleep(double now) +{ + printf("the alien is now sleeping\n"); +} + +void alien_t::think(double now, double dt) +{ + start_moving(target->x, now); + keep_moving(now, dt, 7.0); +} + void alien_t::render_to(render::state_t *render) { bool moving; diff --git a/src/path_finder.cpp b/src/path_finder.cpp index c8cd253..30e9ebd 100644 --- a/src/path_finder.cpp +++ b/src/path_finder.cpp @@ -12,7 +12,7 @@ static const tile_index_t path_offsets[8] = { path_finder_t::~path_finder_t() { - delete nodes; + delete[] nodes; } void path_finder_t::setup_nodes(v2f_t src_, v2f_t dst_, cflags_t cflags_) diff --git a/src/world.cpp b/src/world.cpp index f4aca63..71a7ae7 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -162,9 +162,10 @@ std::list world_t::get_sectors(rectf_t rect) return list; } +static size_t cookie = 0; + std::list world_t::get_entities(rectf_t rect, cflags_t cflags) { - static size_t cookie = 0; std::list list; cookie++; @@ -190,7 +191,6 @@ std::list world_t::get_entities(rectf_t rect, cflags_t cflags) std::list world_t::get_render_entities(rectf_t rect) { - static size_t cookie = 0; std::list list; cookie++; @@ -213,8 +213,6 @@ std::list world_t::get_render_entities(rectf_t rect) bool world_t::test_rect(const cmodel_t *cmodel, const entity_t *ignore) { - static size_t cookie = 0; - cookie++; for (sector_t *sector : get_sectors(cmodel->bounds)) { -- cgit