summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-12-13 19:50:42 +0100
committerPaweł Redman <pawel.redman@gmail.com>2017-12-13 19:50:42 +0100
commit868c3ce7659b1042f27b15774976dd20a0be3f77 (patch)
tree582823b2ab1f8f684a61c2e7a92aa501e33978a2
parentb3b30521e50f1ed0046091b316b19daec646b4ac (diff)
Introduce health and damage; better alien AI.
-rw-r--r--assets/units/human/dead_0.pngbin0 -> 4431 bytes
-rw-r--r--src/game/assets.cpp3
-rw-r--r--src/game/game.cpp20
-rw-r--r--src/game/game.hpp39
-rw-r--r--src/game/units.cpp116
5 files changed, 156 insertions, 22 deletions
diff --git a/assets/units/human/dead_0.png b/assets/units/human/dead_0.png
new file mode 100644
index 0000000..a2accf3
--- /dev/null
+++ b/assets/units/human/dead_0.png
Binary files differ
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);
}