diff --git a/.gitignore b/.gitignore index 07f96f0..4a7e5eb 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ lib *.gcno *.gcda *.o +*.txt diff --git a/assets/menu/fonts/arcade.ttf b/assets/menu/fonts/arcade.ttf new file mode 100644 index 0000000..4730e44 Binary files /dev/null and b/assets/menu/fonts/arcade.ttf differ diff --git a/assets/menu/fonts/kenvector_future_thin.ttf b/assets/menu/fonts/kenvector_future_thin.ttf new file mode 100644 index 0000000..9f4b4fa Binary files /dev/null and b/assets/menu/fonts/kenvector_future_thin.ttf differ diff --git a/assets/menu/img/background.ascii b/assets/menu/img/background.ascii new file mode 100644 index 0000000..e69de29 diff --git a/assets/menu/img/background.png b/assets/menu/img/background.png new file mode 100644 index 0000000..dabb300 Binary files /dev/null and b/assets/menu/img/background.png differ diff --git a/assets/menu/img/icon.png b/assets/menu/img/icon.png new file mode 100644 index 0000000..521e0b4 Binary files /dev/null and b/assets/menu/img/icon.png differ diff --git a/assets/menu/img/middle.ascii b/assets/menu/img/middle.ascii new file mode 100644 index 0000000..4d1261c --- /dev/null +++ b/assets/menu/img/middle.ascii @@ -0,0 +1,15 @@ +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| \ No newline at end of file diff --git a/assets/menu/img/middle.png b/assets/menu/img/middle.png new file mode 100644 index 0000000..ca356cc Binary files /dev/null and b/assets/menu/img/middle.png differ diff --git a/assets/menu/img/space-invader.ascii b/assets/menu/img/space-invader.ascii new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/assets/menu/img/space-invader.ascii @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/assets/menu/img/space-invader.png b/assets/menu/img/space-invader.png new file mode 100644 index 0000000..312e231 Binary files /dev/null and b/assets/menu/img/space-invader.png differ diff --git a/assets/menu/img/title.ascii b/assets/menu/img/title.ascii new file mode 100644 index 0000000..97354b7 --- /dev/null +++ b/assets/menu/img/title.ascii @@ -0,0 +1,4 @@ + ___ __ + / _ | ___________ ____/ /__ + / __ |/ __/ __/ _ `/ _ / -_) +/_/ |_/_/ \__/\_,_/\_,_/\__/ \ No newline at end of file diff --git a/assets/menu/img/title.png b/assets/menu/img/title.png new file mode 100644 index 0000000..df66ad9 Binary files /dev/null and b/assets/menu/img/title.png differ diff --git a/core/main.cpp b/core/main.cpp index db25d09..5a83822 100644 --- a/core/main.cpp +++ b/core/main.cpp @@ -5,21 +5,32 @@ ** main */ +#include #include "Core.hpp" #include "loader/Loader.hpp" -int main(void) +int main(int ac, char **av) { Loader loader; + if (ac != 2) { + std::cerr << "Usage: ./arcade path_to_lib" << std::endl; + return 84; + } + try { loader.loadLibraries("./lib"); - std::cout << "Games libraries:" << loader.getGamesLibraries().size() << std::endl; - std::cout << "Graphics libraries:" << loader.getGraphicsLibraries().size() << std::endl; - Core core(loader.getGamesLibraries(), loader.getGraphicsLibraries()); + auto &games = loader.getGamesLibraries(); + auto &graphics = loader.getGraphicsLibraries(); + auto libName = std::filesystem::canonical(av[1]).string(); + auto it = graphics.find(libName); + if (it == graphics.end()) + throw ArcadeError("No such graphics library: " + libName); + Core core(games, graphics, libName); core.run(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; + return 84; } return 0; } diff --git a/core/src/CMakeLists.txt b/core/src/CMakeLists.txt index e2576e8..6ab01f5 100644 --- a/core/src/CMakeLists.txt +++ b/core/src/CMakeLists.txt @@ -6,3 +6,4 @@ target_sources(arcade PRIVATE add_subdirectory(exception) add_subdirectory(loader) add_subdirectory(utils) +add_subdirectory(menu) diff --git a/core/src/Core.cpp b/core/src/Core.cpp index 6cb8600..6c08ddb 100644 --- a/core/src/Core.cpp +++ b/core/src/Core.cpp @@ -12,19 +12,59 @@ #include "Core.hpp" #include "shared/games/components/IComponent.hpp" -Core::Core(GameProviders &gameProviders, GraphicsProviders &graphicsProviders) : +Core::Core(GameProviders &gameProviders, GraphicsProviders &graphicsProviders, const std::string &graphicNameProvider) : _gameProviders(gameProviders), _graphicsProviders(graphicsProviders), - _gameProvider(gameProviders.at(0)), _graphicsProvider(graphicsProviders.at(0)) {} + _menu(gameProviders, graphicsProviders, this->_gameProvider, this->_graphicsProvider, this->_sceneStage) +{ + this->_sceneStage = MENU; + this->_gameProvider = nullptr; + this->_graphicsProvider = nullptr; + for (auto &graphicsProvider : this->_graphicsProviders) { + if (graphicsProvider.first == graphicNameProvider) + this->_graphicsProvider = graphicsProvider.second; + } +} Core::~Core() {} +std::shared_ptr Core::_getGameProvider(const unsigned char &index) +{ + if (index > this->_gameProviders.size() - 1) { + std::cerr << "Invalid game provider index" << std::endl; + return nullptr; + } + auto it = this->_gameProviders.begin(); + std::advance(it, index); + return it->second; +} + +std::shared_ptr Core::_getGraphicsProvider(const unsigned char &index) +{ + if (index > this->_graphicsProviders.size() - 1) { + std::cerr << "Invalid game provider index" << std::endl; + return nullptr; + } + auto it = this->_graphicsProviders.begin(); + std::advance(it, index); + return it->second; +} + void Core::_initGame() { + if (!this->_gameProvider) { + if (this->_gameProviders.empty()) + throw ArcadeError("No game provider available"); + this->_gameProvider = this->_getGameProvider(0); + std::cout << "No game provider selected, using default provider" << std::endl; + } this->_game = this->_gameProvider->createInstance(); + this->_sceneStage = RESUME; } void Core::_initWindow() { + if (!this->_game) + this->_initGame(); auto gameManifest = this->_game->getManifest(); IWindow::WindowInitProps windowInitProps { this->_game->getSize(), @@ -34,11 +74,23 @@ void Core::_initWindow() gameManifest.iconPath }; + this->_handleWindowClose(); + if (!this->_graphicsProvider) { + if (this->_graphicsProviders.empty()) + throw ArcadeError("No graphic provider available"); + this->_graphicsProvider = this->_getGraphicsProvider(0); + std::cout << "No graphic provider selected, using default provider" << std::endl; + } this->_window = this->_graphicsProvider->createWindow(windowInitProps); + this->_sceneStage = PLAY; } std::shared_ptr Core::_getTexture(std::string bin, std::string ascii) { + for (auto &failedTexture : this->_failedTextures) { + if (failedTexture == bin + ascii) + return nullptr; + } if (this->_textures.find(bin + ascii) == this->_textures.end()) this->_textures[bin + ascii] = this->_graphicsProvider->createTexture(bin, ascii); return this->_textures[bin + ascii]; @@ -46,6 +98,10 @@ std::shared_ptr Core::_getTexture(std::string bin, std::string ascii) std::shared_ptr Core::_getFont(std::string path) { + for (auto &failedTexture : this->_failedTextures) { + if (failedTexture == path) + return nullptr; + } if (this->_fonts.find(path) == this->_fonts.end()) this->_fonts[path] = this->_graphicsProvider->createFont(path); return this->_fonts[path]; @@ -65,6 +121,22 @@ Core::SoundProps Core::_getSound(std::string path) return this->_sounds[path]; } +void Core::_loadFailed(std::shared_ptr texture) +{ + if (!texture) + return; + auto textureProps = texture->getTextureProps(); + this->_failedTextures.push_back(textureProps.sources.bin + textureProps.sources.ascii); +} + +void Core::_loadFailed(std::shared_ptr text) +{ + if (!text) + return; + auto textProps = text->getTextProps(); + this->_failedTextures.push_back(textProps.font.path); +} + TextureProps Core::_getTextureEntity(std::shared_ptr texture) { auto textureProps = texture->getTextureProps(); @@ -144,14 +216,28 @@ void Core::_renderEntities() auto components = entity->getComponents(); for (auto &component : components) { if (component->getType() == components::TEXTURE) { - auto texture = std::dynamic_pointer_cast(component); - unsigned int index = texture->getZIndex(); - entitiesTextureProps[index].push_back(this->_getTextureEntity(texture)); + try { + auto texture = std::dynamic_pointer_cast(component); + unsigned int index = texture->getZIndex(); + auto entityTextureProps = this->_getTextureEntity(texture); + if (entityTextureProps.texture) + entitiesTextureProps[index].push_back(entityTextureProps); + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; + this->_loadFailed(std::dynamic_pointer_cast(component)); + } } if (component->getType() == components::TEXT) { - auto texture = std::dynamic_pointer_cast(component); - unsigned int index = texture->getZIndex(); - entitiesTextProps[index].push_back(this->_getTextEntity(texture)); + try { + auto text = std::dynamic_pointer_cast(component); + unsigned int index = text->getZIndex(); + auto entityTextProps = this->_getTextEntity(text); + if (entityTextProps.font) + entitiesTextProps[index].push_back(entityTextProps); + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; + this->_loadFailed(std::dynamic_pointer_cast(component)); + } } } } @@ -180,12 +266,59 @@ components::IKeyboardComponent::KeyData Core::_convertKeyPressData(events::IKeyE return keyCodeData; } -void Core::_preventWindowClose(std::vector events) +void Core::_preventWindowEvents(std::vector events) { for (auto &event : events) { auto type = event->getType(); if (type == events::WINDOW_CLOSE) this->_handleWindowClose(); + if (type == events::KEY_PRESS) { + auto keyEvent = std::dynamic_pointer_cast(event); + auto keyCode = keyEvent->getKeyCode(); + auto keyType = keyEvent->getKeyType(); + if (keyType == events::IKeyEvent::CHAR && keyCode.character == 27) + this->_sceneStage = MENU; + } + } +} + +void Core::_changeGraphicProvider(const unsigned char &index) +{ + if (index > this->_graphicsProviders.size() - 1) { + std::cout << "Invalid graphic provider index" << std::endl; + return; + } + auto newProvider = this->_getGraphicsProvider(index); + if (newProvider == this->_graphicsProvider) + return; + this->_graphicsProvider = newProvider; + this->_initWindow(); +} + +void Core::_changeGameProvider(const unsigned char &index) +{ + if (index > this->_gameProviders.size() - 1) { + std::cout << "Invalid game provider index" << std::endl; + return; + } + auto newProvider = this->_getGameProvider(index); + this->_gameProvider = newProvider; + this->_initGame(); + this->_initWindow(); +} + +void Core::_handleFunctionKeys(std::shared_ptr &keyEvent) +{ + auto keyCode = keyEvent->getKeyCode(); + auto keyType = keyEvent->getKeyType(); + + if (keyType == events::IKeyEvent::FUNC) { + if (keyCode.func <= 6) + this->_changeGameProvider(keyCode.func - 1); + else if (keyCode.func >= 7 && keyCode.func <= 12) + this->_changeGraphicProvider(keyCode.func - 7); + else + std::cerr << "Invalid function key" << std::endl; } } @@ -195,6 +328,7 @@ void Core::_handleKeyPress(std::shared_ptr &keyEvent, std::sh auto keyType = keyEvent->getKeyType(); auto keyCodeData = this->_convertKeyPressData(keyType, keyCode); + this->_handleFunctionKeys(keyEvent); keyboard->onKeyPress(this->_game, keyCodeData); } @@ -244,7 +378,10 @@ void Core::_handleMouseMove(std::shared_ptr &event, std::sh void Core::_handleWindowClose() { - this->_window->close(); + if (this->_window && this->_window->isOpen()) { + this->_window->close(); + this->_menu.updateScore(this->_game); + } } void Core::_handleWindowResize() @@ -374,12 +511,18 @@ void Core::_handleEvents() { auto gameEvents = this->_window->getEvents(); - this->_preventWindowClose(gameEvents); - for (auto &entity : this->_gameEntities) { - auto components = entity->getComponents(); - for (auto &component : components) { - this->_handleComponentEvents(gameEvents, component); + try { + this->_preventWindowEvents(gameEvents); + if (this->_sceneStage == MENU) + return; + for (auto &entity : this->_gameEntities) { + auto components = entity->getComponents(); + for (auto &component : components) { + this->_handleComponentEvents(gameEvents, component); + } } + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; } } @@ -387,6 +530,9 @@ void Core::run() { auto previousTime = std::chrono::high_resolution_clock::now(); + this->_menu.run(); + if (this->_sceneStage == EXIT || this->_sceneStage == RESUME) + return; this->_initGame(); this->_initWindow(); while (this->_window->isOpen()) { @@ -394,6 +540,17 @@ void Core::run() auto deltaTime = std::chrono::duration_cast(currentTime - previousTime); previousTime = currentTime; + if (this->_sceneStage == MENU) { + this->_handleWindowClose(); + this->_menu.run(); + previousTime = std::chrono::high_resolution_clock::now(); + } + if (this->_sceneStage == EXIT) + return; + if (this->_sceneStage == NEWGAME) + this->_initGame(); + if (this->_sceneStage == RESUME) + this->_initWindow(); this->_game->compute(deltaTime); this->_gameEntities = this->_game->getEntities(); this->_handleEvents(); diff --git a/core/src/Core.hpp b/core/src/Core.hpp index bcab8cc..2b467ec 100644 --- a/core/src/Core.hpp +++ b/core/src/Core.hpp @@ -8,6 +8,8 @@ #pragma once #include +#include "menu/Menu.hpp" +#include "types/Stages.hpp" #include "types/Providers.hpp" #include "shared/graphics/ISound.hpp" #include "shared/graphics/events/IKeyEvent.hpp" @@ -25,7 +27,7 @@ using namespace shared::games; class Core { public: - Core(GameProviders &gameProviders, GraphicsProviders &graphicsProviders); + Core(GameProviders &gameProviders, GraphicsProviders &graphicsProviders, const std::string &graphicNameProvider); ~Core(); /** @@ -44,14 +46,17 @@ class Core { std::shared_ptr _game; std::shared_ptr _window; - std::shared_ptr &_gameProvider; - std::shared_ptr &_graphicsProvider; + std::shared_ptr _gameProvider; + std::shared_ptr _graphicsProvider; std::map> _fonts; std::map> _textures; + std::vector _failedTextures; std::map _sounds; GameProviders &_gameProviders; GraphicsProviders &_graphicsProviders; entity::EntitiesMap _gameEntities; + arcade::core::SceneStage _sceneStage; + Menu _menu; /** * @brief Initialize the window @@ -71,6 +76,20 @@ class Core { */ void _renderEntities(); + /** + * @brief Load the failed texture + * + * @param texture The texture component + */ + void _loadFailed(std::shared_ptr texture); + + /** + * @brief Load the failed text + * + * @param text The text component + */ + void _loadFailed(std::shared_ptr text); + /** * @brief Get a texture * @@ -239,7 +258,7 @@ class Core { * * @param events The events */ - void _preventWindowClose(std::vector events); + void _preventWindowEvents(std::vector events); /** * @brief Handle the key press event @@ -255,6 +274,27 @@ class Core { */ void _handleKeyRelease(std::shared_ptr &event); + /** + * @brief Handle the function keys + * + * @param event The key event + */ + void _handleFunctionKeys(std::shared_ptr &event); + + /** + * @brief Change the graphic provider + * + * @param index The index of the graphic provider + */ + void _changeGraphicProvider(const unsigned char &index); + + /** + * @brief Change the game provider + * + * @param index The index of the game provider + */ + void _changeGameProvider(const unsigned char &index); + /** * @brief Convert the key press data * @@ -270,4 +310,20 @@ class Core { * @param event The mouse button event */ void _handleSoundComponent(std::shared_ptr &component); + + /** + * @brief Get the game provider + * + * @param index The index of the game provider + * @return The game provider + */ + std::shared_ptr _getGameProvider(const unsigned char &index); + + /** + * @brief Get the graphic provider + * + * @param index The index of the graphic provider + * @return The graphic provider + */ + std::shared_ptr _getGraphicsProvider(const unsigned char &index); }; diff --git a/core/src/loader/Loader.cpp b/core/src/loader/Loader.cpp index 09c0e4a..ba4e62c 100644 --- a/core/src/loader/Loader.cpp +++ b/core/src/loader/Loader.cpp @@ -27,7 +27,8 @@ void Loader::_loadGameLibrary(const std::string &filepath, std::shared_ptrloadSymbol(SHARED_STRINGIFY(SHARED_GAME_PROVIDER_GETTER_NAME)); - this->_gamesLibraries.push_back(std::unique_ptr(game())); + auto realFilePath = std::filesystem::canonical(filepath).string(); + this->_gamesLibraries.insert({realFilePath, std::shared_ptr(game())}); this->_libraries.push_back(dlLoader); } @@ -35,7 +36,8 @@ void Loader::_loadGraphicsLibrary(const std::string &filepath, std::shared_ptrloadSymbol(SHARED_STRINGIFY(SHARED_GRAPHICS_PROVIDER_GETTER_NAME)); - this->_graphicsLibraries.push_back(std::unique_ptr(graphics())); + auto realFilePath = std::filesystem::canonical(filepath).string(); + this->_graphicsLibraries.insert({realFilePath, std::shared_ptr(graphics())}); this->_libraries.push_back(dlLoader); } diff --git a/core/src/menu/CMakeLists.txt b/core/src/menu/CMakeLists.txt new file mode 100644 index 0000000..9d298bb --- /dev/null +++ b/core/src/menu/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(arcade PRIVATE + Menu.cpp + Menu.hpp +) + +add_subdirectory(checkBox) +add_subdirectory(entity) diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp new file mode 100644 index 0000000..4b852a7 --- /dev/null +++ b/core/src/menu/Menu.cpp @@ -0,0 +1,671 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Menu +*/ + +#include +#include +#include +#include "Menu.hpp" + +Menu::Menu(GameProviders &gameProviders, GraphicsProviders &graphicsProviders, + std::shared_ptr &gameProvider, std::shared_ptr &graphicsProvider, arcade::core::SceneStage &sceneStage) : + _gameProviders(gameProviders), _graphicsProviders(graphicsProviders), + _gameProvider(gameProvider), _graphicsProvider(graphicsProvider), _sceneStage(sceneStage) +{ + this->_score.player = ""; + this->_score.score = 0; + this->_readScores(); + this->_textType = GAME; +} + +Menu::~Menu() +{ + this->_writeScore(); +} + +std::shared_ptr &Menu::_getGameProvider(const unsigned char &index) +{ + if (index > this->_gameProviders.size() - 1) + throw ArcadeError("Invalid game provider index"); + auto it = this->_gameProviders.begin(); + std::advance(it, index); + return it->second; +} + +std::shared_ptr &Menu::_getGraphicsProvider(const unsigned char &index) +{ + if (index > this->_graphicsProviders.size() - 1) + throw ArcadeError("Invalid graphics provider index"); + auto it = this->_graphicsProviders.begin(); + std::advance(it, index); + return it->second; +} + +void Menu::_sortScores() +{ + std::sort(this->_scores.begin(), this->_scores.end(), [](const Score& a, const Score& b) { + return a.score > b.score; + }); +} + +std::string Menu::_truncString(const std::string &str, int size) +{ + auto strPadding = size - static_cast(str.size()); + std::string newString = str.substr(0, size - 3); + + if (strPadding < 0) + newString += "..."; + else + newString = str; + return newString; +} + +void Menu::_initHiddenAuthors(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + auto authorNames = std::make_shared(font, 35, "Authors:", TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{8, 1}, Vector2f{26, 8}); + this->_hiddenAuthors[checkBox].push_back(authorNames); + + auto authors = gameManifest.authors; + float index = 10.0; + for (auto author : authors) { + auto authorNameText = std::make_shared(font, 30, this->_truncString(author.name, 22) , TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index}); + auto authorMailText = std::make_shared(font, 30, this->_truncString(author.email, 22), TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index + 1}); + auto authorSiteText = std::make_shared(font, 30, this->_truncString(author.website, 22), TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index + 2}); + this->_hiddenAuthors[checkBox].push_back(authorNameText); + this->_hiddenAuthors[checkBox].push_back(authorMailText); + this->_hiddenAuthors[checkBox].push_back(authorSiteText); + index += 4; + } +} + +void Menu::_initHiddenScoreHeader(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + auto truncatName = this->_truncString(gameManifest.name, 23); + auto nameText = std::make_shared(font, 35, truncatName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 8}); + this->_hiddenTexts[checkBox].push_back(nameText); + + auto truncatDesc = this->_truncString(gameManifest.description, 23); + auto descriptionText = std::make_shared(font, 30, truncatDesc, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 10}); + this->_hiddenTexts[checkBox].push_back(descriptionText); +} + +void Menu::_initHiddenScoreBoard(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + auto scoreHI = std::make_shared(font, 30, "HI-SCORE", TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{8, 1}, Vector2f{26, 12}); + this->_hiddenTexts[checkBox].push_back(scoreHI); + + this->_sortScores(); + auto score = 0; + for (auto &scoreElem : this->_scores) { + if (scoreElem.game == gameManifest.name && scoreElem.score > score) + score = scoreElem.score; + } + auto scoreString = std::to_string(score).substr(0, 5); + while (scoreString.length() < 5) + scoreString = "0" + scoreString; + auto scoreText = std::make_shared(font, 30, scoreString, TextAlign::RIGHT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{14, 1}, Vector2f{34, 12}); + this->_hiddenTexts[checkBox].push_back(scoreText); + + float index = 14; + int count = 0; + for (auto &scoreElem : this->_scores) { + if (scoreElem.game == gameManifest.name) { + if (count > 7) + break; + auto playerName = scoreElem.player.empty() ? "Guest" : scoreElem.player; + auto truncatPlayer = this->_truncString(playerName, 17); + auto playerText = std::make_shared(font, 25, truncatPlayer, TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{17, 1}, Vector2f{26, index}); + auto scoreString = std::to_string(scoreElem.score).substr(0, 5); + while (scoreString.length() < 5) + scoreString = "0" + scoreString; + auto scoreText = std::make_shared(font, 25, scoreString, TextAlign::RIGHT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{5, 1}, Vector2f{43, index}); + this->_hiddenTexts[checkBox].push_back(playerText); + this->_hiddenTexts[checkBox].push_back(scoreText); + index += 1; + count += 1; + } + } +} + +void Menu::_initHiddenScore(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + this->_initHiddenScoreHeader(gameManifest, checkBox, font); + this->_initHiddenScoreBoard(gameManifest, checkBox, font); +} + +void Menu::_initNoGameFound() +{ + auto font = this->_font; + + if (this->_gamesCheckBoxes.empty()) { + auto noGames = std::make_shared(font, 35, "No games found", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{2, 11}); + this->_texts.push_back(noGames); + } +} + +void Menu::_initCheckBoxesGames() +{ + auto texture = this->_graphicsProvider->createTexture("assets/menu/img/space-invader.png", "assets/menu/img/space-invader.ascii"); + auto font = this->_font; + float index = 9.0; + int count = 0; + + for (auto gameProvider : this->_gameProviders) { + if (count > 5) + break; + std::string truncatedName = gameProvider.second->getManifest().name.substr(0, 20); + auto pos = 11 - (static_cast(truncatedName.size()) / 2); + auto textCheckBox = std::make_shared(font, 35, truncatedName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{static_cast(truncatedName.size()), 1}, Vector2f{pos + 2, index}); + auto textureCheckBox = std::make_shared(texture, Vector2f{360, 360}, Vector2u{0, 0}, Vector2u{1, 1}, Vector2f{pos, index}); + auto checkBox = std::make_shared(textureCheckBox, textCheckBox); + this->_texts.push_back(textCheckBox); + this->_textures.push_back(textureCheckBox); + this->_gamesCheckBoxes.push_back(checkBox); + this->_initHiddenScore(gameProvider.second->getManifest(), checkBox, font); + this->_initHiddenAuthors(gameProvider.second->getManifest(), checkBox, font); + index += 1; + count += 1; + } + this->_initNoGameFound(); +} + +void Menu::_initHiddenGraphicsHeader(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + auto truncatName = this->_truncString(graphicsManifest.name, 23); + auto nameText = std::make_shared(font, 35, truncatName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 8}); + this->_hiddenTexts[checkBox].push_back(nameText); + + auto truncatDesc = this->_truncString(graphicsManifest.description, 23); + auto descriptionText = std::make_shared(font, 30, truncatDesc, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 10}); + this->_hiddenTexts[checkBox].push_back(descriptionText); +} + +void Menu::_initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + auto authors = graphicsManifest.authors; + float index = 12.0; + for (auto author : authors) { + auto authorNameText = std::make_shared(font, 25, this->_truncString(author.name, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index}); + auto authorMailText = std::make_shared(font, 25, this->_truncString(author.email, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index + 1}); + auto authorSiteText = std::make_shared(font, 25, this->_truncString(author.website, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index + 2}); + this->_hiddenTexts[checkBox].push_back(authorNameText); + this->_hiddenTexts[checkBox].push_back(authorMailText); + this->_hiddenTexts[checkBox].push_back(authorSiteText); + index += 4; + } +} + +void Menu::_initHiddenGraphics(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font) +{ + this->_initHiddenGraphicsHeader(graphicsManifest, checkBox, font); + this->_initHiddenGraphicsBoard(graphicsManifest, checkBox, font); +} + +void Menu::_initCheckBoxesGraphics() +{ + auto texture = this->_graphicsProvider->createTexture("assets/menu/img/space-invader.png", "assets/menu/img/space-invader.ascii"); + auto font = this->_font; + float index = 17.0; + int count = 0; + + for (auto graphicsProvider : this->_graphicsProviders) { + if (count > 5) + break; + std::string truncatedName = graphicsProvider.second->getManifest().name.substr(0, 20); + auto pos = 11 - (static_cast(truncatedName.size()) / 2); + auto textCheckBox = std::make_shared(font, 35, truncatedName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{static_cast(truncatedName.size()), 1}, Vector2f{pos + 2, index}); + auto textureCheckBox = std::make_shared(texture, Vector2f{360, 360}, Vector2u{0, 0}, Vector2u{1, 1}, Vector2f{pos, index}); + auto checkBox = std::make_shared(textureCheckBox, textCheckBox); + this->_texts.push_back(textCheckBox); + this->_textures.push_back(textureCheckBox); + this->_graphicsCheckBoxes.push_back(checkBox); + this->_initHiddenGraphics(graphicsProvider.second->getManifest(), checkBox, font); + index += 1; + count += 1; + } +} + +void Menu::_initTextures() +{ + auto backgroundTexture = this->_graphicsProvider->createTexture("assets/menu/img/background.png", "assets/menu/img/background.ascii"); + this->_textures.push_back(std::make_shared(backgroundTexture, Vector2f{12, 12}, Vector2u{0, 0}, Vector2u{50, 25}, Vector2f{0, 0})); + auto titleTexture = this->_graphicsProvider->createTexture("assets/menu/img/title.png", "assets/menu/img/title.ascii"); + this->_textures.push_back(std::make_shared(titleTexture, Vector2f{17, 17}, Vector2u{0, 0}, Vector2u{31, 5}, Vector2f{10, 1})); + auto middleTexture = this->_graphicsProvider->createTexture("assets/menu/img/middle.png", "assets/menu/img/middle.ascii"); + this->_textures.push_back(std::make_shared(middleTexture, Vector2f{12, 12}, Vector2u{0, 0}, Vector2u{1, 15}, Vector2f{24, 7})); +} + +void Menu::_initTexts() +{ + auto font = this->_graphicsProvider->createFont("assets/menu/fonts/arcade.ttf"); + + this->_font = font; + auto games = std::make_shared(font, 40, "Games", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{24, 1}, Vector2f{1, 7}); + this->_texts.push_back(games); + auto graphics = std::make_shared(font, 40, "Graphics", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{24, 1}, Vector2f{1, 15}); + this->_texts.push_back(graphics); +} + +void Menu::_clearLists() +{ + this->_hiddenAuthors.clear(); + this->_hiddenTexts.clear(); + this->_texts.clear(); + this->_textures.clear(); + this->_gamesCheckBoxes.clear(); + this->_graphicsCheckBoxes.clear(); +} + +void Menu::_preventGraphicsProvider() +{ + if (this->_graphicsProvider) + return; + if (this->_graphicsProviders.empty()) + throw ArcadeError("No graphics provider found"); + this->_graphicsProvider = this->_getGraphicsProvider(0); + std::cout << "No graphics provider found, using default provider" << std::endl; +} + +void Menu::_initWindow() +{ + IWindow::WindowInitProps windowInitProps { + .size = {50, 25}, + .mode = IWindow::WindowMode::WINDOWED, + .fps = 60, + .title = "Menu", + .icon = "assets/menu/img/icon.png" + }; + + this->_clearLists(); + this->_preventGraphicsProvider(); + this->_initTexts(); + this->_initTextures(); + this->_initCheckBoxesGames(); + this->_initCheckBoxesGraphics(); + this->_window = this->_graphicsProvider->createWindow(windowInitProps); +} + +void Menu::_handleSelectUpperCheckBox() +{ + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered()) { + checkBox->unhover(); + auto index = std::distance(this->_gamesCheckBoxes.begin(), std::find(this->_gamesCheckBoxes.begin(), this->_gamesCheckBoxes.end(), checkBox)); + if (index != 0) + this->_gamesCheckBoxes.at(index - 1)->hover(); + else + checkBox->hover(); + break; + } + } + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered()) { + checkBox->unhover(); + auto index = std::distance(this->_graphicsCheckBoxes.begin(), std::find(this->_graphicsCheckBoxes.begin(), this->_graphicsCheckBoxes.end(), checkBox)); + if (index == 0) { + if (!this->_gamesCheckBoxes.empty()) { + this->_gamesCheckBoxes.at(this->_gamesCheckBoxes.size() - 1)->hover(); + this->_checkBoxType = GAME_CHECKBOX; + } else { + checkBox->hover(); + } + } else { + this->_graphicsCheckBoxes.at(index - 1)->hover(); + } + break; + } + } +} + +void Menu::_handleSelectLowerCheckBox() +{ + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered()) { + checkBox->unhover(); + auto index = std::distance(this->_graphicsCheckBoxes.begin(), std::find(this->_graphicsCheckBoxes.begin(), this->_graphicsCheckBoxes.end(), checkBox)); + if (index != this->_graphicsCheckBoxes.size() - 1) + this->_graphicsCheckBoxes.at(index + 1)->hover(); + else + checkBox->hover(); + break; + } + } + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered()) { + checkBox->unhover(); + auto index = std::distance(this->_gamesCheckBoxes.begin(), std::find(this->_gamesCheckBoxes.begin(), this->_gamesCheckBoxes.end(), checkBox)); + if (index == this->_gamesCheckBoxes.size() - 1) { + this->_graphicsCheckBoxes.at(0)->hover(); + this->_checkBoxType = GRAPHICS_CHECKBOX; + } else { + this->_gamesCheckBoxes.at(index + 1)->hover(); + } + break; + } + } +} + +void Menu::_handleKeyboardEvents(std::shared_ptr key) +{ + if (!key) + return; + auto type = key->getKeyType(); + auto code = key->getKeyCode(); + + if (type == events::IKeyEvent::KeyType::ARROW) { + if (code.arrow == events::IKeyEvent::ArrowCode::DOWN) + this->_handleSelectLowerCheckBox(); + if (code.arrow == events::IKeyEvent::ArrowCode::UP) + this->_handleSelectUpperCheckBox(); + if (code.arrow == events::IKeyEvent::ArrowCode::RIGHT) + this->_textType = AUTHOR; + if (code.arrow == events::IKeyEvent::ArrowCode::LEFT) + this->_textType = GAME; + } + if (type == events::IKeyEvent::KeyType::CHAR) { + if (code.character == '\n') + this->_selectGame(); + else if (code.character == 27) + this->_exitAndPlayOldGame(); + else if (code.character == 8) + this->_score.player = this->_score.player.substr(0, this->_score.player.size() - 1); + else if (this->_score.player.size() < 15 && code.character >= 33 && code.character <= 126) + this->_score.player += code.character; + } +} + +void Menu::_selectGame() +{ + if (this->_checkBoxType == GAME_CHECKBOX) { + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered() && checkBox->isChecked()) + this->_exitWithNewGame(); + if (checkBox->isHovered()) + checkBox->check(); + else + checkBox->uncheck(); + } + } else { + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered() && checkBox->isChecked()) + this->_changeGraphics(checkBox); + if (checkBox->isHovered()) + checkBox->check(); + else + checkBox->uncheck(); + } + } +} + +void Menu::_changeGraphics(std::shared_ptr checkBox) +{ + auto index = std::distance(this->_graphicsCheckBoxes.begin(), std::find(this->_graphicsCheckBoxes.begin(), this->_graphicsCheckBoxes.end(), checkBox)); + auto graphicsProvider = this->_getGraphicsProvider(index); + if (graphicsProvider != this->_graphicsProvider) { + this->_graphicsProvider = graphicsProvider; + this->_window->close(); + this->_initWindow(); + } +} + +void Menu::_exitAndPlayOldGame() +{ + this->_sceneStage = RESUME; + this->_window->close(); +} + +void Menu::_exitWithNewGame() +{ + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isChecked()) { + this->_gameProvider = this->_getGameProvider(std::distance(this->_gamesCheckBoxes.begin(), std::find(this->_gamesCheckBoxes.begin(), this->_gamesCheckBoxes.end(), checkBox))); + break; + } + } + this->_sceneStage = NEWGAME; + this->_window->close(); +} + +void Menu::_handleMouseMouveEvents(std::shared_ptr mouse) +{ + if (!mouse) + return; + auto position = mouse->getPosition(); + std::shared_ptr lastHoveredCheckBox = nullptr; + bool hoveredAtLeastOne = false; + + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered()) + lastHoveredCheckBox = checkBox; + } + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered()) + lastHoveredCheckBox = checkBox; + } + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered()) + checkBox->unhover(); + if (checkBox->isHovered(position)) { + checkBox->hover(); + this->_checkBoxType = GAME_CHECKBOX; + hoveredAtLeastOne = true; + } + } + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered()) + checkBox->unhover(); + if (checkBox->isHovered(position)) { + checkBox->hover(); + this->_checkBoxType = GRAPHICS_CHECKBOX; + hoveredAtLeastOne = true; + } + } + if (!hoveredAtLeastOne && lastHoveredCheckBox) + lastHoveredCheckBox->hover(); +} + +void Menu::_handleMouseButtonEvents(std::shared_ptr mouse) +{ + if (!mouse) + return; + auto position = mouse->getPosition(); + auto button = mouse->getButton(); + auto move = std::dynamic_pointer_cast(mouse); + + if (button != events::IMouseButtonEvent::MouseButton::LEFT) + return; + this->_handleMouseMouveEvents(move); + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered(position)) { + this->_selectGame(); + } + } +} + +void Menu::_handleEvents() +{ + auto events = this->_window->getEvents(); + + for (auto event : events) { + auto type = event->getType(); + if (type == events::WINDOW_CLOSE) { + this->_window->close(); + this->_sceneStage = EXIT; + } + if (type == events::KEY_PRESS) { + auto key = std::dynamic_pointer_cast(event); + this->_handleKeyboardEvents(key); + } + if (type == events::MOUSE_MOVE) { + auto mouse = std::dynamic_pointer_cast(event); + this->_handleMouseMouveEvents(mouse); + } + if (type == events::MOUSE_BTN_PRESS) { + auto mouse = std::dynamic_pointer_cast(event); + this->_handleMouseButtonEvents(mouse); + } + } +} + +void Menu::_renderField() +{ + if (this->_score.player.empty()) { + auto placeholder = std::make_shared(this->_font, 30, "Guest", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{16, 1}, Vector2f{17, 23}); + this->_nameField = placeholder; + } else { + auto truncatName = this->_truncString(this->_score.player, 17); + auto name = std::make_shared(this->_font, 35, truncatName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{16, 1}, Vector2f{17, 23}); + this->_nameField = name; + } + if (this->_nameField) + this->_nameField->draw(this->_window); +} + +void Menu::_render() +{ + this->_window->clear(); + for (auto texture : this->_textures) { + texture->draw(this->_window); + } + for (auto text : this->_texts) { + text->draw(this->_window); + } + for (auto checkBox : this->_gamesCheckBoxes) { + if (checkBox->isHovered()) { + if (this->_textType == GAME) { + for (auto text : this->_hiddenTexts[checkBox]) { + text->draw(this->_window); + } + } else { + for (auto text : this->_hiddenAuthors[checkBox]) { + text->draw(this->_window); + } + } + } + } + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered()) { + for (auto text : this->_hiddenTexts[checkBox]) { + text->draw(this->_window); + } + } + } + this->_renderField(); + this->_window->display(); +} + +void Menu::_previousSelectedGame() +{ + this->_checkBoxType = GAME_CHECKBOX; + for (auto gameProvider : this->_gameProviders) { + if (this->_gameProvider == gameProvider.second) { + auto index = std::distance(this->_gameProviders.begin(), std::find(this->_gameProviders.begin(), this->_gameProviders.end(), gameProvider)); + auto checkBox = this->_gamesCheckBoxes.at(index); + checkBox->check(); + checkBox->hover(); + return; + } + } + if (!this->_gamesCheckBoxes.empty()) { + this->_gamesCheckBoxes.at(0)->check(); + this->_gamesCheckBoxes.at(0)->hover(); + } else { + std::cout << "Can't select a previous game, no games found" << std::endl; + } +} + +void Menu::_previousSelectedGraphics() +{ + for (auto graphicsProvider : this->_graphicsProviders) { + if (this->_graphicsProvider == graphicsProvider.second) { + auto index = std::distance(this->_graphicsProviders.begin(), std::find(this->_graphicsProviders.begin(), this->_graphicsProviders.end(), graphicsProvider)); + auto checkBox = this->_graphicsCheckBoxes.at(index); + checkBox->check(); + if (this->_gamesCheckBoxes.empty()) { + checkBox->hover(); + this->_checkBoxType = GRAPHICS_CHECKBOX; + } + return; + } + } + if (!this->_graphicsCheckBoxes.empty()) { + this->_graphicsCheckBoxes.at(0)->check(); + if (this->_gamesCheckBoxes.empty()) { + _graphicsCheckBoxes.at(0)->hover(); + this->_checkBoxType = GRAPHICS_CHECKBOX; + } + } else { + std::cout << "Can't select a previous graphics, no graphics found" << std::endl; + } +} + +void Menu::run() +{ + this->_sceneStage = MENU; + this->_initWindow(); + this->_previousSelectedGame(); + this->_previousSelectedGraphics(); + while (this->_window->isOpen()) { + this->_handleEvents(); + this->_render(); + } +} + +void Menu::_readScores() +{ + std::ifstream scoreFile("./scores.txt"); + + if (!scoreFile.is_open()) { + std::cout << "Can't open scores file" << std::endl; + return; + } + + std::string line; + std::getline(scoreFile, line); + + while (std::getline(scoreFile, line)) { + std::stringstream ss(line); + Score score; + ss >> score.game >> score.player >> score.score; + this->_scores.push_back(score); + } + scoreFile.close(); +} + +void Menu::_writeScore() +{ + std::ofstream scoreFile("./scores.txt"); + + if (!scoreFile.is_open()) { + std::cout << "Can't open scores file" << std::endl; + return; + } + + scoreFile << "Game\tPlayer\tScore" << std::endl; + auto player = this->_score.player.empty() ? "Guest" : this->_score.player; + for (auto score : this->_scores) { + scoreFile << score.game << "\t" << player << "\t" << score.score << std::endl; + } + scoreFile.close(); +} + +void Menu::updateScore(std::shared_ptr game) +{ + this->_score.game = game->getManifest().name; + this->_score.score = game->getScore(); + + std::cout << "Player Score: " << this->_score.score << std::endl; + for (auto &score : this->_scores) { + auto playerName = this->_score.player.empty() ? "Guest" : this->_score.player; + auto scoreName = score.player.empty() ? "Guest" : score.player; + if (score.game == this->_score.game && scoreName == playerName) { + if (score.score < this->_score.score) + score.score = this->_score.score; + return; + } + } + this->_scores.push_back(this->_score); +} diff --git a/core/src/menu/Menu.hpp b/core/src/menu/Menu.hpp new file mode 100644 index 0000000..8ff12d8 --- /dev/null +++ b/core/src/menu/Menu.hpp @@ -0,0 +1,321 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Menu +*/ + +#pragma once + +#include +#include "types/Stages.hpp" +#include "types/Providers.hpp" +#include "checkBox/CheckBox.hpp" +#include "exception/ArcadeError.hpp" +#include "shared/graphics/events/IMouseButtonEvent.hpp" + +using namespace arcade::core; +using namespace shared::games; +using namespace shared::graphics; + +class Menu { + public: + + /** + * @brief Construct a new Menu object + * + * @param gameProviders GameProviders + * @param graphicsProviders GraphicsProviders + * @param gameProvider gameProvider + * @param graphicsProvider graphicsProvider + */ + Menu(GameProviders &gameProviders, GraphicsProviders &graphicsProviders, std::shared_ptr &gameProvider, std::shared_ptr &graphicsProvider, SceneStage &sceneStage); + ~Menu(); + + /** + * @brief Run the menu + * + */ + void run(); + + /** + * @brief Update the score + * + * @param game Game + */ + void updateScore(std::shared_ptr game); + + private: + + typedef struct { + std::string game; + std::string player; + int score; + } Score; + + typedef enum { + GAME, + AUTHOR, + } TextType; + + typedef enum { + GAME_CHECKBOX, + GRAPHICS_CHECKBOX + } CheckBoxType; + + TextType _textType; + CheckBoxType _checkBoxType; + Score _score; + std::vector _scores; + SceneStage &_sceneStage; + std::shared_ptr _window; + GameProviders &_gameProviders; + GraphicsProviders &_graphicsProviders; + std::shared_ptr &_gameProvider; + std::shared_ptr &_graphicsProvider; + std::vector> _gamesCheckBoxes; + std::vector> _graphicsCheckBoxes; + std::vector> _texts; + std::vector> _textures; + std::map, std::vector>> _hiddenTexts; + std::map, std::vector>> _hiddenAuthors; + std::shared_ptr _font; + std::shared_ptr _nameField; + + /** + * @brief Initialize the window + * + */ + void _initWindow(); + + /** + * @brief Clear all lists + * + */ + void _clearLists(); + + /** + * @brief Prevent the graphics provider + * + */ + void _preventGraphicsProvider(); + + /** + * @brief Render the menu + * + */ + void _render(); + + /** + * @brief Render the field name + * + */ + void _renderField(); + + /** + * @brief Handle events + * + */ + void _handleEvents(); + + /** + * @brief Handle mouse mouve events + * + * @param mouse Mouse event + */ + void _handleMouseMouveEvents(std::shared_ptr mouse); + + /** + * @brief Handle mouse button events + * + * @param mouse Mouse event + */ + void _handleMouseButtonEvents(std::shared_ptr mouse); + + /** + * @brief Handle checkbox events + * + * @param key Key event + */ + void _handleKeyboardEvents(std::shared_ptr key); + + /** + * @brief Handle select upper checkbox + * + */ + void _handleSelectUpperCheckBox(); + + /** + * @brief Handle select lower checkbox + * + */ + void _handleSelectLowerCheckBox(); + + /** + * @brief Select the hovered game + * + */ + void _selectGame(); + + /** + * @brief Exit the menu + * + */ + void _exitWithNewGame(); + + /** + * @brief Exit and play old game + * + */ + void _exitAndPlayOldGame(); + + /** + * @brief Change the text type + * + */ + void _changeGraphics(std::shared_ptr checkBox); + + /** + * @brief Initialize checkboxes for games + * + */ + void _initCheckBoxesGames(); + + /** + * @brief Initialize checkboxes for graphics + * + */ + void _initCheckBoxesGraphics(); + + /** + * @brief Initialize textures + * + */ + void _initTextures(); + + /** + * @brief Initialize hidden textures + * + * @param gameManifest GameManifest + * @param checkBox CheckBox + */ + void _initHiddenAuthors(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize hidden texts + * + * @param gameManifest GameManifest + * @param checkBox CheckBox + * @param font IFont + */ + void _initHiddenScore(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize hidden score header + * + * @param gameManifest GameManifest + * @param checkBox CheckBox + * @param font IFont + */ + void _initHiddenScoreHeader(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize hidden score board + * + * @param gameManifest GameManifest + * @param checkBox CheckBox + * @param font IFont + */ + void _initHiddenScoreBoard(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize When No game found + * + */ + void _initNoGameFound(); + + /** + * @brief Initialize hidden graphics + * + * @param graphicsManifest GraphicsManifest + * @param checkBox CheckBox + */ + void _initHiddenGraphics(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize hidden graphics header + * + * @param graphicsManifest GraphicsManifest + * @param checkBox CheckBox + */ + void _initHiddenGraphicsHeader(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize hidden graphics board + * + * @param graphicsManifest GraphicsManifest + * @param checkBox CheckBox + */ + void _initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font); + + /** + * @brief Initialize texts + * + */ + void _initTexts(); + + /** + * @brief Define the previous selected game + * + */ + void _previousSelectedGame(); + + /** + * @brief Define the previous selected graphics + * + */ + void _previousSelectedGraphics(); + + /** + * @brief Truncate a string + * + * @param str + * @param size + * @return std::string + */ + std::string _truncString(const std::string &str, int size); + + /** + * @brief Sort the scores + * + */ + void _sortScores(); + + /** + * @brief Get the game provider object + * + * @param index + * @return std::shared_ptr + */ + std::shared_ptr& _getGameProvider(const unsigned char &index); + + /** + * @brief Get the graphics provider object + * + * @param index + * @return std::shared_ptr + */ + std::shared_ptr& _getGraphicsProvider(const unsigned char &index); + + /** + * @brief Read the scores + * + */ + void _readScores(); + + /** + * @brief Write the scores + * + */ + void _writeScore(); +}; diff --git a/core/src/menu/checkBox/CMakeLists.txt b/core/src/menu/checkBox/CMakeLists.txt new file mode 100644 index 0000000..5db4b4c --- /dev/null +++ b/core/src/menu/checkBox/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(arcade PRIVATE + CheckBox.cpp + CheckBox.hpp +) diff --git a/core/src/menu/checkBox/CheckBox.cpp b/core/src/menu/checkBox/CheckBox.cpp new file mode 100644 index 0000000..68fa0b0 --- /dev/null +++ b/core/src/menu/checkBox/CheckBox.cpp @@ -0,0 +1,63 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** CheckBox +*/ + +#include "CheckBox.hpp" + +CheckBox::CheckBox(std::shared_ptr texture, std::shared_ptr text) : + _texture(texture), _text(text) +{ + this->_checked = false; + this->_hovered = false; + this->_texture->setOrigin({1, 0}); +} + +CheckBox::~CheckBox() {} + +void CheckBox::check() +{ + this->_checked = true; + this->_texture->setOrigin({0, 0}); +} + +void CheckBox::uncheck() +{ + this->_checked = false; + this->_texture->setOrigin({1, 0}); +} + +bool CheckBox::isChecked() const +{ + return this->_checked; +} + +void CheckBox::hover() +{ + this->_hovered = true; + this->_text->setColor(Color{53, 186, 243, 255}); +} + +void CheckBox::unhover() +{ + this->_hovered = false; + this->_text->setColor(Color{255, 255, 255, 255}); +} + +bool CheckBox::isHovered() const +{ + return this->_hovered; +} + +bool CheckBox::isHovered(const Vector2f &mousePos) const +{ + auto pos = this->_text->getPosition(); + auto size = this->_text->getSize(); + + if (mousePos.x > pos.x && mousePos.x < pos.x + size.x && + mousePos.y > pos.y && mousePos.y < pos.y + size.y) + return true; + return false; +} \ No newline at end of file diff --git a/core/src/menu/checkBox/CheckBox.hpp b/core/src/menu/checkBox/CheckBox.hpp new file mode 100644 index 0000000..00bd49c --- /dev/null +++ b/core/src/menu/checkBox/CheckBox.hpp @@ -0,0 +1,87 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** CheckBox +*/ + +#pragma once + +#include +#include +#include "menu/entity/text/Text.hpp" +#include "menu/entity/texture/Texture.hpp" +#include "shared/types/Libraries.hpp" +#include "shared/graphics/events/IKeyEvent.hpp" + +class CheckBox { +public: + + /** + * @brief Construct a new CheckBox object + * + * @param texture + * @param text + */ + CheckBox(std::shared_ptr texture, std::shared_ptr text); + + /** + * @brief Destructor for CheckBox object + */ + ~CheckBox(); + + /** + * @brief Check the checkbox + * + */ + void check(); + + /** + * @brief Uncheck the checkbox + * + */ + void uncheck(); + + /** + * @brief Check if the checkbox is checked + * + * @return true if checked + * @return false if not checked + */ + bool isChecked() const; + + /** + * @brief Hover the checkbox + * + */ + void hover(); + + /** + * @brief Unhover the checkbox + * + */ + void unhover(); + + /** + * @brief Check if the checkbox is hovered + * + * @return true if hovered + * @return false if not hovered + */ + bool isHovered() const; + + /** + * @brief Check if the checkbox is hovered by the mouse + * + * @param mousePos Mouse event + * @return true if hovered + * @return false if not hovered + */ + bool isHovered(const shared::types::Vector2f &mousePos) const; + +private: + bool _checked; + bool _hovered; + std::shared_ptr _text; + std::shared_ptr _texture; +}; diff --git a/core/src/menu/entity/CMakeLists.txt b/core/src/menu/entity/CMakeLists.txt new file mode 100644 index 0000000..c609d44 --- /dev/null +++ b/core/src/menu/entity/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(text) +add_subdirectory(texture) diff --git a/core/src/menu/entity/text/CMakeLists.txt b/core/src/menu/entity/text/CMakeLists.txt new file mode 100644 index 0000000..385ef2d --- /dev/null +++ b/core/src/menu/entity/text/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(arcade PRIVATE + Text.cpp + Text.hpp +) diff --git a/core/src/menu/entity/text/Text.cpp b/core/src/menu/entity/text/Text.cpp new file mode 100644 index 0000000..5d181fe --- /dev/null +++ b/core/src/menu/entity/text/Text.cpp @@ -0,0 +1,47 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Text +*/ + +#include "Text.hpp" + +Text::Text(std::shared_ptr font, unsigned int fontSize, std::string content, + TextAlign align, TextVerticalAlign verticalAlign, Color color, Vector2u size, + Vector2f position) : + _font(font), _fontSize(fontSize), _content(content), _align(align), _verticalAlign(verticalAlign), + _color(color), _size(size), _position(position) {} + +Text::~Text() {} + +void Text::draw(std::shared_ptr window) +{ + TextProps textProps = { + .font = this->_font, + .fontSize = this->_fontSize, + .content = this->_content, + .align = this->_align, + .verticalAlign = this->_verticalAlign, + .color = this->_color, + .size = this->_size, + .position = this->_position + }; + + window->render(textProps); +} + +void Text::setColor(Color color) +{ + this->_color = color; +} + +Vector2u Text::getSize() const +{ + return this->_size; +} + +Vector2f Text::getPosition() const +{ + return this->_position; +} diff --git a/core/src/menu/entity/text/Text.hpp b/core/src/menu/entity/text/Text.hpp new file mode 100644 index 0000000..fa59e3a --- /dev/null +++ b/core/src/menu/entity/text/Text.hpp @@ -0,0 +1,68 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Text +*/ + +#pragma once + +#include +#include +#include "shared/types/Libraries.hpp" +#include "shared/graphics/events/IKeyEvent.hpp" + +using namespace shared::graphics; + +class Text { +public: + Text(std::shared_ptr font, + unsigned int fontSize, + std::string content, + TextAlign align, + TextVerticalAlign verticalAlign, + Color color, + Vector2u size, + Vector2f position); + + /** + * @brief Destructor for Text object + */ + ~Text(); + + /** + * @brief Draw the checkbox + * + * @param window Window to draw on + */ + void draw(std::shared_ptr window); + + /** + * @brief Set the Color object + * + * @param color + */ + void setColor(Color color); + + /** + * @brief Get the size of the text + * + */ + Vector2u getSize() const; + + /** + * @brief Get the position of the text + * + */ + Vector2f getPosition() const; + +private: + std::shared_ptr _font; + unsigned int _fontSize; + std::string _content; + TextAlign _align; + TextVerticalAlign _verticalAlign; + Color _color; + Vector2u _size; + Vector2f _position; +}; diff --git a/core/src/menu/entity/texture/CMakeLists.txt b/core/src/menu/entity/texture/CMakeLists.txt new file mode 100644 index 0000000..074023d --- /dev/null +++ b/core/src/menu/entity/texture/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(arcade PRIVATE + Texture.cpp + Texture.hpp +) diff --git a/core/src/menu/entity/texture/Texture.cpp b/core/src/menu/entity/texture/Texture.cpp new file mode 100644 index 0000000..2df1bb1 --- /dev/null +++ b/core/src/menu/entity/texture/Texture.cpp @@ -0,0 +1,32 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture +*/ + +#include "Texture.hpp" + +Texture::Texture(std::shared_ptr texture, Vector2f binTileSize, Vector2u origin, + Vector2u size, Vector2f position) : _texture(texture), _binTileSize(binTileSize), _origin(origin), + _size(size), _position(position) {} + +Texture::~Texture() {} + +void Texture::draw(std::shared_ptr window) +{ + TextureProps textureProps = { + .texture = this->_texture, + .binTileSize = this->_binTileSize, + .origin = this->_origin, + .size = this->_size, + .position = this->_position + }; + + window->render(textureProps); +} + +void Texture::setOrigin(Vector2u origin) +{ + this->_origin = origin; +} diff --git a/core/src/menu/entity/texture/Texture.hpp b/core/src/menu/entity/texture/Texture.hpp new file mode 100644 index 0000000..41a03ad --- /dev/null +++ b/core/src/menu/entity/texture/Texture.hpp @@ -0,0 +1,57 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture +*/ + +#pragma once + +#include +#include +#include "shared/types/Libraries.hpp" +#include "shared/graphics/events/IKeyEvent.hpp" + +using namespace shared::games; +using namespace shared::graphics; + +class Texture { +public: + + /** + * @brief Construct a new Texture object + * + * @param texture Texture + * @param binTileSize BinTileSize + * @param origin Origin + * @param size Size + */ + Texture(std::shared_ptr texture, Vector2f binTileSize, Vector2u origin, + Vector2u size, Vector2f position); + + /** + * @brief Destructor for Texture object + */ + ~Texture(); + + /** + * @brief Draw the checkbox + * + * @param window Window to draw on + */ + void draw(std::shared_ptr window); + + /** + * @brief Set the Position object + * + * @param position Position + */ + void setOrigin(Vector2u origin); + +private: + std::shared_ptr _texture; + Vector2f _binTileSize; + Vector2u _origin; + Vector2u _size; + Vector2f _position; +}; diff --git a/core/src/types/CMakeLists.txt b/core/src/types/CMakeLists.txt index 3904d4b..98b5ffd 100644 --- a/core/src/types/CMakeLists.txt +++ b/core/src/types/CMakeLists.txt @@ -1,3 +1,4 @@ target_sources(arcade PRIVATE Providers.hpp + Stages.hpp ) diff --git a/core/src/types/Providers.hpp b/core/src/types/Providers.hpp index 518f976..f0c757a 100644 --- a/core/src/types/Providers.hpp +++ b/core/src/types/Providers.hpp @@ -7,7 +7,8 @@ #pragma once +#include #include "shared/types/Libraries.hpp" -typedef std::vector> GameProviders; -typedef std::vector> GraphicsProviders; +typedef std::map> GameProviders; +typedef std::map> GraphicsProviders; diff --git a/core/src/types/Stages.hpp b/core/src/types/Stages.hpp new file mode 100644 index 0000000..ab109a4 --- /dev/null +++ b/core/src/types/Stages.hpp @@ -0,0 +1,19 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Stages +*/ + +#pragma once + +namespace arcade::core { + typedef enum { + MENU, + PAUSE, + RESUME, + PLAY, + NEWGAME, + EXIT, + } SceneStage; +} diff --git a/games/common/components/PositionableComponent.cpp b/games/common/components/PositionableComponent.cpp index 2dd5be7..85b36ba 100644 --- a/games/common/components/PositionableComponent.cpp +++ b/games/common/components/PositionableComponent.cpp @@ -14,7 +14,7 @@ PositionableComponent::PositionableComponent(shared::games::entity::IEntity &ent _position(0, 0), _size(1, 1) { } -shared::types::Vector2i &PositionableComponent::getPosition() noexcept { +shared::types::Vector2f &PositionableComponent::getPosition() noexcept { return this->_position; } diff --git a/games/common/components/PositionableComponent.hpp b/games/common/components/PositionableComponent.hpp index 557e4f5..8c35e3f 100644 --- a/games/common/components/PositionableComponent.hpp +++ b/games/common/components/PositionableComponent.hpp @@ -29,7 +29,7 @@ class arcade::games::common::components::PositionableComponent * @brief Get position of the entity (tiles) * */ - shared::types::Vector2i &getPosition() noexcept override; + shared::types::Vector2f &getPosition() noexcept override; /** * @brief Get size of the entity (tiles) @@ -38,6 +38,6 @@ class arcade::games::common::components::PositionableComponent shared::types::Vector2u &getSize() noexcept override; protected: - shared::types::Vector2i _position; + shared::types::Vector2f _position; shared::types::Vector2u _size; }; diff --git a/games/common/game/AGame.cpp b/games/common/game/AGame.cpp index f8999bf..39f99dd 100644 --- a/games/common/game/AGame.cpp +++ b/games/common/game/AGame.cpp @@ -13,6 +13,7 @@ using namespace arcade::games; common::AGame::AGame(shared::types::Vector2u size, unsigned int fps) : _size(size), _fps(fps) { this->_entities = {}; + this->_score = 0; } const shared::games::entity::EntitiesMap &common::AGame::getEntities() const { @@ -30,3 +31,7 @@ const unsigned int common::AGame::getFps() const noexcept { void common::AGame::_registerEntity(shared::games::entity::EntityPtr entity) { this->_entities.push_back(std::move(entity)); } + +const int common::AGame::getScore() const noexcept { + return this->_score; +} diff --git a/games/common/game/AGame.hpp b/games/common/game/AGame.hpp index db2dcd0..f7251fa 100644 --- a/games/common/game/AGame.hpp +++ b/games/common/game/AGame.hpp @@ -40,6 +40,13 @@ class arcade::games::common::AGame : public virtual shared::games::IGame { */ const unsigned int getFps() const noexcept override; + /** + * @brief Get the score of the game + * + * @return The score of the game + */ + const int getScore() const noexcept override; + protected: /** * @brief Construct a new AGame object @@ -64,6 +71,11 @@ class arcade::games::common::AGame : public virtual shared::games::IGame { */ unsigned int _fps; + /** + * @brief Game score + */ + int _score; + /** * @brief Add an entity to the game * diff --git a/games/snake/src/SnakeGame.cpp b/games/snake/src/SnakeGame.cpp index 0bd6501..248685e 100644 --- a/games/snake/src/SnakeGame.cpp +++ b/games/snake/src/SnakeGame.cpp @@ -89,6 +89,7 @@ void snake::SnakeGame::_loose() { } this->_looseGame = false; + this->_score = 0; } void snake::SnakeGame::setLooseGame(bool state) { @@ -101,4 +102,5 @@ void snake::SnakeGame::addNewPoint() { this->_registerEntity(newTail); this->_apple->generateApple(); this->speedTime -= 2; + this->_score += 10; } diff --git a/graphics/common/events/mouse/AMouseButtonEvent.hpp b/graphics/common/events/mouse/AMouseButtonEvent.hpp index 0071cb0..41564a8 100644 --- a/graphics/common/events/mouse/AMouseButtonEvent.hpp +++ b/graphics/common/events/mouse/AMouseButtonEvent.hpp @@ -32,7 +32,7 @@ class arcade::graphics::common::events::AMouseButtonEvent: public AMouseEvent * @param button Targeted button */ explicit AMouseButtonEvent( - Vector2i pos, + Vector2f pos, MouseButton button ): AMouseEvent(pos), _button(button) {}; diff --git a/graphics/common/events/mouse/AMouseEvent.hpp b/graphics/common/events/mouse/AMouseEvent.hpp index 2bf413a..bb1bbbd 100644 --- a/graphics/common/events/mouse/AMouseEvent.hpp +++ b/graphics/common/events/mouse/AMouseEvent.hpp @@ -26,7 +26,7 @@ class arcade::graphics::common::events::AMouseEvent: public virtual IMouseEvent return T; } - const Vector2i getPosition() const noexcept override { + const Vector2f getPosition() const noexcept override { return _pos; } @@ -36,7 +36,7 @@ class arcade::graphics::common::events::AMouseEvent: public virtual IMouseEvent * * @param pos Position of the mouse */ - explicit AMouseEvent(Vector2i pos): _pos(pos){}; + explicit AMouseEvent(Vector2f pos): _pos(pos){}; - Vector2i _pos; + Vector2f _pos; }; diff --git a/graphics/common/events/mouse/MouseButtonPressEvent.hpp b/graphics/common/events/mouse/MouseButtonPressEvent.hpp index f2865c2..8a33b0e 100644 --- a/graphics/common/events/mouse/MouseButtonPressEvent.hpp +++ b/graphics/common/events/mouse/MouseButtonPressEvent.hpp @@ -19,6 +19,6 @@ namespace arcade::graphics::common::events { class arcade::graphics::common::events::MouseButtonPressEvent : public AMouseButtonEvent { public: - MouseButtonPressEvent(Vector2i pos, MouseButton button) : AMouseButtonEvent(pos, button){}; + MouseButtonPressEvent(Vector2f pos, MouseButton button) : AMouseButtonEvent(pos, button){}; ~MouseButtonPressEvent() override = default; }; diff --git a/graphics/common/events/mouse/MouseMoveEvent.hpp b/graphics/common/events/mouse/MouseMoveEvent.hpp index 76cefef..a2e9fe7 100644 --- a/graphics/common/events/mouse/MouseMoveEvent.hpp +++ b/graphics/common/events/mouse/MouseMoveEvent.hpp @@ -18,7 +18,7 @@ namespace arcade::graphics::common::events { class arcade::graphics::common::events::MouseMoveEvent: public AMouseEvent { public: - explicit MouseMoveEvent(const Vector2i pos): AMouseEvent(pos) {} + explicit MouseMoveEvent(const Vector2f pos): AMouseEvent(pos) {} ~MouseMoveEvent() override = default; }; diff --git a/graphics/sfml/src/window/EventsHandler.cpp b/graphics/sfml/src/window/EventsHandler.cpp index d499aa3..ccef122 100644 --- a/graphics/sfml/src/window/EventsHandler.cpp +++ b/graphics/sfml/src/window/EventsHandler.cpp @@ -207,9 +207,9 @@ EventPtr EventsHandler::_handleMouseButtonPressEvent( sf::Event &event, Window &window ) { - Vector2i pos = window.mapPositionToTile({ - event.mouseMove.x, - event.mouseMove.y + auto pos = window.mapPositionToTile({ + event.mouseButton.x, + event.mouseButton.y }); if (pos.x < 0 || pos.y < 0) diff --git a/graphics/sfml/src/window/Renderer.cpp b/graphics/sfml/src/window/Renderer.cpp index 5b93ce3..c2b78d1 100644 --- a/graphics/sfml/src/window/Renderer.cpp +++ b/graphics/sfml/src/window/Renderer.cpp @@ -125,7 +125,7 @@ void Renderer::_reset(sf::Sprite &sprite) { sprite.setOrigin(0, 0); } -Vector2f Renderer::_entityPixels(const Vector2i &position) { +Vector2f Renderer::_entityPixels(const Vector2f &position) { auto realSize = this->_window.getSize(); Vector2u originalPixels = this->_window.getPixelSizeFromTiles(realSize); diff --git a/graphics/sfml/src/window/Renderer.hpp b/graphics/sfml/src/window/Renderer.hpp index f7db849..6229b2d 100644 --- a/graphics/sfml/src/window/Renderer.hpp +++ b/graphics/sfml/src/window/Renderer.hpp @@ -60,7 +60,7 @@ class arcade::graphics::sfml::window::Renderer { * @param position Tile position * @return Pixel position */ - Vector2f _entityPixels(const Vector2i &position); + Vector2f _entityPixels(const Vector2f &position); /** * @brief Convert a tile size to pixel size diff --git a/graphics/sfml/src/window/Window.cpp b/graphics/sfml/src/window/Window.cpp index 1eedc47..28a14a4 100644 --- a/graphics/sfml/src/window/Window.cpp +++ b/graphics/sfml/src/window/Window.cpp @@ -13,8 +13,9 @@ using namespace arcade::graphics::sfml::window; using namespace arcade::graphics::common::exceptions; -const Vector2u Window::tileSize = { 12, 12 }; +const Vector2u Window::tileSize = { 35, 35 }; +#include Window::Window(const IWindow::WindowInitProps &props): _size(props.size), _initialSize(0, 0), @@ -149,7 +150,7 @@ Vector2u Window::getPixelSizeFromTiles(const Vector2u &size) { return real; } -Vector2i Window::mapPositionToTile(const Vector2i &position) const { +Vector2f Window::mapPositionToTile(const Vector2i &position) const { auto pixelsPosition = _window.mapPixelToCoords({ position.x, position.y @@ -164,10 +165,7 @@ Vector2i Window::mapPositionToTile(const Vector2i &position) const { if (tilesPosition.x >= size.x || tilesPosition.y >= size.y || pixelsPosition.x < 0) return {-1, -1}; - return { - static_cast(tilesPosition.x), - static_cast(tilesPosition.y) - }; + return tilesPosition; } void Window::onResize() @@ -181,7 +179,7 @@ void Window::onResize() _view.setCenter( static_cast(originalPixels.x) / 2, static_cast(originalPixels.y) / 2 ); - if (width < height) { + if ((static_cast(originalPixels.x) / width) > static_cast(originalPixels.y) / height) { _view.zoom(static_cast(originalPixels.x) / width); } else { _view.zoom(static_cast(originalPixels.y) / height); diff --git a/graphics/sfml/src/window/Window.hpp b/graphics/sfml/src/window/Window.hpp index 6ac8d02..78542a7 100644 --- a/graphics/sfml/src/window/Window.hpp +++ b/graphics/sfml/src/window/Window.hpp @@ -137,7 +137,7 @@ class arcade::graphics::sfml::window::Window: public shared::graphics::IWindow { * @brief Convert a position in pixels to a position in tiles * @return Converted position */ - Vector2i mapPositionToTile(const Vector2i &pixelsPosition) const; + Vector2f mapPositionToTile(const Vector2i &pixelsPosition) const; /** * @brief Get the size of a tile diff --git a/shared/games/IGame.hpp b/shared/games/IGame.hpp index bd684c8..956baab 100644 --- a/shared/games/IGame.hpp +++ b/shared/games/IGame.hpp @@ -62,4 +62,11 @@ class shared::games::IGame * @return Entities map of the game */ virtual const entity::EntitiesMap &getEntities(void) const = 0; + + /** + * @brief Get the score of the game + * + * @return The score of the game + */ + virtual const int getScore() const noexcept = 0; }; diff --git a/shared/games/components/IPositionableComponent.hpp b/shared/games/components/IPositionableComponent.hpp index 6eac1cc..8cf9edb 100644 --- a/shared/games/components/IPositionableComponent.hpp +++ b/shared/games/components/IPositionableComponent.hpp @@ -23,7 +23,7 @@ class shared::games::components::IPositionableComponent: public virtual ICompone * @brief Get position of the entity (tiles) * */ - virtual types::Vector2i &getPosition() noexcept = 0; + virtual types::Vector2f &getPosition() noexcept = 0; /** * @brief Get size of the entity (tiles) diff --git a/shared/graphics/events/IMouseEvent.hpp b/shared/graphics/events/IMouseEvent.hpp index 618e5fe..c8d6b03 100644 --- a/shared/graphics/events/IMouseEvent.hpp +++ b/shared/graphics/events/IMouseEvent.hpp @@ -23,5 +23,5 @@ class shared::graphics::events::IMouseEvent : public virtual IEvent { * * @return Position of the mouse */ - virtual const shared::types::Vector2i getPosition(void) const noexcept = 0; + virtual const shared::types::Vector2f getPosition(void) const noexcept = 0; }; diff --git a/shared/graphics/types/TextProps.hpp b/shared/graphics/types/TextProps.hpp index 9f01dc9..d405473 100644 --- a/shared/graphics/types/TextProps.hpp +++ b/shared/graphics/types/TextProps.hpp @@ -37,6 +37,6 @@ namespace shared::graphics { TextVerticalAlign verticalAlign; // Vertical alignment of the text types::Color color; // Color of the text Vector2u size; // Size of the entity - Vector2i position; // Position of the entity + Vector2f position; // Position of the entity } TextProps; } diff --git a/shared/graphics/types/TextureProps.hpp b/shared/graphics/types/TextureProps.hpp index 5847f37..5d72157 100644 --- a/shared/graphics/types/TextureProps.hpp +++ b/shared/graphics/types/TextureProps.hpp @@ -20,6 +20,6 @@ namespace shared::graphics { Vector2f binTileSize; // Size of a binary tile Vector2u origin; // Origin of the texture Vector2u size; // Size of the entity - Vector2i position; // Position of the entity + Vector2f position; // Position of the entity } TextureProps; }