summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2018-04-20 12:35:21 +0200
committerPaweł Redman <pawel.redman@gmail.com>2018-04-20 12:35:21 +0200
commitf4fe2c7f10a8d2e253de27f1a540ca68184d5d29 (patch)
tree4916ce9f704aa2df7a71b6186c08fea2543090fe /src/game
parentfade55e67e1a6944461c16c1495dea9546243756 (diff)
Pseudo 3D firing and misc. fixes.
Diffstat (limited to 'src/game')
-rw-r--r--src/game/assets.cpp2
-rw-r--r--src/game/effects.cpp24
-rw-r--r--src/game/game.cpp5
-rw-r--r--src/game/game.hpp28
-rw-r--r--src/game/rocket.cpp46
-rw-r--r--src/game/unit_repl.cpp2
-rw-r--r--src/game/unit_soldier.cpp34
-rw-r--r--src/game/units.cpp28
8 files changed, 98 insertions, 71 deletions
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<v2f_t> 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<fx_aim_marker_t> 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 <http://www.gnu.org/licenses/>.
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<fx_aim_marker_t>(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<unit_t*>(trace.ent);
@@ -110,6 +114,13 @@ void unit_soldier_t::shoot(v2f_t aim)
entity_t *ent = dynamic_cast<entity_t*>(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;
}