diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2017-12-13 19:50:42 +0100 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2017-12-13 19:50:42 +0100 |
commit | 868c3ce7659b1042f27b15774976dd20a0be3f77 (patch) | |
tree | 582823b2ab1f8f684a61c2e7a92aa501e33978a2 /src | |
parent | b3b30521e50f1ed0046091b316b19daec646b4ac (diff) |
Introduce health and damage; better alien AI.
Diffstat (limited to 'src')
-rw-r--r-- | src/game/assets.cpp | 3 | ||||
-rw-r--r-- | src/game/game.cpp | 20 | ||||
-rw-r--r-- | src/game/game.hpp | 39 | ||||
-rw-r--r-- | src/game/units.cpp | 116 |
4 files changed, 156 insertions, 22 deletions
diff --git a/src/game/assets.cpp b/src/game/assets.cpp index b9b1289..2a91a96 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -11,12 +11,13 @@ void load(void) human.body_idle.load("assets/units/human/body_idle", 2, 2, 2); human.legs_idle.load("assets/units/human/legs_idle", 2, 2); human.legs_walking.load("assets/units/human/legs_walking", 2, 2); + human.dead.load("assets/units/human/dead_", 1); alien.idle.load("assets/units/alien/idle", 2, 2, 2); alien.walking.load("assets/units/alien/walking", 2, 2, 2); world::register_tile(TILE_DIRT, 0); - world::register_tile(TILE_WALL, 1); + world::register_tile(TILE_WALL, CF_SOLID | CF_HUMAN); render::register_tile(TILE_DIRT, "assets/tiles/dirt.png"); render::register_tile(TILE_WALL, "assets/tiles/wall.png"); } diff --git a/src/game/game.cpp b/src/game/game.cpp index b9a46db..04034f7 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -14,9 +14,19 @@ void state_t::start(void) human = new human_t; human->place(&world, v2f_t(0.5, 0.5)); units.insert(human); + human = new human_t; + human->place(&world, v2f_t(1.5, 0.5)); + units.insert(human); + human = new human_t; + human->place(&world, v2f_t(2.5, 0.5)); + units.insert(human); alien = new alien_t; alien->place(&world, v2f_t(15.5, -2.5)); + alien = new alien_t; + alien->place(&world, v2f_t(14.5, -2.5)); + alien = new alien_t; + alien->place(&world, v2f_t(13.5, -2.5)); } void state_t::stop(void) @@ -44,6 +54,9 @@ void state_t::select(rectf_t x) if (unit->type != unit_t::UNIT_HUMAN) continue; + if (unit->dead) + continue; + unit->selected = selection_cookie; selected_units.insert(unit); } @@ -68,6 +81,9 @@ void state_t::tick(double now_, double dt_) for (unit_t *unit : units) { rectf_t wake_range; + if (unit->dead) + continue; + wake_range[0] = unit->x - v2f_t(10, 10); wake_range[1] = unit->x + v2f_t(10, 10); @@ -78,6 +94,10 @@ void state_t::tick(double now_, double dt_) continue; enemy = (unit_t*)ent; + + if (enemy->dead) + continue; + enemy->wake_time = now; if (enemy->awake) diff --git a/src/game/game.hpp b/src/game/game.hpp index f141e85..0ad0614 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -11,6 +11,12 @@ namespace game { TILE_WALL }; + enum { + CF_NONE = 0, + CF_SOLID = 1, + CF_HUMAN = 2 + }; + extern size_t selection_cookie; void worldgen(world::tile_t *tile, world::tile_index_t x, @@ -20,6 +26,7 @@ namespace game { typedef struct { render::oriented_sprite_4M_t head_idle, body_idle; render::oriented_sprite_4M2_t legs_idle, legs_walking; + render::animated_texture_t dead; } human_assets_t; typedef struct { @@ -54,6 +61,8 @@ namespace game { unit_t(type_t type_); + virtual void think(double now, double dt) = 0; + struct { bool moving = false; v2f_t dst; @@ -66,21 +75,27 @@ namespace game { float next_attempt; } move; - 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, double speed); bool start_moving(v2f_t dst_, double now); + bool awake = false; + double wake_time = -INFINITY; virtual void wake(double now, unit_t *by_whom) = 0; virtual void sleep(double now) = 0; - virtual void think(double now, double dt) = 0; + + bool dead = false; + double death_time = -INFINITY; + int health = 1; + void damage(double now, int points); + virtual void die(double now) = 0; + + const wchar_t *say_text; + double say_time = -INFINITY; + void say(const wchar_t *wstr, double now); + + void render_to(render::state_t *render); + }; class human_t : public unit_t { @@ -91,11 +106,14 @@ namespace game { void wake(double now, unit_t *by_whom); void sleep(double now); void think(double now, double dt); + void die(double now); }; class alien_t : public unit_t { - unit_t *target; + double next_targetting = -INFINITY; + double next_attack = -INFINITY; + void attack(double now, unit_t *target, float range); public: alien_t(); void render_to(render::state_t *render); @@ -103,5 +121,6 @@ namespace game { void wake(double now, unit_t *by_whom); void sleep(double now); void think(double now, double dt); + void die(double now); }; }; diff --git a/src/game/units.cpp b/src/game/units.cpp index 4c4e828..abdf216 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -46,7 +46,6 @@ void unit_t::place(world::world_t *world_, v2f_t x_) world = world_; x = x_; move.moving = false; - cflags = 1; unlink(); cmodel = make_cmodel(x); @@ -138,8 +137,22 @@ bool unit_t::start_moving(v2f_t dst_, double now) return true; } +void unit_t::damage(double now, int points) +{ + health -= points; + if (health < 0) { + printf("%p died\n", this); + dead = true; + death_time = now; + cflags = 0; + die(now); + } +} + human_t::human_t() : unit_t(UNIT_HUMAN) { + cflags = CF_HUMAN; + health = 20; size[0] = v2f_t(-0.4f, -0.4f); size[1] = v2f_t(+0.4f, +0.4f); render_size[0] = v2f_t(-0.5f, -1.0f); @@ -159,16 +172,28 @@ void human_t::think(double now, double dt) keep_moving(now, dt, 4.0); } +void human_t::die(double now) +{ + render_size[0] = v2f_t(-0.75f, -0.5f); + render_size[1] = v2f_t(+0.75f, +0.5f); + unlink(); + compute_bounds(); + link(world); +} + void human_t::render_to(render::state_t *render) { - bool moving; + if (!dead) { + bool moving; - moving = move.moving && !move.blocked; + moving = move.moving && !move.blocked; - render->render((moving ? &assets::human.legs_walking : - &assets::human.legs_idle), render_bounds, move.angle); - render->render(&assets::human.body_idle, render_bounds, move.angle); - render->render(&assets::human.head_idle, render_bounds, move.angle); + render->render((moving ? &assets::human.legs_walking : + &assets::human.legs_idle), render_bounds, move.angle); + render->render(&assets::human.body_idle, render_bounds, move.angle); + render->render(&assets::human.head_idle, render_bounds, move.angle); + } else + render->render(&assets::human.dead, render_bounds); if (say_time + 5.0 > render->now) { v2f_t text_pos; @@ -186,6 +211,8 @@ void human_t::render_to(render::state_t *render) alien_t::alien_t() : unit_t(UNIT_ALIEN) { + cflags = CF_SOLID; + health = 4; size[0] = v2f_t(-0.2f, -0.2f); size[1] = v2f_t(+0.2f, +0.2f); render_size[0] = v2f_t(-0.3f, -0.3f); @@ -194,18 +221,85 @@ alien_t::alien_t() : unit_t(UNIT_ALIEN) void alien_t::wake(double now, unit_t *by_whom) { - target = by_whom; - printf("the alien is now awake\n"); + start_moving(by_whom->x, now); + next_targetting = now + 0.4; } void alien_t::sleep(double now) { - printf("the alien is now sleeping\n"); +} + +void alien_t::die(double now) +{ + +} + +static unit_t *find_target(world::world_t *world, v2f_t x, float r, + unit_t::type_t type) +{ + rectf_t rect; + float nearest_dist = INFINITY; + unit_t *nearest = NULL; + + rect[0] = x - v2f_t(r, r); + rect[1] = x + v2f_t(r, r); + + for (world::entity_t *ent : world->get_entities(rect, -1)) { + unit_t *unit; + float dist; + + if (ent->type != ET_UNIT) + continue; + + unit = (unit_t*)ent; + + if (unit->type != type) + continue; + + if (unit->dead) + continue; + + dist = (unit->x - x).len(); + if (dist < nearest_dist) { + nearest_dist = dist; + nearest = unit; + } + } + + return nearest; +} + +void alien_t::attack(double now, unit_t *target, float range) +{ + world::trace_t trace; + + if (now < next_attack) + return; + + if ((x - target->x).len() > range) + return; + + trace = world->trace(x, target->x, CF_SOLID); + if (!trace.hit) + target->damage(now, 12); + + next_attack = now + 1.0; } void alien_t::think(double now, double dt) { - start_moving(target->x, now); + if (now > next_targetting) { + unit_t *target; + + target = find_target(world, x, 5.0f, UNIT_HUMAN); + if (target) { + attack(now, target, 0.75f); + start_moving(target->x, now); + } + + next_targetting = now + 0.2; + } + keep_moving(now, dt, 7.0); } |