diff --git a/main.cpp b/main.cpp index 20363f9..ccd9abb 100644 --- a/main.cpp +++ b/main.cpp @@ -15,6 +15,7 @@ Rectangle walls[] = { Player player; auto player_speed = 5.0f; +auto player_invulnerability = 1.0f; uint32_t score; @@ -26,7 +27,7 @@ double last_fired = 0; double fire_rate = .5; std::mutex enemy_mutex; -float enemy_max_speed = 2.0; +float enemy_max_speed = 3.0; float enemy_radius = 25.0; Enemy enemies[100] = {}; @@ -54,6 +55,14 @@ Vector2 Player::center() const noexcept { return {.x = this->x + this->width / 2, .y = this->y + this->height / 2}; } +Rectangle Player::rect() const noexcept { + return {.x = x, .y = y, .width = width, .height = height}; +} + +bool Player::is_invulnerable(const double now) const noexcept { + return now < this->last_hit + player_invulnerability; +} + void Player::move(const float delta_x, const float delta_y) { const auto x = std::min( std::max(this->x + delta_x, 0.0f), @@ -110,31 +119,25 @@ struct EnemySpawner { const auto starting_x = Rng::generate(static_cast(screen_width)); const auto starting_y = Rng::generate(static_cast(screen_height)); - for (auto &[center, radius, moving, alive]: enemies) { + for (auto &[center, radius, speed, alive]: enemies) { if (alive) continue; alive = true; radius = enemy_radius; - const float normalized_dir = Rng::generate(-1, 1); if (num < 0.25) { center = {.x = starting_x, .y = 0}; - moving = {.x = normalized_dir, .y = 1}; } else if (0.25 <= num && num < 0.5) { center = { .x = starting_x, .y = (screen_height) }; - moving = {.x = normalized_dir, .y = -1}; } else if (0.5 <= num && num < 0.75) { center = {.x = 0, .y = starting_y}; - moving = {.x = 1, .y = normalized_dir}; } else { center = { .x = (screen_width), .y = starting_y }; - moving = {.x = -1, .y = normalized_dir}; } - const auto speed = Rng::generate(static_cast(enemy_max_speed)); - moving = Vector2Scale(moving, speed); + speed = Rng::generate(static_cast(enemy_max_speed)); break; } @@ -210,17 +213,21 @@ int main() { InitWindow(800, 600, "Isaac++"); SetTargetFPS(60); - EnemySpawner spawner{3}; + EnemySpawner spawner{2}; spawner.start(); player.width = 50; player.height = 50; player.x = screen_width / 2 - player.width / 2; player.y = screen_height / 2 - player.height / 2; + player.lives = 3; + player.last_hit = -10; - std::string score_text_buffer{64}; + std::string score_text_buffer; score_text_buffer.reserve(64); - score_text_buffer.clear(); + + std::string lives_text_buffer; + lives_text_buffer.reserve(64); while (!WindowShouldClose()) { if (IsWindowResized()) { @@ -252,7 +259,8 @@ int main() { tear_direction = DOWN; } - if (const auto now = GetTime(); last_fired + fire_rate < now && tear_direction.has_value()) { + const auto now = GetTime(); + if (last_fired + fire_rate < now && tear_direction.has_value()) { last_fired = now; spawn_tear(player.center(), tear_direction.value()); } @@ -261,7 +269,7 @@ int main() { BeginDrawing(); ClearBackground(RAYWHITE); - DrawRectangleRec(player, BLUE); + DrawRectangleRec(player.rect(), player.is_invulnerable(now) ? GOLD : BLUE); for (const auto wall: walls) { DrawRectangleRec(wall, GREEN); @@ -275,15 +283,21 @@ int main() { { std::lock_guard enemy_guard{enemy_mutex}; - for (auto &[center, radius, moving, alive]: enemies) { + for (auto &[center, radius, speed, alive]: enemies) { if (alive) { - center = Vector2Add(center, moving); + center = Vector2MoveTowards(center, player.center(), speed); DrawCircleV(center, radius, RED); if (center.x < 0 || screen_width < center.x || center.y < 0 || screen_height < center.y) { alive = false; } + + if (CheckCollisionCircleRec(center, radius, player.rect()) && + player.last_hit + player_invulnerability < now) { + player.lives--; + player.last_hit = now; + } } } } @@ -292,6 +306,10 @@ int main() { DrawText(score_text_buffer.c_str(), 50, static_cast(screen_height) - 100, 20, BLACK); score_text_buffer.clear(); + std::format_to(std::back_inserter(lives_text_buffer), "Lives: {}", player.lives); + DrawText(lives_text_buffer.c_str(), 50, static_cast(screen_height) - 50, 20, BLACK); + lives_text_buffer.clear(); + EndDrawing(); } CloseWindow(); diff --git a/types.h b/types.h index f2788d9..b36f388 100644 --- a/types.h +++ b/types.h @@ -8,7 +8,11 @@ #include "raylib.h" struct Player : Rectangle { + uint8_t lives; + double last_hit; [[nodiscard]] Vector2 center() const noexcept; + [[nodiscard]] Rectangle rect() const noexcept; + [[nodiscard]] bool is_invulnerable(double now) const noexcept; void move(float delta_x, float delta_y); }; @@ -34,6 +38,6 @@ struct Tear { struct Enemy { Vector2 center; float radius; - Vector2 moving; + float speed; bool alive; };