Merge pull request #28 from BreizhHardware/new_menu

New menu
This commit is contained in:
Félix MARQUET
2024-12-12 17:00:34 +01:00
committed by GitHub
10 changed files with 213 additions and 20 deletions

View File

@@ -55,4 +55,5 @@ endif()
# Options pour la liaison statique en mode release
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
target_sources(bloubloulespoissons PRIVATE resource.rc)
endif()

34
event.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef EVENTHANDLER_H
#define EVENTHANDLER_H
#include <functional>
#include <unordered_map>
#include <string>
class EventHandler {
public:
using EventCallback = std::function<void()>;
template <typename EventCallback, typename... Args>
void registerEvent(const std::string& eventName, EventCallback callback, Args&&... args) {
eventCallbacks[eventName] = [callback, ...args = std::forward<Args>(args)]() {
callback(args.get()...);
};
}
void triggerEvent(const std::string& eventName) {
if (eventCallbacks.find(eventName) != eventCallbacks.end()) {
eventCallbacks[eventName]();
}
}
private:
std::unordered_map<std::string, EventCallback> eventCallbacks;
};
#endif

BIN
img/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 306 KiB

View File

@@ -24,6 +24,8 @@
#include "network/networking_client.h"
#include "shark.h"
#include "event.h"
#include <system_error>
@@ -195,7 +197,7 @@ bool initSDL() {
return false;
}
SDL_Surface* iconSurface = IMG_Load("../img/mory.png");
SDL_Surface* iconSurface = IMG_Load("../img/logo.png");
if(iconSurface == nullptr) {
std::cerr << "Erreur de chargement de l'icône: " << IMG_GetError() << std::endl;
} else {
@@ -306,6 +308,14 @@ void updateShark(Shark &shark) {
}
}
void onPlayerLost(Menu &menu){
menuRunning = true;
menu.changePage("Main");
menu.show();
}
EventHandler eventHandler;
int main(int argc, char* args[]) {
SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, "0");
@@ -315,17 +325,23 @@ int main(int argc, char* args[]) {
return -1;
}
Menu menu(renderer);
menu.addPage("Main");
menu.addPage("Multi");
menu.addPage("Multi-Join");
menu.changePage("Main");
eventHandler.registerEvent("playerLost", onPlayerLost, std::ref(menu));
std::thread menu_thread = createThread("Menu thread", HandleMenuClick, std::ref(menu));
std::thread quit_thread = createThread("Quit thread", handleQuitThread);
menu.addText("Main", (windowWidth/2) - 300, 50, 600, 100, "BloubBloub les poissons", 1024);
menu.addImage("Main", (windowWidth/2) - 100, 150, 200, 200, "../img/logo.png");
menu.addText("Multi-Join", (windowWidth/2) - 100, 50, 200, 100, "Join", 1024);
menu.addButton("Main", (windowWidth/2) - 100, windowHeight/2 - 25, 200, 50, "Solo", 1024, [](){
@@ -507,7 +523,8 @@ int pas_la_fontion_main_enfin_ce_nest_pas_la_fontion_principale_du_programme_mai
std::cerr << "Exception caught 5: " << e.what() << std::endl;
}
std::cout << "All threads killed" << std::endl;
running = false;
// running = false;
eventHandler.triggerEvent("playerLost");
return 0;
}
@@ -614,7 +631,7 @@ int pas_la_fontion_main_enfin_ce_nest_pas_la_fontion_principale_du_programme_mai
std::cerr << "Exception caught 5: " << e.what() << std::endl;
}
running = false;
eventHandler.triggerEvent("playerLost");
}
else if (argc > 0 && argc < 65535 && args != "") {
int port = 1234;
@@ -674,7 +691,7 @@ int pas_la_fontion_main_enfin_ce_nest_pas_la_fontion_principale_du_programme_mai
} catch (const std::system_error& e) {
std::cerr << "Exception caught 4: " << e.what() << std::endl;
}
running = false;
eventHandler.triggerEvent("playerLost");
}
}

155
menu.cpp
View File

