Skip to content

Nikola/lighthouse #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/enemy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Enemy::Enemy(gsl::not_null<le::ServiceLocator const*> 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) {
Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/enemy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<le::ServiceLocator const*> m_services;
Expand Down
23 changes: 23 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>
#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"
Expand All @@ -30,14 +31,18 @@ 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();
m_time_since_last_wave_spawn = kvf::Seconds{};
}
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
Expand All @@ -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() {
Expand All @@ -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<le::Context>().framebuffer_size();
float const x = (static_cast<float>(framebuffer_size.x) * 0.5f) - 150.0f;
float const y = (static_cast<float>(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
4 changes: 3 additions & 1 deletion src/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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};
Expand Down
9 changes: 9 additions & 0 deletions src/lighhouse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include <le2d/event.hpp>
#include <le2d/renderer.hpp>
#include <le2d/service_locator.hpp>
#include <cstddef>
#include <optional>
#include "enemy.hpp"
#include "le2d/texture.hpp"

namespace miracle {
Expand All @@ -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<le::ServiceLocator const*> m_services;
float m_hitbox_diameter{150.0f};
float m_visibility_diameter{250.0f};
std::optional<le::Texture> m_texture;
le::drawable::Circle m_sprite{};
float m_health{100};
};
} // namespace miracle
2 changes: 1 addition & 1 deletion src/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand Down
20 changes: 19 additions & 1 deletion src/lighthouse.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include <lighhouse.hpp>
#include "glm/geometric.hpp"
#include "le2d/asset_loader.hpp"
#include "le2d/data_loader.hpp"

namespace miracle {
Lighthouse::Lighthouse(gsl::not_null<le::ServiceLocator const*> services) : m_services(services) {
m_sprite.create(200.0f);
m_sprite.create(m_hitbox_diameter);
auto const& data_loader = services->get<le::IDataLoader>();
auto const& context = services->get<le::Context>();
auto const asset_loader = le::AssetLoader{&data_loader, &context};
Expand All @@ -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
Loading