From 49751ea09e2148ddc8f0762bcde5fdaa1a6b7a39 Mon Sep 17 00:00:00 2001 From: Grant Horner Date: Sun, 30 Nov 2025 21:00:04 -0500 Subject: [PATCH] refactor spawner --- main.cpp | 101 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/main.cpp b/main.cpp index ccd9abb..02b3e40 100644 --- a/main.cpp +++ b/main.cpp @@ -9,9 +9,7 @@ float screen_width = 800; float screen_height = 600; -Rectangle walls[] = { - // {.x = 100, .y = 100, .width = 5, .height = 100} -}; +Rectangle walls[] = {}; Player player; auto player_speed = 5.0f; @@ -29,7 +27,6 @@ double fire_rate = .5; std::mutex enemy_mutex; float enemy_max_speed = 3.0; float enemy_radius = 25.0; -Enemy enemies[100] = {}; struct Rng { static std::random_device dev; @@ -94,18 +91,22 @@ void Player::move(const float delta_x, const float delta_y) { } } -struct EnemySpawner { - std::mutex m; +template +struct Spawner { + std::mutex mutex; std::condition_variable cv; std::atomic running; std::atomic paused; - std::thread timer; + std::optional timer; 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) { } + virtual void spawn() {} + void start() { running.store(true); timer = std::thread([&] { @@ -113,50 +114,64 @@ struct EnemySpawner { const auto start = std::chrono::steady_clock::now(); if (!paused.load()) { - std::lock_guard lock(enemy_mutex); + std::lock_guard lock(mutex); - const auto num = Rng::generate(); - const auto starting_x = Rng::generate(static_cast(screen_width)); - const auto starting_y = Rng::generate(static_cast(screen_height)); - - for (auto &[center, radius, speed, alive]: enemies) { - if (alive) continue; - alive = true; - radius = enemy_radius; - if (num < 0.25) { - center = {.x = starting_x, .y = 0}; - } else if (0.25 <= num && num < 0.5) { - center = { - .x = starting_x, .y = (screen_height) - }; - } else if (0.5 <= num && num < 0.75) { - center = {.x = 0, .y = starting_y}; - } else { - center = { - .x = (screen_width), .y = starting_y - }; - } - - speed = Rng::generate(static_cast(enemy_max_speed)); - - break; - } + spawn(); } auto next = start + std::chrono::seconds(rate_secs); - std::unique_lock lock{m}; + std::unique_lock lock{mutex}; cv.wait_until(lock, next, [&] { return !running.load(); }); } }); } - ~EnemySpawner() { + virtual ~Spawner() { running.store(false); cv.notify_all(); - timer.join(); + if (timer) { + timer.value().join(); + } } }; +struct EnemySpawner final : Spawner { + explicit EnemySpawner(const long long rate_secs) + : Spawner(rate_secs) { + } + + void spawn() override { + const auto num = Rng::generate(); + const auto starting_x = Rng::generate(static_cast(screen_width)); + const auto starting_y = Rng::generate(static_cast(screen_height)); + + for (auto &[center, radius, speed, alive]: this->values) { + if (alive) continue; + alive = true; + radius = enemy_radius; + if (num < 0.25) { + center = {.x = starting_x, .y = 0}; + } else if (0.25 <= num && num < 0.5) { + center = { + .x = starting_x, .y = (screen_height) + }; + } else if (0.5 <= num && num < 0.75) { + center = {.x = 0, .y = starting_y}; + } else { + center = { + .x = (screen_width), .y = starting_y + }; + } + + speed = Rng::generate(static_cast(enemy_max_speed)); + + break; + } + } +}; + +EnemySpawner enemy_spawner{2}; + void spawn_tear(const Vector2 center, const Direction direction) { for (auto &[tear_center, tear_direction, tear_active, starting_center]: tears) { if (!tear_active) { @@ -179,8 +194,8 @@ void update_tears() { } } - for (auto &enemy: enemies) { - if (CheckCollisionCircles(center, tear_radius, enemy.center, enemy.radius)) { + for (auto &enemy: enemy_spawner.values) { + if (enemy.alive && CheckCollisionCircles(center, tear_radius, enemy.center, enemy.radius)) { active = false; enemy.alive = false; score++; @@ -213,8 +228,8 @@ int main() { InitWindow(800, 600, "Isaac++"); SetTargetFPS(60); - EnemySpawner spawner{2}; - spawner.start(); + + enemy_spawner.start(); player.width = 50; player.height = 50; @@ -283,7 +298,7 @@ int main() { { 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) { center = Vector2MoveTowards(center, player.center(), speed); DrawCircleV(center, radius, RED);