-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame.cpp
More file actions
100 lines (89 loc) · 3.47 KB
/
game.cpp
File metadata and controls
100 lines (89 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <game.hpp>
#include <glm/gtx/norm.hpp>
#include <le2d/context.hpp>
#include <cstddef>
#include <format>
#include <iterator>
#include <string>
#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"
#include "le2d/drawable/text.hpp"
#include "lighhouse.hpp"
#include "util/random.hpp"
namespace miracle {
Game::Game(gsl::not_null<le::ServiceLocator const*> services) : m_services(services), m_lighthouse(services), m_light(services) {
spawn_wave();
auto const& data_loader = services->get<le::IDataLoader>();
auto const& context = services->get<le::Context>();
auto const asset_loader = le::AssetLoader{&data_loader, &context};
m_font = asset_loader.load_font("fonts/specialElite.ttf");
}
void Game::on_cursor_pos(le::event::CursorPos const& cursor_pos) {
auto const framebuffer_size = m_services->get<le::Context>().framebuffer_size();
m_cursor_pos = cursor_pos.normalized.to_target(framebuffer_size);
}
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
auto res = std::erase_if(m_enemies, [](Enemy const& enemy) { return !enemy.get_health(); });
update_score(static_cast<int>(res * 10));
m_light.set_position(m_cursor_pos);
m_lighthouse.rotate_towards_cursor(m_cursor_pos);
}
void Game::render(le::Renderer& renderer) const {
m_light.render(renderer);
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() {
++m_wave_count;
m_wave_interval += kvf::Seconds{5};
std::vector<Enemy> new_wave;
std::size_t const wave_size = m_wave_count * 3;
new_wave.reserve(wave_size);
for (std::size_t i = 0; i < wave_size; ++i) {
new_wave.emplace_back(m_services, EnemyParams{.target_pos = glm::vec2{0.0f, 0.0f}, .move_speed = util::random_range(35.0f, 65.0f)});
}
m_enemies.insert(m_enemies.end(), std::make_move_iterator(new_wave.begin()), std::make_move_iterator(new_wave.end()));
}
void Game::update_score(int points) {
auto const framebuffer_size = m_services->get<le::Context>().framebuffer_size();
m_score_text.transform.position.y = static_cast<float>(framebuffer_size.y) / 2.0f - 50.0f;
m_score += points;
m_score_str.clear();
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