LCOV - code coverage report
Current view: top level - client - MenuWindow.cpp (source / functions) Hit Total Coverage
Test: code-coverage.info.cleaned Lines: 0 196 0.0 %
Date: 2023-01-28 00:08:57 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #include <client.hpp>
       2             : #include <iostream>
       3             : #include <json/json.h>
       4             : #include <fstream>
       5             : #include <string>
       6             : #include <codecvt>
       7             : #include <stdexcept>
       8             : 
       9             : #define REFRESH_TIME 30
      10             : 
      11             : #define BUTTON_TEXT_SIZE 25
      12             : 
      13             : #define BUTTON_CREAT 1
      14             : #define BUTTON_USERNAME 2
      15             : #define BUTTON_SERVER 3
      16             : #define BUTTON_PORT 4
      17             : #define BUTTON_LOAD 4
      18             : #define BUTTON_ID 5
      19             : #define BUTTON_PLAYER 5
      20             : #define BUTTON_SEED 6
      21             : #define BUTTON_CONNECT 6
      22             : #define BUTTON_START 7
      23             : 
      24             : #define QUIT_OFFSET 10
      25             : #define QUIT_SCALE 0.09375
      26             : 
      27             : #define CREATE_GAME "new"
      28             : 
      29             : #define ASCI_BEGIN 41
      30             : #define ASCI_END 123
      31             : 
      32             : #ifndef RESOURCES_PATH
      33             : #define RESOURCES_PATH "../resources"
      34             : #endif
      35             : 
      36             : const sf::Color buttonColor = sf::Color(247, 200, 195);
      37             : 
      38             : using namespace client;
      39             : 
      40             : /*!
      41             :  * @brief Constructor
      42             :  *
      43             :  * Constructor of MenuWindow class
      44             :  */
      45           0 : MenuWindow::MenuWindow()
      46             : {
      47           0 :     currentMenu = &menuButtons;
      48           0 :     currentText = &menuTexts;
      49           0 : }
      50             : 
      51             : /*!
      52             :  * @brief Display all the menu on the screen
      53             :  */
      54           0 : void MenuWindow::displayWindow()
      55             : {
      56             : 
      57           0 :     gameEnginePtr->clientWindow->clear(sf::Color::Blue);
      58             : 
      59           0 :     gameEnginePtr->clientWindow->draw(backgroundTexture->getSprite());
      60           0 :     gameEnginePtr->clientWindow->draw(quitTexture->getSprite());
      61             : 
      62           0 :     for (unsigned i = 0; i < currentMenu->size(); i++)
      63             :     {
      64           0 :         gameEnginePtr->clientWindow->draw(*currentMenu->at(i).buttonRect);
      65           0 :         gameEnginePtr->clientWindow->draw(*currentMenu->at(i).buttonText);
      66             :     }
      67             : 
      68           0 :     for (unsigned i = 0; i < currentText->size(); i++)
      69             :     {
      70           0 :         gameEnginePtr->clientWindow->draw(currentText->at(i));
      71             :     }
      72             : 
      73           0 :     gameEnginePtr->clientWindow->display();
      74           0 : }
      75             : 
      76             : /*!
      77             :  * @brief Loop that look for events to happend and call displayWindow()
      78             :  * @param clientWindow is window that comes from the engine
      79             :  * @param quitGame is the function used to quit the menu, it is load as an attribut
      80             :  */
      81           0 : void MenuWindow::startMenu()
      82             : {
      83           0 :     loadMenuTexture();
      84           0 :     if (gameEnginePtr == nullptr)
      85             :     {
      86           0 :         return;
      87             :     }
      88             : 
      89           0 :     long lastUpdateTimer = getCurrentTime(false);
      90             : 
      91           0 :     while (gameEnginePtr->clientWindow->isOpen())
      92             :     {
      93             : 
      94           0 :         if (getCurrentTime(false) - lastUpdateTimer > (REFRESH_TIME))
      95             :         {
      96           0 :             displayWindow();
      97           0 :             lastUpdateTimer = getCurrentTime(false);
      98             :         }
      99             : 
     100             :         // handle events
     101             :         sf::Event event;
     102           0 :         while (gameEnginePtr->clientWindow->pollEvent(event))
     103             :         {
     104           0 :             if (menuEventHappened(event))
     105             :             {
     106           0 :                 return;
     107             :             }
     108             :         }
     109             :     }
     110             : }
     111             : 
     112             : /*!
     113             :  * @brief Test events and do actions corresponding to the event
     114             :  * @param event pointer to the event
     115             :  */
     116           0 : bool MenuWindow::menuEventHappened(sf::Event &event)
     117             : {
     118             : 
     119           0 :     std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
     120           0 :     std::string utf8;
     121           0 :     sf::Vector2i clickPoint;
     122           0 :     bool isOnButton = false;
     123             : 
     124           0 :     switch (event.type)
     125             :     {
     126           0 :     case sf::Event::MouseButtonPressed:
     127             : 
     128           0 :         clickPoint = sf::Mouse::getPosition(*gameEnginePtr->clientWindow);
     129             : 
     130           0 :         for (unsigned i = 0; i < currentMenu->size(); i++)
     131             :         {
     132           0 :             if (clickAction(clickPoint, i, isOnButton))
     133             :             {
     134           0 :                 return true;
     135             :             }
     136             :         }
     137             : 
     138           0 :         break;
     139             : 
     140           0 :     case sf::Event::TextEntered:
     141           0 :         if (event.text.unicode > ASCI_BEGIN && event.text.unicode < ASCI_END)
     142             :         {
     143           0 :             writeChar(converter.to_bytes(event.text.unicode));
     144             :         }
     145           0 :         break;
     146             : 
     147           0 :     case sf::Event::KeyPressed:
     148             : 
     149           0 :         switch (event.key.code)
     150             :         {
     151           0 :         case sf::Keyboard::BackSpace:
     152           0 :             deleteChar();
     153           0 :             break;
     154             : 
     155           0 :         default:
     156           0 :             break;
     157             :         }
     158             : 
     159           0 :         break;
     160             : 
     161           0 :     case sf::Event::Closed:
     162           0 :         gameEnginePtr->handleQuitMenu(true);
     163           0 :         return true;
     164             : 
     165           0 :     default:
     166           0 :         break;
     167             :     }
     168             : 
     169           0 :     return false;
     170           0 : }
     171             : 
     172             : /*!
     173             :  * @brief Do the action corresponding to a click on a particular button
     174             :  * @param clickPoint cursor coordonate
     175             :  * @param index index of the testing button
     176             :  */
     177           0 : bool MenuWindow::clickAction(sf::Vector2i clickPoint, int index, bool isOnButton)
     178             : {
     179           0 :     currentMenu->at(index).setInactive();
     180             : 
     181           0 :     if (gameEnginePtr->intersectPointRect(
     182             :             clickPoint,
     183           0 :             currentMenu->at(index).buttonRect->getGlobalBounds()))
     184             :     {
     185           0 :         isOnButton = currentMenu->at(index).clickButton();
     186             :     }
     187           0 :     if (gameEnginePtr->intersectPointRect( 
     188             :         clickPoint, 
     189           0 :         quitTexture->getSprite().getGlobalBounds()))
     190             :     {
     191           0 :         gameEnginePtr->handleQuitMenu(true);
     192           0 :         return true;
     193             :     }
     194           0 :     if (isOnButton && index == BUTTON_CREAT && currentMenu == &menuButtons)
     195             :     {
     196           0 :         currentMenu = &newGameButtons;
     197           0 :         currentText = &newGameTexts;
     198             :     }
     199           0 :     else if (isOnButton && index == BUTTON_CONNECT && currentMenu == &menuButtons)
     200             :     {
     201           0 :         if(menuButtons[BUTTON_ID]().size() == 6 && menuButtons[BUTTON_USERNAME]().size() != 0)
     202             :         {
     203           0 :             return connectToGame(menuButtons[BUTTON_ID]());
     204             :         }
     205           0 :         else if(menuButtons[BUTTON_ID]().size() != 6)
     206             :         {
     207           0 :             menuButtons[BUTTON_ID].buttonText->setString("Wrong");
     208           0 :             menuButtons[BUTTON_ID].centerText(false);
     209             :         }
     210           0 :         if (menuButtons[BUTTON_USERNAME]().size() == 0)
     211             :         {
     212           0 :             menuButtons[BUTTON_USERNAME].buttonText->setString("Write Username");
     213           0 :             menuButtons[BUTTON_USERNAME].centerText(false);
     214             :         }
     215             :         
     216             :     }
     217           0 :     else if (isOnButton && index == BUTTON_LOAD && currentMenu == &newGameButtons)
     218             :     {
     219           0 :         std::cout << "Load a Game: Not implemented today\n";
     220             :     }
     221           0 :     else if (isOnButton && index == BUTTON_START && currentMenu == &newGameButtons)
     222             :     {
     223           0 :         if (menuButtons[BUTTON_USERNAME]().size() == 0)
     224             :         {
     225           0 :             menuButtons[BUTTON_USERNAME].buttonText->setString("Write Username");
     226           0 :             menuButtons[BUTTON_USERNAME].centerText(false);
     227           0 :             return false;
     228             :         }
     229           0 :         return connectToGame(CREATE_GAME);
     230             :     }
     231           0 :     return false;
     232             : }
     233             : 
     234             : /*!
     235             :  * @brief connect to the server
     236             :  * @param gameID id of the new Game
     237             :  */
     238           0 : bool MenuWindow::connectToGame(std::string gameID)
     239             : {
     240           0 :     bool isConnected = gameEnginePtr->tryConnection(
     241             :         gameID,
     242           0 :         menuButtons[BUTTON_USERNAME](),
     243           0 :         menuButtons[BUTTON_SERVER](),
     244           0 :         menuButtons[BUTTON_PORT]());
     245             : 
     246           0 :     if (isConnected)
     247             :     {
     248           0 :         gameEnginePtr->handleQuitMenu(false);
     249           0 :         currentMenu = &menuButtons;
     250           0 :         currentText = &menuTexts;
     251           0 :         return true;
     252             :     }
     253           0 :     return false;
     254             : }
     255             : 
     256             : /*!
     257             :  * @brief Add a letter to the selected button
     258             :  * @param ch letter to add
     259             :  */
     260           0 : void MenuWindow::writeChar(std::string ch)
     261             : {
     262           0 :     for (unsigned i = 0; i < currentMenu->size(); i++)
     263             :     {
     264           0 :         std::string newString = currentMenu->at(i)();
     265           0 :         if (currentMenu->at(i).redBorder 
     266           0 :             && i == BUTTON_PLAYER 
     267           0 :             && currentMenu == &newGameButtons)
     268             :         {
     269           0 :             int numberOfPlayer = 0;
     270             :             try
     271             :             {
     272           0 :                 numberOfPlayer = std::stoi(ch);
     273             :             }
     274           0 :             catch ( ... )
     275             :             {
     276           0 :                 numberOfPlayer = -1;
     277           0 :             }
     278           0 :             if (numberOfPlayer > 1 && numberOfPlayer < 5)
     279             :             {
     280           0 :                 currentMenu->at(i).buttonText->setString(ch);
     281           0 :                 currentMenu->at(i).centerText(true);
     282             :             }
     283           0 :             return;
     284             :         }
     285           0 :         if (currentMenu->at(i).redBorder &&
     286           0 :             (int)((std::string)currentMenu->at(i)()).size() < currentMenu->at(i).maxTextSize)
     287             :         {
     288           0 :             currentMenu->at(i).addChar(ch);
     289           0 :             return;
     290             :         }
     291           0 :     }
     292             : }
     293             : 
     294             : /*!
     295             :  * @brief Delete a letter to the selected button
     296             :  */
     297           0 : void MenuWindow::deleteChar()
     298             : {
     299             : 
     300           0 :     for (auto &button : *currentMenu)
     301             :     {
     302           0 :         std::string newString = button();
     303           0 :         if (button.redBorder && newString.size() != 0 && button.maxTextSize != 0)
     304             :         {
     305           0 :             button.delChar();
     306             :         }
     307           0 :     }
     308           0 : }
     309             : 
     310             : /*!
     311             :  * @brief Load all the textures that will be display on the menu
     312             :  */
     313           0 : void MenuWindow::loadMenuTexture()
     314             : {
     315             : 
     316           0 :     backgroundTexture = std::make_unique<TextureDisplayer>(RESOURCES_PATH "/menu/background.png");
     317           0 :     backgroundTexture->addSprite();
     318           0 :     float backgroundScale = 1 / (float(backgroundTexture->getWidth()) / float(gameEnginePtr->clientWindow->getSize().x));
     319           0 :     backgroundTexture->setHudSpritePosition(backgroundScale, gameEnginePtr->clientWindow->getSize().x, gameEnginePtr->clientWindow->getSize().y, 0, 0);
     320             : 
     321           0 :     quitTexture = std::make_unique<TextureDisplayer>(RESOURCES_PATH "/hud/leave.png");
     322           0 :     quitTexture->addSprite();
     323           0 :     quitTexture->moveSpritePosition(QUIT_OFFSET, QUIT_OFFSET);
     324           0 :     quitTexture->getSprite().setScale(QUIT_SCALE, QUIT_SCALE);
     325             : 
     326             : 
     327           0 :     if (!titleMenuFont.loadFromFile(RESOURCES_PATH "/font/EnchantedLand.otf"))
     328             :     {
     329           0 :         std::cerr << "Font not loaded" << std::endl;
     330             :     }
     331             : 
     332           0 :     if (!menuFont.loadFromFile(RESOURCES_PATH "/font/MorrisRomanBlack.otf"))
     333             :     {
     334           0 :         std::cerr << "Font not loaded" << std::endl;
     335             :     }
     336             : 
     337           0 :     std::ifstream file(RESOURCES_PATH "/menu/menu.json");
     338           0 :     if (!file.is_open())
     339             :     {
     340           0 :         std::cerr << "Error while opening json ressources file /menu/menu.json" << std::endl;
     341           0 :         exit(1);
     342             :     }
     343           0 :     std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
     344             : 
     345           0 :     std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(Json::CharReaderBuilder().newCharReader());
     346           0 :     Json::Value obj;
     347           0 :     std::string errors;
     348           0 :     reader->parse(str.c_str(), str.c_str() + str.size(), &obj, &errors);
     349             : 
     350           0 :     loadText(obj["welcomeTexts"]);
     351           0 :     loadButton(obj["welcomeButtons"]);
     352             : 
     353           0 :     currentMenu = &newGameButtons;
     354           0 :     currentText = &newGameTexts;
     355             : 
     356           0 :     newGameButtons.push_back(menuButtons[BUTTON_USERNAME]);
     357           0 :     newGameButtons.push_back(menuButtons[BUTTON_SERVER]);
     358           0 :     newGameButtons.push_back(menuButtons[BUTTON_PORT]);
     359             : 
     360           0 :     loadText(obj["newGameTexts"]);
     361           0 :     loadButton(obj["newGameButtons"]);
     362             : 
     363           0 :     currentMenu = &menuButtons;
     364           0 :     currentText = &menuTexts;
     365           0 : }
     366             : 
     367             : /*!
     368             :  * @brief Load all the text of a Button from a JSon
     369             :  * @param data where the data is stored
     370             :  */
     371           0 : void MenuWindow::loadText(Json::Value &data)
     372             : {
     373           0 :     for (auto &dataMenu : data)
     374             :     {
     375           0 :         if(dataMenu["size"].asInt() == 200)
     376             :         {
     377           0 :             currentText->emplace_back(dataMenu["text"].asString(), titleMenuFont, dataMenu["size"].asInt());
     378             :         }
     379             :         else
     380             :         {
     381           0 :             currentText->emplace_back(dataMenu["text"].asString(), menuFont, dataMenu["size"].asInt());
     382             :         }
     383           0 :         if (dataMenu["bold"].asBool())
     384             :         {
     385           0 :             currentText->back().setStyle(sf::Text::Bold);
     386             :         }
     387           0 :         currentText->back().setFillColor(sf::Color::Black);
     388           0 :         currentText->back().setPosition(setXAxisButtonTextPosition(dataMenu["xOffset"].asFloat()),
     389           0 :                                         setYAxisButtonTextPosition(dataMenu["yOffset"].asFloat()));
     390             :     }
     391           0 : }
     392             : 
     393             : /*!
     394             :  * @brief Load all the button from a JSon
     395             :  * @param data where the data is stored
     396             :  */
     397           0 : void MenuWindow::loadButton(Json::Value &data)
     398             : {
     399           0 :     for (auto &dataMenu : data)
     400             :     {
     401           0 :         currentMenu->emplace_back(setButtonSize(dataMenu["width"].asFloat(), dataMenu["height"].asFloat()),
     402           0 :                                   setButtonPosition(dataMenu["x"].asFloat(), dataMenu["y"].asFloat()),
     403             :                                   buttonColor);
     404             : 
     405           0 :         currentMenu->back().setText(BUTTON_TEXT_SIZE, sf::Vector2f(0, 0), dataMenu["text"].asString(), menuFont, dataMenu["sizeMax"].asInt());
     406             :     }
     407           0 : }
     408             : 
     409             : /*!
     410             :  * @brief Calcul the x offset of the text of a button
     411             :  * @param offset x offset of the text
     412             :  */
     413           0 : int MenuWindow::setXAxisButtonTextPosition(float offset)
     414             : {
     415           0 :     return (int)(gameEnginePtr->clientWindow->getSize().x 
     416           0 :         - offset 
     417           0 :         * currentText->back().getLocalBounds().height 
     418           0 :         - currentText->back().getLocalBounds().width);
     419             : }
     420             : 
     421             : /*!
     422             :  * @brief Calcul the y offset of the text of a button
     423             :  * @param offset y offset of the text
     424             :  */
     425           0 : int MenuWindow::setYAxisButtonTextPosition(float offset)
     426             : {
     427           0 :     return (int)(gameEnginePtr->clientWindow->getSize().y 
     428           0 :         - offset 
     429           0 :         * currentText->back().getLocalBounds().height);
     430             : }
     431             : 
     432             : /*!
     433             :  * @brief Calcul the size of a button
     434             :  * @param width value comming from the JSon file
     435             :  * @param height value comming from the JSon file
     436             :  */
     437           0 : sf::Vector2f MenuWindow::setButtonSize(float width, float height)
     438             : {
     439           0 :     return sf::Vector2f(width * menuTexts[0].getLocalBounds().width,
     440           0 :                         height * menuTexts[0].getLocalBounds().height);
     441             : }
     442             : 
     443             : /*!
     444             :  * @brief Calcul the position of a button
     445             :  * @param x value comming from the JSon file
     446             :  * @param y value comming from the JSon file
     447             :  */
     448           0 : sf::Vector2f MenuWindow::setButtonPosition(float x, float y)
     449             : {
     450           0 :     return sf::Vector2f(menuTexts[0].getPosition().x + x * menuTexts[0].getLocalBounds().width,
     451           0 :                         menuTexts[0].getPosition().y - y * menuTexts[0].getLocalBounds().height);
     452             : }
     453             : 
     454             : /*!
     455             :  * @brief Function that deteck where the user click and what to send to the engine
     456             :  * @param timeSecond is a boolean used to
     457             :  */
     458           0 : long MenuWindow::getCurrentTime(bool timeSecond)
     459             : {
     460           0 :     if (timeSecond)
     461             :     {
     462           0 :         return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
     463             :     }
     464             :     else
     465             :     {
     466           0 :         return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
     467             :     }
     468             : }

Generated by: LCOV version 1.14