diff --git a/CMakeLists.txt b/CMakeLists.txt index afebafd4..cf696742 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ set(SOURCES sources/System/EndCondition/EndConditionSystem.hpp sources/System/EndCondition/EndConditionSystem.cpp sources/Runner/LobbyScene.cpp + sources/Runner/HowToPlayScene.cpp sources/Runner/ScoreScene.cpp sources/System/Shaders/ShaderSystem.cpp sources/System/Shaders/ShaderSystem.hpp @@ -152,6 +153,14 @@ set(SOURCES sources/Component/Shaders/Items/BombExplosionShaderComponent.hpp sources/Component/Shaders/Items/WhiteShaderComponent.cpp sources/Component/Shaders/Items/WhiteShaderComponent.hpp + sources/System/Timer/TimerUISystem.hpp + sources/System/Timer/TimerUISystem.cpp + sources/System/Bonus/BonusUISystem.hpp + sources/System/Bonus/BonusUISystem.cpp + sources/Component/Color/ColorComponent.hpp + sources/Component/Color/ColorComponent.cpp + sources/Component/Stat/StatComponent.cpp + sources/Component/Stat/StatComponent.hpp ) add_executable(bomberman diff --git a/assets/buttons/button_htp.png b/assets/buttons/button_htp.png new file mode 100644 index 00000000..c54d0afd Binary files /dev/null and b/assets/buttons/button_htp.png differ diff --git a/assets/buttons/button_htp_hovered.png b/assets/buttons/button_htp_hovered.png new file mode 100644 index 00000000..227dcc7c Binary files /dev/null and b/assets/buttons/button_htp_hovered.png differ diff --git a/assets/game_background.png b/assets/game_background.png new file mode 100644 index 00000000..366ef882 Binary files /dev/null and b/assets/game_background.png differ diff --git a/assets/player/ui/blue.png b/assets/player/ui/blue.png new file mode 100644 index 00000000..5243a306 Binary files /dev/null and b/assets/player/ui/blue.png differ diff --git a/assets/player/ui/green.png b/assets/player/ui/green.png new file mode 100644 index 00000000..2a24f76c Binary files /dev/null and b/assets/player/ui/green.png differ diff --git a/assets/player/ui/red.png b/assets/player/ui/red.png new file mode 100644 index 00000000..ad00d65c Binary files /dev/null and b/assets/player/ui/red.png differ diff --git a/assets/player/ui/yellow.png b/assets/player/ui/yellow.png new file mode 100644 index 00000000..a06c28ea Binary files /dev/null and b/assets/player/ui/yellow.png differ diff --git a/sources/Component/Color/ColorComponent.cpp b/sources/Component/Color/ColorComponent.cpp new file mode 100644 index 00000000..994f7f10 --- /dev/null +++ b/sources/Component/Color/ColorComponent.cpp @@ -0,0 +1,24 @@ +// +// +// + +#include "ColorComponent.hpp" + +namespace BBM +{ + + ColorComponent::ColorComponent(WAL::Entity &entity, RAY::Color color) + : Component(entity), + color(color) + {} + + ColorComponent::ColorComponent(WAL::Entity &entity, unsigned char r, unsigned char g, unsigned char b, unsigned char a) + : Component(entity), + color(r, g, b, a) + {} + + WAL::Component *ColorComponent::clone(WAL::Entity &entity) const + { + return new ColorComponent(entity, this->color); + } +} // namespace WAL \ No newline at end of file diff --git a/sources/Component/Color/ColorComponent.hpp b/sources/Component/Color/ColorComponent.hpp new file mode 100644 index 00000000..d75b5818 --- /dev/null +++ b/sources/Component/Color/ColorComponent.hpp @@ -0,0 +1,33 @@ +// +// +// + +#pragma once + +#include "Color.hpp" +#include "Component/Component.hpp" + +namespace BBM +{ + //! @brief A basic color component + class ColorComponent : public WAL::Component + { + public: + //! @brief Get the editable color of this entity + RAY::Color color; + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief Create a new ColorComponent at a certain color + ColorComponent(WAL::Entity &entity, RAY::Color color); + //! @brief Create a new ColorComponent at a certain color + ColorComponent(WAL::Entity &entity, unsigned char r, unsigned char g, unsigned char b, unsigned char a); + //! @brief A color component is copy constructable + ColorComponent(const ColorComponent &) = default; + //! @brief A default destructor + ~ColorComponent() override = default; + //! @brief A color component is not assignable + ColorComponent &operator=(const ColorComponent &) = delete; + }; +} // namespace WAL \ No newline at end of file diff --git a/sources/Component/Stat/StatComponent.cpp b/sources/Component/Stat/StatComponent.cpp new file mode 100644 index 00000000..2e20f6f6 --- /dev/null +++ b/sources/Component/Stat/StatComponent.cpp @@ -0,0 +1,19 @@ +// +// +// + +#include "StatComponent.hpp" + +namespace BBM +{ + + StatComponent::StatComponent(WAL::Entity &entity, WAL::Callback callback) + : Component(entity), + updater(callback) + {} + + WAL::Component *StatComponent::clone(WAL::Entity &entity) const + { + return new StatComponent(entity, this->updater); + } +} // namespace WAL \ No newline at end of file diff --git a/sources/Component/Stat/StatComponent.hpp b/sources/Component/Stat/StatComponent.hpp new file mode 100644 index 00000000..75f9733f --- /dev/null +++ b/sources/Component/Stat/StatComponent.hpp @@ -0,0 +1,33 @@ +// +// +// + +#pragma once + +#include "Component/Component.hpp" +#include "Models/Callback.hpp" +#include "Wal.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" + +namespace BBM +{ + //! @brief A Stat component which contains a text and a callback + class StatComponent : public WAL::Component + { + public: + //! @brief onEvent callback + WAL::Callback updater; + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief Create a new StatComponent with a callback + StatComponent(WAL::Entity &entity, WAL::Callback callback); + //! @brief A color component is copy constructable + StatComponent(const StatComponent &) = default; + //! @brief A default destructor + ~StatComponent() override = default; + //! @brief A color component is not assignable + StatComponent &operator=(const StatComponent &) = delete; + }; +} // namespace WAL \ No newline at end of file diff --git a/sources/Models/GameState.hpp b/sources/Models/GameState.hpp index da17fdc1..b3d506be 100644 --- a/sources/Models/GameState.hpp +++ b/sources/Models/GameState.hpp @@ -26,6 +26,7 @@ namespace BBM LobbyScene, TitleScreenScene, CreditScene, + HowToPlayScene, ScoreScene, }; diff --git a/sources/Runner/GameScene.cpp b/sources/Runner/GameScene.cpp index af6de202..b2e6f279 100644 --- a/sources/Runner/GameScene.cpp +++ b/sources/Runner/GameScene.cpp @@ -18,16 +18,20 @@ #include "Component/Renderer/Drawable3DComponent.hpp" #include "Component/Renderer/Drawable2DComponent.hpp" #include -#include "Component/Button/ButtonComponent.hpp" #include "Drawables/2D/Text.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Button/ButtonComponent.hpp" +#include "Drawables/Texture.hpp" #include "Component/Gravity/GravityComponent.hpp" #include "Component/BumperTimer/BumperTimerComponent.hpp" #include "Component/Timer/TimerComponent.hpp" #include "Model/Model.hpp" #include "Map/Map.hpp" #include "Component/Score/ScoreComponent.hpp" +#include "Drawables/2D/Text.hpp" namespace RAY3D = RAY::Drawables::Drawables3D; +namespace RAY2D = RAY::Drawables::Drawables2D; namespace BBM { @@ -40,7 +44,9 @@ namespace BBM scene->addEntity("Timer") .addComponent(std::chrono::minutes (3), [](WAL::Entity &, WAL::Wal &) { Runner::gameState.nextScene = GameState::ScoreScene; - }); + }) + .addComponent(1920 / 2 - 2 * 30, 30, 0) + .addComponent("", 60, RAY::Vector2(), ORANGE); scene->addEntity("background image") .addComponent(true, "assets/background_game.png", false) .addComponent(); diff --git a/sources/Runner/HowToPlayScene.cpp b/sources/Runner/HowToPlayScene.cpp new file mode 100644 index 00000000..cfb2cb7e --- /dev/null +++ b/sources/Runner/HowToPlayScene.cpp @@ -0,0 +1,81 @@ +#include +#include +#include "Runner.hpp" +#include +#include "Component/Music/MusicComponent.hpp" +#include "Component/Sound/SoundComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Keyboard/KeyboardComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Button/ButtonComponent.hpp" +#include "Drawables/2D/Text.hpp" + +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + std::shared_ptr Runner::loadHowToPlayScene() + { + auto scene = std::make_shared(); + static const std::map sounds = { + {SoundComponent::JUMP, "assets/sounds/click.ogg"} + }; + + addMenuControl(*scene); + scene->addEntity("Control entity") + .addComponent("assets/musics/music_player_select.ogg") + .addComponent(sounds); + scene->addEntity("background") + .addComponent() + .addComponent("assets/plain_menu_background.png"); + scene->addEntity("scene title text") + .addComponent(1920 / 3, 100, 0) + .addComponent("How To Play?", 120, RAY::Vector2(), ORANGE); + + scene->addEntity("select text") + .addComponent(1920 / 8, 1080 / 3, 0) + .addComponent("Select:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("select") + .addComponent(1920 / 7, 1080 / 2.5, 0) + .addComponent("Space/A Button", 35, RAY::Vector2(), BLACK); + scene->addEntity("change skin text") + .addComponent(1920 / 8, 1080 / 2, 0) + .addComponent("Change Skin/Drop Bomb:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("change skin") + .addComponent(1920 / 7, 1080 / 1.75, 0) + .addComponent("E/B Button", 35, RAY::Vector2(), BLACK); + scene->addEntity("move text") + .addComponent(1920 / 1.75, 1080 / 3, 0) + .addComponent("Move:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("move") + .addComponent(1920 / 1.75, 1080 / 2.5, 0) + .addComponent("Q-Z-S-D/Arrow/Joystick", 35, RAY::Vector2(), BLACK); + scene->addEntity("back text") + .addComponent(1920 / 1.75, 1080 / 2, 0) + .addComponent("Back/Pause:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("back") + .addComponent(1920 / 1.75, 1080 / 1.75, 0) + .addComponent("Esc / Controller's Home button:", 35, RAY::Vector2(), BLACK); + auto &back = scene->addEntity("back to menu") + .addComponent(10, 1080 - 85, 0) + .addComponent("assets/buttons/button_back.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::LobbyScene; + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_back.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_back_hovered.png"); + }); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/LobbyScene.cpp b/sources/Runner/LobbyScene.cpp index bf6e3323..7254006e 100644 --- a/sources/Runner/LobbyScene.cpp +++ b/sources/Runner/LobbyScene.cpp @@ -59,39 +59,55 @@ namespace BBM .addComponent([](WAL::Entity &entity, WAL::Wal &wal) { if (Runner::gameState.currentScene != GameState::LobbyScene - || !LobbySystem::playersAreReady(*wal.getScene())) + || !LobbySystem::playersAreReady(*wal.getScene())) return; LobbySystem::switchToGame(wal); }) .addComponent>(); - - auto &back = scene->addEntity("back to menu") .addComponent(10, 1080 - 85, 0) .addComponent("assets/buttons/button_back.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + .addComponent([](WAL::Entity &entity, WAL::Wal &) { gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; - wal.getSystem().unloadLobby(); }) .addComponent([](WAL::Entity &entity, WAL::Wal &) { - auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - texture->use("assets/buttons/button_back.png"); + texture->use("assets/buttons/button_back.png"); }) .addComponent([](WAL::Entity &entity, WAL::Wal &) { - auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); texture->use("assets/buttons/button_back_hovered.png"); }); + auto &howToPlay = scene->addEntity("to to play") + .addComponent(1920 - 10 - 75, 1080 - 85, 0) + .addComponent("assets/buttons/button_htp.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::HowToPlayScene; + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_htp.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_htp_hovered.png"); + }); auto &lavaOption = scene->addEntity("lava option text") .addComponent(1920 / 6, 1.85 * 1080 / 3, 0) .addComponent("Lava: Off", 70, RAY::Vector2(), BLACK) .addComponent([](WAL::Entity &entity, WAL::Wal &wal) { - auto *text = dynamic_cast(entity.getComponent().drawable.get()); + RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); if (text->getString().find("Off") != std::string::npos) { text->setText("Lava: On"); @@ -186,7 +202,8 @@ namespace BBM scene->addEntity("camera") .addComponent(8, 20, 7) .addComponent(Vector3f(8, 0, 8)); - play.getComponent().setButtonLinks(&heightOption, &back, &back, nullptr); + play.getComponent().setButtonLinks(&lavaOption, &back, &back, &howToPlay); + howToPlay.getComponent().setButtonLinks(&play, nullptr, &play); back.getComponent().setButtonLinks(&play, nullptr, nullptr, &play); lavaOption.getComponent().setButtonLinks(nullptr, &heightOption, nullptr, &aiMore); heightOption.getComponent().setButtonLinks(&lavaOption, &play, nullptr, &aiLess); diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index 6ca48e55..2bcc5fc4 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -16,6 +16,7 @@ #include "Runner.hpp" #include "Models/GameState.hpp" #include +#include #include #include #include @@ -40,6 +41,7 @@ #include "System/Score/ScoreSystem.hpp" #include "System/EndCondition/EndConditionSystem.hpp" #include "Component/Lobby/LobbyComponent.hpp" +#include "System/Bonus/BonusUISystem.hpp" namespace BBM { @@ -51,14 +53,11 @@ namespace BBM auto &view = engine.getScene()->view(); if (RAY::Window::getInstance().shouldClose()) engine.shouldClose = true; - if (gameState.currentScene == GameState::SceneID::GameScene || gameState.currentScene == GameState::SceneID::SplashScreen) { + if (gameState.currentScene == GameState::SceneID::GameScene) { for (auto &[_, component]: engine.getScene()->view()) { if (component.pause && gameState.currentScene == GameState::SceneID::GameScene) { gameState.nextScene = GameState::SceneID::PauseMenuScene; break; - } else if (gameState.currentScene == GameState::SceneID::SplashScreen && component.select) { - gameState.nextScene = GameState::SceneID::TitleScreenScene; - break; } } } @@ -74,6 +73,7 @@ namespace BBM void Runner::addSystems(WAL::Wal &wal) { wal.addSystem() + .addSystem() .addSystem() .addSystem() .addSystem() @@ -82,6 +82,7 @@ namespace BBM .addSystem() .addSystem() .addSystem() + .addSystem() .addSystem() .addSystem() .addSystem() @@ -133,6 +134,7 @@ namespace BBM gameState._loadedScenes[GameState::SceneID::CreditScene] = loadCreditScene(); gameState._loadedScenes[GameState::SceneID::SplashScreen] = loadSplashScreenScene(); gameState._loadedScenes[GameState::SceneID::LobbyScene] = loadLobbyScene(); + gameState._loadedScenes[GameState::SceneID::HowToPlayScene] = loadHowToPlayScene(); } int Runner::run() diff --git a/sources/Runner/Runner.hpp b/sources/Runner/Runner.hpp index a0700ccd..4fa9f6a1 100644 --- a/sources/Runner/Runner.hpp +++ b/sources/Runner/Runner.hpp @@ -61,6 +61,8 @@ namespace BBM //! @brief load all data related to splash screen static std::shared_ptr loadSplashScreenScene(); + //! @brief load how to play screen + static std::shared_ptr loadHowToPlayScene(); //! @brief load all data related to score scene screen //! @param gameScene scene containing players (to know the scores) static std::shared_ptr loadScoreScene(WAL::Scene &gameScene); diff --git a/sources/Runner/SplashScreenScene.cpp b/sources/Runner/SplashScreenScene.cpp index a22d20da..3d0cc1ae 100644 --- a/sources/Runner/SplashScreenScene.cpp +++ b/sources/Runner/SplashScreenScene.cpp @@ -30,7 +30,13 @@ namespace BBM .addComponent("powered by", 30, RAY::Vector2(), BLACK); auto &skipText = scene->addEntity("Press space to skip") .addComponent(1920 - 250, 1080 - 30, 0) - .addComponent("Press space to skip", 20, RAY::Vector2(), BLACK); + .addComponent("Press space to skip", 20, RAY::Vector2(), BLACK) + .addComponent() + .addComponent() + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::TitleScreenScene; + }); return scene; } } \ No newline at end of file diff --git a/sources/System/Bonus/BonusUISystem.cpp b/sources/System/Bonus/BonusUISystem.cpp new file mode 100644 index 00000000..d6ac5598 --- /dev/null +++ b/sources/System/Bonus/BonusUISystem.cpp @@ -0,0 +1,17 @@ +// +// Created by hbenjamin on 09/06/2021. +// + +#include "BonusUISystem.hpp" + +namespace BBM +{ + BonusUISystem::BonusUISystem(WAL::Wal &wal) + : System(wal) + {} + + void BonusUISystem::onFixedUpdate(WAL::ViewEntity &entity) + { + entity.get().updater(entity.get()); + } +} \ No newline at end of file diff --git a/sources/System/Bonus/BonusUISystem.hpp b/sources/System/Bonus/BonusUISystem.hpp new file mode 100644 index 00000000..ddc6f95f --- /dev/null +++ b/sources/System/Bonus/BonusUISystem.hpp @@ -0,0 +1,32 @@ +// +// +// + +#pragma once + +#include "System/System.hpp" +#include "Wal.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Stat/StatComponent.hpp" + +namespace BBM +{ + //! @brief The system that allow the text of the ui to display current values + class BonusUISystem : public WAL::System + { + private: + public: + //! @inherit + void onFixedUpdate(WAL::ViewEntity &entity) override; + + //! @brief A default constructor + explicit BonusUISystem(WAL::Wal &wal); + //! @brief A bomb holder system is copy constructable + BonusUISystem(const BonusUISystem &) = default; + //! @brief A default destructor + ~BonusUISystem() override = default; + //! @brief A bomb holder system is not assignable. + BonusUISystem &operator=(const BonusUISystem &) = delete; + }; +} + diff --git a/sources/System/Lobby/LobbySystem.cpp b/sources/System/Lobby/LobbySystem.cpp index 6fcee4ac..4d2fd563 100644 --- a/sources/System/Lobby/LobbySystem.cpp +++ b/sources/System/Lobby/LobbySystem.cpp @@ -14,8 +14,15 @@ #include #include #include +#include +#include +#include "Component/Color/ColorComponent.hpp" +#include "Component/Stat/StatComponent.hpp" +#include "Component/Bonus/PlayerBonusComponent.hpp" +#include "Component/BombHolder/BombHolderComponent.hpp" namespace RAY3D = RAY::Drawables::Drawables3D; +namespace RAY2D = RAY::Drawables::Drawables2D; namespace BBM { @@ -198,8 +205,10 @@ namespace BBM int mapWidth = 16; int mapHeight = 16; int playerCount = 0; + int playerID = 0; for (auto &[_, lobby] : wal.getScene()->view()) { + playerID++; if (lobby.layout == ControllableComponent::NONE) continue; auto &player = Runner::createPlayer(*scene); @@ -209,6 +218,67 @@ namespace BBM mapHeight * (!(playerCount % 3))); auto *model = dynamic_cast(player.getComponent().drawable.get()); model->setTextureToMaterial(MAP_DIFFUSE, "assets/player/textures/" + _colors[lobby.color] + ".png"); + std::string texturePath = "assets/player/ui/" + _colors[lobby.color] + ".png"; + int x = (playerID % 2 == 0) ? 1920 - 10 - 320 : 10; + int y = playerID > 2 ? 1080 - 10 - 248 : 10; + scene->addEntity("player color tile") + .addComponent(x, y - 2, 0) + .addComponent(x, y, 320, 248, _rayColors[lobby.color]); + scene->addEntity("player ui tile") + .addComponent(x, y, 0) + .addComponent(texturePath); + scene->addEntity("player hide fireup") + .addComponent(x + 220, y + 35, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const BombHolderComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(std::to_string(bonus->explosionRadius)); + }); + scene->addEntity("player hide bombup") + .addComponent(x + 220, y + 77, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const BombHolderComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(std::to_string(bonus->bombCount) + " / " + std::to_string(bonus->maxBombCount)); + }); + scene->addEntity("player hide speedup") + .addComponent(x + 220, y + 122, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const ControllableComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(std::to_string(static_cast(bonus->speed * 100))); + }); + scene->addEntity("player hide wall") + .addComponent(x + 220, y + 161, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const PlayerBonusComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(bonus->isNoClipOn ? "YES" : "NO"); + }); playerCount++; } Runner::gameState._loadedScenes[GameState::SceneID::GameScene] = scene; diff --git a/sources/System/MenuControllable/MenuControllableSystem.cpp b/sources/System/MenuControllable/MenuControllableSystem.cpp index d70ae7bc..d3158774 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.cpp +++ b/sources/System/MenuControllable/MenuControllableSystem.cpp @@ -7,6 +7,12 @@ #include "System/MenuControllable/MenuControllableSystem.hpp" #include "Component/Controllable/ControllableComponent.hpp" #include "Entity/Entity.hpp" +#include "Drawables/Texture.hpp" +#include "Drawables/2D/Text.hpp" +#include "Controllers/Mouse.hpp" + +namespace RAYControl = RAY::Controller; +namespace RAY2D = RAY::Drawables::Drawables2D; namespace BBM { @@ -45,14 +51,41 @@ namespace BBM this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); } - void MenuControllableSystem::onFixedUpdate(WAL::ViewEntity &entity) + bool MenuControllableSystem::_mouseOnButton(WAL::ViewEntity &entity) const { - auto &controllable = entity.get(); - auto &buttons = _wal.getScene()->view(); + auto &positionComponent = entity.get(); + RAY::Vector2 rayMousePos = RAYControl::Mouse::getCursorPosition(); + RAY::Texture *texture = dynamic_cast(entity.get().drawable.get()); + RAY2D::Text *text = dynamic_cast(entity.get().drawable.get()); + Vector2f buttonPos(positionComponent.getX(), positionComponent.getY()); + Vector2f mousePos(rayMousePos.x, rayMousePos.y); + Vector2f dimensions; + + WAL::Entity *newButton = nullptr; + + if (texture) { + dimensions.x = texture->getDimensions().x; + dimensions.y = texture->getDimensions().y; + } else if (text) { + dimensions.y = text->getFontSize(); + dimensions.x = text->getString().size() * (text->getLetterSpacing() + text->getFontSize()); + } else + return false; + return ((buttonPos.x <= mousePos.x && mousePos.x <= buttonPos.x + dimensions.x) + && (buttonPos.y <= mousePos.y && mousePos.y <= buttonPos.y + dimensions.y)); + } + + void MenuControllableSystem::onSelfUpdate() + { + + auto &controllableView = this->_wal.getScene()->view(); + auto &buttons = _wal.getScene()->view(); + if (this->_currentButton && this->_currentButton->_scene.getID() != this->_wal.getScene()->getID()) { this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); this->_currentButton = nullptr; + return; } if (this->_currentButton == nullptr && buttons.size()) { this->_currentButton = &(*buttons.front()); @@ -60,6 +93,20 @@ namespace BBM } if (!this->_currentButton) return; - this->_updateCurrentButton(controllable.select, controllable.move); + for (auto &[_, controllable]: controllableView) + if (controllable.move.x || controllable.move.y || controllable.select) { + this->_updateCurrentButton(controllable.select, controllable.move); + return; + } + for (auto &entity: buttons) { + if (_mouseOnButton(entity)) { + if (this->_currentButton) + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + this->_currentButton = &(*entity); + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + if (RAYControl::Mouse::isPressed(RAYControl::Mouse::Button::MOUSE_BUTTON_LEFT)) + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + } + } } } \ No newline at end of file diff --git a/sources/System/MenuControllable/MenuControllableSystem.hpp b/sources/System/MenuControllable/MenuControllableSystem.hpp index 0ad43a45..67254369 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.hpp +++ b/sources/System/MenuControllable/MenuControllableSystem.hpp @@ -7,11 +7,14 @@ #include "Component/Controllable/ControllableComponent.hpp" #include "Models/Vector2.hpp" #include "System/System.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Button/ButtonComponent.hpp" namespace BBM { //! @brief A system to handle Controllable entities in a menu. - class MenuControllableSystem : public WAL::System + class MenuControllableSystem : public WAL::System<> { private: //! @brief index of the current button selected @@ -21,11 +24,13 @@ namespace BBM //! @param selected lets know if te new selected button is 'pressed' void _updateCurrentButton(bool selected, Vector2f move); + //! @return true if mouse on entity + bool _mouseOnButton(WAL::ViewEntity &entity) const; public: //! @brief time (in millisecond) since last check std::chrono::time_point now; //! @inherit - void onFixedUpdate(WAL::ViewEntity &entities) override; + void onSelfUpdate() override; //! @brief A default constructor explicit MenuControllableSystem(WAL::Wal &wal); diff --git a/sources/System/Timer/TimerSystem.cpp b/sources/System/Timer/TimerSystem.cpp index f6c82c2b..3760534c 100644 --- a/sources/System/Timer/TimerSystem.cpp +++ b/sources/System/Timer/TimerSystem.cpp @@ -4,6 +4,7 @@ #include "TimerSystem.hpp" #include "Component/Timer/TimerComponent.hpp" +#include "Drawables/2D/Text.hpp" using namespace std::chrono_literals; diff --git a/sources/System/Timer/TimerSystem.hpp b/sources/System/Timer/TimerSystem.hpp index c7b20bc2..2be1c1f7 100644 --- a/sources/System/Timer/TimerSystem.hpp +++ b/sources/System/Timer/TimerSystem.hpp @@ -7,6 +7,7 @@ #include #include #include +#include "Component/Renderer/Drawable2DComponent.hpp" namespace BBM { diff --git a/sources/System/Timer/TimerUISystem.cpp b/sources/System/Timer/TimerUISystem.cpp new file mode 100644 index 00000000..a1f4cfa4 --- /dev/null +++ b/sources/System/Timer/TimerUISystem.cpp @@ -0,0 +1,30 @@ +// +// Created by Zoe Roux on 5/31/21. +// + +#include "TimerUISystem.hpp" +#include "Component/Timer/TimerComponent.hpp" +#include "Drawables/2D/Text.hpp" + +using namespace std::chrono_literals; +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + TimerUISystem::TimerUISystem(WAL::Wal &wal) + : System(wal) + {} + + void TimerUISystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &timer = entity.get(); + RAY2D::Text *text = dynamic_cast(entity.get().drawable.get()); + + if (text) { + unsigned long second = std::chrono::duration_cast(timer.ringIn).count(); + unsigned long minutes = second / 60; + second = second % 60; + text->setText(std::to_string(minutes) + ":" + std::to_string(second)); + } + } +} \ No newline at end of file diff --git a/sources/System/Timer/TimerUISystem.hpp b/sources/System/Timer/TimerUISystem.hpp new file mode 100644 index 00000000..c21a0300 --- /dev/null +++ b/sources/System/Timer/TimerUISystem.hpp @@ -0,0 +1,29 @@ +// +// Created by Zoe Roux on 5/31/21. +// + +#pragma once + +#include +#include +#include +#include "Component/Renderer/Drawable2DComponent.hpp" + +namespace BBM +{ + class TimerUISystem : public WAL::System + { + public: + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @brief A default constructor + TimerUISystem(WAL::Wal &); + //! @brief A timer system is copy constructable. + TimerUISystem(const TimerUISystem &) = default; + //! @brief A default destructor + ~TimerUISystem() override = default; + //! @breief A timer system is assignable. + TimerUISystem &operator=(const TimerUISystem &) = default; + }; +}