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>
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;
//TODO: Set limiter
//TODO: Iter limiter
do
base_pos = rand_v2i({ -_GRID_BOUNDS, -_GRID_BOUNDS }, { _GRID_BOUNDS, _GRID_BOUNDS });
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 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);
_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)
{
rend->color(0, 127, 0);
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
{
class Airfield;
class AFSpawner : public WorldObject
{
private:
@@ -27,15 +29,19 @@ private:
const int _MIN_AF_TTL = 3000;
const int _MAX_AF_TTL = 9000;
void spawn_airfield(World *world);
public:
AFSpawner()
{
_airfields = std::map<vec2i, Airfield*>();
_next_spawn = 1;
_next_spawn = -1;
}
void tick(float timestep, World *world) override;
void draw(Renderer *rend) override;
Airfield *get_random_airfield(Airfield *exclude);
};
} // namespace dxd::sim

View File

@@ -16,7 +16,7 @@ private:
int _trail_cooldown;
const int _TRAIL_DELAY = 120;
const int _TRAIL_DURATION = 420;
const int _TRAIL_DURATION = 600;
const float _MAX_TURN_RATE = 0.3f;
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)
{
world->remove_obj(this);
//TODO: Free space in af_spawner
return;
}
if (--_next_spawn == 0)
{
vec2 pos = _position + polar_to_vec2(_rw_heading, _WR_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);
vec2 pos = _position + polar_to_vec2(_rw_heading, _RW_LENGTH+0.5);
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);
_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->color(64, 64, 255);
vec2 a = _position + polar_to_vec2(_rw_heading, +_WR_LENGTH);
vec2 b = _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, -_RW_LENGTH);
rend->line(a, b);
}

View File

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