feat: Grid af spawning

This commit is contained in:
2026-04-23 22:26:43 +01:00
parent 153fb762af
commit b7c4a2fa36
9 changed files with 121 additions and 25 deletions

View File

@@ -1,5 +1,7 @@
#include "dxd_math.hpp"
#include <SDL3/SDL.h>
vec2 operator+(vec2 const &v)
{
return { .x = v.x, .y = v.y };
@@ -40,6 +42,16 @@ bool operator>(vec2 const &a, vec2 const &b)
return a.x > b.x && a.y > b.y;
}
bool operator<(vec2i const &a, vec2i const &b)
{
return a.x < b.x && a.y < b.y;
}
bool operator>(vec2i const &a, vec2i const &b)
{
return a.x > b.x && a.y > b.y;
}
float dot(vec2 const &a, vec2 const &b)
{
return a.x * b.x + a.y * b.y;
@@ -76,7 +88,7 @@ vec2 max2(vec2 const &a, vec2 const &b)
};
}
vec2 polar_to_vec2(const float angle, const float len)
vec2 polar_to_vec2(float const angle, float const len)
{
return {
.x = len * sinf(angle),
@@ -84,11 +96,16 @@ vec2 polar_to_vec2(const float angle, const float len)
};
}
float vec2_angle(const vec2 v)
float vec2_angle(vec2 const v)
{
return atan2f(v.x, v.y);
}
vec2 v2i_to_v2(vec2i const v)
{
return { (float)v.x, (float)v.y };
}
float normalize_angle(const float angle)
{
float a = angle;
@@ -104,3 +121,28 @@ float normalize_angle_diff(const float diff)
while (d < -M_PIf) d += 2*M_PIf;
return d;
}
int rand_int(int const min, int const max)
{
return SDL_rand(max - min) + min;
}
float rand_float(float const min, float const max)
{
return SDL_randf() * (max - min) + min;
}
float rand_angle()
{
return rand_float(0, 2*M_PIf);
}
vec2i rand_v2i(vec2i const min, vec2i const max)
{
return { rand_int(min.x, max.x), rand_int(min.y, max.y) };
}
vec2 rand_v2(vec2 const min, vec2 const max)
{
return { rand_float(min.x, max.x), rand_float(min.y, max.y) };
}

View File

@@ -17,6 +17,7 @@ static const vec2 vec2_min = { -FLT_MAX, -FLT_MAX };
static const vec2i vec2i_zero = { 0, 0 };
static const vec2i vec2i_one = { 1, 1 };
// vec2 operators
vec2 operator+(vec2 const &v);
vec2 operator-(vec2 const &v);
vec2 operator+(vec2 const &a, vec2 const &b);
@@ -26,15 +27,30 @@ vec2 operator/(vec2 const &a, float const &b);
bool operator<(vec2 const &a, vec2 const &b);
bool operator>(vec2 const &a, vec2 const &b);
// vec2i operators
bool operator<(vec2i const &a, vec2i const &b);
bool operator>(vec2i const &a, vec2i const &b);
// vec2 functions
float dot(vec2 const &a, vec2 const &b);
float norm2(vec2 const &v);
float norm(vec2 const &v);
vec2 normalize(vec2 const &v);
vec2 min2(vec2 const &a, vec2 const &b);
vec2 max2(vec2 const &a, vec2 const &b);
vec2 polar_to_vec2(float const angle, float const len);
float vec2_angle(vec2 const v);
vec2 polar_to_vec2(const float angle, const float len);
float vec2_angle(const vec2 v);
// vec2i functions
vec2 v2i_to_v2(vec2i const v);
float normalize_angle(const float angle);
float normalize_angle_diff(const float diff);
// Angle functions
float normalize_angle(float const angle);
float normalize_angle_diff(float const diff);
// Random generation functions
int rand_int(int const min, int const max);
float rand_float(float const min, float const max);
float rand_angle();
vec2i rand_v2i(vec2i const min, vec2i const max);
vec2 rand_v2(vec2 const min, vec2 const max);

View File

@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
dxd::Renderer renderer = dxd::Renderer(sdl_renderer, width, height);
// World init
dxd::sim::World world = dxd::sim::World({ .x = 10, .y = 10 });
dxd::sim::World world = dxd::sim::World();
world.add_obj(new dxd::sim::AFSpawner());
SDL_Event event;
@@ -79,11 +79,17 @@ int main(int argc, char *argv[])
world.draw(&renderer);
world.tick(1.0f / 60.0f);
// Usual test
renderer.color(64, 64, 64, 255);
// World axis
renderer.color(32, 32, 32, 255);
renderer.line(-vec2_unity * 2000, vec2_unity * 2000);
renderer.line(-vec2_unitx * 2000, vec2_unitx * 2000);
// Scale and position
vec2 center = renderer.get_camera_pos();
float zoom = 100.0f/renderer.get_zoom();
renderer.color(128, 128, 255, 255);
renderer.dbg_txt(0, 0, "(%0.1f, %0.1f) @%0.2f", center.x, center.y, zoom);
SDL_RenderPresent(sdl_renderer);
SDL_Delay(1000 / 60);
}

