Compare commits
7 Commits
ef716b7425
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 668d8b47be | |||
| d1ff0e6a15 | |||
| 4e7f79dadc | |||
| b7c4a2fa36 | |||
| 153fb762af | |||
| 6cab255d92 | |||
| 2920749387 |
5
makefile
5
makefile
@@ -1,5 +1,5 @@
|
||||
CC=g++
|
||||
C_FLAGS=-g -Wall -Wextra -O0 -Wno-unused-function
|
||||
C_FLAGS=-g -Wall -Wextra -O0 -Wno-unused-function -MMD -MP
|
||||
VAL_FLAGS=--leak-check=full --show-leak-kinds=all --track-origins=yes -s
|
||||
|
||||
DIR_SRC=src
|
||||
@@ -11,6 +11,7 @@ OUTBIN=$(DIR_BUILD)/bin/main
|
||||
|
||||
SRCS=$(shell find $(DIR_SRC)/ -type f -name '*.cpp')
|
||||
OBJS=$(patsubst $(DIR_SRC)/%.cpp,$(DIR_BUILD)/obj/%.o,$(SRCS))
|
||||
DEPMF=$(patsubst $(DIR_SRC)/%.cpp,$(DIR_BUILD)/obj/%.d,$(SRCS))
|
||||
|
||||
DEPS_EXT=$(patsubst %,-l%,$(DEPS))
|
||||
INCS_EXT=$(patsubst %,-I%,$(DIR_INC))
|
||||
@@ -38,6 +39,8 @@ $(DIR_BUILD)/obj/%.o: $(DIR_SRC)/%.cpp
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(C_FLAGS) $(INCS_EXT) -c $< -o $@
|
||||
|
||||
-include $(DEPMF)
|
||||
|
||||
dbg: $(DBG_BIN)
|
||||
gdb $(GDB_FLAGS) ./$(OUTBIN)
|
||||
|
||||
|
||||
158
src/dxd_math.cpp
Normal file
158
src/dxd_math.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "dxd_math.hpp"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
vec2 operator+(vec2 const &v)
|
||||
{
|
||||
return { .x = v.x, .y = v.y };
|
||||
}
|
||||
|
||||
vec2 operator-(vec2 const &v)
|
||||
{
|
||||
return { .x = -v.x, .y = -v.y };
|
||||
}
|
||||
|
||||
vec2 operator+(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return { .x = a.x + b.x, .y = a.y + b.y };
|
||||
}
|
||||
|
||||
vec2 operator-(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return { .x = a.x - b.x, .y = a.y - b.y };
|
||||
}
|
||||
|
||||
vec2 operator*(vec2 const &a, float const &b)
|
||||
{
|
||||
return { .x = a.x * b, .y = a.y * b };
|
||||
}
|
||||
|
||||
vec2 operator/(vec2 const &a, float const &b)
|
||||
{
|
||||
return { .x = a.x / b, .y = a.y / b };
|
||||
}
|
||||
|
||||
bool operator<(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return a.x < b.x && a.y < b.y;
|
||||
}
|
||||
|
||||
bool operator>(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return a.x > b.x && a.y > b.y;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
float norm2(vec2 const &v)
|
||||
{
|
||||
return v.x * v.x + v.y * v.y;
|
||||
}
|
||||
|
||||
float norm(vec2 const &v)
|
||||
{
|
||||
return std::sqrtf(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 const &v)
|
||||
{
|
||||
return v / std::sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
vec2 min2(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return {
|
||||
.x = a.x < b.x ? a.x : b.x,
|
||||
.y = a.y < b.y ? a.y : b.y,
|
||||
};
|
||||
}
|
||||
|
||||
vec2 max2(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return {
|
||||
.x = a.x > b.x ? a.x : b.x,
|
||||
.y = a.y > b.y ? a.y : b.y,
|
||||
};
|
||||
}
|
||||
|
||||
vec2 polar_to_vec2(float const angle, float const len)
|
||||
{
|
||||
return {
|
||||
.x = len * sinf(angle),
|
||||
.y = len * cosf(angle)
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
while (a > 2*M_PIf) a -= 2*M_PIf;
|
||||
while (a < 0) a += 2*M_PIf;
|
||||
return a;
|
||||
}
|
||||
|
||||
float normalize_angle_diff(const float diff)
|
||||
{
|
||||
float d = diff;
|
||||
while (d > M_PIf) d -= 2*M_PIf;
|
||||
while (d < -M_PIf) d += 2*M_PIf;
|
||||
return d;
|
||||
}
|
||||
|
||||
float angle_to_heading(float const angle)
|
||||
{
|
||||
return normalize_angle(angle) * 180.0f / M_PIf;
|
||||
}
|
||||
|
||||
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) };
|
||||
}
|
||||
58
src/dxd_math.hpp
Normal file
58
src/dxd_math.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
|
||||
typedef struct vec2 { float x, y; } vec2;
|
||||
typedef struct vec2i { int x, y; } vec2i;
|
||||
|
||||
static const vec2 vec2_zero = { 0, 0 };
|
||||
static const vec2 vec2_one = { 1, 1 };
|
||||
static const vec2 vec2_unitx = { 1, 0 };
|
||||
static const vec2 vec2_unity = { 0, 1 };
|
||||
static const vec2 vec2_max = { FLT_MAX, FLT_MAX };
|
||||
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);
|
||||
vec2 operator-(vec2 const &a, vec2 const &b);
|
||||
vec2 operator*(vec2 const &a, float const &b);
|
||||
vec2 operator/(vec2 const &a, float const &b);
|
||||
bool operator<(vec2 const &a, vec2 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);
|
||||
|
||||
// vec2i functions
|
||||
vec2 v2i_to_v2(vec2i const v);
|
||||
|
||||
// Angle functions
|
||||
float normalize_angle(float const angle);
|
||||
float normalize_angle_diff(float const diff);
|
||||
float angle_to_heading(float const angle);
|
||||
|
||||
// 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);
|
||||
14
src/main.cpp
14
src/main.cpp
@@ -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;
|
||||
@@ -72,18 +72,24 @@ int main(int argc, char *argv[])
|
||||
if (key_states[SDL_SCANCODE_E]) renderer.zoom_camera(-zoom_spd * (1.0f / 60.0f));
|
||||
|
||||
// Clear
|
||||
renderer.color(0, 0, 0, 255);
|
||||
renderer.color(0, 0, 0);
|
||||
SDL_RenderClear(sdl_renderer);
|
||||
|
||||
// World draw
|
||||
world.draw(&renderer);
|
||||
world.tick(1.0f / 60.0f);
|
||||
|
||||
// Usual test
|
||||
renderer.color(64, 64, 64, 255);
|
||||
// World axis
|
||||
renderer.color(32, 32, 32);
|
||||
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);
|
||||
renderer.dbg_txt(0, 0, "(%0.1f, %0.1f) @%0.2f", center.x, center.y, zoom);
|
||||
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
SDL_Delay(1000 / 60);
|
||||
}
|
||||
|
||||
109
src/math.hpp
109
src/math.hpp
@@ -1,109 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
//#define epsilon 0.0000001
|
||||
|
||||
|
||||
|
||||
typedef struct vec2 { float x, y; } vec2;
|
||||
typedef struct vec2i { int x, y; } vec2i;
|
||||
|
||||
static const vec2 vec2_zero = { 0, 0 };
|
||||
static const vec2 vec2_one = { 1, 1 };
|
||||
static const vec2 vec2_unitx = { 1, 0 };
|
||||
static const vec2 vec2_unity = { 0, 1 };
|
||||
static const vec2 vec2_max = { FLT_MAX, FLT_MAX };
|
||||
static const vec2 vec2_min = { -FLT_MAX, -FLT_MAX };
|
||||
static const vec2i vec2i_zero = { 0, 0 };
|
||||
static const vec2i vec2i_one = { 1, 1 };
|
||||
|
||||
static vec2 operator+(vec2 const &v)
|
||||
{
|
||||
return { .x = v.x, .y = v.y };
|
||||
}
|
||||
|
||||
static vec2 operator-(vec2 const &v)
|
||||
{
|
||||
return { .x = -v.x, .y = -v.y };
|
||||
}
|
||||
|
||||
static vec2 operator+(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return { .x = a.x + b.x, .y = a.y + b.y };
|
||||
}
|
||||
|
||||
static vec2 operator-(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return { .x = a.x - b.x, .y = a.y - b.y };
|
||||
}
|
||||
|
||||
static vec2 operator*(vec2 const &a, float const &b)
|
||||
{
|
||||
return { .x = a.x * b, .y = a.y * b };
|
||||
}
|
||||
|
||||
static vec2 operator/(vec2 const &a, float const &b)
|
||||
{
|
||||
return { .x = a.x / b, .y = a.y / b };
|
||||
}
|
||||
|
||||
static bool operator<(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return a.x < b.x && a.y < b.y;
|
||||
}
|
||||
|
||||
static bool operator>(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return a.x > b.x && a.y > b.y;
|
||||
}
|
||||
|
||||
static float dot(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y;
|
||||
}
|
||||
|
||||
static float norm2(vec2 const &v)
|
||||
{
|
||||
return v.x * v.x + v.y * v.y;
|
||||
}
|
||||
|
||||
static float norm(vec2 const &v)
|
||||
{
|
||||
return std::sqrtf(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
static vec2 normalize(vec2 const &v)
|
||||
{
|
||||
return v / norm(v);
|
||||
}
|
||||
|
||||
static inline vec2 normalize_h(vec2 const &v)
|
||||
{
|
||||
return v / std::sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
static vec2 min2(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return {
|
||||
.x = a.x < b.x ? a.x : b.x,
|
||||
.y = a.y < b.y ? a.y : b.y,
|
||||
};
|
||||
}
|
||||
|
||||
static vec2 max2(vec2 const &a, vec2 const &b)
|
||||
{
|
||||
return {
|
||||
.x = a.x > b.x ? a.x : b.x,
|
||||
.y = a.y > b.y ? a.y : b.y,
|
||||
};
|
||||
}
|
||||
|
||||
static vec2 polar_to_vec2(const float angle, const float len)
|
||||
{
|
||||
return {
|
||||
.x = len * sinf(angle),
|
||||
.y = len * cosf(angle)
|
||||
};
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "dxd_math.hpp"
|
||||
|
||||
namespace dxd
|
||||
{
|
||||
@@ -60,14 +60,19 @@ public:
|
||||
_scale /= 1 + delta;
|
||||
}
|
||||
|
||||
vec2 get_camera_pos()
|
||||
{
|
||||
return _center;
|
||||
}
|
||||
|
||||
float get_zoom()
|
||||
{
|
||||
return 1.0f / _scale;
|
||||
}
|
||||
|
||||
void color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
void color(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
SDL_SetRenderDrawColor(_sdl, r, g, b, a);
|
||||
SDL_SetRenderDrawColor(_sdl, r, g, b, 255);
|
||||
}
|
||||
|
||||
void line(vec2 a, vec2 b)
|
||||
@@ -120,6 +125,31 @@ public:
|
||||
points[4] = points[0];
|
||||
SDL_RenderLines(_sdl, points, 5);
|
||||
}
|
||||
|
||||
void dbg_txt(float const x, float const y, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
SDL_RenderDebugTextFormat(_sdl, x, y, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void txt(vec2 const pos, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
char buf[128];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
|
||||
vec2 p = to_screenv2(to_viewv2(pos));
|
||||
SDL_RenderDebugText(_sdl, p.x, p.y, buf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dxd
|
||||
|
||||
@@ -1,17 +1,64 @@
|
||||
#include "af_spawner.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
void dxd::sim::AFSpawner::spawn_airfield(World *world)
|
||||
{
|
||||
vec2i base_pos;
|
||||
//TODO: Iter 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(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);
|
||||
|
||||
//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};
|
||||
Airfield *af = new Airfield(pos, _MIN_AF_TTL + SDL_rand(_MAX_AF_TTL));
|
||||
world->add_obj(af);
|
||||
_airfields.push_back(af);
|
||||
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;
|
||||
if (!af->is_active())
|
||||
af = exclude;
|
||||
} while(af == exclude);
|
||||
|
||||
return af;
|
||||
}
|
||||
|
||||
@@ -1,34 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "../math.hpp"
|
||||
#include "../dxd_math.hpp"
|
||||
#include "world_object.hpp"
|
||||
#include "airfield.hpp"
|
||||
|
||||
namespace dxd::sim
|
||||
{
|
||||
|
||||
class Airfield;
|
||||
|
||||
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 = 10;
|
||||
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;
|
||||
|
||||
void spawn_airfield(World *world);
|
||||
|
||||
public:
|
||||
AFSpawner()
|
||||
{
|
||||
_airfields = std::vector<Airfield*>();
|
||||
_next_spawn = 1;
|
||||
_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;
|
||||
|
||||
Airfield *get_random_airfield(Airfield *exclude);
|
||||
};
|
||||
|
||||
} // namespace dxd::sim
|
||||
|
||||
@@ -3,8 +3,25 @@
|
||||
|
||||
void dxd::sim::Aircraft::tick(float timestep, World *world)
|
||||
{
|
||||
(void)world;
|
||||
// Refactor into own function
|
||||
float target_dist = norm2(_target - _position);
|
||||
if (target_dist < _TARGET_REACHED_DIST2)
|
||||
{
|
||||
if (_target == _destination->get_position())
|
||||
{
|
||||
_destination->arrived_at();
|
||||
world->remove_obj(this);
|
||||
}
|
||||
_target = _destination->get_position();
|
||||
}
|
||||
|
||||
float target_angle = vec2_angle(_target - _position);
|
||||
float target_deviation = target_angle - _direction;
|
||||
|
||||
target_deviation = normalize_angle_diff(target_deviation);
|
||||
|
||||
_direction += SDL_clamp(target_deviation, -_MAX_TURN_RATE, _MAX_TURN_RATE) * timestep;
|
||||
_direction = normalize_angle(_direction);
|
||||
_position = _position + polar_to_vec2(_direction, _speed) * timestep;
|
||||
|
||||
if (--_trail_cooldown == 0)
|
||||
@@ -16,7 +33,17 @@ void dxd::sim::Aircraft::tick(float timestep, World *world)
|
||||
|
||||
void dxd::sim::Aircraft::draw(Renderer *rend)
|
||||
{
|
||||
rend->color(255, 255, 255, 255);
|
||||
// Indicator
|
||||
rend->color(255, 255, 255);
|
||||
rend->box(_position, 1);
|
||||
rend->line(_position, _position + polar_to_vec2(_direction, 3));
|
||||
|
||||
// Status
|
||||
rend->color(0, 255, 0);
|
||||
rend->txt(_position - vec2_unity, "%03.0f", angle_to_heading(_direction));
|
||||
rend->txt(_position - vec2_unity*2.5f, "%03.0f", _speed * _SPD_TO_KTS);
|
||||
|
||||
// Target
|
||||
rend->color(255, 64, 64);
|
||||
rend->diamond(_target, 1);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../math.hpp"
|
||||
#include "../dxd_math.hpp"
|
||||
#include "world_object.hpp"
|
||||
#include "airfield.hpp"
|
||||
|
||||
namespace dxd::sim
|
||||
{
|
||||
@@ -12,16 +13,24 @@ private:
|
||||
vec2 _position;
|
||||
float _direction;
|
||||
float _speed;
|
||||
Airfield *_destination;
|
||||
vec2 _target;
|
||||
int _trail_cooldown;
|
||||
|
||||
const int _TRAIL_DELAY = 60;
|
||||
const int _TRAIL_DURATION = 420;
|
||||
const int _TRAIL_DELAY = 120;
|
||||
const int _TRAIL_DURATION = 600;
|
||||
const float _MAX_TURN_RATE = 0.3f;
|
||||
const float _SPD_TO_KTS = 60.0f;
|
||||
const float _TARGET_REACHED_DIST = 0.5f;
|
||||
const float _TARGET_REACHED_DIST2 = _TARGET_REACHED_DIST*_TARGET_REACHED_DIST;
|
||||
|
||||
public:
|
||||
Aircraft(vec2 position, float direction, float speed)
|
||||
: _position(position), _direction(direction), _speed(speed)
|
||||
Aircraft(vec2 position, float direction, float speed, Airfield *destination)
|
||||
: _position(position), _direction(direction), _speed(speed), _destination(destination)
|
||||
{
|
||||
_trail_cooldown = _TRAIL_DELAY;
|
||||
_target = destination->get_approach_point();
|
||||
destination->going_to();
|
||||
}
|
||||
|
||||
void tick(float timestep, World *world) override;
|
||||
|
||||
@@ -13,6 +13,6 @@ void dxd::sim::AircraftTrail::tick(float timestep, World *world)
|
||||
|
||||
void dxd::sim::AircraftTrail::draw(Renderer *rend)
|
||||
{
|
||||
rend->color(128, 128, 128, 255);
|
||||
rend->color(128, 128, 128);
|
||||
rend->box(_position, .5);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../math.hpp"
|
||||
#include "../dxd_math.hpp"
|
||||
#include "world_object.hpp"
|
||||
|
||||
namespace dxd::sim
|
||||
|
||||
@@ -5,23 +5,42 @@ void dxd::sim::Airfield::tick(float timestep, World *world)
|
||||
{
|
||||
(void)timestep;
|
||||
|
||||
if (--_ttl == 0)
|
||||
if (--_ttl <= 0)
|
||||
{
|
||||
world->remove_obj(this);
|
||||
if (_pending_arrivals == 0)
|
||||
{
|
||||
world->remove_obj(this);
|
||||
//TODO: Free space in af_spawner
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (--_next_spawn == 0)
|
||||
{
|
||||
Aircraft *af = new Aircraft(_position, SDL_randf() * 2 * M_PIf, 5.0f);
|
||||
vec2 pos = _position + polar_to_vec2(_rw_heading, _RW_LENGTH+0.5);
|
||||
|
||||
Airfield *target = _parent->get_random_airfield(this);
|
||||
|
||||
Aircraft *af = new Aircraft(pos, _rw_heading, 2.0f, target);
|
||||
world->add_obj(af);
|
||||
|
||||
_next_spawn = _MIN_TAKEOFF_DELAY + SDL_rand(_MAX_TAKEOFF_DELAY - _MIN_TAKEOFF_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void dxd::sim::Airfield::draw(Renderer *rend)
|
||||
{
|
||||
rend->color(127, 127, 127, 255);
|
||||
rend->color(127, 127, 127);
|
||||
rend->rect(_position, 5);
|
||||
rend->diamond(_position, 5);
|
||||
|
||||
rend->color(64, 64, 255);
|
||||
vec2 a = _position + polar_to_vec2(_rw_heading, +_RW_LENGTH);
|
||||
vec2 b = _position + polar_to_vec2(_rw_heading, -_RW_LENGTH);
|
||||
rend->line(a, b);
|
||||
}
|
||||
|
||||
vec2 dxd::sim::Airfield::get_approach_point()
|
||||
{
|
||||
return _position - polar_to_vec2(_rw_heading, _RW_LENGTH + _APPROACH_DIST);
|
||||
}
|
||||
|
||||
@@ -2,28 +2,44 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../math.hpp"
|
||||
#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;
|
||||
int _pending_arrivals;
|
||||
|
||||
int const _MIN_TAKEOFF_DELAY = 600;
|
||||
int const _MAX_TAKEOFF_DELAY = 3000;
|
||||
int const _RW_LENGTH = 6;
|
||||
float const _APPROACH_DIST = 20.0f;
|
||||
|
||||
public:
|
||||
Airfield(vec2 position, int ttl) : _position(position), _ttl(ttl)
|
||||
Airfield(AFSpawner *parent, vec2 position, int ttl, float rw_heading)
|
||||
: _parent(parent), _position(position), _ttl(ttl), _rw_heading(rw_heading)
|
||||
{
|
||||
_next_spawn = 30;
|
||||
_next_spawn = _MIN_TAKEOFF_DELAY;
|
||||
}
|
||||
|
||||
vec2 get_position() { return _position; }
|
||||
vec2 get_approach_point();
|
||||
void going_to() { ++_pending_arrivals; }
|
||||
void arrived_at() { --_pending_arrivals; }
|
||||
bool is_active() { return _ttl > 0; }
|
||||
|
||||
void tick(float timestep, World *world) override;
|
||||
void draw(Renderer *rend) override;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../math.hpp"
|
||||
#include "../dxd_math.hpp"
|
||||
#include "world_object.hpp"
|
||||
|
||||
namespace dxd::sim
|
||||
@@ -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*>();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../math.hpp"
|
||||
#include "../dxd_math.hpp"
|
||||
#include "../renderer.hpp"
|
||||
#include "world.hpp"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user