refactor spawner
This commit is contained in:
101
main.cpp
101
main.cpp
@@ -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,50 +114,64 @@ 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);
|
||||||
|
|
||||||
const auto num = Rng::generate();
|
spawn();
|
||||||
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) {
|
|
||||||
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<uint32_t>(enemy_max_speed));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto next = start + std::chrono::seconds(rate_secs);
|
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(); });
|
cv.wait_until(lock, next, [&] { return !running.load(); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
~EnemySpawner() {
|
virtual ~Spawner() {
|
||||||
running.store(false);
|
running.store(false);
|
||||||
cv.notify_all();
|
cv.notify_all();
|
||||||
timer.join();
|
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]: 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<uint32_t>(enemy_max_speed));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user