r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
createRoom.cpp
Go to the documentation of this file.
1#include <cmath>
2
5#include "Utils/Event.hpp"
6#include "Utils/Logger.hpp"
7
8#include "ECS/Component.hpp"
10#include "Utils/Common.hpp"
11
12static char keyToChar(const eng::Key key, bool shift = false)
13{
14 switch (key)
15 {
16 case eng::Key::Q:
17 return shift ? 'A' : 'a';
18 case eng::Key::W:
19 return shift ? 'Z' : 'z';
20 case eng::Key::E:
21 return shift ? 'E' : 'e';
22 case eng::Key::R:
23 return shift ? 'R' : 'r';
24 case eng::Key::T:
25 return shift ? 'T' : 't';
26 case eng::Key::Y:
27 return shift ? 'Y' : 'y';
28 case eng::Key::U:
29 return shift ? 'U' : 'u';
30 case eng::Key::I:
31 return shift ? 'I' : 'i';
32 case eng::Key::O:
33 return shift ? 'O' : 'o';
34 case eng::Key::P:
35 return shift ? 'P' : 'p';
36
37 case eng::Key::A:
38 return shift ? 'Q' : 'q';
39 case eng::Key::S:
40 return shift ? 'S' : 's';
41 case eng::Key::D:
42 return shift ? 'D' : 'd';
43 case eng::Key::F:
44 return shift ? 'F' : 'f';
45 case eng::Key::G:
46 return shift ? 'G' : 'g';
47 case eng::Key::H:
48 return shift ? 'H' : 'h';
49 case eng::Key::J:
50 return shift ? 'J' : 'j';
51 case eng::Key::K:
52 return shift ? 'K' : 'k';
53 case eng::Key::M:
54 return shift ? 'M' : 'm';
55 case eng::Key::L:
56 return shift ? 'L' : 'l';
57
58 case eng::Key::Z:
59 return shift ? 'W' : 'w';
60 case eng::Key::X:
61 return shift ? 'X' : 'x';
62 case eng::Key::C:
63 return shift ? 'C' : 'c';
64 case eng::Key::V:
65 return shift ? 'V' : 'v';
66 case eng::Key::B:
67 return shift ? 'B' : 'b';
68 case eng::Key::N:
69 return shift ? 'N' : 'n';
70
71 case eng::Key::Num0:
72 return '0';
73 case eng::Key::Num1:
74 return '1';
75 case eng::Key::Num2:
76 return '2';
77 case eng::Key::Num3:
78 return '3';
79 case eng::Key::Num4:
80 return '4';
81 case eng::Key::Num5:
82 return '5';
83 case eng::Key::Num6:
84 return '6';
85 case eng::Key::Num7:
86 return '7';
87 case eng::Key::Num8:
88 return '8';
89 case eng::Key::Num9:
90 return '9';
91 case eng::Key::Space:
92 return ' ';
93 default:
94 return '\0';
95 }
96}
97
98gme::CreateRoomScene::CreateRoomScene(const eng::id assignedId, const std::shared_ptr<eng::IRenderer> &renderer)
99 : AScene(assignedId)
100{
101 auto &registry = AScene::getRegistry();
102
103 registry.onComponentAdded(
104 [&renderer, &registry](const ecs::Entity e, const std::type_info &type)
105 {
106 const auto *colorComp = registry.getComponent<ecs::Color>(e);
107 const auto *fontComp = registry.getComponent<ecs::Font>(e);
108 const auto *textComp = registry.getComponent<ecs::Text>(e);
109 const auto *transform = registry.getComponent<ecs::Transform>(e);
110
111 if (type == typeid(ecs::Text))
112 {
113 if (textComp && transform && fontComp)
114 {
115 renderer->createFont(fontComp->id, fontComp->path);
116 renderer->createText(
117 {.font_name = fontComp->id,
118 .color = {.r = colorComp->r, .g = colorComp->g, .b = colorComp->b, .a = colorComp->a},
119 .content = textComp->content,
120 .size = textComp->font_size,
121 .x = transform->x,
122 .y = transform->y,
123 .name = textComp->id});
124 }
125 }
126 });
127
129 registry.createEntity()
130 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
131 .with<ecs::Transform>("transform_title", 100.F, 60.F, 0.F)
134 .with<ecs::Text>("title", std::string("CREATE ROOM"), 72U)
135 .build();
136
137 for (size_t i = 0; i < m_options.size(); ++i)
138 {
139 registry.createEntity()
140 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
141 .with<ecs::Transform>("transform_option_" + std::to_string(i), 100.F, 200.F + i * 50.F, 0.F)
142 .with<ecs::Color>("color_option_" + std::to_string(i), utl::Config::Color::GRAY_BLUE_SUBTLE.r,
145 .with<ecs::Text>("option_" + m_options[i], m_options[i], 32U)
146 .build();
147 }
148
150 registry.createEntity()
151 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
152 .with<ecs::Transform>("transform_room_name_value", 580.F, 200.F, 0.F)
153 .with<ecs::Color>("color_room_name_value", utl::Config::Color::TEXT_VALUE_COLOR.r,
156 .with<ecs::Text>("room_name_value", m_roomName, 24U)
157 .build();
158
160 registry.createEntity()
161 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
162 .with<ecs::Transform>("transform_max_players_value", 580.F, 250.F, 0.F)
163 .with<ecs::Color>("color_max_players_value", utl::Config::Color::TEXT_VALUE_COLOR.r,
166 .with<ecs::Text>("max_players_value", std::to_string(m_maxPlayers), 24U)
167 .build();
171}
172
173void gme::CreateRoomScene::update(const float dt, const eng::WindowSize & /*size*/)
174{
175 auto &reg = getRegistry();
176 auto &colors = reg.getAll<ecs::Color>();
177 auto &texts = reg.getAll<ecs::Text>();
178
179 m_animationTime += dt;
180
181 processEventBus();
182
183 for (auto &[entity, text] : texts)
184 {
185 for (size_t i = 0; i < m_options.size(); ++i)
186 {
187 if (text.id == "option_" + m_options[i])
188 {
189 auto &color = colors.at(entity);
190
191 if (i == m_selectedIndex)
192 {
193 const float glowIntensity = std::sin(m_animationTime * 2.5F);
194 color.r = 0U;
195 color.g = static_cast<unsigned char>(191U + (glowIntensity * 50));
196 color.b = 255U;
197 }
198 else
199 {
203 }
204 break;
205 }
206 }
207 }
208}
209
211{
212 switch (event.type)
213 {
215 if (event.key == eng::Key::Escape)
216 {
217 if (onBackToMulti)
218 {
219 onBackToMulti();
220 }
221 }
222 else if (event.key == eng::Key::Up)
223 {
224 m_playMusic = true;
225 m_selectedIndex = (m_selectedIndex == 0) ? m_options.size() - 1 : m_selectedIndex - 1;
226 }
227 else if (event.key == eng::Key::Down)
228 {
229 m_playMusic = true;
230 m_selectedIndex = (m_selectedIndex == m_options.size() - 1) ? 0 : m_selectedIndex + 1;
231 }
232 else if (event.key == eng::Key::Enter)
233 {
234 if (m_selectedIndex == 2 && onCreate)
235 {
236 createRoom();
237 onCreate(m_roomName, m_maxPlayers);
238 }
239 else if (m_selectedIndex == 3 && onBackToMulti)
240 {
241 onBackToMulti();
242 }
243 }
244 else if (event.key == eng::Key::Left || event.key == eng::Key::Right)
245 {
246 if (m_selectedIndex == 1)
247 {
248 if (event.key == eng::Key::Left && m_maxPlayers > 2)
249 {
250 m_maxPlayers--;
251 updateValueDisplay();
252 }
253 else if (event.key == eng::Key::Right && m_maxPlayers < 4)
254 {
255 m_maxPlayers++;
256 updateValueDisplay();
257 }
258 }
259 }
260 else if (event.key == eng::Key::Delete)
261 {
262 if (m_selectedIndex == 0)
263 {
264 if (!m_roomName.empty())
265 {
266 m_roomName.pop_back();
267 updateValueDisplay();
268 }
269 }
270 }
271 else
272 {
273 if (m_selectedIndex == 0)
274 {
275 const char inputChar = keyToChar(event.key);
276
277 if (inputChar != '\0')
278 {
279 if (m_roomName.length() < 20)
280 {
281 m_roomName += inputChar;
282 updateValueDisplay();
283 }
284 }
285 }
286 }
287 break;
289 break;
290 default:
291 break;
292 }
293}
294
296{
297 auto &reg = getRegistry();
298
299 if (auto *roomNameText = reg.getComponent<ecs::Text>(m_roomNameValueEntity))
300 {
301 roomNameText->content = m_roomName;
302 }
303
304 if (auto *maxPlayersText = reg.getComponent<ecs::Text>(m_maxPlayersValueEntity))
305 {
306 maxPlayersText->content = std::to_string(m_maxPlayers);
307 }
308}
309
311{
312 utl::Logger::log("CreateRoomScene: Creating room '" + m_roomName + "' with " + std::to_string(m_maxPlayers) +
313 " max players",
315
316 rnp::PacketLobbyCreate packet{};
317 packet.maxPlayers = static_cast<std::uint8_t>(m_maxPlayers);
318 packet.gameMode = 0;
319 packet.nameLen = static_cast<uint8_t>(m_roomName.size());
320 for (size_t i = 0; i < m_roomName.size(); ++i)
321 {
322 packet.lobbyName[i] = m_roomName[i];
323 }
324
325 utl::Logger::log("CreateRoomScene: Publishing LOBBY_CREATE event to component " +
326 std::to_string(utl::NETWORK_CLIENT),
328 m_eventBus.publish(utl::EventType::LOBBY_CREATE, packet, m_eventComponentId, utl::NETWORK_CLIENT);
329 utl::Logger::log("CreateRoomScene: LOBBY_CREATE event published successfully", utl::LogLevel::INFO);
330}
331
333{
334 for (const auto events = m_eventBus.consumeForTarget(m_eventComponentId); const auto &event : events)
335 {
337 {
338 rnp::Serializer serializer(event.data);
339 if (const auto [lobbyId, success, errorCode] = serializer.deserializeLobbyCreateResponse(); success != 0U)
340 {
341 utl::Logger::log("CreateRoomScene: Lobby created successfully with ID " + std::to_string(lobbyId),
343
344 if (onRoomCreated)
345 {
346 onRoomCreated(static_cast<int>(lobbyId), nullptr);
347 }
348 }
349 else
350 {
351 utl::Logger::log("CreateRoomScene: Failed to create lobby, error code " + std::to_string(errorCode),
353 }
354 }
355 }
356}
This file contains the component definitions.
Lobby creation scene for R-Type multiplayer.
Event structures and types for event-driven communication.
This file contains the Logger class.
This file contains the network protocol.
Network packet serializer for RNP protocol.
utl::EventBus & m_eventBus
Definition IScene.hpp:84
std::uint32_t m_eventComponentId
Definition IScene.hpp:85
std::string m_roomName
Current room name input (default: "My Room")
void update(float dt, const eng::WindowSize &size) override
Update the scene (called each frame)
void processEventBus() const
Process events from the event bus.
const std::vector< std::string > m_options
void updateValueDisplay()
Update the visual display of configuration values.
int m_maxPlayers
Maximum players setting (default: 4)
ecs::Entity m_titleEntity
Title text entity.
ecs::Entity m_roomNameValueEntity
Text entity displaying room name.
ecs::Entity m_maxPlayersValueEntity
Text entity displaying max players.
void event(const eng::Event &event) override
Handle input events.
void createRoom() const
Send lobby creation request to server.
CreateRoomScene(eng::id assignedId, const std::shared_ptr< eng::IRenderer > &renderer)
Constructor.
Binary serializer for RNP protocol packets.
PacketLobbyCreateResponse deserializeLobbyCreateResponse()
Deserialize LOBBY_CREATE_RESPONSE packet.
void registerComponent(std::uint32_t componentId, const std::string &name)
Register component name for better debugging.
Definition EventBus.hpp:423
void subscribe(std::uint32_t componentId, EventType type)
Subscribe component to specific event types.
Definition EventBus.hpp:384
static void log(const std::string &message, const LogLevel &logLevel)
Definition Logger.hpp:51
static char keyToChar(const eng::Key key, bool shift=false)
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 TEXT_VALUE_COLOR
Definition Common.hpp:66
static constexpr eng::Color GRAY_BLUE_SUBTLE
Definition Common.hpp:57
static constexpr eng::Color CYAN_ELECTRIC
Definition Common.hpp:56
constexpr auto FONTS_RTYPE
Definition Common.hpp:97
static constexpr std::uint32_t NETWORK_CLIENT
Definition Event.hpp:17
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
LOBBY_CREATE packet payload.
Definition Protocol.hpp:261
std::uint8_t maxPlayers
Definition Protocol.hpp:264