feat: Primitive airfield navigation

This commit is contained in:
2026-04-23 23:18:06 +01:00
parent 4e7f79dadc
commit d1ff0e6a15
5 changed files with 69 additions and 22 deletions

View File

@@ -2,17 +2,10 @@
#include <math.h> #include <math.h>
void dxd::sim::AFSpawner::tick(float timestep, World *world) void dxd::sim::AFSpawner::spawn_airfield(World *world)
{ {
(void)timestep;
if (--_next_spawn != 0)
return;
_next_spawn = _MIN_SPAWN_DELAY + SDL_rand(_MAX_SPAWN_DELAY);
vec2i base_pos; vec2i base_pos;
//TODO: Set limiter //TODO: Iter limiter
do do
base_pos = rand_v2i({ -_GRID_BOUNDS, -_GRID_BOUNDS }, { _GRID_BOUNDS, _GRID_BOUNDS }); base_pos = rand_v2i({ -_GRID_BOUNDS, -_GRID_BOUNDS }, { _GRID_BOUNDS, _GRID_BOUNDS });
while (_airfields.find(base_pos) != _airfields.end()); while (_airfields.find(base_pos) != _airfields.end());
@@ -20,13 +13,50 @@ void dxd::sim::AFSpawner::tick(float timestep, World *world)
vec2 off = rand_v2({ -_GRID_JITTER, -_GRID_JITTER }, { _GRID_JITTER, _GRID_JITTER }); vec2 off = rand_v2({ -_GRID_JITTER, -_GRID_JITTER }, { _GRID_JITTER, _GRID_JITTER });
vec2 pos = v2i_to_v2(base_pos) * _GRID_STRIDE + off; vec2 pos = v2i_to_v2(base_pos) * _GRID_STRIDE + off;
Airfield *af = new Airfield(pos, _MIN_AF_TTL + SDL_rand(_MAX_AF_TTL), SDL_randf()*2*M_PIf); Airfield *af = new Airfield(this, pos, _MIN_AF_TTL + SDL_rand(_MAX_AF_TTL), SDL_randf()*2*M_PIf);
world->add_obj(af); world->add_obj(af);
_airfields.emplace(base_pos, af); _airfields.emplace(base_pos, af);
} }
void dxd::sim::AFSpawner::tick(float timestep, World *world)
{
(void)timestep;
if (_next_spawn == -1) //Init
{
spawn_airfield(world);
spawn_airfield(world);
_next_spawn = _MIN_SPAWN_DELAY;
return;
}
if (--_next_spawn != 0)
return;
_next_spawn = _MIN_SPAWN_DELAY + SDL_rand(_MAX_SPAWN_DELAY);
spawn_airfield(world);
}
void dxd::sim::AFSpawner::draw(Renderer *rend) void dxd::sim::AFSpawner::draw(Renderer *rend)
{ {
rend->color(0, 127, 0); rend->color(0, 127, 0);
rend->rect(vec2_zero, _SPAWN_BOUNDS*2); rend->rect(vec2_zero, _SPAWN_BOUNDS*2);
} }
dxd::sim::Airfield *dxd::sim::AFSpawner::get_random_airfield(Airfield *exclude)
{
int count = (int)_airfields.size();
Airfield *af = exclude;
//TODO: Iter limiter
do
{
int sel = rand_int(0, count);
auto it = _airfields.begin();
for (; it != _airfields.end() && sel; ++it, --sel);
af = it->second;
} while(af == exclude);
return af;
}

View File

