r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
game.cpp
Go to the documentation of this file.
1#include <cmath>
2#include <cstdlib>
3#include <ctime>
4
5#include "ECS/Component.hpp"
7#include "Utils/Common.hpp"
10
11enum class PipeType
12{
13 Small,
14 Medium,
15 Large
16};
17
19{
20 const int r = rand() % 3;
21 if (r == 0)
22 return PipeType::Small;
23 if (r == 1)
24 return PipeType::Medium;
25 return PipeType::Large;
26}
27
28float getGapSize(const PipeType type)
29{
30 switch (type)
31 {
32 case PipeType::Small:
33 return 140.f;
35 return 180.f;
36 case PipeType::Large:
37 return 220.f;
38 }
39 return 180.f;
40}
41
42gme::Game::Game(const eng::id assignedId, const std::shared_ptr<eng::IRenderer> &renderer,
43 const std::shared_ptr<eng::IAudio> &audio, bool &showDebug, int skinIndex,
44 const std::string &playerName)
45 : AScene(assignedId), m_renderer(renderer), m_audio(audio), m_showDebug(showDebug), m_skinIndex(skinIndex),
46 m_playerName(playerName)
47{
48 auto &registry = AScene::getRegistry();
49
50 registry.onComponentAdded(
51 [&renderer, &audio, &registry](const ecs::Entity e, const std::type_info &type)
52 {
53 const auto *audioComp = registry.getComponent<ecs::Audio>(e);
54 const auto *colorComp = registry.getComponent<ecs::Color>(e);
55 const auto *fontComp = registry.getComponent<ecs::Font>(e);
56 const auto *rectComp = registry.getComponent<ecs::Rect>(e);
57 const auto *scaleComp = registry.getComponent<ecs::Scale>(e);
58 const auto *textComp = registry.getComponent<ecs::Text>(e);
59 const auto *textureComp = registry.getComponent<ecs::Texture>(e);
60 const auto *transform = registry.getComponent<ecs::Transform>(e);
61 const auto *hitBox = registry.getComponent<ecs::Hitbox>(e);
62
63 if (hitBox && transform)
64 {
65 bool isPipe = false;
66 if (registry.hasComponent<ecs::Texture>(e))
67 {
68 const auto *texture = registry.getComponent<ecs::Texture>(e);
69 if (texture && (texture->id.find("pipe") != std::string::npos))
70 {
71 isPipe = true;
72 }
73 }
74
75 if (!isPipe)
76 {
77 renderer->createCircleShape({.name = "hitbox_" + std::to_string(e),
78 .radius = hitBox->radius,
79 .color = {.r = 255, .g = 0, .b = 0, .a = 100},
80 .x = transform->x + hitBox->offsetX,
81 .y = transform->y + hitBox->offsetY,
82 .outline_thickness = 1.0f,
83 .outline_color = {.r = 255, .g = 0, .b = 0, .a = 200}});
84 }
85 }
86
87 if (type == typeid(ecs::Text))
88 {
89 if (textComp && transform && fontComp)
90 {
91 renderer->createFont(fontComp->id, fontComp->path);
92 renderer->createText(
93 {.font_name = fontComp->id,
94 .color = {.r = colorComp->r, .g = colorComp->g, .b = colorComp->b, .a = colorComp->a},
95 .content = textComp->content,
96 .size = textComp->font_size,
97 .x = transform->x,
98 .y = transform->y,
99 .name = textComp->id});
100 }
101 }
102 else if (type == typeid(ecs::Texture))
103 {
104 const float scale_x = scaleComp ? scaleComp->x : 1.F;
105 const float scale_y = scaleComp ? scaleComp->y : 1.F;
106
107 renderer->createTexture(textureComp->id, textureComp->path);
108
109 if (transform && textureComp)
110 {
111 if (rectComp)
112 {
113 renderer->createSprite(textureComp->id + std::to_string(e), textureComp->id, transform->x,
114 transform->y, scale_x, scale_y, static_cast<int>(rectComp->pos_x),
115 static_cast<int>(rectComp->pos_y), rectComp->size_x, rectComp->size_y);
116 }
117 else
118 {
119 renderer->createSprite(textureComp->id + std::to_string(e), textureComp->id, transform->x,
120 transform->y);
121 }
122 }
123 }
124 else if (type == typeid(ecs::Audio))
125 {
126 if (audioComp)
127 {
128 audio->createAudio(audioComp->path, audioComp->volume, audioComp->loop,
129 audioComp->id + std::to_string(e));
130 }
131 }
132 });
133
134 m_playerEntity = createPlayer(registry);
135
136 m_playerNameEntity = registry.createEntity()
137 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
138 .with<ecs::Transform>("transform_player_name", 200.0F, 160.0F, 0.F)
139 .with<ecs::Color>("color_player_name", utl::Config::Color::CYAN_ELECTRIC.r,
142 .with<ecs::Text>("id_player_name", m_playerName.empty() ? "Player" : m_playerName, 20U)
143 .build();
144
145 auto [width, height] = m_renderer->getWindowSize();
146 m_pipes.emplace_back(createPipePair(registry, width + 200.f, height / 2.f));
147 m_pipes.emplace_back(createPipePair(registry, width + 600.f, height / 2.f + 50.f));
148 m_pipes.emplace_back(createPipePair(registry, width + 1000.f, height / 2.f - 50.f));
149 m_pipeScored = {false, false, false};
150
151 m_scoreEntity = registry.createEntity()
152 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
153 .with<ecs::Transform>("transform_score", 50.0F, 50.0F, 0.F)
154 .with<ecs::Color>("color_score", utl::Config::Color::CYAN_ELECTRIC.r,
157 .with<ecs::Text>("id_score", std::string("Score: 0"), 32U)
158 .build();
159
161 registry.createEntity()
162 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
163 .with<ecs::Transform>("transform_loose", 0.0F, height / 2.0F, 0.F)
166 .with<ecs::Text>("id_loose", std::string("You loose, press R to restart"), 24U)
167 .build();
168 m_looseSound = registry.createEntity()
169 .with<ecs::Audio>("audio" + std::to_string(m_looseSound), "assets/audio/flappy-die.ogg", 10.0F,
170 false, false)
171 .build();
172 m_flapSound = registry.createEntity()
173 .with<ecs::Audio>("audio" + std::to_string(m_flapSound), "assets/audio/flappy-flap.ogg", 10.0F,
174 false, false)
175 .build();
176}
177
178void gme::Game::update(const float dt, const eng::WindowSize &size)
179{
180 auto &registry = AScene::getRegistry();
181 auto *transformLooseText = registry.getComponent<ecs::Transform>(m_looseText);
182 auto *soundLoose = registry.getComponent<ecs::Audio>(m_looseSound);
183
184 transformLooseText->x = 90000.0F;
185
186 if (m_gameOver)
187 {
188 transformLooseText->x = 100.0F;
189 if (!m_gameOverShown)
190 {
191 soundLoose->play = true;
192 m_gameOverShown = true;
193 }
194 return;
195 }
196
197 checkCollisions(registry);
198 checkScore(registry);
199
200 if (m_showDebug)
201 {
202 drawDebugRectangles(registry);
203 }
204
205 auto *transform = registry.getComponent<ecs::Transform>(m_playerEntity);
206 auto *velocity = registry.getComponent<ecs::Velocity>(m_playerEntity);
207 auto *playerNameTransform = registry.getComponent<ecs::Transform>(m_playerNameEntity);
208
209 if (transform && velocity)
210 {
211 constexpr float gravity = 900.f;
212 velocity->y += gravity * dt;
213
214 // Update player name position to follow the player
215 if (playerNameTransform)
216 {
217 playerNameTransform->x = transform->x;
218 playerNameTransform->y = transform->y - 40.0F;
219 }
220 transform->y += velocity->y * dt;
221
222 if (transform->y > size.height - 50)
223 {
224 transform->y = size.height - 50;
225 velocity->y = 0.f;
226 m_gameOver = true;
227 }
228 if (transform->y < 0)
229 {
230 transform->y = 0;
231 velocity->y = 0.f;
232 }
233
234 m_renderer->setSpritePosition("player_texture" + std::to_string(m_playerEntity), transform->x, transform->y);
235 }
236
237 for (std::size_t i = 0; i < m_pipes.size(); ++i)
238 {
239 auto &[topPipe, bottomPipe] = m_pipes[i];
240 auto *topTransform = registry.getComponent<ecs::Transform>(topPipe);
241 auto *botTransform = registry.getComponent<ecs::Transform>(bottomPipe);
242 const auto *topVel = registry.getComponent<ecs::Velocity>(topPipe);
243
244 if (const auto *botVel = registry.getComponent<ecs::Velocity>(bottomPipe);
245 topTransform && botTransform && topVel && botVel)
246 {
247 topTransform->x += topVel->x * dt;
248 botTransform->x += botVel->x * dt;
249
250 if (topTransform->x < -150)
251 {
252 topTransform->x = size.width + 200.f;
253 botTransform->x = size.width + 200.f;
254
255 const PipeType type = randomPipeType();
256 const float gapSize = getGapSize(type);
257 const float gapY = static_cast<float>(100 + rand() % (size.height - 100 - static_cast<int>(gapSize)));
258
259 const float scale = static_cast<float>(size.width) / 1920.f;
260 const float pipeHeight = 153.f * scale * 3.f;
261 topTransform->y = gapY - pipeHeight / 2.f;
262 botTransform->y = gapY + gapSize + pipeHeight / 2.f;
263
264 if (i < m_pipeScored.size())
265 {
266 m_pipeScored[i] = false;
267 }
268 }
269
270 m_renderer->setSpritePosition("pipe_top_texture" + std::to_string(topPipe), topTransform->x,
271 topTransform->y);
272 m_renderer->setSpritePosition("pipe_bottom_texture" + std::to_string(bottomPipe), botTransform->x,
273 botTransform->y);
274 }
275 }
276}
277
278void gme::Game::event(const eng::Event &event)
279{
280 auto &registry = AScene::getRegistry();
281 auto *soundFlap = registry.getComponent<ecs::Audio>(m_flapSound);
282
283 switch (event.type)
284 {
286 if (event.key == eng::Key::Space && !m_gameOver)
287 {
288 soundFlap->play = true;
289 if (auto *vel = registry.getComponent<ecs::Velocity>(m_playerEntity))
290 vel->y = -300.f;
291 }
292 else if (event.key == eng::Key::R && m_gameOver)
293 {
294 resetGame();
295 }
296 break;
297
298 default:
299 break;
300 }
301}
302
304{
306 const float skinPosY = m_skinIndex * utl::GameConfig::Player::SPRITE_HEIGHT;
307
308 return registry.createEntity()
309 .with<ecs::Transform>("player_transform", 200.0F, 200.0F, 0.F)
310 .with<ecs::Velocity>("player_velocity", 0.F, 0.F)
311 .with<ecs::Rect>("player_rect", 0.F, skinPosY, 33, 17)
312 .with<ecs::Scale>("player_scale", 2.0F, 2.0F)
313 .with<ecs::Texture>("player_texture", utl::Path::Texture::TEXTURE_PLAYER)
314 .with<ecs::Player>("player", true)
315 .with<ecs::Hitbox>("player_hitbox", 20.0F, offsetX, offsetY)
316 .build();
317}
318
319std::pair<ecs::Entity, ecs::Entity> gme::Game::createPipePair(ecs::Registry &registry, float x, float /*gapY*/) const
320{
321 auto [width, height] = m_renderer->getWindowSize();
322 const float scale = width / 1920.f;
323 const float pipeOriginalWidth = 153.f;
324 const float pipeOriginalHeight = 22.f;
325 const float pipeScaledWidth = pipeOriginalWidth * scale * 3.f;
326 const float pipeScaledHeight = pipeOriginalHeight * scale * 3.f;
327 const float pipeRadius = pipeScaledWidth / 2.f * 1.2f;
328
329 auto topPipe = registry.createEntity()
330 .with<ecs::Transform>("pipe_top_transform", x, 0.f, 0.f)
331 .with<ecs::Velocity>("pipe_top_velocity", -200.f * scale, 0.f)
332 .with<ecs::Scale>("pipe_top_scale", scale * 3.f, scale * 3.f)
333 .with<ecs::Texture>("pipe_top_texture", "assets/sprites/flappybird-pipe-xl.png")
334 .with<ecs::Hitbox>("pipe_top_hitbox", pipeRadius, 0.f, 0.f)
335 .build();
336
337 m_renderer->setSpriteRotation("pipe_top_texture" + std::to_string(topPipe), -90.f);
338 m_renderer->setSpriteOrigin("pipe_top_texture" + std::to_string(topPipe));
339
340 auto bottomPipe = registry.createEntity()
341 .with<ecs::Transform>("pipe_bottom_transform", x, static_cast<float>(height), 0.f)
342 .with<ecs::Velocity>("pipe_bottom_velocity", -200.f * scale, 0.f)
343 .with<ecs::Scale>("pipe_bottom_scale", scale * 3.f, scale * 3.f)
344 .with<ecs::Texture>("pipe_bottom_texture", "assets/sprites/flappybird-pipe-xl.png")
345 .with<ecs::Hitbox>("pipe_bottom_hitbox", pipeRadius, 0.f, 0.f)
346 .build();
347
348 m_renderer->setSpriteRotation("pipe_bottom_texture" + std::to_string(bottomPipe), 90.f);
349 m_renderer->setSpriteOrigin("pipe_bottom_texture" + std::to_string(bottomPipe));
350
351 return {topPipe, bottomPipe};
352}
353
355{
356 auto &registry = AScene::getRegistry();
357 auto *playerTransform = registry.getComponent<ecs::Transform>(m_playerEntity);
358
359 if (auto *playerVel = registry.getComponent<ecs::Velocity>(m_playerEntity);
360 (playerTransform != nullptr) && playerVel)
361 {
362 playerTransform->x = 200.f;
363 playerTransform->y = 200.f;
364 playerVel->y = 0.f;
365 }
366
367 auto [width, height] = m_renderer->getWindowSize();
368 const float scale = width / 1920.f;
369 float startX = width + 200.f;
370
371 for (std::size_t i = 0; i < m_pipes.size(); ++i)
372 {
373 auto &[topPipe, bottomPipe] = m_pipes[i];
374 auto *topTransform = registry.getComponent<ecs::Transform>(topPipe);
375 if (auto *botTransform = registry.getComponent<ecs::Transform>(bottomPipe); topTransform && botTransform)
376 {
377 topTransform->x = startX;
378 botTransform->x = startX;
379 const PipeType type = randomPipeType();
380 const float gapSize = getGapSize(type);
381 const float gapY = static_cast<float>(100 + rand() % (height - 100 - static_cast<int>(gapSize)));
382
383 const float pipeHeight = 153.f * scale * 3.f;
384 topTransform->y = gapY - pipeHeight / 2.f;
385 botTransform->y = gapY + gapSize + pipeHeight / 2.f;
386 }
387 startX += 400.f;
388 if (i < m_pipeScored.size())
389 {
390 m_pipeScored[i] = false;
391 }
392 }
393
394 m_gameOver = false;
395 m_gameOverShown = false;
396 m_score = 0;
397 if (auto *scoreText = registry.getComponent<ecs::Text>(m_scoreEntity))
398 {
399 scoreText->content = "Score: 0";
400 m_renderer->setTextContent("id_score", "Score: 0");
401 }
402}
403
404bool gme::Game::checkCircleCollision(float x1, float y1, float r1, float x2, float y2, float r2) const
405{
406 const float dx = x1 - x2;
407 const float dy = y1 - y2;
408 const float distance = std::sqrt(dx * dx + dy * dy);
409 const float combinedRadius = r1 + r2;
410
411 return distance < combinedRadius;
412}
413
414bool gme::Game::checkCircleRectCollision(float circleX, float circleY, float circleR, float rectX, float rectY, float rectW, float rectH) const
415{
416 const float closestX = std::max(rectX, std::min(circleX, rectX + rectW));
417 const float closestY = std::max(rectY, std::min(circleY, rectY + rectH));
418
419 const float dx = circleX - closestX;
420 const float dy = circleY - closestY;
421 const float distanceSquared = dx * dx + dy * dy;
422
423 return distanceSquared < circleR * circleR;
424}
425
427{
428 if (m_gameOver)
429 return;
430
431 auto *playerTransform = registry.getComponent<ecs::Transform>(m_playerEntity);
432 auto *playerHitbox = registry.getComponent<ecs::Hitbox>(m_playerEntity);
433
434 if (!playerTransform || !playerHitbox)
435 return;
436
437 const float playerX = playerTransform->x + playerHitbox->offsetX;
438 const float playerY = playerTransform->y + playerHitbox->offsetY;
439 const float playerRadius = playerHitbox->radius;
440
441 auto [width, height] = m_renderer->getWindowSize();
442 const float scale = width / 1920.f;
443 const float pipeOriginalWidth = 153.f;
444 const float pipeOriginalHeight = 22.f;
445 const float pipeScaledWidth = pipeOriginalWidth * scale * 3.f;
446 const float pipeScaledHeight = pipeOriginalHeight * scale * 3.f;
447
448 for (const auto &[topPipe, bottomPipe] : m_pipes)
449 {
450 auto *topTransform = registry.getComponent<ecs::Transform>(topPipe);
451 auto *botTransform = registry.getComponent<ecs::Transform>(bottomPipe);
452
453 if (!topTransform || !botTransform)
454 continue;
455
456 const float topRectX = topTransform->x - pipeScaledHeight / 2.f;
457 const float topRectY = topTransform->y - pipeScaledWidth / 2.f;
458 const float topRectW = pipeScaledHeight;
459 const float topRectH = pipeScaledWidth;
460
461 const float botRectX = botTransform->x - pipeScaledHeight / 2.f;
462 const float botRectY = botTransform->y - pipeScaledWidth / 2.f;
463 const float botRectW = pipeScaledHeight;
464 const float botRectH = pipeScaledWidth;
465
466 if (checkCircleRectCollision(playerX, playerY, playerRadius, topRectX, topRectY, topRectW, topRectH) ||
467 checkCircleRectCollision(playerX, playerY, playerRadius, botRectX, botRectY, botRectW, botRectH))
468 {
469 m_gameOver = true;
470 return;
471 }
472 }
473}
474
476{
477 if (m_gameOver)
478 return;
479
480 auto *playerTransform = registry.getComponent<ecs::Transform>(m_playerEntity);
481 if (!playerTransform)
482 return;
483
484 const float playerX = playerTransform->x;
485
486 for (std::size_t i = 0; i < m_pipes.size(); ++i)
487 {
488 if (i >= m_pipeScored.size())
489 continue;
490
491 if (m_pipeScored[i])
492 continue;
493
494 auto &[topPipe, bottomPipe] = m_pipes[i];
495 auto *topTransform = registry.getComponent<ecs::Transform>(topPipe);
496
497 if (!topTransform)
498 continue;
499
500 if (playerX > topTransform->x + 100.f)
501 {
502 m_pipeScored[i] = true;
503 m_score++;
504 if (auto *scoreText = registry.getComponent<ecs::Text>(m_scoreEntity))
505 {
506 scoreText->content = "Score: " + std::to_string(m_score);
507 m_renderer->setTextContent("id_score", "Score: " + std::to_string(m_score));
508 }
509 }
510 }
511}
512
514{
515 auto [width, height] = m_renderer->getWindowSize();
516 const float scale = width / 1920.f;
517 const float pipeOriginalWidth = 153.f;
518 const float pipeOriginalHeight = 22.f;
519 const float pipeScaledWidth = pipeOriginalWidth * scale * 3.f;
520 const float pipeScaledHeight = pipeOriginalHeight * scale * 3.f;
521
522 const eng::Color debugColor = {.r = 0, .g = 255, .b = 0, .a = 200};
523
524 for (const auto &[topPipe, bottomPipe] : m_pipes)
525 {
526 auto *topTransform = registry.getComponent<ecs::Transform>(topPipe);
527 auto *botTransform = registry.getComponent<ecs::Transform>(bottomPipe);
528
529 if (!topTransform || !botTransform)
530 continue;
531
532 const float topRectX = topTransform->x - pipeScaledHeight / 2.f;
533 const float topRectY = topTransform->y - pipeScaledWidth / 2.f;
534 const float topRectW = pipeScaledHeight;
535 const float topRectH = pipeScaledWidth;
536
537 const float botRectX = botTransform->x - pipeScaledHeight / 2.f;
538 const float botRectY = botTransform->y - pipeScaledWidth / 2.f;
539 const float botRectW = pipeScaledHeight;
540 const float botRectH = pipeScaledWidth;
541
542 const float step = 2.f;
543 for (float x = topRectX; x <= topRectX + topRectW; x += step)
544 {
545 m_renderer->drawPoint(x, topRectY, debugColor);
546 m_renderer->drawPoint(x, topRectY + topRectH, debugColor);
547 }
548 for (float y = topRectY; y <= topRectY + topRectH; y += step)
549 {
550 m_renderer->drawPoint(topRectX, y, debugColor);
551 m_renderer->drawPoint(topRectX + topRectW, y, debugColor);
552 }
553
554 for (float x = botRectX; x <= botRectX + botRectW; x += step)
555 {
556 m_renderer->drawPoint(x, botRectY, debugColor);
557 m_renderer->drawPoint(x, botRectY + botRectH, debugColor);
558 }
559 for (float y = botRectY; y <= botRectY + botRectH; y += step)
560 {
561 m_renderer->drawPoint(botRectX, y, debugColor);
562 m_renderer->drawPoint(botRectX + botRectW, y, debugColor);
563 }
564 }
565}
This file contains the component definitions.
Configuration constants for the multiplayer game.
This file contains the solo Game scene.
Utility functions for hitbox calculations.
EntityBuilder & with(Args &&...args)
Definition Registry.hpp:40
Class for managing entities and their components.
Definition Registry.hpp:25
EntityBuilder createEntity()
Definition Registry.hpp:53
T * getComponent(Entity e)
Definition Registry.hpp:71
virtual WindowSize getWindowSize()=0
std::pair< ecs::Entity, ecs::Entity > createPipePair(ecs::Registry &registry, float x, float gapY) const
Definition game.cpp:319
ecs::Entity m_playerEntity
Definition Game.hpp:52
Game(eng::id assignedId, const std::shared_ptr< eng::IRenderer > &renderer, const std::shared_ptr< eng::IAudio > &audio, bool &showDebug, int skinIndex=0, const std::string &playerName="Player")
Definition game.cpp:42
void update(float dt, const eng::WindowSize &size) override
Definition game.cpp:178
void resetGame()
Definition game.cpp:354
void checkCollisions(ecs::Registry &registry)
Definition game.cpp:426
void event(const eng::Event &event) override
Definition game.cpp:278
const std::shared_ptr< eng::IRenderer > & m_renderer
Definition Game.hpp:49
ecs::Entity createPlayer(ecs::Registry &registry)
Definition game.cpp:303
std::string m_playerName
Definition Game.hpp:66
bool checkCircleCollision(float x1, float y1, float r1, float x2, float y2, float r2) const
Definition game.cpp:404
ecs::Entity m_flapSound
Definition Game.hpp:55
void checkScore(ecs::Registry &registry)
Definition game.cpp:475
ecs::Entity m_playerNameEntity
Definition Game.hpp:53
ecs::Entity m_looseSound
Definition Game.hpp:56
std::vector< std::pair< ecs::Entity, ecs::Entity > > m_pipes
Definition Game.hpp:58
bool checkCircleRectCollision(float circleX, float circleY, float circleR, float rectX, float rectY, float rectW, float rectH) const
Definition game.cpp:414
void drawDebugRectangles(ecs::Registry &registry) const
Definition game.cpp:513
std::vector< bool > m_pipeScored
Definition Game.hpp:59
ecs::Entity m_scoreEntity
Definition Game.hpp:57
ecs::Entity m_looseText
Definition Game.hpp:54
PipeType
Definition game.cpp:12
float getGapSize(const PipeType type)
Definition game.cpp:28
PipeType randomPipeType()
Definition game.cpp:18
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 CYAN_ELECTRIC
Definition Common.hpp:56
constexpr float SCALE
constexpr float SPRITE_HEIGHT
constexpr float SPRITE_WIDTH
constexpr auto FONTS_RTYPE
Definition Common.hpp:97
constexpr auto TEXTURE_PLAYER
Definition Common.hpp:114
std::pair< float, float > calculateHitboxOffsets(const float spriteWidth, const float spriteHeight, const float scale)
Calculate hitbox offsets to center the hitbox on the sprite.
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