@@ -1,14 +1,98 @@
#include "menu.h"
void Menu::draw(SDL_Renderer* renderer){
void drawRoundedRectWithGradient(SDL_Renderer* renderer, SDL_Rect rect, int radius, SDL_Color startColor, SDL_Color endColor, int gradientWidth) {
for (int i = 0; i < gradientWidth; i++) {
Uint8 r = startColor.r + i * (endColor.r - startColor.r) / gradientWidth;
Uint8 g = startColor.g + i * (endColor.g - startColor.g) / gradientWidth;
Uint8 b = startColor.b + i * (endColor.b - startColor.b) / gradientWidth;
Uint8 a = startColor.a + i * (endColor.a - startColor.a) / gradientWidth;
SDL_Color gradientColor = {r, g, b, a};
SDL_SetRenderDrawColor(renderer, gradientColor.r, gradientColor.g, gradientColor.b, gradientColor.a);
SDL_Rect gradientRect = {
rect.x - i,
rect.y - i,
rect.w + 2 * i,
rect.h + 2 * i
};
auto drawRoundedCorners = [&](int x, int y, int r) {
for (int dy = -r; dy <= r; dy++) {
for (int dx = -r; dx <= r; dx++) {
if (dx * dx + dy * dy <= r * r) {
SDL_RenderDrawPoint(renderer, x + dx, y + dy);
}
}
}
};
drawRoundedCorners(gradientRect.x + radius, gradientRect.y + radius, radius);
drawRoundedCorners(gradientRect.x + gradientRect.w - radius, gradientRect.y + radius, radius);
drawRoundedCorners(gradientRect.x + radius, gradientRect.y + gradientRect.h - radius, radius);
drawRoundedCorners(gradientRect.x + gradientRect.w - radius, gradientRect.y + gradientRect.h - radius, radius);
SDL_Rect top = {gradientRect.x + radius, gradientRect.y, gradientRect.w - 2 * radius, radius};
SDL_Rect bottom = {gradientRect.x + radius, gradientRect.y + gradientRect.h - radius, gradientRect.w - 2 * radius, radius};
SDL_Rect left = {gradientRect.x, gradientRect.y + radius, radius, gradientRect.h - 2 * radius};
SDL_Rect right = {gradientRect.x + gradientRect.w - radius, gradientRect.y + radius, radius, gradientRect.h - 2 * radius};
SDL_Rect center = {gradientRect.x + radius, gradientRect.y + radius, gradientRect.w - 2 * radius, gradientRect.h - 2 * radius};
SDL_RenderDrawRect(renderer, &top);
SDL_RenderDrawRect(renderer, &bottom);
SDL_RenderDrawRect(renderer, &left);
SDL_RenderDrawRect(renderer, &right);
}
}
void drawRoundedRect(SDL_Renderer* renderer, SDL_Rect rect, int radius, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
auto drawRoundedCorners = [&](int x, int y, int r) {
for (int dy = -r; dy <= r; dy++) {
for (int dx = -r; dx <= r; dx++) {
if (dx * dx + dy * dy <= r * r) {
SDL_RenderDrawPoint(renderer, x + dx, y + dy);
}
}
}
};
drawRoundedCorners(rect.x + radius, rect.y + radius, radius);
drawRoundedCorners(rect.x + rect.w - radius, rect.y + radius, radius);
drawRoundedCorners(rect.x + radius, rect.y + rect.h - radius, radius);
drawRoundedCorners(rect.x + rect.w - radius, rect.y + rect.h - radius, radius);
SDL_Rect top = {rect.x + radius, rect.y, rect.w - 2 * radius, radius};
SDL_Rect bottom = {rect.x + radius, rect.y + rect.h - radius, rect.w - 2 * radius, radius};
SDL_Rect left = {rect.x, rect.y + radius, radius, rect.h - 2 * radius};
SDL_Rect right = {rect.x + rect.w - radius, rect.y + radius, radius, rect.h - 2 * radius};
SDL_Rect center = {rect.x + radius, rect.y + radius, rect.w - 2 * radius, rect.h - 2 * radius};
SDL_RenderFillRect(renderer, &top);
SDL_RenderFillRect(renderer, &bottom);
SDL_RenderFillRect(renderer, &left);
SDL_RenderFillRect(renderer, &right);
SDL_RenderFillRect(renderer, &center);
}
void Menu::draw(SDL_Renderer* renderer) {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, backgroundTxt, nullptr, &backgroundRect);
if(pages.size() > 0){
if(currentPage == -1 && pages.size() > 0){
if (pages.size() > 0) {
if (currentPage == -1 && pages.size() > 0) {
currentPage = 0;
}
for(Text& text : pages[currentPage].texts){
for (ImagePage image : pages[currentPage].images) {
SDL_RenderCopy(renderer, image.image, nullptr, &image.rect);
}
for (Text& text : pages[currentPage].texts) {
SDL_RenderCopy(renderer, text.txt, nullptr, &text.rect);
}
@@ -16,13 +100,21 @@ void Menu::draw(SDL_Renderer* renderer){
SDL_GetMouseState(&mouseX, &mouseY);
bool hover = false;
for(Button& button : pages[currentPage].buttons){
for (Button& button : pages[currentPage].buttons) {
// Activer le blending pour l'arrière-plan du bouton
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, button.bgColor.r, button.bgColor.g, button.bgColor.b, button.bgColor.a);
SDL_RenderFillRect(renderer, &button.rect);
// Dessiner la bordure du bouton
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer, button.borderColor.r, button.borderColor.g, button.borderColor.b, button.borderColor.a);
SDL_Rect borderRect = {button.rect.x - button.borderWidth, button.rect.y - button.borderWidth, button.rect.w + 2 * button.borderWidth, button.rect.h + 2 * button.borderWidth};
SDL_RenderDrawRect(renderer, &borderRect);
SDL_RenderCopy(renderer, button.txt, nullptr, &button.txtRect);
if (button.isTextInput) {
// Afficher le texte saisi
TTF_Font* font_txt = TTF_OpenFont("../fonts/arial.ttf", 24);
SDL_Surface* textSurface = TTF_RenderText_Solid(font_txt, button.inputText.c_str(), button.fontColor);
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
@@ -51,9 +143,16 @@ void Menu::draw(SDL_Renderer* renderer){
SDL_RenderPresent(renderer);
}
void Menu::handleClickedButton(){
void Menu::handleClickedButton() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
return;
}
if (event.type == SDL_MOUSEBUTTONDOWN) {
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
@@ -71,7 +170,7 @@ void Menu::handleClickedButton(){
}
}
}
}else if (event.type == SDL_TEXTINPUT) {
} else if (event.type == SDL_TEXTINPUT) {
if (activeTextInputIndex != -1) {
Button& button = pages[currentPage].buttons[activeTextInputIndex];
if (button.isTextInput) {
@@ -109,27 +208,34 @@ void Menu::changePage(std::string title){
}
}
void Menu::addButton(std::string page, int x, int y, int w, int h, std::string text, int size, std::function<void()> callback, bool isTextInput){
for(Page& p : pages){
if(p.title == page){
void Menu::addButton(std::string page, int x, int y, int w, int h, std::string text, int size, std::function<void()> callback, bool isTextInput) {
for (Page& p : pages) {
if (p.title == page) {
TTF_Font* font_txt = TTF_OpenFont("../fonts/arial.ttf", size);
if (font_txt == nullptr) {
std::cerr << "Erreur de chargement de la police: " << TTF_GetError() << std::endl;
}
Button button;
button.rect = {x, y, w, h};
int textWidth = w/2;
int textHeight = h/1.5;
button.txtRect = {x + (w/2) - (textWidth/2), y + (h/2) - (textHeight/2), textWidth, textHeight};
int textWidth = w / 2;
int textHeight = h / 1.5;
button.txtRect = {x + (w / 2) - (textWidth / 2), y + (h / 2) - (textHeight / 2), textWidth, textHeight};
button.fontColor = {255, 255, 255};
button.bgColor = {0, 0, 255, 255};
button.bgColor = {0, 0, 0, 75}; // Fond noir avec opacité de 13%
button.borderColor = {40, 120, 122, 255}; // Couleur de la bordure
button.borderWidth = 5; // Largeur de la bordure
button.borderRadius = 17; // Rayon de la bordure
button.isTextInput = isTextInput;
SDL_Surface* textSurface = TTF_RenderText_Solid(font_txt, text.c_str(), button.fontColor);
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
SDL_FreeSurface(textSurface);
button.txt = textTexture;
button.callback = callback;
button.startGradientColor = {40, 120, 122, 255};
button.endGradientColor = {55, 171, 189, 255};
button.gradientWidth = 10;
p.buttons.push_back(button);
TTF_CloseFont(font_txt);
}
@@ -167,4 +273,21 @@ void Menu::addPage(std::string title){
std::vector<Button> Menu::getButtons(){
return pages[currentPage].buttons;
}
void Menu::addImage(std::string page, int x, int y, int w, int h, std::string path) {
for (Page& p : pages) {
if (p.title == page) {
SDL_Surface* imageSurface = IMG_Load(path.c_str());
if (imageSurface == nullptr) {
std::cerr << "Erreur de chargement de l'image: " << IMG_GetError() << std::endl;
return;
}
SDL_Texture* imageTexture = SDL_CreateTextureFromSurface(renderer, imageSurface);
SDL_FreeSurface(imageSurface);
SDL_Rect imageRect = {x, y, w, h};
p.images.push_back(ImagePage(imageTexture, imageRect));
}
}
}

17
menu.h
View File

@@ -18,6 +18,12 @@ struct Button {
std::function<void()> callback;
bool isTextInput = false;
std::string inputText;
SDL_Color borderColor;
int borderWidth;
int borderRadius;
SDL_Color startGradientColor;
SDL_Color endGradientColor;
int gradientWidth;
};
struct Text {
@@ -27,13 +33,22 @@ struct Text {
SDL_Rect txtRect;
};
struct ImagePage {
SDL_Texture* image;
SDL_Rect rect;
};
struct Page {
std::string title;
std::vector<Button> buttons;
std::vector<Text> texts;
std::vector<ImagePage> images;
};
void drawRoundedRectWithGradient(SDL_Renderer* renderer, SDL_Rect rect, int radius, SDL_Color startColor, SDL_Color endColor, int gradientWidth);
void drawRoundedRect(SDL_Renderer* renderer, SDL_Rect rect, int radius, SDL_Color color);
class Menu {
private:
SDL_Texture* backgroundTxt = nullptr;
@@ -76,6 +91,8 @@ class Menu {
void addPage(std::string title);
void addImage(std::string page, int x, int y, int w, int h, std::string path);
std::vector<Button> getButtons();
};

1
resource.rc Normal file
View File

@@ -0,0 +1 @@
IDI_ICON1 ICON "../img/logo.ico"

Binary file not shown.