refactor spawner
This commit is contained in:
71
main.cpp
71
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 <typename T, size_t N>
|
||||
struct Spawner {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::atomic<bool> running;
|
||||
std::atomic<bool> paused;
|
||||
std::thread timer;
|
||||
std::optional<std::thread> 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,13 +114,38 @@ struct EnemySpawner {
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
|
||||
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 starting_x = Rng::generate(static_cast<uint32_t>(screen_width));
|
||||
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;
|
||||
alive = true;
|
||||
radius = enemy_radius;
|
||||
@@ -142,21 +168,10 @@ struct EnemySpawner {
|
||||
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) {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user