@@ -10,6 +10,8 @@
namespace dxd::sim namespace dxd::sim
{ {
class Airfield;
class AFSpawner : public WorldObject class AFSpawner : public WorldObject
{ {
private: private:
@@ -27,15 +29,19 @@ private:
const int _MIN_AF_TTL = 3000; const int _MIN_AF_TTL = 3000;
const int _MAX_AF_TTL = 9000; const int _MAX_AF_TTL = 9000;
void spawn_airfield(World *world);
public: public:
AFSpawner() AFSpawner()
{ {
_airfields = std::map<vec2i, Airfield*>(); _airfields = std::map<vec2i, Airfield*>();
_next_spawn = 1; _next_spawn = -1;
} }
void tick(float timestep, World *world) override; void tick(float timestep, World *world) override;
void draw(Renderer *rend) override; void draw(Renderer *rend) override;
Airfield *get_random_airfield(Airfield *exclude);
}; };
} // namespace dxd::sim } // namespace dxd::sim

View File

@@ -16,7 +16,7 @@ private:
int _trail_cooldown; int _trail_cooldown;
const int _TRAIL_DELAY = 120; const int _TRAIL_DELAY = 120;
const int _TRAIL_DURATION = 420; const int _TRAIL_DURATION = 600;
const float _MAX_TURN_RATE = 0.3f; const float _MAX_TURN_RATE = 0.3f;
const float _SPD_TO_KTS = 60.0f; const float _SPD_TO_KTS = 60.0f;

View File

@@ -8,15 +8,20 @@ void dxd::sim::Airfield::tick(float timestep, World *world)
if (--_ttl == 0) if (--_ttl == 0)
{ {
world->remove_obj(this); world->remove_obj(this);
//TODO: Free space in af_spawner
return; return;
} }
if (--_next_spawn == 0) if (--_next_spawn == 0)
{ {
vec2 pos = _position + polar_to_vec2(_rw_heading, _WR_LENGTH+0.5); vec2 pos = _position + polar_to_vec2(_rw_heading, _RW_LENGTH+0.5);
vec2 tgt = _position + polar_to_vec2(SDL_randf()*2*M_PIf, 30);
Aircraft *af = new Aircraft(pos, _rw_heading, 2.0f, tgt); Airfield *target = _parent->get_random_airfield(this);
vec2 tgt_pos = target->get_position();
Aircraft *af = new Aircraft(pos, _rw_heading, 2.0f, tgt_pos);
world->add_obj(af); world->add_obj(af);
_next_spawn = _MIN_TAKEOFF_DELAY + SDL_rand(_MAX_TAKEOFF_DELAY - _MIN_TAKEOFF_DELAY); _next_spawn = _MIN_TAKEOFF_DELAY + SDL_rand(_MAX_TAKEOFF_DELAY - _MIN_TAKEOFF_DELAY);
} }
} }
@@ -28,7 +33,7 @@ void dxd::sim::Airfield::draw(Renderer *rend)
rend->diamond(_position, 5); rend->diamond(_position, 5);
rend->color(64, 64, 255); rend->color(64, 64, 255);
vec2 a = _position + polar_to_vec2(_rw_heading, +_WR_LENGTH); vec2 a = _position + polar_to_vec2(_rw_heading, +_RW_LENGTH);
vec2 b = _position + polar_to_vec2(_rw_heading, -_WR_LENGTH); vec2 b = _position + polar_to_vec2(_rw_heading, -_RW_LENGTH);
rend->line(a, b); rend->line(a, b);
} }

View File

@@ -4,29 +4,35 @@
#include "../dxd_math.hpp" #include "../dxd_math.hpp"
#include "world_object.hpp" #include "world_object.hpp"
#include "af_spawner.hpp"
namespace dxd::sim namespace dxd::sim
{ {
class AFSpawner;
class Airfield : public WorldObject class Airfield : public WorldObject
{ {
private: private:
AFSpawner *_parent;
vec2 _position; vec2 _position;
int _ttl; int _ttl;
int _next_spawn; int _next_spawn;
float _rw_heading; float _rw_heading;
const int _MIN_TAKEOFF_DELAY = 240; int const _MIN_TAKEOFF_DELAY = 600;
const int _MAX_TAKEOFF_DELAY = 600; int const _MAX_TAKEOFF_DELAY = 3000;
const int _WR_LENGTH = 6; int const _RW_LENGTH = 6;
public: public:
Airfield(vec2 position, int ttl, float rw_heading) Airfield(AFSpawner *parent, vec2 position, int ttl, float rw_heading)
: _position(position), _ttl(ttl), _rw_heading(rw_heading) : _parent(parent), _position(position), _ttl(ttl), _rw_heading(rw_heading)
{ {
_next_spawn = _MIN_TAKEOFF_DELAY; _next_spawn = _MIN_TAKEOFF_DELAY;
} }
vec2 get_position() { return _position; }
void tick(float timestep, World *world) override; void tick(float timestep, World *world) override;
void draw(Renderer *rend) override; void draw(Renderer *rend) override;
}; };