refactor spawner

This commit is contained in:
2025-11-30 21:00:04 -05:00
parent b77af66c9c
commit 49751ea09e

View File

@@ -9,9 +9,7 @@
float screen_width = 800; float screen_width = 800;
float screen_height = 600; float screen_height = 600;
Rectangle walls[] = { Rectangle walls[] = {};
// {.x = 100, .y = 100, .width = 5, .height = 100}
};
Player player; Player player;
auto player_speed = 5.0f; auto player_speed = 5.0f;
@@ -29,7 +27,6 @@ double fire_rate = .5;
std::mutex enemy_mutex; std::mutex enemy_mutex;
float enemy_max_speed = 3.0; float enemy_max_speed = 3.0;
float enemy_radius = 25.0; float enemy_radius = 25.0;
Enemy enemies[100] = {};
struct Rng { struct Rng {
static std::random_device dev; static std::random_device dev;
@@ -94,18 +91,22 @@ void Player::move(const float delta_x, const float delta_y) {
} }
} }
struct EnemySpawner { template <typename T, size_t N>
std::mutex m; struct Spawner {
std::mutex mutex;
std::condition_variable cv; std::condition_variable cv;
std::atomic<bool> running; std::atomic<bool> running;
std::atomic<bool> paused; std::atomic<bool> paused;
std::thread timer; std::optional<std::thread> timer;
long long rate_secs; long long rate_secs;
T values[N];
explicit EnemySpawner(const long long rate_secs) explicit Spawner(const long long rate_secs)
: rate_secs(rate_secs) { : rate_secs(rate_secs) {
} }
virtual void spawn() {}
void start() { void start() {
running.store(true); running.store(true);
timer = std::thread([&] { timer = std::thread([&] {
@@ -113,13 +114,38 @@ struct EnemySpawner {
const auto start = std::chrono::steady_clock::now(); const auto start = std::chrono::steady_clock::now();
if (!paused.load()) { if (!paused.load()) {
std::lock_guard lock(enemy_mutex); std::lock_guard lock(mutex);
spawn();
}
auto next = start + std::chrono::seconds(rate_secs);
std::unique_lock lock{mutex};
cv.wait_until(lock, next, [&] { return !running.load(); });
}
});
}
virtual ~Spawner() {
running.store(false);
cv.notify_all();
if (timer) {
timer.value().join();
}
}
};
struct EnemySpawner final : Spawner<Enemy, 100> {
explicit EnemySpawner(const long long rate_secs)
: Spawner<Enemy, 100>(rate_secs) {
}
void spawn() override {
const auto num = Rng::generate(); const auto num = Rng::generate();
const auto starting_x = Rng::generate(static_cast<uint32_t>(screen_width)); const auto starting_x = Rng::generate(static_cast<uint32_t>(screen_width));
const auto starting_y = Rng::generate(static_cast<uint32_t>(screen_height)); const auto starting_y = Rng::generate(static_cast<uint32_t>(screen_height));
for (auto &[center, radius, speed, alive]: enemies) { for (auto &[center, radius, speed, alive]: this->values) {
if (alive) continue; if (alive) continue;
alive = true; alive = true;
radius = enemy_radius; radius = enemy_radius;
@@ -142,21 +168,10 @@ struct EnemySpawner {
break; break;
} }
} }
auto next = start + std::chrono::seconds(rate_secs);
std::unique_lock lock{m};
cv.wait_until(lock, next, [&] { return !running.load(); });
}
});
}
~EnemySpawner() {
running.store(false);
cv.notify_all();
timer.join();
}
}; };
EnemySpawner enemy_spawner{2};
void spawn_tear(const Vector2 center, const Direction direction) { void spawn_tear(const Vector2 center, const Direction direction) {
for (auto &[tear_center, tear_direction, tear_active, starting_center]: tears) { for (auto &[tear_center, tear_direction, tear_active, starting_center]: tears) {
if (!tear_active) { if (!tear_active) {
@@ -179,8 +194,8 @@ void update_tears() {
} }
} }
for (auto &enemy: enemies) { for (auto &enemy: enemy_spawner.values) {
if (CheckCollisionCircles(center, tear_radius, enemy.center, enemy.radius)) { if (enemy.alive && CheckCollisionCircles(center, tear_radius, enemy.center, enemy.radius)) {
active = false; active = false;
enemy.alive = false; enemy.alive = false;
score++; score++;
@@ -213,8 +228,8 @@ int main() {
InitWindow(800, 600, "Isaac++"); InitWindow(800, 600, "Isaac++");
SetTargetFPS(60); SetTargetFPS(60);
EnemySpawner spawner{2};
spawner.start(); enemy_spawner.start();
player.width = 50; player.width = 50;
player.height = 50; player.height = 50;
@@ -283,7 +298,7 @@ int main() {
{ {
std::lock_guard enemy_guard{enemy_mutex}; std::lock_guard enemy_guard{enemy_mutex};
for (auto &[center, radius, speed, alive]: enemies) { for (auto &[center, radius, speed, alive]: enemy_spawner.values) {
if (alive) { if (alive) {
center = Vector2MoveTowards(center, player.center(), speed); center = Vector2MoveTowards(center, player.center(), speed);
DrawCircleV(center, radius, RED); DrawCircleV(center, radius, RED);