diff --git a/src/enemy.cpp b/src/enemy.cpp index 8f4d28e..8e54e1e 100644 --- a/src/enemy.cpp +++ b/src/enemy.cpp @@ -18,7 +18,7 @@ Enemy::Enemy(gsl::not_null services, EnemyParams cons } void Enemy::render(le::Renderer& renderer) const { - if (m_can_render) { m_sprite.draw(renderer); } + if (can_render) { m_sprite.draw(renderer); } } void Enemy::translate(kvf::Seconds const dt) { @@ -29,7 +29,7 @@ void Enemy::translate(kvf::Seconds const dt) { CollisionParams Enemy::get_collision_params() const { return {.pos = m_sprite.transform.position, .diameter = m_diameter}; } void Enemy::take_damage(std::size_t dmg) { - m_can_render = true; + can_render = true; m_health = (dmg >= m_health) ? 0 : (m_health - dmg); } diff --git a/src/enemy.hpp b/src/enemy.hpp index b3a10ad..961c946 100644 --- a/src/enemy.hpp +++ b/src/enemy.hpp @@ -23,7 +23,7 @@ class Enemy { void take_damage(std::size_t dmg); [[nodiscard]] std::size_t get_health() const { return m_health; } [[nodiscard]] CollisionParams get_collision_params() const; - bool m_can_render{false}; + bool can_render{false}; private: gsl::not_null m_services; diff --git a/src/game.cpp b/src/game.cpp index 401b402..aebad4f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -8,6 +8,7 @@ #include #include "enemy.hpp" #include "enemy_params.hpp" +#include "glm/ext/vector_float2.hpp" #include "kvf/time.hpp" #include "le2d/asset_loader.hpp" #include "le2d/data_loader.hpp" @@ -30,7 +31,9 @@ void Game::on_cursor_pos(le::event::CursorPos const& cursor_pos) { } void Game::tick([[maybe_unused]] kvf::Seconds const dt) { + m_running = m_lighthouse.get_health() > 0; if (!m_running) { return; } + m_time_since_last_wave_spawn += dt; if (m_time_since_last_wave_spawn >= m_wave_interval) { spawn_wave(); @@ -38,6 +41,8 @@ void Game::tick([[maybe_unused]] kvf::Seconds const dt) { } for (auto& enemy : m_enemies) { m_light.check_enemy_collision(enemy); + m_lighthouse.check_visibility_range(enemy); + update_health_text(); enemy.translate(dt); } // Keep track of how many enemies were defeated and calculate score @@ -52,6 +57,7 @@ void Game::render(le::Renderer& renderer) const { m_lighthouse.render(renderer); for (auto const& enemy : m_enemies) { enemy.render(renderer); } m_score_text.draw(renderer); + m_health_text.draw(renderer); } void Game::spawn_wave() { @@ -74,4 +80,21 @@ void Game::update_score(int points) { std::format_to(std::back_inserter(m_score_str), "Score: {}", m_score); m_score_text.set_string(m_font, m_score_str); } + +void Game::update_health_text() { + auto const framebuffer_size = m_services->get().framebuffer_size(); + float const x = (static_cast(framebuffer_size.x) * 0.5f) - 150.0f; + float const y = (static_cast(framebuffer_size.y) * 0.5f) - 50.0f; + m_health_text.transform.position = {x, y}; + + m_health_str.clear(); + if (m_lighthouse.get_health() <= 0.0f) { + std::format_to(std::back_inserter(m_health_str), "Game Over"); + } else { + std::format_to(std::back_inserter(m_health_str), "Health: {:.1f}", m_lighthouse.get_health()); + } + + m_health_text.set_string(m_font, m_health_str); +} + } // namespace miracle diff --git a/src/game.hpp b/src/game.hpp index ddb4749..857e444 100644 --- a/src/game.hpp +++ b/src/game.hpp @@ -21,6 +21,7 @@ class Game { void tick(kvf::Seconds dt); void render(le::Renderer& renderer) const; void update_score(int points); + void update_health_text(); void spawn_wave(); private: @@ -30,9 +31,10 @@ class Game { le::Font m_font{}; le::drawable::Text m_score_text{}; + le::drawable::Text m_health_text{}; int m_score{}; std::string m_score_str; - + std::string m_health_str; glm::vec2 m_cursor_pos{}; std::size_t m_wave_count{}; bool m_running{true}; diff --git a/src/lighhouse.hpp b/src/lighhouse.hpp index 8696fa7..cfc4bf2 100644 --- a/src/lighhouse.hpp +++ b/src/lighhouse.hpp @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include "enemy.hpp" #include "le2d/texture.hpp" namespace miracle { @@ -16,10 +18,17 @@ class Lighthouse { void rotate_towards_cursor(glm::vec2 cursor_pos); void render(le::Renderer& renderer) const; + void check_visibility_range(Enemy& enemy); + void check_damage_taken(Enemy& enemy); + void take_damage(float dmg); + [[nodiscard]] float get_health() const; private: gsl::not_null m_services; + float m_hitbox_diameter{150.0f}; + float m_visibility_diameter{250.0f}; std::optional m_texture; le::drawable::Circle m_sprite{}; + float m_health{100}; }; } // namespace miracle diff --git a/src/light.cpp b/src/light.cpp index 5866311..1f717cb 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -9,7 +9,7 @@ void Light::check_enemy_collision(Enemy& enemy) { if (glm::distance(pos, m_sprite.transform.position) < (diameter + m_diameter) / 2) { enemy.take_damage(1); } else { - enemy.m_can_render = false; + enemy.can_render = false; } } void Light::render(le::Renderer& renderer) const { m_sprite.draw(renderer); } diff --git a/src/lighthouse.cpp b/src/lighthouse.cpp index d40c723..27ed7eb 100644 --- a/src/lighthouse.cpp +++ b/src/lighthouse.cpp @@ -1,10 +1,11 @@ #include +#include "glm/geometric.hpp" #include "le2d/asset_loader.hpp" #include "le2d/data_loader.hpp" namespace miracle { Lighthouse::Lighthouse(gsl::not_null services) : m_services(services) { - m_sprite.create(200.0f); + m_sprite.create(m_hitbox_diameter); auto const& data_loader = services->get(); auto const& context = services->get(); auto const asset_loader = le::AssetLoader{&data_loader, &context}; @@ -23,6 +24,23 @@ void Lighthouse::rotate_towards_cursor(glm::vec2 cursor_pos) { m_sprite.transform.orientation = cursor_pos.x > 0.0f ? -angle : angle; } } +void Lighthouse::check_visibility_range(Enemy& enemy) { + auto [enemy_pos, enemy_diameter] = enemy.get_collision_params(); + if (glm::distance(m_sprite.transform.position, enemy_pos) < (m_visibility_diameter + enemy_diameter) / 2.0f) { + enemy.can_render = true; + // No need to check for damage taken if enemy isn't already in visibility radius + check_damage_taken(enemy); + } +} +void Lighthouse::check_damage_taken(Enemy& enemy) { + auto [enemy_pos, enemy_diameter] = enemy.get_collision_params(); + if (glm::distance(m_sprite.transform.position, enemy_pos) < (m_hitbox_diameter + enemy_diameter) / 2.0f) { + take_damage(enemy_diameter / 200); + } // magic numbers +} + +void Lighthouse::take_damage(float dmg) { m_health -= dmg; } +float Lighthouse::get_health() const { return m_health; } void Lighthouse::render(le::Renderer& renderer) const { m_sprite.draw(renderer); } } // namespace miracle