View File

@@ -60,6 +60,11 @@ public:
_scale /= 1 + delta;
}
vec2 get_camera_pos()
{
return _center;
}
float get_zoom()
{
return 1.0f / _scale;
@@ -120,6 +125,16 @@ public:
points[4] = points[0];
SDL_RenderLines(_sdl, points, 5);
}
void dbg_txt(float x, float y, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
SDL_RenderDebugTextFormat(_sdl, x, y, fmt, args);
va_end(args);
}
};
} // namespace dxd

View File

@@ -11,9 +11,22 @@ void dxd::sim::AFSpawner::tick(float timestep, World *world)
_next_spawn = _MIN_SPAWN_DELAY + SDL_rand(_MAX_SPAWN_DELAY);
//Pos should spawn in a grid, check if free, and offset random from grid coord to look natural
vec2 pos = {(SDL_randf()-.5f)*2*60.0f, (SDL_randf()-.5f)*2*60.0f};
vec2i base_pos;
//TODO: Set limiter
do
base_pos = rand_v2i({ -_GRID_BOUNDS, -_GRID_BOUNDS }, { _GRID_BOUNDS, _GRID_BOUNDS });
while (_airfields.find(base_pos) != _airfields.end());
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);
world->add_obj(af);
_airfields.push_back(af);
_airfields.emplace(base_pos, af);
}
void dxd::sim::AFSpawner::draw(Renderer *rend)
{
rend->color(0, 127, 0, 255);
rend->rect(vec2_zero, _SPAWN_BOUNDS*2);
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <map>
#include "../dxd_math.hpp"
#include "world_object.hpp"
@@ -12,23 +13,29 @@ namespace dxd::sim
class AFSpawner : public WorldObject
{
private:
std::vector<Airfield*> _airfields;
std::map<vec2i, Airfield*> _airfields;
int _next_spawn;
const int _SPAWN_BOUNDS = 150;
const int _GRID_STRIDE = 4;
const int _GRID_MARGIN = 5;
const int _GRID_BOUNDS = (_SPAWN_BOUNDS - _GRID_MARGIN * 2) / _GRID_STRIDE;
const float _GRID_JITTER = (float)_GRID_STRIDE * 0.4f;
const int _MIN_SPAWN_DELAY = 450;
const int _MAX_SPAWN_DELAY = 3000;
const int _MIN_AF_TTL = 1200;
const int _MAX_AF_TTL = 6000;
const int _MIN_AF_TTL = 3000;
const int _MAX_AF_TTL = 9000;
public:
AFSpawner()
{
_airfields = std::vector<Airfield*>();
_airfields = std::map<vec2i, Airfield*>();
_next_spawn = 1;
}
void tick(float timestep, World *world) override;
void draw(Renderer *rend) override { (void)rend; }
void draw(Renderer *rend) override;
};
} // namespace dxd::sim

View File

@@ -17,7 +17,7 @@ private:
const int _TRAIL_DELAY = 60;
const int _TRAIL_DURATION = 420;
const float _MAX_TURN_RATE = 0.5f;
const float _MAX_TURN_RATE = 0.3f;
public:
Aircraft(vec2 position, float direction, float speed, vec2 target)

View File

@@ -14,12 +14,10 @@ void dxd::sim::Airfield::tick(float timestep, World *world)
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);
vec2 tgt = _position + polar_to_vec2(0, 30);
Aircraft *af = new Aircraft(pos, _rw_heading, 5.0f, tgt);
vec2 tgt = _position + polar_to_vec2(SDL_randf()*2*M_PIf, 30);
Aircraft *af = new Aircraft(pos, _rw_heading, 2.0f, tgt);
world->add_obj(af);
//_next_spawn = _MIN_TAKEOFF_DELAY + SDL_rand(_MAX_TAKEOFF_DELAY - _MIN_TAKEOFF_DELAY);
_next_spawn = 99999999;
_next_spawn = _MIN_TAKEOFF_DELAY + SDL_rand(_MAX_TAKEOFF_DELAY - _MIN_TAKEOFF_DELAY);
}
}

View File

@@ -13,13 +13,12 @@ class WorldObject;
class World
{
private:
vec2 _size;
std::vector<WorldObject*> _objs;
std::vector<WorldObject*> _pending_removes;
std::vector<WorldObject*> _pending_adds;
public:
World(vec2 size) : _size(size)
World()
{
_objs = std::vector<WorldObject*>();
_pending_adds = std::vector<WorldObject*>();