diff --git a/assets/buttons/cpu_add.png b/assets/buttons/cpu_add.png new file mode 100644 index 00000000..adf5167f Binary files /dev/null and b/assets/buttons/cpu_add.png differ diff --git a/assets/buttons/cpu_add_hovered.png b/assets/buttons/cpu_add_hovered.png new file mode 100644 index 00000000..51c828d9 Binary files /dev/null and b/assets/buttons/cpu_add_hovered.png differ diff --git a/assets/buttons/cpu_remove.png b/assets/buttons/cpu_remove.png new file mode 100644 index 00000000..cdec18dd Binary files /dev/null and b/assets/buttons/cpu_remove.png differ diff --git a/assets/buttons/cpu_remove_hovered.png b/assets/buttons/cpu_remove_hovered.png new file mode 100644 index 00000000..03d935bf Binary files /dev/null and b/assets/buttons/cpu_remove_hovered.png differ diff --git a/assets/player/icons/ai.png b/assets/player/icons/ai.png index ccd108e6..7e069b3e 100644 Binary files a/assets/player/icons/ai.png and b/assets/player/icons/ai.png differ diff --git a/lib/Ray/sources/Drawables/Texture.cpp b/lib/Ray/sources/Drawables/Texture.cpp index de774471..ee017382 100644 --- a/lib/Ray/sources/Drawables/Texture.cpp +++ b/lib/Ray/sources/Drawables/Texture.cpp @@ -58,4 +58,10 @@ namespace RAY { return; DrawTextureEx(*this, this->_position, this->_rotation, this->_scale, this->_color); } + + void Texture::unload() + { + this->_texture = nullptr; + this->_resourcePath = ""; + } } diff --git a/lib/Ray/sources/Drawables/Texture.hpp b/lib/Ray/sources/Drawables/Texture.hpp index e1a83aa1..fe7fe9f1 100644 --- a/lib/Ray/sources/Drawables/Texture.hpp +++ b/lib/Ray/sources/Drawables/Texture.hpp @@ -44,6 +44,9 @@ namespace RAY //! @brief Load texture from file, lets one use one entity for multiple files Texture &use(const std::string &filename); + //! @brief Unload the current texture (calls to drawOn will no-op). + void unload(); + //! @return path of loaded texture const std::string &getResourcePath() const; diff --git a/sources/Component/Controllable/ControllableComponent.hpp b/sources/Component/Controllable/ControllableComponent.hpp index e6c2c644..f16de468 100644 --- a/sources/Component/Controllable/ControllableComponent.hpp +++ b/sources/Component/Controllable/ControllableComponent.hpp @@ -25,13 +25,14 @@ namespace BBM GAMEPAD_0, GAMEPAD_1, GAMEPAD_2, - GAMEPAD_3 + GAMEPAD_3, + AI }; //! @brief The X and Z abscis of the movement. Vector2f move; - //! @brief input value for jump - bool jump = false; + //! @brief input value to select + bool select = false; //! @brief input value for bomb bool bomb = false; //! @brief input value for pause diff --git a/sources/Runner/GameScene.cpp b/sources/Runner/GameScene.cpp index 8a334361..af6de202 100644 --- a/sources/Runner/GameScene.cpp +++ b/sources/Runner/GameScene.cpp @@ -9,13 +9,11 @@ #include "Component/Position/PositionComponent.hpp" #include "Component/Animator/AnimatorComponent.hpp" #include "Component/Animation/AnimationsComponent.hpp" -#include #include "Component/Health/HealthComponent.hpp" #include "Component/Renderer/CameraComponent.hpp" #include "Component/Collision/CollisionComponent.hpp" #include "Component/Movable/MovableComponent.hpp" #include "Component/BombHolder/BombHolderComponent.hpp" -#include "Component/Shaders/ShaderComponent.hpp" #include "Component/Tag/TagComponent.hpp" #include "Component/Renderer/Drawable3DComponent.hpp" #include "Component/Renderer/Drawable2DComponent.hpp" @@ -46,7 +44,7 @@ namespace BBM scene->addEntity("background image") .addComponent(true, "assets/background_game.png", false) .addComponent(); - MapGenerator::loadMap(16, 16, MapGenerator::createMap(16, 16), scene); + MapGenerator::loadMap(16, 16, MapGenerator::createMap(16, 16, hasHeights), scene); return scene; } @@ -62,13 +60,11 @@ namespace BBM return scene.addEntity("player") .addComponent() .addComponent("assets/player/player.iqm", true) - //.addComponent(GenMeshSphere(1, 16, 16)) .addComponent() .addComponent() .addComponent() .addComponent() .addComponent() -// .addComponent("assets/shaders/glsl330/predator.fs") .addComponent>() .addComponent("assets/player/player.iqm", 3) .addComponent(BBM::Vector3f{0.25, 0, 0.25}, BBM::Vector3f{.75, 2, .75}) diff --git a/sources/Runner/LobbyScene.cpp b/sources/Runner/LobbyScene.cpp index 32dc6233..21711e12 100644 --- a/sources/Runner/LobbyScene.cpp +++ b/sources/Runner/LobbyScene.cpp @@ -44,94 +44,131 @@ namespace BBM .addComponent(1920 / 2.75, 100, 0) .addComponent(false, "Get Ready", 120, RAY::Vector2(), ORANGE); auto &play = scene->addEntity("play button") - .addComponent(1920 / 2.5, 1080 - 180, 0) - .addComponent(false, "assets/buttons/button_new_game.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - auto *texture = dynamic_cast(entity.getComponent().drawable.get()); - texture->use("assets/buttons/button_new_game.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - auto *texture = dynamic_cast(entity.getComponent().drawable.get()); - texture->use("assets/buttons/button_new_game_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - if (Runner::gameState.currentScene != GameState::LobbyScene - || !LobbySystem::playersAreReady(*wal.getScene())) - return; - LobbySystem::switchToGame(wal); - }) - .addComponent>(); + .addComponent(1920 / 2.5, 1080 - 180, 0) + .addComponent(false, "assets/buttons/button_new_game.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/button_new_game.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/button_new_game_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + if (Runner::gameState.currentScene != GameState::LobbyScene + || !LobbySystem::playersAreReady(*wal.getScene())) + return; + LobbySystem::switchToGame(wal); + }) + .addComponent>(); auto &back = scene->addEntity("back to menu") .addComponent(10, 1080 - 85, 0) .addComponent(false, "assets/buttons/button_back.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; - }) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; + wal.getSystem().unloadLobby(); + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + { + auto *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 &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); - texture->use("assets/buttons/button_back_hovered.png"); - }); + texture->use("assets/buttons/button_back_hovered.png"); + }); auto &lavaOption = scene->addEntity("lava option text") - .addComponent(1920 / 6, 2 * 1080 / 3, 0) + .addComponent(1920 / 6, 1.85 * 1080 / 3, 0) .addComponent(false, "Lava: Off", 70, RAY::Vector2(), BLACK) .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); + { + auto *text = dynamic_cast(entity.getComponent().drawable.get()); - if (text->getString().find("Off") != std::string::npos) { - text->setText("Lava: On"); - //do - } else { - text->setText("Lava: Off"); - //do - } - }) + if (text->getString().find("Off") != std::string::npos) { + text->setText("Lava: On"); + //do + } else { + text->setText("Lava: Off"); + //do + } + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) + { + entity.getComponent().drawable->setColor(BLACK); + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); + { + entity.getComponent().drawable->setColor(ORANGE); + }); auto &heightOption = scene->addEntity("Height option text") - .addComponent(1920 / 1.75, 2 * 1080 / 3, 0) + .addComponent(1920 / 6, 2.1 * 1080 / 3, 0) .addComponent(false, "2nd Level: Off", 70, RAY::Vector2(), BLACK) .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); + { + auto *text = dynamic_cast(entity.getComponent().drawable.get()); - if (text->getString().find("Off") != std::string::npos) { - text->setText("2nd Level: On"); - //do - } else { - text->setText("2nd Level: Off"); - //do - } - }) + if (text->getString().find("Off") != std::string::npos) { + text->setText("2nd Level: On"); + Runner::hasHeights = true; + } else { + text->setText("2nd Level: Off"); + Runner::hasHeights = false; + } + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) + { + entity.getComponent().drawable->setColor(BLACK); + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); + { + entity.getComponent().drawable->setColor(ORANGE); + }); + + auto &aiMore = scene->addEntity("AI+") + .addComponent(1920 / 1.75, 1.85 * 1080 / 3, 0) + .addComponent("assets/buttons/cpu_add.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + wal.getSystem().addAI(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_add.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_add_hovered.png"); + }); + + auto &aiLess = scene->addEntity("AI-") + .addComponent(1920 / 1.75, 2.10 * 1080 / 3, 0) + .addComponent("assets/buttons/cpu_remove.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + wal.getSystem().removeAI(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_remove.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_remove_hovered.png"); + }); for (int i = 0; i < 4; i++) { auto &playerTile = scene->addEntity("player tile") @@ -149,10 +186,12 @@ namespace BBM scene->addEntity("camera") .addComponent(8, 20, 7) .addComponent(Vector3f(8, 0, 8)); - play.getComponent().setButtonLinks(&lavaOption, &back, &back, nullptr); + play.getComponent().setButtonLinks(&heightOption, &back, &back, nullptr); back.getComponent().setButtonLinks(&play, nullptr, nullptr, &play); - lavaOption.getComponent().setButtonLinks(nullptr, &play, nullptr, &heightOption); - heightOption.getComponent().setButtonLinks(nullptr, &play, &lavaOption, nullptr); + lavaOption.getComponent().setButtonLinks(nullptr, &heightOption, nullptr, &aiMore); + heightOption.getComponent().setButtonLinks(&lavaOption, &play, nullptr, &aiLess); + aiMore.getComponent().setButtonLinks(nullptr, &aiLess, &lavaOption, nullptr); + aiLess.getComponent().setButtonLinks(&aiMore, &play, &heightOption, nullptr); return scene; } } \ No newline at end of file diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index 83f19e15..6ca48e55 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -44,6 +44,7 @@ namespace BBM { GameState Runner::gameState; + bool Runner::hasHeights = false; void Runner::updateState(WAL::Wal &engine, GameState &state) { @@ -55,7 +56,7 @@ namespace BBM if (component.pause && gameState.currentScene == GameState::SceneID::GameScene) { gameState.nextScene = GameState::SceneID::PauseMenuScene; break; - } else if (gameState.currentScene == GameState::SceneID::SplashScreen && component.jump) { + } else if (gameState.currentScene == GameState::SceneID::SplashScreen && component.select) { gameState.nextScene = GameState::SceneID::TitleScreenScene; break; } diff --git a/sources/Runner/Runner.hpp b/sources/Runner/Runner.hpp index e0dcee97..a0700ccd 100644 --- a/sources/Runner/Runner.hpp +++ b/sources/Runner/Runner.hpp @@ -9,9 +9,11 @@ namespace BBM { class Runner { - public: + public: + //! @brief Has the map heights or is it disabled? + static bool hasHeights; - //! @brief store current scenes informations + //! @brief store current scenes information static GameState gameState; //! @brief Start the game and run a Bomberman. //! @return 0 on success, another value on error. diff --git a/sources/System/Gamepad/GamepadSystem.cpp b/sources/System/Gamepad/GamepadSystem.cpp index 623d5edd..7ff78016 100644 --- a/sources/System/Gamepad/GamepadSystem.cpp +++ b/sources/System/Gamepad/GamepadSystem.cpp @@ -24,7 +24,7 @@ namespace BBM Gamepad gamepad(gamepadComponent.getID()); const std::map keyPressedMap = { - {gamepadComponent.keyJump, controllable.jump}, + {gamepadComponent.keyJump, controllable.select}, {gamepadComponent.keyBomb, controllable.bomb}, {gamepadComponent.keyPause, controllable.pause} }; diff --git a/sources/System/Keyboard/KeyboardSystem.cpp b/sources/System/Keyboard/KeyboardSystem.cpp index 334b757a..8dbda5ab 100644 --- a/sources/System/Keyboard/KeyboardSystem.cpp +++ b/sources/System/Keyboard/KeyboardSystem.cpp @@ -22,7 +22,7 @@ namespace BBM auto &controllable = entity.get(); const std::map keyPressedMap = { - {keyboard.keyJump, controllable.jump}, + {keyboard.keyJump, controllable.select}, {keyboard.keyBomb, controllable.bomb}, {keyboard.keyPause, controllable.pause} }; diff --git a/sources/System/Lobby/LobbySystem.cpp b/sources/System/Lobby/LobbySystem.cpp index 9c020625..6fcee4ac 100644 --- a/sources/System/Lobby/LobbySystem.cpp +++ b/sources/System/Lobby/LobbySystem.cpp @@ -67,7 +67,7 @@ namespace BBM if (lobby.layout == ControllableComponent::NONE) { for (auto &[_, ctrl] : this->_wal.getScene()->view()) { auto &controller = ctrl; - if (controller.jump) { + if (controller.select) { if (std::any_of(this->getView().begin(), this->getView().end(), [&controller](WAL::ViewEntity &view) { return view.get().layout == controller.layout; })) @@ -76,7 +76,7 @@ namespace BBM lobby.color = -1; this->_nextColor(entity); lobby.layout = controller.layout; - controller.jump = false; + controller.select = false; return; } } @@ -85,10 +85,10 @@ namespace BBM for (auto &[_, controller] : this->_wal.getScene()->view()) { if (controller.layout != lobby.layout) continue; - if (controller.jump && !lobby.ready) { + if (controller.select && !lobby.ready) { lobby.ready = true; lobby.lastInput = lastTick; - controller.jump = false; + controller.select = false; this->_wal.getSystem().now = lastTick; auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); if (texture) @@ -101,6 +101,47 @@ namespace BBM } } + void LobbySystem::addAI() + { + for (auto entity : this->getView()) { + auto &lobby = entity.get(); + if (lobby.layout != ControllableComponent::NONE) + continue; + lobby.color = -1; + this->_nextColor(entity); + lobby.layout = ControllableComponent::AI; + lobby.ready = true; + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->use("assets/player/icons/ai.png"); + return; + } + } + + void LobbySystem::removeAI() + { + std::optional> last; + for (auto &entity : this->getView()) { + auto &lobby = entity.get(); + if (lobby.layout == ControllableComponent::AI) + last.emplace(entity); + } + if (!last) + return; + auto &entity = *last; + auto &lobby = entity.get(); + auto &drawable = entity.get(); + this->_colorTaken[lobby.color] = false; + lobby.color = -1; + lobby.layout = ControllableComponent::NONE; + lobby.ready = false; + drawable.drawable = std::make_shared("assets/player/icons/none.png"); + lobby.coloredTile.getComponent().drawable->setColor(RAY::Color(0, 0, 0, 0)); + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->unload(); + } + void LobbySystem::onSelfUpdate() { auto &view = this->_wal.getScene()->view, Drawable2DComponent>(); @@ -143,6 +184,9 @@ namespace BBM case ControllableComponent::GAMEPAD_3: player.addComponent(3); break; + case ControllableComponent::AI: +// throw std::runtime_error("Not implemented error"); + break; default: throw std::runtime_error("Invalid controller for a player."); } @@ -162,12 +206,28 @@ namespace BBM _addController(player, lobby.layout); player.getComponent().position = Vector3f(mapWidth * (playerCount % 2), 0, - mapHeight * ((playerCount + 1) % 2)); + mapHeight * (!(playerCount % 3))); auto *model = dynamic_cast(player.getComponent().drawable.get()); model->setTextureToMaterial(MAP_DIFFUSE, "assets/player/textures/" + _colors[lobby.color] + ".png"); playerCount++; } Runner::gameState._loadedScenes[GameState::SceneID::GameScene] = scene; Runner::gameState.nextScene = BBM::GameState::SceneID::GameScene; + wal.getSystem().unloadLobby(); + } + + void LobbySystem::unloadLobby() + { + this->_colorTaken.fill(false); + for (auto &[_, lobby, drawable] : this->getView()) { + lobby.layout = ControllableComponent::NONE; + lobby.ready = false; + lobby.color = -1; + drawable.drawable = std::make_shared("assets/player/icons/none.png"); + lobby.coloredTile.getComponent().drawable->setColor(RAY::Color(0, 0, 0, 0)); + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->unload(); + } } } \ No newline at end of file diff --git a/sources/System/Lobby/LobbySystem.hpp b/sources/System/Lobby/LobbySystem.hpp index b0a91bb3..2cbf0258 100644 --- a/sources/System/Lobby/LobbySystem.hpp +++ b/sources/System/Lobby/LobbySystem.hpp @@ -42,6 +42,15 @@ namespace BBM //! @param wal The engine. static void switchToGame(WAL::Wal &wal); + //! @brief Reset the lobby scene to it's default state. + void unloadLobby(); + + //! @brief Add an AI to the game. + void addAI(); + + //! @brief Remove an AI from the game. + void removeAI(); + //! @brief A default constructor explicit LobbySystem(WAL::Wal &wal); //! @brief A Lobby system is copy constructable diff --git a/sources/System/MenuControllable/MenuControllableSystem.cpp b/sources/System/MenuControllable/MenuControllableSystem.cpp index 6dcc95e3..d70ae7bc 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.cpp +++ b/sources/System/MenuControllable/MenuControllableSystem.cpp @@ -60,6 +60,6 @@ namespace BBM } if (!this->_currentButton) return; - this->_updateCurrentButton(controllable.jump, controllable.move); + this->_updateCurrentButton(controllable.select, controllable.move); } } \ No newline at end of file diff --git a/sources/System/Sound/MenuSoundManagerSystem.cpp b/sources/System/Sound/MenuSoundManagerSystem.cpp index c1261f32..7f3e57e4 100644 --- a/sources/System/Sound/MenuSoundManagerSystem.cpp +++ b/sources/System/Sound/MenuSoundManagerSystem.cpp @@ -20,7 +20,7 @@ namespace BBM { std::map soundIndex = { {controllable.move.x, SoundComponent::MOVE}, {controllable.move.y, SoundComponent::MOVE}, - {controllable.jump, SoundComponent::JUMP}, + {controllable.select, SoundComponent::JUMP}, }; for (auto &a : soundIndex) { if (a.first) { diff --git a/sources/System/Sound/PlayerSoundManagerSystem.cpp b/sources/System/Sound/PlayerSoundManagerSystem.cpp index dac45304..4068a5e3 100644 --- a/sources/System/Sound/PlayerSoundManagerSystem.cpp +++ b/sources/System/Sound/PlayerSoundManagerSystem.cpp @@ -19,9 +19,9 @@ namespace BBM { sound.setVolume(sound.volume); std::map soundIndex = { - {health.getHealthPoint() <= 0, SoundComponent::DEATH}, - {controllable.bomb, SoundComponent::BOMB}, - {controllable.jump, SoundComponent::JUMP}, + {health.getHealthPoint() <= 0, SoundComponent::DEATH}, + {controllable.bomb, SoundComponent::BOMB}, + {controllable.select, SoundComponent::JUMP}, {controllable.move.x != 0 || controllable.move.y != 0, SoundComponent::MOVE} }; for (auto &a : soundIndex) {