Skip to content

Commit 35428c8

Browse files
authored
Nikola/light (#6)
* Add Light class - move light to separate class - let light manage its effect on the enemies - enemies take tick damage * Add simple score tracking and display * Add conditional enemy rendering * Fix initalization order * Fix redundant assignment * Refactor for PR - add collision parameters struct - fix collision calculation - improve text score handling - remove redundand initialization of text * Fix type casting long to int
1 parent 037c44e commit 35428c8

File tree

8 files changed

+102
-13
lines changed

8 files changed

+102
-13
lines changed

assets/fonts/specialElite.ttf

148 KB
Binary file not shown.

src/EnemyColliderInfo.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
#include <glm/vec2.hpp>
3+
4+
namespace miracle {
5+
struct CollisionParams {
6+
glm::vec2 pos;
7+
float diameter;
8+
};
9+
} // namespace miracle

src/enemy.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,20 @@ Enemy::Enemy(gsl::not_null<le::ServiceLocator const*> services, EnemyParams cons
1717
// TODO: add proper textures
1818
}
1919

20-
void Enemy::render(le::Renderer& renderer) const { m_sprite.draw(renderer); }
20+
void Enemy::render(le::Renderer& renderer) const {
21+
if (m_can_render) { m_sprite.draw(renderer); }
22+
}
2123

2224
void Enemy::translate(kvf::Seconds const dt) {
2325
glm::vec2 const direction = glm::normalize(m_target_pos - m_sprite.transform.position);
2426
glm::vec2 const movement = direction * m_move_speed * dt.count();
2527
m_sprite.transform.position += movement;
2628
}
2729

28-
void Enemy::check_collision(glm::vec2 pos, float radius) {
29-
if (glm::distance(pos, m_sprite.transform.position) < radius + m_diameter / 2) { m_health = 0; }
30+
CollisionParams Enemy::get_collision_params() const { return {.pos = m_sprite.transform.position, .diameter = m_diameter}; }
31+
void Enemy::take_damage(std::size_t dmg) {
32+
m_can_render = true;
33+
m_health = (dmg >= m_health) ? 0 : (m_health - dmg);
3034
}
3135

3236
} // namespace miracle

src/enemy.hpp

Lines changed: 5 additions & 2 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 "EnemyColliderInfo.hpp"
1012
#include "enemy_params.hpp"
1113
#include "glm/vec2.hpp"
1214
#include "le2d/texture.hpp"
@@ -18,9 +20,10 @@ class Enemy {
1820

1921
void render(le::Renderer& renderer) const;
2022
void translate(kvf::Seconds dt);
21-
// There are temporary parameters, will take the light beam object once it is created
22-
void check_collision(glm::vec2 pos, float radius);
23+
void take_damage(std::size_t dmg);
2324
[[nodiscard]] std::size_t get_health() const { return m_health; }
25+
[[nodiscard]] CollisionParams get_collision_params() const;
26+
bool m_can_render{false};
2427

2528
private:
2629
gsl::not_null<le::ServiceLocator const*> m_services;

src/game.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,26 @@
22
#include <glm/gtx/norm.hpp>
33
#include <le2d/context.hpp>
44
#include <cstddef>
5+
#include <format>
6+
#include <iterator>
7+
#include <string>
58
#include <vector>
69
#include "enemy.hpp"
710
#include "enemy_params.hpp"
811
#include "kvf/time.hpp"
12+
#include "le2d/asset_loader.hpp"
13+
#include "le2d/data_loader.hpp"
14+
#include "le2d/drawable/text.hpp"
915
#include "lighhouse.hpp"
1016
#include "util/random.hpp"
1117

1218
namespace miracle {
13-
Game::Game(gsl::not_null<le::ServiceLocator const*> services) : m_services(services), m_lighthouse(services) {
14-
m_circle.create(70.0f);
19+
Game::Game(gsl::not_null<le::ServiceLocator const*> services) : m_services(services), m_lighthouse(services), m_light(services) {
1520
spawn_wave();
21+
auto const& data_loader = services->get<le::IDataLoader>();
22+
auto const& context = services->get<le::Context>();
23+
auto const asset_loader = le::AssetLoader{&data_loader, &context};
24+
m_font = asset_loader.load_font("fonts/specialElite.ttf");
1625
}
1726

1827
void Game::on_cursor_pos(le::event::CursorPos const& cursor_pos) {
@@ -28,18 +37,21 @@ void Game::tick([[maybe_unused]] kvf::Seconds const dt) {
2837
m_time_since_last_wave_spawn = kvf::Seconds{};
2938
}
3039
for (auto& enemy : m_enemies) {
31-
enemy.check_collision(m_circle.transform.position, 50.0f);
40+
m_light.check_enemy_collision(enemy);
3241
enemy.translate(dt);
3342
}
34-
std::erase_if(m_enemies, [](Enemy const& enemy) { return !enemy.get_health(); });
35-
m_circle.transform.position = m_cursor_pos;
43+
// Keep track of how many enemies were defeated and calculate score
44+
auto res = std::erase_if(m_enemies, [](Enemy const& enemy) { return !enemy.get_health(); });
45+
update_score(static_cast<int>(res * 10));
46+
m_light.set_position(m_cursor_pos);
3647
m_lighthouse.rotate_towards_cursor(m_cursor_pos);
3748
}
3849

3950
void Game::render(le::Renderer& renderer) const {
40-
m_circle.draw(renderer);
51+
m_light.render(renderer);
4152
m_lighthouse.render(renderer);
4253
for (auto const& enemy : m_enemies) { enemy.render(renderer); }
54+
m_score_text.draw(renderer);
4355
}
4456

4557
void Game::spawn_wave() {
@@ -53,4 +65,13 @@ void Game::spawn_wave() {
5365
}
5466
m_enemies.insert(m_enemies.end(), std::make_move_iterator(new_wave.begin()), std::make_move_iterator(new_wave.end()));
5567
}
68+
69+
void Game::update_score(int points) {
70+
auto const framebuffer_size = m_services->get<le::Context>().framebuffer_size();
71+
m_score_text.transform.position.y = static_cast<float>(framebuffer_size.y) / 2.0f - 50.0f;
72+
m_score += points;
73+
m_score_str.clear();
74+
std::format_to(std::back_inserter(m_score_str), "Score: {}", m_score);
75+
m_score_text.set_string(m_font, m_score_str);
76+
}
5677
} // namespace miracle

src/game.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
#include <le2d/service_locator.hpp>
77
#include <cstddef>
88
#include "enemy.hpp"
9+
#include "le2d/drawable/text.hpp"
10+
#include "le2d/font.hpp"
911
#include "lighhouse.hpp"
12+
#include "light.hpp"
1013

1114
namespace miracle {
1215
class Game {
@@ -17,13 +20,19 @@ class Game {
1720

1821
void tick(kvf::Seconds dt);
1922
void render(le::Renderer& renderer) const;
23+
void update_score(int points);
2024
void spawn_wave();
2125

2226
private:
2327
gsl::not_null<le::ServiceLocator const*> m_services;
24-
25-
le::drawable::Circle m_circle{};
2628
Lighthouse m_lighthouse;
29+
Light m_light;
30+
31+
le::Font m_font{};
32+
le::drawable::Text m_score_text{};
33+
int m_score{};
34+
std::string m_score_str;
35+
2736
glm::vec2 m_cursor_pos{};
2837
std::size_t m_wave_count{};
2938
bool m_running{true};

src/light.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <light.hpp>
2+
#include "kvf/color.hpp"
3+
4+
namespace miracle {
5+
Light::Light(gsl::not_null<le::ServiceLocator const*> services) : m_services(services), m_diameter(100) { m_sprite.create(150.0f, kvf::white_v); }
6+
7+
void Light::check_enemy_collision(Enemy& enemy) {
8+
auto const [pos, diameter] = enemy.get_collision_params();
9+
if (glm::distance(pos, m_sprite.transform.position) < (diameter + m_diameter) / 2) {
10+
enemy.take_damage(1);
11+
} else {
12+
enemy.m_can_render = false;
13+
}
14+
}
15+
void Light::render(le::Renderer& renderer) const { m_sprite.draw(renderer); }
16+
void Light::set_position(glm::vec2 cursor_pos) { m_sprite.transform.position = cursor_pos; }
17+
} // namespace miracle

src/light.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include "enemy.hpp"
4+
#include "glm/vec2.hpp"
5+
#include "gsl/pointers"
6+
#include "le2d/drawable/shape.hpp"
7+
#include "le2d/renderer.hpp"
8+
#include "le2d/service_locator.hpp"
9+
#include "le2d/texture.hpp"
10+
11+
namespace miracle {
12+
class Light {
13+
public:
14+
explicit Light(gsl::not_null<le::ServiceLocator const*> services);
15+
16+
void render(le::Renderer& renderer) const;
17+
void set_position(glm::vec2 cursor_pos);
18+
void check_enemy_collision(Enemy& enemy);
19+
20+
private:
21+
gsl::not_null<le::ServiceLocator const*> m_services;
22+
std::optional<le::Texture> m_texture;
23+
le::drawable::Circle m_sprite{};
24+
float m_diameter{};
25+
};
26+
} // namespace miracle

0 commit comments

Comments
 (0)