R-Type
Distributed multiplayer game engine in C++
Loading...
Searching...
No Matches
RoomListMenu.cpp
Go to the documentation of this file.
1/*
2** EPITECH PROJECT, 2025
3** r-type
4** File description:
5** RoomListMenu - Menu for selecting or creating a room
6*/
7
9#include <cstring>
10#include <sstream>
11#include "../common/Logger/Logger.hpp"
12
13namespace Game {
15 : BaseMenu(uiFactory), _graphics(graphics) {}
16
17 void RoomListMenu::SetOnRoomSelected(std::function<void(const std::string &)> onRoomSelected) {
18 _onRoomSelected = std::move(onRoomSelected);
19 }
20
21 void RoomListMenu::SetOnCreateRoom(std::function<void()> onCreateRoom) {
22 _onCreateRoom = std::move(onCreateRoom);
23 }
24
25 void RoomListMenu::SetOnBack(std::function<void()> onBack) {
26 _onBack = std::move(onBack);
27 }
28
29 void RoomListMenu::UpdateRoomList(const std::vector<RoomInfo> &rooms) {
30 _rooms = rooms;
32 }
33
35 _rooms.clear();
37 }
38
45
47 if (!_menu) {
48 return;
49 }
50
51 _menu->Clear();
52 _roomButtons.clear();
53
55
56 // Add "Create Room" button at bottom center
57 const float buttonWidth = 180.0f;
58 const float buttonHeight = 45.0f;
59 const float bottomMargin = 120.0f;
60
61 auto createRoomPtr = _uiFactory.CreateButton();
62 createRoomPtr->SetSize(buttonWidth, buttonHeight);
63 createRoomPtr->SetAlign(UI::Align::CENTER_HORIZONTAL);
64 createRoomPtr->ApplyAlignment();
65
66 float x, y;
67 createRoomPtr->GetPosition(x, y);
68 float screenHeight = static_cast<float>(_graphics.GetScreenHeight());
69 createRoomPtr->SetPosition(x, screenHeight - bottomMargin);
70
71 createRoomPtr->SetText("Create Room");
72 createRoomPtr->SetBackgroundColor(0xFF4CAF50); // Green
73 createRoomPtr->SetHoverColor(0xFF66BB6A);
74 createRoomPtr->SetTextColor(0xFFFFFFFF);
75 createRoomPtr->SetCallback(WrapWithClickSound([this]() { OnCreateRoomClicked(); }));
76
77 _createRoomButton = std::move(createRoomPtr);
78 _menu->AddButton(_createRoomButton);
79
80 // Add "Back" button at bottom left
81 const float leftMargin = 20.0f;
82 auto backPtr = _uiFactory.CreateButton();
83 backPtr->SetSize(150.0f, 45.0f);
84 backPtr->SetPosition(leftMargin, screenHeight - bottomMargin);
85 backPtr->SetText("Back");
86 backPtr->SetBackgroundColor(0xFF424242); // Dark gray
87 backPtr->SetHoverColor(0xFF616161);
88 backPtr->SetTextColor(0xFFFFFFFF);
89 backPtr->SetCallback(WrapWithClickSound([this]() { OnBackClicked(); }));
90
91 _backButton = std::move(backPtr);
92 _menu->AddButton(_backButton);
93 }
94
96 if (!_menu || !_menu->IsVisible()) {
97 return;
98 }
100 }
101
103 if (!_menu || !_menu->IsVisible()) {
104 return;
105 }
106
107 // Draw title
108 const char *title = "Select a Room";
109 int screenWidth = _graphics.GetScreenWidth();
110 int titleFontSize = 32;
111 int titleWidth = static_cast<int>(strlen(title) * titleFontSize * 0.5f);
112 int titleX = (screenWidth - titleWidth) / 2;
113 _graphics.DrawText(title, titleX, 30, titleFontSize, 0xFFFFFFFF);
114
115 // Draw room count
116 std::string countText = "Available Rooms: " + std::to_string(_rooms.size());
117 int countFontSize = 18;
118 int countWidth = static_cast<int>(countText.length() * countFontSize * 0.5f);
119 int countX = (screenWidth - countWidth) / 2;
120 _graphics.DrawText(countText.c_str(), countX, 70, countFontSize, 0xFFAAAAAA);
121
123 }
124
126 if (!_menu) {
127 return;
128 }
129
130 // Clear the entire menu and rebuild everything
131 _menu->Clear();
132 _roomButtons.clear();
133
134 // Create buttons for each room
135 float currentY = LIST_START_Y;
136 for (size_t i = 0; i < _rooms.size() && i < MAX_VISIBLE_ROOMS; ++i) {
137 const auto &room = _rooms[i];
138
139 // Room button
140 auto buttonPtr = _uiFactory.CreateButton();
141 buttonPtr->SetSize(ROOM_BUTTON_WIDTH, ROOM_BUTTON_HEIGHT);
142 buttonPtr->SetAlign(UI::Align::CENTER_HORIZONTAL);
143 buttonPtr->ApplyAlignment();
144
145 float x, y;
146 buttonPtr->GetPosition(x, y);
147 buttonPtr->SetPosition(x, currentY);
148
149 // Button text: "RoomName [2/4] - WAITING"
150 std::ostringstream oss;
151 oss << room.roomName << " [" << room.playerCount << "/" << room.maxPlayers << "]";
152 if (room.isPrivate) {
153 oss << " 🔒";
154 }
155
156 // State text
157 const char *stateText = " - WAITING";
158 if (room.state == 1)
159 stateText = " - STARTING";
160 else if (room.state == 2)
161 stateText = " - IN PROGRESS";
162 else if (room.state == 3)
163 stateText = " - FINISHED";
164 oss << stateText;
165
166 buttonPtr->SetText(oss.str());
167
168 // Color based on room state
169 if (room.state == 0) { // WAITING
170 buttonPtr->SetBackgroundColor(0xFF4CAF50); // Green
171 buttonPtr->SetHoverColor(0xFF66BB6A);
172 } else if (room.state == 1) { // STARTING
173 buttonPtr->SetBackgroundColor(0xFFFFA726); // Orange
174 buttonPtr->SetHoverColor(0xFFFFB74D);
175 } else if (room.state == 2) { // IN_PROGRESS (spectator join allowed)
176 buttonPtr->SetBackgroundColor(0xFF2196F3); // Blue for spectate
177 buttonPtr->SetHoverColor(0xFF64B5F6);
178 } else { // FINISHED
179 buttonPtr->SetBackgroundColor(0xFF9E9E9E); // Gray (disabled)
180 buttonPtr->SetHoverColor(0xFF9E9E9E);
181 }
182
183 buttonPtr->SetTextColor(0xFFFFFFFF);
184 buttonPtr->SetTextSize(16);
185
186 size_t index = i; // Capture by value for lambda
187
188 // Allow joining WAITING/STARTING normally and IN_PROGRESS as spectator
189 if (room.state <= 2) { // WAITING, STARTING, IN_PROGRESS
190 buttonPtr->SetCallback(WrapWithClickSound([this, index]() { OnRoomClicked(index); }));
191 } else {
192 buttonPtr->SetCallback(WrapWithClickSound(
193 []() { LOG_INFO("[RoomListMenu] Cannot join this room - game finished"); }));
194 }
195
196 std::shared_ptr<UI::IButton> button = std::move(buttonPtr);
197 _roomButtons.push_back(button);
198 _menu->AddButton(button);
199
201 }
202
203 // Re-add persistent buttons
204 if (_createRoomButton) {
205 _menu->AddButton(_createRoomButton);
206 }
207 if (_backButton) {
208 _menu->AddButton(_backButton);
209 }
210 }
211
212 void RoomListMenu::OnRoomClicked(size_t index) {
213 if (index >= _rooms.size()) {
214 LOG_ERROR("[RoomListMenu] Invalid room index: ", index);
215 return;
216 }
217
218 const auto &room = _rooms[index];
219 LOG_INFO("[RoomListMenu] Selected room: ", room.roomName, " (ID: ", room.roomId, ")");
220
221 if (_onRoomSelected) {
222 _onRoomSelected(room.roomId);
223 }
224 }
225
227 LOG_INFO("[RoomListMenu] Create Room button clicked");
228 if (_onCreateRoom) {
230 }
231 }
232
234 LOG_INFO("[RoomListMenu] Back button clicked");
235 if (_onBack) {
236 _onBack();
237 }
238 }
239} // namespace Game
#define LOG_INFO(...)
Definition Logger.hpp:181
#define LOG_ERROR(...)
Definition Logger.hpp:183
virtual void PlayRoomMenuOpenSound()=0
Play the room menu open sound effect.
Base class for all menu implementations.
Definition BaseMenu.hpp:26
virtual void Show()
Show the menu.
Definition BaseMenu.cpp:28
virtual void Update()
Update menu state (should be called every frame).
Definition BaseMenu.cpp:16
std::shared_ptr< UI::IMenu > _menu
Definition BaseMenu.hpp:101
Audio::ISoundEffectService * _soundService
Definition BaseMenu.hpp:102
virtual void Render()
Render menu (should be called every frame).
Definition BaseMenu.cpp:22
std::function< void()> WrapWithClickSound(std::function< void()> callback)
Wrap a callback to play click sound before executing.
Definition BaseMenu.cpp:48
UI::IUIFactory & _uiFactory
Definition BaseMenu.hpp:100
void SetOnBack(std::function< void()> onBack)
Set callback triggered when Back button is clicked.
std::shared_ptr< UI::IButton > _createRoomButton
std::vector< std::shared_ptr< UI::IButton > > _roomButtons
void UpdateRoomList(const std::vector< RoomInfo > &rooms)
Update the room list.
static constexpr float ROOM_BUTTON_HEIGHT
void SetOnRoomSelected(std::function< void(const std::string &roomId)> onRoomSelected)
Set callback triggered when a room is selected.
void Update() override
Update menu state (should be called every frame).
void SetOnCreateRoom(std::function< void()> onCreateRoom)
Set callback triggered when "Create Room" button is clicked.
std::function< void(const std::string &)> _onRoomSelected
void Render() override
Render menu (should be called every frame).
static constexpr size_t MAX_VISIBLE_ROOMS
static constexpr float ROOM_BUTTON_SPACING
std::function< void()> _onCreateRoom
void Show() override
Show the menu and play the room menu open sound effect.
std::shared_ptr< UI::IButton > _backButton
void ClearRooms()
Clear all rooms.
Graphics::IGraphics & _graphics
RoomListMenu(UI::IUIFactory &uiFactory, Graphics::IGraphics &graphics)
std::function< void()> _onBack
static constexpr float ROOM_BUTTON_WIDTH
void OnRoomClicked(size_t index)
void Initialize() override
Initialize menu (must be implemented by derived classes).
static constexpr float LIST_START_Y
std::vector< RoomInfo > _rooms
Abstract interface for graphics rendering operations.
Definition IGraphics.hpp:32
virtual void DrawText(int fontHandle, const char *text, int x, int y, int fontSize, unsigned int color)=0
Draw text using a loaded font.
virtual int GetScreenHeight() const =0
Get the screen height (same as window height)
virtual int GetScreenWidth() const =0
Get the screen width (same as window width)
Abstract factory interface for creating UI elements.
virtual std::unique_ptr< IButton > CreateButton()=0
Create a button instance.
@ CENTER_HORIZONTAL
Center on the X axis.