r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
winCondition.cpp
Go to the documentation of this file.
1#include <cmath>
2#include <cstdlib>
3#include <random>
4
6#include "ECS/Component.hpp"
8#include "Utils/Common.hpp"
9
10cli::WinCondition::WinCondition(const eng::id assignedId, const std::shared_ptr<eng::IRenderer> &renderer,
11 const std::shared_ptr<eng::IAudio> &audio)
12 : AScene(assignedId), m_renderer(renderer), m_audio(audio)
13{
14 auto &registry = AScene::getRegistry();
15
16 registry.onComponentAdded(
17 [&renderer, &registry, &audio](const ecs::Entity e, const std::type_info &type)
18 {
19 const auto *audioComp = registry.getComponent<ecs::Audio>(e);
20 const auto *colorComp = registry.getComponent<ecs::Color>(e);
21 const auto *fontComp = registry.getComponent<ecs::Font>(e);
22 const auto *scaleComp = registry.getComponent<ecs::Scale>(e);
23 const auto *textComp = registry.getComponent<ecs::Text>(e);
24 const auto *textureComp = registry.getComponent<ecs::Texture>(e);
25 const auto *transform = registry.getComponent<ecs::Transform>(e);
26 const auto *rectComp = registry.getComponent<ecs::Rect>(e);
27
28 if (type == typeid(ecs::Text))
29 {
30 if (textComp && transform && fontComp)
31 {
32 renderer->createFont(fontComp->id, fontComp->path);
33 renderer->createText(
34 {.font_name = fontComp->id,
35 .color = {.r = colorComp->r, .g = colorComp->g, .b = colorComp->b, .a = colorComp->a},
36 .content = textComp->content,
37 .size = textComp->font_size,
38 .x = transform->x,
39 .y = transform->y,
40 .name = textComp->id});
41 }
42 }
43 else if (type == typeid(ecs::Texture))
44 {
45 const float scale_x = scaleComp ? scaleComp->x : 1.F;
46 const float scale_y = scaleComp ? scaleComp->y : 1.F;
47
48 renderer->createTexture(textureComp->id, textureComp->path);
49
50 if (transform && textureComp)
51 {
52 if (rectComp)
53 {
54 renderer->createSprite(textureComp->id + std::to_string(e), textureComp->id, transform->x,
55 transform->y, scale_x, scale_y, static_cast<int>(rectComp->pos_x),
56 static_cast<int>(rectComp->pos_y), rectComp->size_x, rectComp->size_y);
57 }
58 else
59 {
60 renderer->createSprite(textureComp->id + std::to_string(e), textureComp->id, transform->x,
61 transform->y);
62 }
63 }
64 }
65 else if (type == typeid(ecs::Audio))
66 {
67 if (audioComp)
68 {
69 audio->createAudio(audioComp->path, audioComp->volume, audioComp->loop,
70 audioComp->id + std::to_string(e));
71 }
72 }
73 });
74
75 auto [width, height] = renderer->getWindowSize();
76
78 registry.createEntity().with<ecs::Audio>("victory_sound", "assets/audio/coin.mp3", 30.0F, false, true).build();
79
81 registry.createEntity()
82 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
83 .with<ecs::Transform>("title_transform", width * 0.32F, height * 0.25F, 0.F)
86 .with<ecs::Text>("title_text", std::string("VICTORY!"), 96U)
87 .build();
88
89 m_subtitleEntity = registry.createEntity()
90 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
91 .with<ecs::Transform>("subtitle_transform", width * 0.28F, height * 0.45F, 0.F)
94 .with<ecs::Text>("subtitle_text", std::string("Mission Accomplished"), 42U)
95 .build();
96
98 registry.createEntity()
99 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
100 .with<ecs::Transform>("instruction_transform", width * 0.25F, height * 0.75F, 0.F)
101 .with<ecs::Color>("instruction_color", utl::Config::Color::GRAY_BLUE_SUBTLE.r,
104 .with<ecs::Text>("instruction_text", std::string("Press ENTER to quit"), 28U)
105 .build();
106
107 m_iconEntity = registry.createEntity()
108 .with<ecs::Transform>("icon_transform", width * 0.45F, height * 0.55F)
109 .with<ecs::Scale>("icon_scale", 0.5F, 0.5F)
112 .with<ecs::Texture>("icon_texture", utl::Path::Icons::ICON_APP)
113 .build();
114}
115
116void cli::WinCondition::update(const float dt, const eng::WindowSize &size)
117{
118 auto &reg = getRegistry();
119 m_elapsedTime += dt;
120 m_titlePulseTime += dt;
121 m_particleSpawnTimer += dt;
122
123 if (auto *titleColor = reg.getComponent<ecs::Color>(m_titleEntity))
124 {
125 if (m_elapsedTime < 0.5F)
126 {
127 titleColor->a = static_cast<uint8_t>(std::min(255.0F, (m_elapsedTime / 0.5F) * 255.0F));
128 }
129 else
130 {
131 const float pulse = (std::sin(m_titlePulseTime * 3.0F) + 1.0F) * 0.5F;
132 titleColor->r = static_cast<uint8_t>(utl::Config::Color::CYAN_ELECTRIC.r * (0.7F + pulse * 0.3F));
133 titleColor->g = static_cast<uint8_t>(utl::Config::Color::CYAN_ELECTRIC.g * (0.7F + pulse * 0.3F));
134 titleColor->b = static_cast<uint8_t>(utl::Config::Color::CYAN_ELECTRIC.b * (0.9F + pulse * 0.1F));
135 titleColor->a = 255;
136 }
137 }
138
139 if (auto *titleTransform = reg.getComponent<ecs::Transform>(m_titleEntity))
140 {
141 if (m_elapsedTime > 0.5F)
142 {
143 titleTransform->y = size.height * 0.25F + std::sin(m_titlePulseTime * 1.5F) * 8.0F;
144 }
145 }
146
147 if (auto *subtitleColor = reg.getComponent<ecs::Color>(m_subtitleEntity))
148 {
149 if (m_elapsedTime > 0.8F && m_elapsedTime < 1.5F)
150 {
151 const float t = (m_elapsedTime - 0.8F) / 0.7F;
152 subtitleColor->a = static_cast<uint8_t>(std::min(255.0F, t * 255.0F));
153 }
154 else if (m_elapsedTime >= 1.5F)
155 {
156 subtitleColor->a = 255;
157 }
158 }
159
160 if (auto *iconColor = reg.getComponent<ecs::Color>(m_iconEntity))
161 {
162 if (m_elapsedTime > 1.0F && m_elapsedTime < 2.0F)
163 {
164 const float t = (m_elapsedTime - 1.0F);
165 iconColor->a = static_cast<uint8_t>(std::min(255.0F, t * 255.0F));
166
167 if (auto *iconScale = reg.getComponent<ecs::Scale>(m_iconEntity))
168 {
169 const float scale = 0.5F + std::sin(t * 3.14159F) * 0.2F;
170 iconScale->x = scale;
171 iconScale->y = scale;
172 }
173 }
174 else if (m_elapsedTime >= 2.0F)
175 {
176 iconColor->a = 255;
177 if (auto *iconScale = reg.getComponent<ecs::Scale>(m_iconEntity))
178 {
179 const float breathe = 0.5F + std::sin(m_titlePulseTime * 0.8F) * 0.1F;
180 iconScale->x = breathe;
181 iconScale->y = breathe;
182 }
183 }
184 }
185
186 if (auto *instructionColor = reg.getComponent<ecs::Color>(m_instructionEntity))
187 {
188 if (m_elapsedTime > 2.5F)
189 {
190 const float blink = (std::sin(m_titlePulseTime * 2.0F) + 1.0F) * 0.5F;
191 instructionColor->a = static_cast<uint8_t>(150.0F + blink * 105.0F);
192 }
193 }
194
195 if (m_elapsedTime > 1.0F && m_particleSpawnTimer > 0.3F && m_particles.size() < 50)
196 {
197 m_particleSpawnTimer = 0.0F;
198
199 std::random_device rd;
200 std::mt19937 gen(rd());
201 std::uniform_real_distribution<float> angleDist(0.0F, 6.28318F);
202 std::uniform_real_distribution<float> speedDist(50.0F, 150.0F);
203 std::uniform_real_distribution<float> lifetimeDist(1.0F, 3.0F);
204
205 const float angle = angleDist(gen);
206 const float speed = speedDist(gen);
207 const float lifetime = lifetimeDist(gen);
208
209 Particle p;
210 p.x = size.width * 0.5F;
211 p.y = size.height * 0.35F;
212 p.vx = std::cos(angle) * speed;
213 p.vy = std::sin(angle) * speed;
214 p.lifetime = 0.0F;
215 p.maxLifetime = lifetime;
216
217 p.entity = reg.createEntity()
218 .with<ecs::Transform>("particle_transform", p.x, p.y)
219 .with<ecs::Scale>("particle_scale", 0.15F, 0.15F)
220 .with<ecs::Color>("particle_color", utl::Config::Color::CYAN_ELECTRIC.r,
223 .with<ecs::Texture>("particle_texture", utl::Path::Icons::ICON_APP)
224 .build();
225
226 m_particles.push_back(p);
227 }
228
229 for (auto it = m_particles.begin(); it != m_particles.end();)
230 {
231 it->lifetime += dt;
232 it->x += it->vx * dt;
233 it->y += it->vy * dt;
234
235 if (auto *transform = reg.getComponent<ecs::Transform>(it->entity))
236 {
237 transform->x = it->x;
238 transform->y = it->y;
239 }
240
241 if (auto *color = reg.getComponent<ecs::Color>(it->entity))
242 {
243 const float alpha = 1.0F - (it->lifetime / it->maxLifetime);
244 color->a = static_cast<uint8_t>(std::max(0.0F, alpha * 255.0F));
245 }
246
247 if (it->lifetime >= it->maxLifetime)
248 {
249 it = m_particles.erase(it);
250 }
251 else
252 {
253 ++it;
254 }
255 }
256}
257
259{
260 if (event.type == eng::EventType::KeyPressed)
261 {
262 if (event.key == eng::Key::Enter && m_elapsedTime > 2.5F)
263 {
264 std::exit(0);
265 }
266 }
267}
This file contains the component definitions.
This file contains the Audio interface.
This file contains the win condition scene.
ecs::Entity m_iconEntity
ecs::Entity m_titleEntity
ecs::Entity m_subtitleEntity
ecs::Entity m_soundEntity
WinCondition(eng::id assignedId, const std::shared_ptr< eng::IRenderer > &renderer, const std::shared_ptr< eng::IAudio > &audio)
void event(const eng::Event &event) override
ecs::Entity m_instructionEntity
void update(float dt, const eng::WindowSize &size) override
This file contains common definitions and constants.
std::uint32_t Entity
Definition Entity.hpp:13
unsigned int id
Definition IScene.hpp:20
static constexpr eng::Color GRAY_BLUE_SUBTLE
Definition Common.hpp:57
static constexpr eng::Color CYAN_ELECTRIC
Definition Common.hpp:56
static constexpr eng::Color WHITE_LOW
Definition Common.hpp:65
static constexpr eng::Color GREEN
Definition Common.hpp:71
constexpr auto FONTS_RTYPE
Definition Common.hpp:97
constexpr auto ICON_APP
Definition Common.hpp:80
unsigned char a
Definition Component.hpp:29
std::string id
Definition Component.hpp:15
unsigned char r
Definition IRenderer.hpp:17
unsigned char a
Definition IRenderer.hpp:20
unsigned char g
Definition IRenderer.hpp:18
unsigned char b
Definition IRenderer.hpp:19
EventType type
unsigned int width
unsigned int height