Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
Binary file added assets/fonts/specialElite.ttf
Binary file not shown.
11 changes: 8 additions & 3 deletions src/enemy.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <enemy.hpp>
#include <algorithm>
#include <utility>
#include "enemy_params.hpp"
#include "glm/geometric.hpp"
#include "glm/vec2.hpp"
Expand All @@ -17,16 +18,20 @@ Enemy::Enemy(gsl::not_null<le::ServiceLocator const*> services, EnemyParams cons
// TODO: add proper textures
}

void Enemy::render(le::Renderer& renderer) const { m_sprite.draw(renderer); }
void Enemy::render(le::Renderer& renderer) const {
if (m_can_render) { m_sprite.draw(renderer); }
}

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

void Enemy::check_collision(glm::vec2 pos, float radius) {
if (glm::distance(pos, m_sprite.transform.position) < radius + m_diameter / 2) { m_health = 0; }
std::pair<glm::vec2, float> Enemy::get_pos_diameter() const { return {m_sprite.transform.position, m_diameter}; }
void Enemy::take_damage(std::size_t dmg) {
m_can_render = true;
m_health = (dmg >= m_health) ? 0 : (m_health - dmg);
}

} // namespace miracle
6 changes: 4 additions & 2 deletions src/enemy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <le2d/event.hpp>
#include <le2d/renderer.hpp>
#include <le2d/service_locator.hpp>
#include <cstddef>
#include <optional>
#include "enemy_params.hpp"
#include "glm/vec2.hpp"
Expand All @@ -18,9 +19,10 @@ class Enemy {

void render(le::Renderer& renderer) const;
void translate(kvf::Seconds dt);
// There are temporary parameters, will take the light beam object once it is created
void check_collision(glm::vec2 pos, float radius);
void take_damage(std::size_t dmg);
[[nodiscard]] std::size_t get_health() const { return m_health; }
[[nodiscard]] std::pair<glm::vec2, float> get_pos_diameter() const;
bool m_can_render{false};

private:
gsl::not_null<le::ServiceLocator const*> m_services;
Expand Down
31 changes: 25 additions & 6 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@
#include <glm/gtx/norm.hpp>
#include <le2d/context.hpp>
#include <cstddef>
#include <string>
#include <vector>
#include "enemy.hpp"
#include "enemy_params.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_circle.create(70.0f);
Game::Game(gsl::not_null<le::ServiceLocator const*> services)
: m_services(services), m_lighthouse(services), m_light(services), m_score_text(le::drawable::Text()) {
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");
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;
}

void Game::on_cursor_pos(le::event::CursorPos const& cursor_pos) {
Expand All @@ -28,18 +39,21 @@ void Game::tick([[maybe_unused]] kvf::Seconds const dt) {
m_time_since_last_wave_spawn = kvf::Seconds{};
}
for (auto& enemy : m_enemies) {
enemy.check_collision(m_circle.transform.position, 50.0f);
m_light.check_enemy_collision(enemy);
enemy.translate(dt);
}
std::erase_if(m_enemies, [](Enemy const& enemy) { return !enemy.get_health(); });
m_circle.transform.position = m_cursor_pos;
// 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(); });
increase_score(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_circle.draw(renderer);
m_light.render(renderer);
m_lighthouse.render(renderer);
for (auto const& enemy : m_enemies) { enemy.render(renderer); }
m_score_text.draw(renderer);
}

void Game::spawn_wave() {
Expand All @@ -53,4 +67,9 @@ void Game::spawn_wave() {
}
m_enemies.insert(m_enemies.end(), std::make_move_iterator(new_wave.begin()), std::make_move_iterator(new_wave.end()));
}

void Game::increase_score(std::size_t points) {
m_score += points;
m_score_text.set_string(m_font, "Score: " + std::to_string(m_score));
}
} // namespace miracle
12 changes: 10 additions & 2 deletions src/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
#include <le2d/service_locator.hpp>
#include <cstddef>
#include "enemy.hpp"
#include "le2d/drawable/text.hpp"
#include "le2d/font.hpp"
#include "lighhouse.hpp"
#include "light.hpp"

namespace miracle {
class Game {
Expand All @@ -17,18 +20,23 @@ class Game {

void tick(kvf::Seconds dt);
void render(le::Renderer& renderer) const;
void increase_score(std::size_t points);
[[nodiscard]] std::string get_score_string() const;
void spawn_wave();

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

le::drawable::Circle m_circle{};
Lighthouse m_lighthouse;
Light m_light;

le::Font m_font{};
le::drawable::Text m_score_text{};
glm::vec2 m_cursor_pos{};
std::size_t m_wave_count{};
bool m_running{true};
kvf::Seconds m_wave_interval{};
kvf::Seconds m_time_since_last_wave_spawn{};
std::vector<Enemy> m_enemies{};
std::size_t m_score{};
};
} // namespace miracle
17 changes: 17 additions & 0 deletions src/light.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <light.hpp>
#include "kvf/color.hpp"

namespace miracle {
Light::Light(gsl::not_null<le::ServiceLocator const*> services) : m_services(services), m_diameter(100) { m_sprite.create(150.0f, kvf::white_v); }

void Light::check_enemy_collision(Enemy& enemy) {
auto [pos, diameter] = enemy.get_pos_diameter();
if (glm::distance(pos, m_sprite.transform.position) < (diameter + m_diameter)) {
enemy.take_damage(1);
} else {
enemy.m_can_render = false;
}
}
void Light::render(le::Renderer& renderer) const { m_sprite.draw(renderer); }
void Light::set_position(glm::vec2 cursor_pos) { m_sprite.transform.position = cursor_pos; }
} // namespace miracle
26 changes: 26 additions & 0 deletions src/light.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "enemy.hpp"
#include "glm/vec2.hpp"
#include "gsl/pointers"
#include "le2d/drawable/shape.hpp"
#include "le2d/renderer.hpp"
#include "le2d/service_locator.hpp"
#include "le2d/texture.hpp"

namespace miracle {
class Light {
public:
explicit Light(gsl::not_null<le::ServiceLocator const*> services);

void render(le::Renderer& renderer) const;
void set_position(glm::vec2 cursor_pos);
void check_enemy_collision(Enemy& enemy);

private:
gsl::not_null<le::ServiceLocator const*> m_services;
std::optional<le::Texture> m_texture;
le::drawable::Circle m_sprite{};
float m_diameter{};
};
} // namespace miracle