Skip to content

Commit e2d0c8c

Browse files
authored
Nikola/lighthouse (#7)
* Improve Lighthouse - Add visibility radius in which enemies are revealed - Lighthouse takes damage with enemy contact - Stop game when Lighthouse HP reaches 0 - Add Health text
1 parent 35428c8 commit e2d0c8c

File tree

7 files changed

+58
-6
lines changed

7 files changed

+58
-6
lines changed

src/enemy.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Enemy::Enemy(gsl::not_null<le::ServiceLocator const*> services, EnemyParams cons
1818
}
1919

2020
void Enemy::render(le::Renderer& renderer) const {
21-
if (m_can_render) { m_sprite.draw(renderer); }
21+
if (can_render) { m_sprite.draw(renderer); }
2222
}
2323

2424
void Enemy::translate(kvf::Seconds const dt) {
@@ -29,7 +29,7 @@ void Enemy::translate(kvf::Seconds const dt) {
2929

3030
CollisionParams Enemy::get_collision_params() const { return {.pos = m_sprite.transform.position, .diameter = m_diameter}; }
3131
void Enemy::take_damage(std::size_t dmg) {
32-
m_can_render = true;
32+
can_render = true;
3333
m_health = (dmg >= m_health) ? 0 : (m_health - dmg);
3434
}
3535

src/enemy.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Enemy {
2323
void take_damage(std::size_t dmg);
2424
[[nodiscard]] std::size_t get_health() const { return m_health; }
2525
[[nodiscard]] CollisionParams get_collision_params() const;
26-
bool m_can_render{false};
26+
bool can_render{false};
2727

2828
private:
2929
gsl::not_null<le::ServiceLocator const*> m_services;

src/game.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <vector>
99
#include "enemy.hpp"
1010
#include "enemy_params.hpp"
11+
#include "glm/ext/vector_float2.hpp"
1112
#include "kvf/time.hpp"
1213
#include "le2d/asset_loader.hpp"
1314
#include "le2d/data_loader.hpp"
@@ -30,14 +31,18 @@ void Game::on_cursor_pos(le::event::CursorPos const& cursor_pos) {
3031
}
3132

3233
void Game::tick([[maybe_unused]] kvf::Seconds const dt) {
34+
m_running = m_lighthouse.get_health() > 0;
3335
if (!m_running) { return; }
36+
3437
m_time_since_last_wave_spawn += dt;
3538
if (m_time_since_last_wave_spawn >= m_wave_interval) {
3639
spawn_wave();
3740
m_time_since_last_wave_spawn = kvf::Seconds{};
3841
}
3942
for (auto& enemy : m_enemies) {
4043
m_light.check_enemy_collision(enemy);
44+
m_lighthouse.check_visibility_range(enemy);
45+
update_health_text();
4146
enemy.translate(dt);
4247
}
4348
// Keep track of how many enemies were defeated and calculate score
@@ -52,6 +57,7 @@ void Game::render(le::Renderer& renderer) const {
5257
m_lighthouse.render(renderer);
5358
for (auto const& enemy : m_enemies) { enemy.render(renderer); }
5459
m_score_text.draw(renderer);
60+
m_health_text.draw(renderer);
5561
}
5662

5763
void Game::spawn_wave() {
@@ -74,4 +80,21 @@ void Game::update_score(int points) {
7480
std::format_to(std::back_inserter(m_score_str), "Score: {}", m_score);
7581
m_score_text.set_string(m_font, m_score_str);
7682
}
83+
84+
void Game::update_health_text() {
85+
auto const framebuffer_size = m_services->get<le::Context>().framebuffer_size();
86+
float const x = (static_cast<float>(framebuffer_size.x) * 0.5f) - 150.0f;
87+
float const y = (static_cast<float>(framebuffer_size.y) * 0.5f) - 50.0f;
88+
m_health_text.transform.position = {x, y};
89+
90+
m_health_str.clear();
91+
if (m_lighthouse.get_health() <= 0.0f) {
92+
std::format_to(std::back_inserter(m_health_str), "Game Over");
93+
} else {
94+
std::format_to(std::back_inserter(m_health_str), "Health: {:.1f}", m_lighthouse.get_health());
95+
}
96+
97+
m_health_text.set_string(m_font, m_health_str);
98+
}
99+
77100
} // namespace miracle

src/game.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Game {
2121
void tick(kvf::Seconds dt);
2222
void render(le::Renderer& renderer) const;
2323
void update_score(int points);
24+
void update_health_text();
2425
void spawn_wave();
2526

2627
private:
@@ -30,9 +31,10 @@ class Game {
3031

3132
le::Font m_font{};
3233
le::drawable::Text m_score_text{};
34+
le::drawable::Text m_health_text{};
3335
int m_score{};
3436
std::string m_score_str;
35-
37+
std::string m_health_str;
3638
glm::vec2 m_cursor_pos{};
3739
std::size_t m_wave_count{};
3840
bool m_running{true};

src/lighhouse.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
#include <le2d/event.hpp>
77
#include <le2d/renderer.hpp>
88
#include <le2d/service_locator.hpp>
9+
#include <cstddef>
910
#include <optional>
11+
#include "enemy.hpp"
1012
#include "le2d/texture.hpp"
1113

1214
namespace miracle {
@@ -16,10 +18,17 @@ class Lighthouse {
1618

1719
void rotate_towards_cursor(glm::vec2 cursor_pos);
1820
void render(le::Renderer& renderer) const;
21+
void check_visibility_range(Enemy& enemy);
22+
void check_damage_taken(Enemy& enemy);
23+
void take_damage(float dmg);
24+
[[nodiscard]] float get_health() const;
1925

2026
private:
2127
gsl::not_null<le::ServiceLocator const*> m_services;
28+
float m_hitbox_diameter{150.0f};
29+
float m_visibility_diameter{250.0f};
2230
std::optional<le::Texture> m_texture;
2331
le::drawable::Circle m_sprite{};
32+
float m_health{100};
2433
};
2534
} // namespace miracle

src/light.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ void Light::check_enemy_collision(Enemy& enemy) {
99
if (glm::distance(pos, m_sprite.transform.position) < (diameter + m_diameter) / 2) {
1010
enemy.take_damage(1);
1111
} else {
12-
enemy.m_can_render = false;
12+
enemy.can_render = false;
1313
}
1414
}
1515
void Light::render(le::Renderer& renderer) const { m_sprite.draw(renderer); }

src/lighthouse.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#include <lighhouse.hpp>
2+
#include "glm/geometric.hpp"
23
#include "le2d/asset_loader.hpp"
34
#include "le2d/data_loader.hpp"
45

56
namespace miracle {
67
Lighthouse::Lighthouse(gsl::not_null<le::ServiceLocator const*> services) : m_services(services) {
7-
m_sprite.create(200.0f);
8+
m_sprite.create(m_hitbox_diameter);
89
auto const& data_loader = services->get<le::IDataLoader>();
910
auto const& context = services->get<le::Context>();
1011
auto const asset_loader = le::AssetLoader{&data_loader, &context};
@@ -23,6 +24,23 @@ void Lighthouse::rotate_towards_cursor(glm::vec2 cursor_pos) {
2324
m_sprite.transform.orientation = cursor_pos.x > 0.0f ? -angle : angle;
2425
}
2526
}
27+
void Lighthouse::check_visibility_range(Enemy& enemy) {
28+
auto [enemy_pos, enemy_diameter] = enemy.get_collision_params();
29+
if (glm::distance(m_sprite.transform.position, enemy_pos) < (m_visibility_diameter + enemy_diameter) / 2.0f) {
30+
enemy.can_render = true;
31+
// No need to check for damage taken if enemy isn't already in visibility radius
32+
check_damage_taken(enemy);
33+
}
34+
}
35+
void Lighthouse::check_damage_taken(Enemy& enemy) {
36+
auto [enemy_pos, enemy_diameter] = enemy.get_collision_params();
37+
if (glm::distance(m_sprite.transform.position, enemy_pos) < (m_hitbox_diameter + enemy_diameter) / 2.0f) {
38+
take_damage(enemy_diameter / 200);
39+
} // magic numbers
40+
}
41+
42+
void Lighthouse::take_damage(float dmg) { m_health -= dmg; }
2643

44+
float Lighthouse::get_health() const { return m_health; }
2745
void Lighthouse::render(le::Renderer& renderer) const { m_sprite.draw(renderer); }
2846
} // namespace miracle

0 commit comments

Comments
 (0)