From 38edebe4bdeb8caedccf6127a86fddfe9c5808a8 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sat, 16 Dec 2017 22:41:48 +0000 Subject: Fully working nests. --- src/common.hpp | 4 +- src/game/assets.cpp | 5 ++- src/game/decos.cpp | 5 --- src/game/effects.cpp | 3 +- src/game/game.cpp | 14 ++----- src/game/game.hpp | 30 ++++++++++++--- src/game/text.cpp | 6 +++ src/game/units.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++------- src/game/worldgen.cpp | 18 +++++---- src/procgen.cpp | 7 ++++ 10 files changed, 149 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/common.hpp b/src/common.hpp index 872a40d..02e8b1a 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -25,6 +25,7 @@ namespace procgen { uint32_t next(void); float next_float(void); void unit_vec(float out[2]); + v2f_t unit_vec2(void); }; @@ -210,12 +211,11 @@ namespace game { std::unordered_set awake_entities; std::unordered_set selected_units; - - procgen::prng_t dice_prng; public: world::world_t world; interface::state_t *interface; double now, dt; + procgen::prng_t dice_prng; void start(void); void stop(void); diff --git a/src/game/assets.cpp b/src/game/assets.cpp index a4a03e5..6751435 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -4,6 +4,7 @@ namespace game::assets { soldier_assets_t soldier; spider_assets_t spider; +nest_assets_t nest; fx_assets_t fx; deco_assets_t deco; @@ -21,11 +22,13 @@ void load(void) spider.walking.load("assets/units/spider/walking", 2, 2, 2); spider.dead.load("assets/units/spider/dead_", 1); + nest.idle.load("assets/units/nest/idle_", 5); + nest.dead.load("assets/units/nest/dead_", 1); + fx.blood.load("assets/units/blood_", 4); deco.stone.load("assets/deco/stone_", 1); deco.eyething.load("assets/deco/eyething_", 2); - deco.nest.load("assets/deco/nest_", 5); world::register_tile(TILE_DIRT, 0); render::register_tile(TILE_DIRT, "assets/tiles/dirt.png"); diff --git a/src/game/decos.cpp b/src/game/decos.cpp index 7f81bbb..07e6b10 100644 --- a/src/game/decos.cpp +++ b/src/game/decos.cpp @@ -23,11 +23,6 @@ static const struct { &assets::deco.eyething, {-0.4f, +0.1f}, {+0.4f, +0.4f}, CF_SOLID, {-0.4f, -1.2f}, {+0.4f, +0.4f}, 0.3 - }, - { - &assets::deco.nest, - {-0.6f, +0.2f}, {+0.6f, +0.6f}, CF_SOLID, - {-0.6f, -0.6f}, {+0.6f, +0.6f}, 1.0 } }; diff --git a/src/game/effects.cpp b/src/game/effects.cpp index 8e7d2d7..844f365 100644 --- a/src/game/effects.cpp +++ b/src/game/effects.cpp @@ -4,7 +4,8 @@ namespace game { effect_t::effect_t(state_t *game_) : game::entity_t(game_, ET_EFFECT) { - always_awake = true; + ignore_waking = true; + wake(); } void effect_t::on_think(void) diff --git a/src/game/game.cpp b/src/game/game.cpp index 9584817..64dd224 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -32,7 +32,7 @@ void entity_t::place(world::world_t *world_) if (do_spawn) on_spawn(); - if (always_awake) + if (!ignore_waking) wake(); } @@ -51,7 +51,7 @@ void entity_t::wake(void) wake_time = game->now; game->awake_entities.insert(this); - if (!always_awake) + if (!ignore_waking) on_wake(); } @@ -64,7 +64,6 @@ void entity_t::sleep(void) void state_t::start(void) { unit_soldier_t *soldier; - unit_spider_t *spider; world.generator = worldgen; world.generator_data = (void*)this; @@ -75,13 +74,6 @@ void state_t::start(void) soldier->place(&world, v2f_t(1.5, 0.5)); soldier = new unit_soldier_t(this); soldier->place(&world, v2f_t(2.5, 0.5)); - - spider = new unit_spider_t(this); - spider->place(&world, v2f_t(15.5, -2.5)); - spider = new unit_spider_t(this); - spider->place(&world, v2f_t(14.5, -2.5)); - spider = new unit_spider_t(this); - spider->place(&world, v2f_t(13.5, -2.5)); } void state_t::stop(void) @@ -171,7 +163,7 @@ void state_t::wake_everything(v2f_t x, float range) if (!ent) continue; - if (ent->always_awake || ent->awake) + if (ent->ignore_waking || ent->awake) continue; ent->wake(); diff --git a/src/game/game.hpp b/src/game/game.hpp index b2bf0dd..e2ac514 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -39,16 +39,21 @@ namespace game { render::animated_texture_t dead; } spider_assets_t; + typedef struct { + render::animated_texture_t idle, dead; + } nest_assets_t; + typedef struct { render::animated_texture_t blood; } fx_assets_t; typedef struct { - render::animated_texture_t stone, eyething, nest; + render::animated_texture_t stone, eyething; } deco_assets_t; extern soldier_assets_t soldier; extern spider_assets_t spider; + extern nest_assets_t nest; extern fx_assets_t fx; extern deco_assets_t deco; @@ -70,6 +75,7 @@ namespace game { SAY_MOVING, UNIT_NAME_SPIDER, UNIT_NAME_SOLDIER, + UNIT_NAME_NEST, UNIT_DEATH, UNIT_ATTACK, UNIT_MISS, @@ -94,7 +100,7 @@ namespace game { void place(world::world_t *world); void place(world::world_t *world, v2f_t x_); - bool always_awake = false; + bool ignore_waking = false; bool awake = false; double wake_time = -INFINITY; void wake(void); @@ -115,7 +121,8 @@ namespace game { typedef enum { UNIT_SOLDIER, - UNIT_SPIDER + UNIT_SPIDER, + UNIT_NEST } type_t; type_t type; @@ -189,6 +196,20 @@ namespace game { void on_death(void); }; + class unit_nest_t : public unit_t { + double next_spawning = -INFINITY; + + public: + unit_nest_t(game::state_t *game_); + ~unit_nest_t(void) {}; + void render_to(render::state_t *render); + + void on_think(void); + void on_spawn(void); + void on_death(void); + void on_wake(void) {}; + }; + class effect_t : public game::entity_t { public: double ttl = +INFINITY; @@ -225,8 +246,7 @@ namespace game { typedef enum { DECO_STONE, DECO_STONE_SMALL, - DECO_EYETHING, - DECO_NEST + DECO_EYETHING } deco_type_t; class deco_t : public game::entity_t { diff --git a/src/game/text.cpp b/src/game/text.cpp index 3b611e2..bdd68ed 100644 --- a/src/game/text.cpp +++ b/src/game/text.cpp @@ -29,6 +29,9 @@ static std::string get_english(index_t index) case UNIT_NAME_SOLDIER: return soldier_names[rand() % count(soldier_names)]; + case UNIT_NAME_NEST: + return "Nest"; + case UNIT_DEATH: return "died"; @@ -73,6 +76,9 @@ static std::string get_polish(index_t index) case UNIT_NAME_SOLDIER: return soldier_names[rand() % count(soldier_names)]; + case UNIT_NAME_NEST: + return "Gniazdo"; + case UNIT_DEATH: return "nie żyje"; diff --git a/src/game/units.cpp b/src/game/units.cpp index a1e233c..49ae050 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -164,9 +164,14 @@ void unit_t::damage(int points, unit_t *attacker) void unit_t::die(unit_t *killer) { game->interface->print(name + " " + text::get(text::UNIT_DEATH) + "."); + dead = true; death_time = game->now; cmodel.cflags = 0; + + sleep(); + ignore_waking = true; + on_death(); } @@ -203,7 +208,7 @@ void unit_t::try_attack(unit_t *target) } static unit_t *find_target(world::world_t *world, v2f_t x, float r, - unit_t::type_t type) + bool friendly) { rectf_t rect; float nearest_dist = INFINITY; @@ -221,7 +226,7 @@ static unit_t *find_target(world::world_t *world, v2f_t x, float r, unit = (unit_t*)ent; - if (unit->type != type) + if (unit->friendly != friendly) continue; if (unit->dead) @@ -247,26 +252,24 @@ unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER) name = text::get(text::UNIT_NAME_SOLDIER); - always_awake = true; + ignore_waking = true; // Always awake. + wake(); friendly = true; controllable = true; health = max_health = 20; cs.armor_class = 10; - cs.hit_die = die_t(4); + cs.hit_die = die_t(8); } void unit_soldier_t::on_think(void) { - if (dead) - return; - game->wake_everything(x, 10); if (game->now > next_targetting) { unit_t *target; - target = find_target(world, x, 10.0f, UNIT_SPIDER); + target = find_target(world, x, 10.0f, false); if (target) { last_target_time = game->now; last_target_x = target->x; @@ -348,19 +351,16 @@ unit_spider_t::unit_spider_t(game::state_t *game) : unit_t(game, UNIT_SPIDER) name = text::get(text::UNIT_NAME_SPIDER); health = max_health = 4; - cs.armor_class = 5; - cs.hit_die = die_t(3, 6, 1); + cs.armor_class = 15; + cs.hit_die = die_t(3, 6); } void unit_spider_t::on_think(void) { - if (dead) - return; - if (game->now > next_targetting) { unit_t *target; - target = find_target(world, x, 10.0f, UNIT_SOLDIER); + target = find_target(world, x, 10.0f, true); if (target) { if (last_attack + 0.5 < game->now) { world::trace_t trace; @@ -381,6 +381,9 @@ void unit_spider_t::on_think(void) } keep_moving(7.0); + + if (!move.moving && wake_time + 5 > game->now) + sleep(); } void unit_spider_t::on_wake(void) @@ -409,4 +412,76 @@ void unit_spider_t::render_to(render::state_t *render) unit_t::render_to(render); } +unit_nest_t::unit_nest_t(game::state_t *game_) : unit_t(game_, UNIT_NEST) +{ + size[0] = {-0.6f, +0.2f}; + size[1] = {+0.6f, +0.6f}; + render_size[0] = {-0.6f, -0.6f}; + render_size[1] = {+0.6f, +0.6f}; + cmodel.cflags = CF_BACKGROUND; + + name = text::get(text::UNIT_NAME_NEST); + + health = max_health = 45; + cs.armor_class = 5; + + next_spawning = game->now + 5.0; +} + +void spawn_spider(game::state_t *game, v2f_t nest) +{ + for (size_t i = 0; i < 5; i++) { // Try a few times before giving up. + v2f_t offset, x; + world::cmodel_t cmodel; + unit_spider_t *spider; + + offset = game->dice_prng.unit_vec2(); + x = nest + offset * (game->dice_prng.next_float() * 0.2 + 0.4); + + cmodel.bounds = rectf_t(v2f_t(-0.5f, -0.5f), v2f_t(0.5f, 0.5f)) + x; + cmodel.cflags = CF_BODY_SMALL; + if (game->world.test_rect(&cmodel, NULL)) + continue; + + spider = new unit_spider_t(game); + spider->place(&game->world, x); + return; + } +} + +void unit_nest_t::on_think(void) +{ + if (wake_time + 30 > game->now) + sleep(); + + if (next_spawning > game->now) + return; + + spawn_spider(game, x); + next_spawning = game->now + game->dice_prng.next_float() * 10 + 5; +} + +void unit_nest_t::on_spawn(void) +{ + spawn_spider(game, x); + spawn_spider(game, x); + spawn_spider(game, x); +} + +void unit_nest_t::on_death(void) +{ + render_layer = -1; + cmodel.cflags = CF_BACKGROUND; +} + +void unit_nest_t::render_to(render::state_t *render) +{ + if (!dead) + render->render(game->now, &assets::nest.idle, render_bounds); + else + render->render(game->now, &assets::nest.dead, render_bounds); + + unit_t::render_to(render); +} + } // namespace game diff --git a/src/game/worldgen.cpp b/src/game/worldgen.cpp index e5f19c8..18a98b5 100644 --- a/src/game/worldgen.cpp +++ b/src/game/worldgen.cpp @@ -13,19 +13,23 @@ void add_decoration(world_t *world, state_t *game, v2f_t x, float noise) if (noise < 0.3) return; - if (noise > 0.5) - type = DECO_NEST; - else if (noise > 0.40) + offset[0] = world->perlin.get(x, 0.17331f); + offset[1] = world->perlin.get(x, 0.19571f); + center = x + v2f_t(0.5f, 0.5f) + offset.norm() * 0.1; + + if (noise > 0.5) { + unit_nest_t *nest = new unit_nest_t(game); + nest->place(world, center); + return; + } + + if (noise > 0.40) type = DECO_EYETHING; else if (noise > 0.35) type = DECO_STONE; else type = DECO_STONE_SMALL; - offset[0] = world->perlin.get(x, 0.17331f); - offset[1] = world->perlin.get(x, 0.19571f); - center = x + v2f_t(0.5f, 0.5f) + offset.norm() * 0.1; - deco = new deco_t(game, type); deco->phase_shift = offset[0] * 500.0; deco->place(world, x); diff --git a/src/procgen.cpp b/src/procgen.cpp index bfff2c4..a57ed3a 100644 --- a/src/procgen.cpp +++ b/src/procgen.cpp @@ -32,6 +32,13 @@ void prng_t::unit_vec(float out[2]) out[1] = sin(t); } +v2f_t prng_t::unit_vec2(void) +{ + float t; + t = next_float() * 2.0f * M_PI; + return {cos(t), sin(t)}; +} + void perlin_noise_t::generate(prng_t *prng, size_t size_) { if (table) -- cgit