From f4fe2c7f10a8d2e253de27f1a540ca68184d5d29 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Fri, 20 Apr 2018 12:35:21 +0200 Subject: Pseudo 3D firing and misc. fixes. --- LICENSE | 1 + assets/fx/ricochet.ogg | Bin 0 -> 12676 bytes assets/fx/ricochet_0.png | Bin 0 -> 291 bytes assets/fx/ricochet_1.png | Bin 0 -> 315 bytes assets/fx/ricochet_2.png | Bin 0 -> 308 bytes src/common.hpp | 1 + src/game/assets.cpp | 2 ++ src/game/effects.cpp | 24 ++++++++++++++++++++++++ src/game/game.cpp | 5 +---- src/game/game.hpp | 28 ++++++++++++++++++---------- src/game/rocket.cpp | 46 +++++++++++++++++++++++----------------------- src/game/unit_repl.cpp | 2 +- src/game/unit_soldier.cpp | 34 +++++++++++++++++++++++----------- src/game/units.cpp | 28 ++++++---------------------- src/world.cpp | 12 ++++++++++++ 15 files changed, 112 insertions(+), 71 deletions(-) create mode 100644 assets/fx/ricochet.ogg create mode 100644 assets/fx/ricochet_0.png create mode 100644 assets/fx/ricochet_1.png create mode 100644 assets/fx/ricochet_2.png diff --git a/LICENSE b/LICENSE index 3a856df..d86aa53 100644 --- a/LICENSE +++ b/LICENSE @@ -23,6 +23,7 @@ The following assets are from Tremulous and are licensed under CC-BY-SA: FILE assets/ambience/wind.ogg +assets/fx/ricochet.ogg assets/units/nest/*.ogg assets/units/repl/damage*.ogg assets/units/soldier/death*.ogg diff --git a/assets/fx/ricochet.ogg b/assets/fx/ricochet.ogg new file mode 100644 index 0000000..0ef4337 Binary files /dev/null and b/assets/fx/ricochet.ogg differ diff --git a/assets/fx/ricochet_0.png b/assets/fx/ricochet_0.png new file mode 100644 index 0000000..0decd95 Binary files /dev/null and b/assets/fx/ricochet_0.png differ diff --git a/assets/fx/ricochet_1.png b/assets/fx/ricochet_1.png new file mode 100644 index 0000000..1c7f2b0 Binary files /dev/null and b/assets/fx/ricochet_1.png differ diff --git a/assets/fx/ricochet_2.png b/assets/fx/ricochet_2.png new file mode 100644 index 0000000..7885095 Binary files /dev/null and b/assets/fx/ricochet_2.png differ diff --git a/src/common.hpp b/src/common.hpp index 74fa9de..ff5839f 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -202,6 +202,7 @@ namespace world { trace_t ray_v_ents(v2f_t start, v2f_t end, cflags_t cflags, const entity_t *ignore); trace_t ray_v_tiles(v2f_t start, v2f_t end, cflags_t cflags); trace_t ray_v_all(v2f_t start, v2f_t end, cflags_t cflags, const entity_t *ignore); + trace_t ray_v_all_p3d(v2f_t start, v2f_t end, cflags_t cflags, cflags_t end_cflags, const entity_t *ignore); struct { size_t sectors = 0, tiles = 0; diff --git a/src/game/assets.cpp b/src/game/assets.cpp index f3b4cd3..05b647a 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -87,6 +87,8 @@ void load(void) fx.explosion.load("assets/fx/explosion_", 7); fx.explosion_sound.load("assets/fx/explosion.ogg"); fx.explosion_sound.volume = 3.0f; + fx.ricochet.load("assets/fx/ricochet_", 3); + fx.ricochet_sound.load("assets/fx/ricochet.ogg"); deco.stone.load("assets/deco/stone_", 1); deco.stone_cracked.load("assets/deco/stone_cracked_", 1); diff --git a/src/game/effects.cpp b/src/game/effects.cpp index da045ef..501b296 100644 --- a/src/game/effects.cpp +++ b/src/game/effects.cpp @@ -182,4 +182,28 @@ void fx_explosion_t::render_to(render::state_t *render) render->render(phase, &assets::fx.explosion, render_bounds, sf::Color::White); } +fx_ricochet_t::fx_ricochet_t(state_t *game_, v2f_t x_) : effect_t(game_) +{ + ttl = game->now + 0.3; + + x = x_; + + render_bounds[0] = x - v2f_t(0.12f, 0.12f); + render_bounds[1] = x + v2f_t(0.12f, 0.12f); + render_bounds = render_bounds.norm(); + cmodel.bounds = render_bounds; + cmodel.cflags = 0; + + ignore_waking = true; + wake(); + + assets::fx.ricochet_sound.play_3d(x); +} + +void fx_ricochet_t::render_to(render::state_t *render) +{ + double phase = (game->now - ttl) / 0.3f; + render->render(phase, &assets::fx.ricochet, render_bounds, sf::Color::White); +} + } // namespace game diff --git a/src/game/game.cpp b/src/game/game.cpp index f71b9d2..f6a741c 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -250,10 +250,7 @@ static void command_soldier(unit_soldier_t *soldier, v2f_t x, int number) soldier->rocket_fired = true; from = soldier->x + v2f_t(0, -0.5); - v = x - from; - v *= 1.0f / v.len() * 10.0f; - - rocket = new rocket_t(soldier->game, from, v, soldier); + rocket = new rocket_t(soldier->game, from, x, soldier); rocket->place(&soldier->game->world, from); } } diff --git a/src/game/game.hpp b/src/game/game.hpp index 6d6a80b..61ea146 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -43,7 +43,7 @@ namespace game { CF_WATER = 16, CF_DECOS = 32 }; - + enum { AMBIENT_NEXUS, AMBIENT_CHASM, @@ -86,8 +86,8 @@ namespace game { } repl_assets_t; typedef struct { - render::animated_texture_t blood, flash, explosion; - audio::sound_t explosion_sound; + render::animated_texture_t blood, flash, explosion, ricochet; + audio::sound_t explosion_sound, ricochet_sound; } fx_assets_t; typedef struct { @@ -198,15 +198,12 @@ namespace game { world::cflags_t cflags; bool moving = false; + bool blocked; v2f_t dst; float angle = 0.0f; std::list path; - bool blocked; - size_t attempts_left; - float next_attempt; - v2f_t last_step; ntime_t random_walk_time = 0; @@ -393,6 +390,16 @@ namespace game { void render_to(render::state_t *render); }; + class fx_ricochet_t : public effect_t { + v2f_t x; + + public: + fx_ricochet_t(game::state_t *game_, v2f_t x_); + ~fx_ricochet_t(void) {}; + + void render_to(render::state_t *render); + }; + typedef enum { DECO_STONE, DECO_STONE_CRACKED, @@ -423,15 +430,16 @@ namespace game { class rocket_t : public game::entity_t { unit_t *shooter; - v2f_t v; + v2f_t target, v; + std::unique_ptr aim_marker; public: - rocket_t(game::state_t *game, v2f_t x_, v2f_t v_, unit_t *shooter_); + rocket_t(game::state_t *game, v2f_t x_, v2f_t target_, unit_t *shooter_); void render_to(render::state_t *render); void render_late_to(render::state_t *render) {}; void on_think(void); - void on_spawn(void) {}; + void on_spawn(void); void on_wake(void) {}; void damage(int points, unit_t *attacker) {}; }; diff --git a/src/game/rocket.cpp b/src/game/rocket.cpp index e88f599..a03b169 100644 --- a/src/game/rocket.cpp +++ b/src/game/rocket.cpp @@ -19,29 +19,13 @@ along with Minitrem. If not, see . namespace game { -/* - class rocket_t : public game::entity_t { - unit_t *shooter; - v2f_t v; - - public: - rocket_t(game::state_t *game, v2f_t x, v2f_t v, unit_t *shooter_); - void render_to(render::state_t *render); - void render_late_to(render::state_t *render) {}; - - void on_think(void); - void on_spawn(void) {}; - void on_wake(void) {}; - void damage(int points, unit_t *attacker) {}; - } -*/ - const v2f_t rocket_radius(1.0f, 1.0f); -rocket_t::rocket_t(game::state_t *game, v2f_t x_, v2f_t v_, unit_t *shooter_) : entity_t(game, ET_ROCKET) +rocket_t::rocket_t(game::state_t *game, v2f_t x_, v2f_t target_, unit_t *shooter_) : entity_t(game, ET_ROCKET) { x = x_; - v = v_; + target = target_; + v = (target - x).norm() * 10.0f; shooter = shooter_; size = rectf_t(v2f_t(-0.1f, -0.1f), v2f_t(0.1f, 0.1f)); @@ -51,15 +35,31 @@ rocket_t::rocket_t(game::state_t *game, v2f_t x_, v2f_t v_, unit_t *shooter_) : wake(); } +void rocket_t::on_spawn(void) +{ + aim_marker = std::make_unique(game, target); +} + void rocket_t::on_think(void) { + float Ds, ds; v2f_t end; world::trace_t trace; - end = x + v * game->dt; - trace = world->ray_v_all(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, shooter); - if (trace.frac < 1.0f) { - game->explosion(x); + Ds = (target - x) * v.norm(); + ds = v.len() * game->dt; + + if (Ds > ds) { + end = x + v * game->dt; + trace = world->ray_v_all(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, shooter); + } else { + end = target; + trace = world->ray_v_all_p3d(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, -1, nullptr); + trace.hit = true; + } + + if (trace.hit) { + game->explosion(trace.end); delete this; return; } diff --git a/src/game/unit_repl.cpp b/src/game/unit_repl.cpp index be3e8fa..fb66176 100644 --- a/src/game/unit_repl.cpp +++ b/src/game/unit_repl.cpp @@ -25,7 +25,7 @@ unit_repl_t::unit_repl_t(game::state_t *game_) : unit_t(game_, UNIT_REPL) size[1] = {+0.4f, +0.4f}; render_size = size; render_layer = render::LAYER_FLAT; - cmodel.cflags = CF_BODY_SMALL; + cmodel.cflags = CF_BACKGROUND; name = text::get(text::UNIT_NAME_REPL); ignore_waking = false; diff --git a/src/game/unit_soldier.cpp b/src/game/unit_soldier.cpp index 433f88d..4cf840d 100644 --- a/src/game/unit_soldier.cpp +++ b/src/game/unit_soldier.cpp @@ -64,14 +64,18 @@ void unit_soldier_t::check_area(void) } } -static v2f_t spread_aim(v2f_t aim, float cof, procgen::prng_t *prng) +static v2f_t spread_aim(v2f_t x, v2f_t aim, float cof, procgen::prng_t *prng) { - float t; + float r, r_, dth; + v2f_t tmp; - t = prng->next_float(-cof / 2, cof / 2); + r = (aim - x).len(); + r_ = r + cof * r * prng->next_float(-1.0f, 1.0f); + tmp = (aim - x) / r * r_; - return v2f_t(cos(t) * aim[0] - sin(t) * aim[1], - sin(t) * aim[0] + cos(t) * aim[1]); + dth = cof * prng->next_float(-1.0f, 1.0f); + return x + v2f_t(cos(dth) * tmp[0] - sin(dth) * tmp[1], + sin(dth) * tmp[0] + cos(dth) * tmp[1]); } void unit_soldier_t::shoot(v2f_t aim) @@ -82,9 +86,9 @@ void unit_soldier_t::shoot(v2f_t aim) fx_tracer_t *tracer; fx_flash_t *flash; - end = x + (aim - x).norm() * 40; + end = spread_aim(x, aim, 0.1f, &game->prng); - trace = world->ray_v_all(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, this); + trace = world->ray_v_all_p3d(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, -1, this); if (!manual_firing && trace.hit && trace.ent && trace.ent->type == ET_UNIT) { unit_t *unit = dynamic_cast(trace.ent); @@ -110,6 +114,13 @@ void unit_soldier_t::shoot(v2f_t aim) entity_t *ent = dynamic_cast(trace.ent); ent->damage(3, this); } + + if (!trace.hit || (trace.ent && trace.ent->type != ET_UNIT)) { + fx_ricochet_t *ricochet; + + ricochet = new fx_ricochet_t(game, trace.end); + ricochet->place(&game->world); + } } void unit_soldier_t::target_and_attack(void) @@ -144,15 +155,13 @@ skip_targetting: if (last_attack + game->prng.next_float(1.4f, 1.6f) > game->now) return; - shoot(spread_aim(aim, 0.01, &game->prng)); + shoot(aim); } void unit_soldier_t::on_think(void) { - check_area(); - target_and_attack(); - keep_moving(2.0); + if (!move.moving) move_marker.reset(); @@ -160,6 +169,9 @@ void unit_soldier_t::on_think(void) move.last_step = x; assets::soldier.step_stone.play_3d(x); } + + check_area(); + target_and_attack(); } void unit_soldier_t::on_damage(unit_t *attacker) diff --git a/src/game/units.cpp b/src/game/units.cpp index 968e93e..20e74a7 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -110,11 +110,7 @@ bool unit_t::keep_moving(double speed) if (!move.moving) return true; - if (move.blocked && game->now < move.next_attempt) - return true; - time = game->dt * speed; - move.blocked = true; while (time > 0.0f) { v2f_t delta, next, x_new; @@ -142,25 +138,17 @@ bool unit_t::keep_moving(double speed) test_cmodel.bounds = size + x_new; test_cmodel.cflags = move.cflags; - if (!world->test_rect(&test_cmodel, this)) { - x = x_new; - cmodel.bounds = test_cmodel.bounds; - move.blocked = false; - continue; + if (world->test_rect(&test_cmodel, this)) { + rv = false; + break; } - if (move.attempts_left) { - move.attempts_left--; - move.next_attempt = game->now + 0.2f; - } else { - if ((x - move.dst).len() > 1.5f) - rv = false; - move.moving = false; - } - break; + x = x_new; + cmodel.bounds = test_cmodel.bounds; } place(world, x); + move.blocked = !rv; return rv; } @@ -186,10 +174,6 @@ bool unit_t::start_moving(v2f_t dst) } move.moving = true; - - move.blocked = false; - move.attempts_left = 10; - move.next_attempt = -INFINITY; return true; } diff --git a/src/world.cpp b/src/world.cpp index 1066545..0d96234 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -515,6 +515,18 @@ trace_t world_t::ray_v_all(v2f_t start, v2f_t end, cflags_t cflags, return v_ents; } +trace_t world_t::ray_v_all_p3d(v2f_t start, v2f_t end, cflags_t cflags, + cflags_t end_cflags, const entity_t *ignore) +{ + trace_t trace; + + trace = ray_v_all(start, end, cflags, ignore); + if (!trace.hit) + trace = ray_v_all(end, end, end_cflags, ignore); + + return trace; +} + entity_t::entity_t(int type_) { -- cgit