diff --git a/CMakeLists.txt b/CMakeLists.txt index 64299c95..5cc80c6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,10 @@ set(SOURCES sources/System/Sound/PlayerSoundManagerSystem.hpp sources/System/Music/MusicSystem.hpp sources/System/Music/MusicSystem.cpp + sources/System/Lobby/LobbySystem.cpp + sources/System/Lobby/LobbySystem.hpp + sources/Component/Lobby/LobbyComponent.cpp + sources/Component/Lobby/LobbyComponent.hpp sources/Component/Gravity/GravityComponent.hpp sources/Component/Gravity/GravityComponent.cpp sources/System/Gravity/GravitySystem.hpp @@ -130,6 +134,7 @@ set(SOURCES sources/Runner/PauseMenuScene.cpp sources/Runner/SettingsMenuScene.cpp sources/Runner/CreditScene.cpp + sources/Runner/LobbyScene.cpp ) add_executable(bomberman sources/main.cpp diff --git a/assets/player/icons/ai.png b/assets/player/icons/ai.png new file mode 100644 index 00000000..ccd108e6 Binary files /dev/null and b/assets/player/icons/ai.png differ diff --git a/assets/player/icons/blue.png b/assets/player/icons/blue.png new file mode 100644 index 00000000..eb9ce70c Binary files /dev/null and b/assets/player/icons/blue.png differ diff --git a/assets/player/icons/green.png b/assets/player/icons/green.png new file mode 100644 index 00000000..f8b9032d Binary files /dev/null and b/assets/player/icons/green.png differ diff --git a/assets/player/icons/none.png b/assets/player/icons/none.png new file mode 100644 index 00000000..90adb3c0 Binary files /dev/null and b/assets/player/icons/none.png differ diff --git a/assets/player/icons/ready.png b/assets/player/icons/ready.png new file mode 100644 index 00000000..1c2f6327 Binary files /dev/null and b/assets/player/icons/ready.png differ diff --git a/assets/player/icons/red.png b/assets/player/icons/red.png new file mode 100644 index 00000000..7fc80d11 Binary files /dev/null and b/assets/player/icons/red.png differ diff --git a/assets/player/icons/yellow.png b/assets/player/icons/yellow.png new file mode 100644 index 00000000..f6a83fd0 Binary files /dev/null and b/assets/player/icons/yellow.png differ diff --git a/assets/player/blue.png b/assets/player/textures/blue.png similarity index 100% rename from assets/player/blue.png rename to assets/player/textures/blue.png diff --git a/assets/player/cyan.png b/assets/player/textures/cyan.png similarity index 100% rename from assets/player/cyan.png rename to assets/player/textures/cyan.png diff --git a/assets/player/green.png b/assets/player/textures/green.png similarity index 100% rename from assets/player/green.png rename to assets/player/textures/green.png diff --git a/assets/player/purple.png b/assets/player/textures/purple.png similarity index 100% rename from assets/player/purple.png rename to assets/player/textures/purple.png diff --git a/assets/player/red.png b/assets/player/textures/red.png similarity index 100% rename from assets/player/red.png rename to assets/player/textures/red.png diff --git a/assets/player/yellow.png b/assets/player/textures/yellow.png similarity index 100% rename from assets/player/yellow.png rename to assets/player/textures/yellow.png diff --git a/lib/Ray/sources/Drawables/2D/Rectangle.hpp b/lib/Ray/sources/Drawables/2D/Rectangle.hpp index 6442a7f1..1a829ea2 100644 --- a/lib/Ray/sources/Drawables/2D/Rectangle.hpp +++ b/lib/Ray/sources/Drawables/2D/Rectangle.hpp @@ -29,7 +29,7 @@ namespace RAY::Drawables::Drawables2D { //! @param length length of the rectangle //! @param Color Color of the rectangle Rectangle(int x, int y, int width, int height, const Color &color = WHITE); - + //! @brief A default copy constructor Rectangle(const Rectangle &) = default; @@ -37,7 +37,7 @@ namespace RAY::Drawables::Drawables2D { Rectangle &operator=(const Rectangle &) = default; //! @brief A default destructor - virtual ~Rectangle() override = default; + ~Rectangle() override = default; //! @return the dimensions of the rectangle const Vector2 &getDimensions(void); diff --git a/lib/Ray/sources/Drawables/Texture.cpp b/lib/Ray/sources/Drawables/Texture.cpp index dfdf1213..7a70a459 100644 --- a/lib/Ray/sources/Drawables/Texture.cpp +++ b/lib/Ray/sources/Drawables/Texture.cpp @@ -11,7 +11,11 @@ namespace RAY { - Cache<::Texture> Texture::_texturesCache(LoadTexture, UnloadTexture); + Cache<::Texture> Texture::_texturesCache(LoadTexture, UnloadTexture); + + Texture::Texture() + : Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE) + {} Texture::Texture(const std::string &filename, bool lonely): Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE), @@ -34,6 +38,7 @@ namespace RAY { return *this; this->_texture = this->_texturesCache.fetch(filename); this->_resourcePath = filename; + this->_dimensions = Vector2(this->_texture->width, this->_texture->height); return *this; } @@ -44,6 +49,9 @@ namespace RAY { void Texture::drawOn(RAY::Window &) { + if (!this->_texture) + return; + float scale = this->_dimensions.x / this->_texture->width; DrawTextureEx(*this, this->_position, 0, scale, this->_color); diff --git a/lib/Ray/sources/Drawables/Texture.hpp b/lib/Ray/sources/Drawables/Texture.hpp index 931699e2..74eab4c8 100644 --- a/lib/Ray/sources/Drawables/Texture.hpp +++ b/lib/Ray/sources/Drawables/Texture.hpp @@ -21,7 +21,10 @@ namespace RAY //! @brief Create an texture, loading a file //! @param filename: path to file to load //! @param lonely: should be set to true if the entity's loaded data must be independant from others - Texture(const std::string &filename, bool lonely = false); + explicit Texture(const std::string &filename, bool lonely = false); + + //! @brief Create an empty texture + Texture(); //! @brief A texture is copy constructable Texture(const Texture &) = default; @@ -33,7 +36,7 @@ namespace RAY Texture &operator=(const Texture &) = default; //! @brief Texture destructor, will not unload ressources - ~Texture() = default; + ~Texture() override = default; //! @brief draw texture on a window void drawOn(RAY::Window &) override; diff --git a/lib/Ray/sources/Model/ModelAnimation.cpp b/lib/Ray/sources/Model/ModelAnimation.cpp index 8569c6dd..af20acb7 100644 --- a/lib/Ray/sources/Model/ModelAnimation.cpp +++ b/lib/Ray/sources/Model/ModelAnimation.cpp @@ -5,9 +5,10 @@ ** ModelAnimation */ +#include #include "Model/ModelAnimation.hpp" -RAY::ModelAnimation::ModelAnimation(::ModelAnimation &animation): +RAY::ModelAnimation::ModelAnimation(::ModelAnimation animation): _animation(animation), _frameCounter(0) { } @@ -38,9 +39,4 @@ RAY::ModelAnimation &RAY::ModelAnimation::incrementFrameCounter() RAY::ModelAnimation::operator ::ModelAnimation() const { return this->_animation; -} - -RAY::ModelAnimation::operator ::ModelAnimation *() -{ - return &this->_animation; } \ No newline at end of file diff --git a/lib/Ray/sources/Model/ModelAnimation.hpp b/lib/Ray/sources/Model/ModelAnimation.hpp index 308599ba..1fa32ec1 100644 --- a/lib/Ray/sources/Model/ModelAnimation.hpp +++ b/lib/Ray/sources/Model/ModelAnimation.hpp @@ -17,7 +17,7 @@ namespace RAY { public: //! @brief A Model animation constructor //! @param animationPtr an animation pointer, returned by the nimation-loading function - ModelAnimation(::ModelAnimation &animationPtr); + explicit ModelAnimation(::ModelAnimation animation); //! @brief A default copy-constructor ModelAnimation(const ModelAnimation &) = default; @@ -41,13 +41,10 @@ namespace RAY { ~ModelAnimation() = default; private: - ::ModelAnimation &_animation; + ::ModelAnimation _animation; size_t _frameCounter; INTERNAL: - //! @brief Castin Object to raw model animation pointer - operator ::ModelAnimation *(); - //! @brief Castin Object to raw model animation pointer operator ::ModelAnimation() const; }; diff --git a/lib/Ray/sources/Model/ModelAnimations.hpp b/lib/Ray/sources/Model/ModelAnimations.hpp index 2b99e1d7..5b7508eb 100644 --- a/lib/Ray/sources/Model/ModelAnimations.hpp +++ b/lib/Ray/sources/Model/ModelAnimations.hpp @@ -19,7 +19,7 @@ namespace RAY { public: //! @brief A Model animation constructor //! @param filePath Path to the file containing animations - ModelAnimations(const std::string &filePath); + explicit ModelAnimations(const std::string &filePath); //! @brief default copy ctor ModelAnimations(const ModelAnimations &) = default; @@ -59,7 +59,7 @@ namespace RAY { int _animationCount; //! @brief The file where the animations were loaded (used to create a copy of this class) - const std::string _filePath; + std::string _filePath; static Cache<::ModelAnimation> _animationsCache; }; diff --git a/lib/Ray/sources/Utils/Cache.hpp b/lib/Ray/sources/Utils/Cache.hpp index 73e6a8b6..beb1ff89 100644 --- a/lib/Ray/sources/Utils/Cache.hpp +++ b/lib/Ray/sources/Utils/Cache.hpp @@ -73,24 +73,6 @@ namespace RAY { template<> class Cache<::ModelAnimation> { - public: - Cache(std::function<::ModelAnimation *(const char *, int *)> dataLoader, std::functiondataUnloader): - _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) - {}; - std::shared_ptr<::ModelAnimation> fetch(const std::string &path, int *counter) - { - if (this->_cache.find(path) != this->_cache.end()) - return this->_cache[path]; - - ::ModelAnimation *animations = this->_dataLoader(path.c_str(), counter); - unsigned int animCount = *counter; - - this->_cache.emplace(path, std::shared_ptr<::ModelAnimation>( - animations, [this, animCount](::ModelAnimation *p) { - this->_dataUnloader(p, animCount); - })); - return this->_cache[path]; - }; private: //! @brief function to call to load data std::function<::ModelAnimation *(const char *, int *)> _dataLoader; @@ -98,10 +80,34 @@ namespace RAY { //! @brief function to call when the ray data will be unloaded std::function _dataUnloader; - //! @brief map storing shared ptr of caches - std::unordered_map> _cache; - }; + typedef struct { + std::shared_ptr<::ModelAnimation> animations; + int animationsCount; + } AnimationsHolder; + //! @brief map storing shared ptr of caches + std::unordered_map _cache; + public: + Cache(std::function<::ModelAnimation *(const char *, int *)> dataLoader, std::functiondataUnloader): + _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) + {}; + std::shared_ptr<::ModelAnimation> fetch(const std::string &path, int *counter) + { + if (this->_cache.find(path) != this->_cache.end()) { + *counter = this->_cache[path].animationsCount; + } else { + ::ModelAnimation *animations = this->_dataLoader(path.c_str(), counter); + int animCount = *counter; + AnimationsHolder holder = {std::shared_ptr<::ModelAnimation>( + animations, [this, animCount](::ModelAnimation *p) { + this->_dataUnloader(p, animCount); + }),animCount}; + + this->_cache.emplace(path, holder); + } + return this->_cache[path].animations; + }; + }; template<> class Cache<::Shader> { diff --git a/lib/wal/sources/Scene/Scene.hpp b/lib/wal/sources/Scene/Scene.hpp index e0aad880..dd786d73 100644 --- a/lib/wal/sources/Scene/Scene.hpp +++ b/lib/wal/sources/Scene/Scene.hpp @@ -74,13 +74,12 @@ namespace WAL //! @brief A default constructor Scene() = default; - //! @brief A scene is copy constructable - Scene(const Scene &) = default; + //! @brief A scene is not copy constructable + Scene(const Scene &) = delete; //! @brief A default destructor ~Scene() = default; //! @brief A scene is assignable Scene &operator=(const Scene &); - Scene(Scene &&) = default; friend Entity; }; diff --git a/lib/wal/sources/View/View.hpp b/lib/wal/sources/View/View.hpp index 50726a82..68b82fd7 100644 --- a/lib/wal/sources/View/View.hpp +++ b/lib/wal/sources/View/View.hpp @@ -61,14 +61,20 @@ namespace WAL std::optional> _entity; public: - ViewEntity &operator*() + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = ViewEntity; + using pointer = value_type *; + using reference = value_type &; + + reference operator*() { if (!this->_entity) this->_entity.emplace(*this->_it); return *this->_entity; } - ViewEntity *operator->() + pointer operator->() { if (!this->_entity) this->_entity =(*this->_it); diff --git a/sources/Component/Animation/AnimationsComponent.cpp b/sources/Component/Animation/AnimationsComponent.cpp index 4461cc8e..26367a0b 100644 --- a/sources/Component/Animation/AnimationsComponent.cpp +++ b/sources/Component/Animation/AnimationsComponent.cpp @@ -8,9 +8,9 @@ namespace BBM { - AnimationsComponent::AnimationsComponent(WAL::Entity &entity, RAY::ModelAnimations modelAnimation, int animIndex, bool play) + AnimationsComponent::AnimationsComponent(WAL::Entity &entity, const std::string &path, int animIndex, bool play) : WAL::Component(entity), - _modelAnimation(std::move(modelAnimation)), + _modelAnimation(path), _currentAnimIndex(animIndex), _animDisabled(play) { @@ -20,7 +20,7 @@ namespace BBM WAL::Component *AnimationsComponent::clone(WAL::Entity &entity) const { return new AnimationsComponent(entity, - RAY::ModelAnimations(this->_modelAnimation.getFilePath()), + this->_modelAnimation.getFilePath(), this->_currentAnimIndex); } diff --git a/sources/Component/Animation/AnimationsComponent.hpp b/sources/Component/Animation/AnimationsComponent.hpp index 463f241f..36f22a6a 100644 --- a/sources/Component/Animation/AnimationsComponent.hpp +++ b/sources/Component/Animation/AnimationsComponent.hpp @@ -52,7 +52,7 @@ namespace BBM bool isAnimDisabled() const; //! @brief ctor entity and the path of the animation file - explicit AnimationsComponent(WAL::Entity &entity, RAY::ModelAnimations modelAnimation, int animIndex, bool play = true); + explicit AnimationsComponent(WAL::Entity &entity, const std::string &path, int animIndex, bool play = true); //! @brief copy ctor AnimationsComponent(const AnimationsComponent &) = default; //! @brief dtor diff --git a/sources/Component/Controllable/ControllableComponent.hpp b/sources/Component/Controllable/ControllableComponent.hpp index 2d62a8e8..e6c2c644 100644 --- a/sources/Component/Controllable/ControllableComponent.hpp +++ b/sources/Component/Controllable/ControllableComponent.hpp @@ -17,6 +17,17 @@ namespace BBM class ControllableComponent : public WAL::Component { public: + enum Layout + { + NONE, + KEYBOARD_0, + KEYBOARD_1, + GAMEPAD_0, + GAMEPAD_1, + GAMEPAD_2, + GAMEPAD_3 + }; + //! @brief The X and Z abscis of the movement. Vector2f move; //! @brief input value for jump @@ -27,6 +38,8 @@ namespace BBM bool pause = false; //! @brief The speed applied to every controllable entities. float speed = .15f; + //! @brief The layout used for this controllable. + Layout layout = NONE; //! @inherit WAL::Component *clone(WAL::Entity &entity) const override; diff --git a/sources/Component/Gamepad/GamepadComponent.cpp b/sources/Component/Gamepad/GamepadComponent.cpp index 0b889b7a..ff48b9e4 100644 --- a/sources/Component/Gamepad/GamepadComponent.cpp +++ b/sources/Component/Gamepad/GamepadComponent.cpp @@ -3,6 +3,7 @@ // Edited by Benjamin Henry on 2021-05-20. // +#include #include "GamepadComponent.hpp" namespace BBM @@ -31,4 +32,27 @@ namespace BBM return this->_ID; } + void GamepadComponent::onStart() + { + auto *controller = this->_entity.tryGetComponent(); + if (!controller) + return; + switch (this->_ID) { + case 0: + controller->layout = ControllableComponent::GAMEPAD_0; + break; + case 1: + controller->layout = ControllableComponent::GAMEPAD_1; + break; + case 2: + controller->layout = ControllableComponent::GAMEPAD_2; + break; + case 3: + controller->layout = ControllableComponent::GAMEPAD_3; + break; + default: + return; + } + } + } // namespace BMM diff --git a/sources/Component/Gamepad/GamepadComponent.hpp b/sources/Component/Gamepad/GamepadComponent.hpp index 3825645d..696926ce 100644 --- a/sources/Component/Gamepad/GamepadComponent.hpp +++ b/sources/Component/Gamepad/GamepadComponent.hpp @@ -44,6 +44,8 @@ namespace BBM //! @inherit WAL::Component *clone(WAL::Entity &entity) const override; + void onStart() override; + //! @brief Create a new gampad component using default keys. explicit GamepadComponent(WAL::Entity &entity); diff --git a/sources/Component/Keyboard/KeyboardComponent.cpp b/sources/Component/Keyboard/KeyboardComponent.cpp index b23ac18e..ba5f6f8f 100644 --- a/sources/Component/Keyboard/KeyboardComponent.cpp +++ b/sources/Component/Keyboard/KeyboardComponent.cpp @@ -3,25 +3,44 @@ // Edited by Benjamin Henry on 2021-05-20. // +#include #include "KeyboardComponent.hpp" namespace BBM { - KeyboardComponent::KeyboardComponent(WAL::Entity &entity, - Key up, - Key down, - Key left, - Key right, - Key jump, - Key bomb, - Key pause) - : WAL::Component(entity), keyJump(jump), keyBomb(bomb), keyPause(pause), - keyRight(right), keyLeft(left), keyUp(up), keyDown(down) - {} + KeyboardComponent::KeyboardComponent(WAL::Entity &entity, ControllableComponent::Layout layout) + : WAL::Component(entity), layout(layout) + { + if (layout == ControllableComponent::KEYBOARD_0) { + this->keyUp = KEY_W; + this->keyDown = KEY_S; + this->keyLeft = KEY_A; + this->keyRight = KEY_D; + this->keyJump = KEY_SPACE; + this->keyBomb = KEY_E; + this->keyPause = KEY_ESCAPE; + } else { + this->keyUp = KEY_UP; + this->keyDown = KEY_DOWN; + this->keyLeft = KEY_LEFT; + this->keyRight = KEY_RIGHT; + this->keyJump = KEY_RIGHT_CONTROL; + this->keyBomb = KEY_ENTER; + this->keyPause = KEY_BACKSPACE; + } + } WAL::Component *KeyboardComponent::clone(WAL::Entity &entity) const { - return new KeyboardComponent(entity); + return new KeyboardComponent(entity, this->layout); + } + + void KeyboardComponent::onStart() + { + auto *controller = this->_entity.tryGetComponent(); + if (!controller) + return; + controller->layout = this->layout; } } // namespace BMM diff --git a/sources/Component/Keyboard/KeyboardComponent.hpp b/sources/Component/Keyboard/KeyboardComponent.hpp index b461f215..eebe85e1 100644 --- a/sources/Component/Keyboard/KeyboardComponent.hpp +++ b/sources/Component/Keyboard/KeyboardComponent.hpp @@ -7,6 +7,7 @@ #include #include "Component/Component.hpp" +#include "Component/Controllable/ControllableComponent.hpp" #include "Entity/Entity.hpp" using Key = RAY::Controller::Keyboard::Key; @@ -30,19 +31,16 @@ namespace BBM Key keyUp = KEY_W; //! @brief move down key Key keyDown = KEY_S; + //! @brief Layout + ControllableComponent::Layout layout; //! @inherit WAL::Component *clone(WAL::Entity &entity) const override; + void onStart() override; + //! @brief Create a new keyboard component using custom keys. - explicit KeyboardComponent(WAL::Entity &entity, - Key up = KEY_W, - Key down = KEY_S, - Key left = KEY_A, - Key right = KEY_D, - Key jump = KEY_SPACE, - Key bomb = KEY_E, - Key pause = KEY_ESCAPE); + explicit KeyboardComponent(WAL::Entity &entity, ControllableComponent::Layout layout = ControllableComponent::Layout::KEYBOARD_0); //! @brief A Keyboard component is copy constructable. KeyboardComponent(const KeyboardComponent &) = default; diff --git a/sources/Component/Lobby/LobbyComponent.cpp b/sources/Component/Lobby/LobbyComponent.cpp new file mode 100644 index 00000000..a945f112 --- /dev/null +++ b/sources/Component/Lobby/LobbyComponent.cpp @@ -0,0 +1,20 @@ +// +// Created by Zoe Roux on 6/11/21. +// + +#include "LobbyComponent.hpp" + +namespace BBM +{ + LobbyComponent::LobbyComponent(WAL::Entity &entity, int playerID, WAL::Entity &readyButton, WAL::Entity &coloredTile) + : WAL::Component(entity), + playerID(playerID), + readyButton(readyButton), + coloredTile(coloredTile) + {} + + WAL::Component *LobbyComponent::clone(WAL::Entity &entity) const + { + return new LobbyComponent(entity, this->playerID, this->readyButton, this->coloredTile); + } +} \ No newline at end of file diff --git a/sources/Component/Lobby/LobbyComponent.hpp b/sources/Component/Lobby/LobbyComponent.hpp new file mode 100644 index 00000000..4061d1ce --- /dev/null +++ b/sources/Component/Lobby/LobbyComponent.hpp @@ -0,0 +1,44 @@ +// +// Created by Zoe Roux on 6/11/21. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace BBM +{ + class LobbyComponent : public WAL::Component + { + public: + //! @brief The layout used for this player. + ControllableComponent::Layout layout = ControllableComponent::NONE; + //! @brief The ID of the lobby player (from 0 to 3) + int playerID; + //! @brief The color of the player (as an index) + int color; + //! @brief Is this player ready + bool ready = false; + //! @brief The entity containing the ready display. + WAL::Entity &readyButton; + //! @brief The colored rectangle behind the player. + WAL::Entity &coloredTile; + //! @brief The time of last input that this lobby player has made. + std::chrono::time_point lastInput; + + Component *clone(WAL::Entity &entity) const override; + + //! @brief Create a new lobby component. + explicit LobbyComponent(WAL::Entity &entity, int playerID, WAL::Entity &readyButton, WAL::Entity &coloredTile); + //! @brief A lobby component is copyable. + LobbyComponent(const LobbyComponent &) = default; + //! @brief A default destructor + ~LobbyComponent() override = default; + //! @brief A lobby component is not assignable. + LobbyComponent &operator=(const LobbyComponent &) = delete; + }; +} diff --git a/sources/Component/Tag/TagComponent.hpp b/sources/Component/Tag/TagComponent.hpp index 00fa27d5..c4b3b9c1 100644 --- a/sources/Component/Tag/TagComponent.hpp +++ b/sources/Component/Tag/TagComponent.hpp @@ -50,5 +50,8 @@ namespace BBM TagComponent &operator=(const TagComponent &) = delete; }; + // interact with bombs & stop the explosion constexpr const char Blowable[] = "Blowable"; + // interact with bombs (getting damage etc) but doesn't stop explosion + constexpr const char BlowablePass[] = "BlowablePass"; } diff --git a/sources/Map/Map.cpp b/sources/Map/Map.cpp index e2e3b5de..2128c39c 100644 --- a/sources/Map/Map.cpp +++ b/sources/Map/Map.cpp @@ -101,7 +101,7 @@ namespace BBM return; wal.getScene()->scheduleNewEntity("Bonus") .addComponent(position) - .addComponent>() + .addComponent>() .addComponent() .addComponent(1, [](WAL::Entity &entity, WAL::Wal &wal) { entity.scheduleDeletion(); diff --git a/sources/Runner/CreditScene.cpp b/sources/Runner/CreditScene.cpp index 38c9b77e..d87e47be 100644 --- a/sources/Runner/CreditScene.cpp +++ b/sources/Runner/CreditScene.cpp @@ -23,13 +23,12 @@ namespace BBM {SoundComponent::JUMP, "assets/sounds/click.ogg"} }; + addMenuControl(*scene); scene->addEntity("background") .addComponent() .addComponent("assets/plain_menu_background.png"); scene->addEntity("Control entity") - .addComponent() - .addComponent() .addComponent("assets/musics/music_title.ogg") .addComponent(sounds); diff --git a/sources/Runner/GameScene.cpp b/sources/Runner/GameScene.cpp index 7668a043..50242df1 100644 --- a/sources/Runner/GameScene.cpp +++ b/sources/Runner/GameScene.cpp @@ -2,11 +2,11 @@ #include #include "Runner.hpp" #include +#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/Animator/AnimatorComponent.hpp" #include "Component/Animation/AnimationsComponent.hpp" #include "Component/Health/HealthComponent.hpp" @@ -14,7 +14,6 @@ #include "Component/Collision/CollisionComponent.hpp" #include "Component/Movable/MovableComponent.hpp" #include "Component/BombHolder/BombHolderComponent.hpp" -#include "Component/Bonus/PlayerBonusComponent.hpp" #include "Component/Shaders/ShaderComponent.hpp" #include "Component/Tag/TagComponent.hpp" #include "Component/Renderer/Drawable3DComponent.hpp" @@ -29,45 +28,44 @@ namespace RAY3D = RAY::Drawables::Drawables3D; namespace BBM { - std::shared_ptr Runner::loadGameScene() + std::shared_ptr Runner::loadGameScene() { auto scene = std::make_shared(); - scene->addEntity("control") - .addComponent() - .addComponent(); + scene->addEntity("camera") + .addComponent(8, 20, 7) + .addComponent(Vector3f(8, 0, 8)); + MapGenerator::loadMap(16, 16, MapGenerator::createMap(16, 16), scene); + return scene; + } + + WAL::Entity &Runner::createPlayer(WAL::Scene &scene) + { std::map soundPath ={ - {SoundComponent::JUMP, "assets/sounds/jump.wav"}, - {SoundComponent::MOVE, "assets/sounds/move.ogg"}, - {SoundComponent::BOMB, "assets/sounds/bomb_drop.ogg"}, - //{SoundComponent::DEATH, "assets/sounds/death.ogg"} + {SoundComponent::JUMP, "assets/sounds/jump.wav"}, + {SoundComponent::MOVE, "assets/sounds/move.ogg"}, + {SoundComponent::BOMB, "assets/sounds/bomb_drop.ogg"}, + //{SoundComponent::DEATH, "assets/sounds/death.ogg"} }; - scene->addEntity("player") - .addComponent(0, 1.01, 0) - .addComponent("assets/player/player.iqm", true, std::make_pair(MAP_DIFFUSE, "assets/player/blue.png")) + + return scene.addEntity("player") + .addComponent() + .addComponent("assets/player/player.iqm", true) .addComponent() .addComponent() .addComponent() .addComponent() - .addComponent() - .addComponent("assets/shaders/glsl330/predator.fs") - .addComponent>() - //.addComponent(0) - .addComponent(RAY::ModelAnimations("assets/player/player.iqm"), 3) +// .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}) .addComponent() .addComponent(soundPath) .addComponent("assets/musics/music_battle.ogg") .addComponent() .addComponent() - .addComponent(1, [](WAL::Entity &entity, WAL::Wal &wal) { + .addComponent(1, [](WAL::Entity &entity, WAL::Wal &) { auto &animation = entity.getComponent(); animation.setAnimIndex(5); }); - scene->addEntity("camera") - .addComponent(8, 20, 7) - .addComponent(Vector3f(8, 0, 8)); - MapGenerator::loadMap(16, 16, MapGenerator::createMap(16, 16), scene); - - return scene; } } \ No newline at end of file diff --git a/sources/Runner/LobbyScene.cpp b/sources/Runner/LobbyScene.cpp new file mode 100644 index 00000000..54e45191 --- /dev/null +++ b/sources/Runner/LobbyScene.cpp @@ -0,0 +1,157 @@ +// +// Created by Zoe Roux on 2021-06-14. +// + +#include +#include "System/Movable/MovableSystem.hpp" +#include +#include +#include +#include +#include "Component/Button/ButtonComponent.hpp" +#include "Component/Renderer/CameraComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Runner.hpp" +#include "Models/GameState.hpp" +#include +#include +#include +#include "System/Sound/PlayerSoundManagerSystem.hpp" +#include "System/Music/MusicSystem.hpp" +#include "System/Lobby/LobbySystem.hpp" +#include "Component/Lobby/LobbyComponent.hpp" + +namespace RAY3D = RAY::Drawables::Drawables3D; +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + std::shared_ptr Runner::loadLobbyScene() + { + static const std::map sounds = { + {SoundComponent::JUMP, "assets/sounds/click.ogg"} + }; + auto scene = std::make_shared(); + + 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("lobby text") + .addComponent(1920 / 2.75, 100, 0) + .addComponent("Get Ready", 120, RAY::Vector2(), ORANGE); + auto &play = scene->addEntity("play button") + .addComponent(1920 / 2.5, 1080 - 180, 0) + .addComponent("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("assets/buttons/button_back.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; + }) + .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"); + }); + auto &lavaOption = scene->addEntity("lava option text") + .addComponent(1920 / 6, 2 * 1080 / 3, 0) + .addComponent("Lava: Off", 70, RAY::Vector2(), BLACK) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + RAY2D::Text *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 + } + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(BLACK); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(ORANGE); + }); + + auto &heightOption = scene->addEntity("Height option text") + .addComponent(1920 / 1.75, 2 * 1080 / 3, 0) + .addComponent("2nd Level: Off", 70, RAY::Vector2(), BLACK) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + RAY2D::Text *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 + } + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(BLACK); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(ORANGE); + }); + + for (int i = 0; i < 4; i++) { + auto &playerTile = scene->addEntity("player tile") + .addComponent(224 * (i + 1) + 200 * i, 1080 / 3, 0) + .addComponent(RAY::Vector2(224 * (i + 1) + 200 * i, 1080 / 3), RAY::Vector2(200, 200), RAY::Color(0, 0, 0, 0)); + auto &player = scene->addEntity("player") + .addComponent(224 * (i + 1) + 200 * i, 1080 / 3, 0) + .addComponent("assets/player/icons/none.png"); + auto &ready = scene->addEntity("ready") + .addComponent(224 * (i + 1) + 200 * i, 1080 / 3, 0) + .addComponent(); + player.addComponent(i, ready, playerTile); + } + scene->addEntity("camera") + .addComponent(8, 20, 7) + .addComponent(Vector3f(8, 0, 8)); + play.getComponent().setButtonLinks(&lavaOption, &back, &back, nullptr); + back.getComponent().setButtonLinks(&play, nullptr, nullptr, &play); + lavaOption.getComponent().setButtonLinks(nullptr, &play, nullptr, &heightOption); + heightOption.getComponent().setButtonLinks(nullptr, &play, &lavaOption, nullptr); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/MainMenuScene.cpp b/sources/Runner/MainMenuScene.cpp index 3a515c1e..42067222 100644 --- a/sources/Runner/MainMenuScene.cpp +++ b/sources/Runner/MainMenuScene.cpp @@ -23,9 +23,8 @@ namespace BBM }; auto scene = std::make_shared(); + addMenuControl(*scene); scene->addEntity("Control entity") - .addComponent() - .addComponent() .addComponent("assets/musics/music_title.ogg") .addComponent(sounds); scene->addEntity("background") @@ -51,7 +50,7 @@ namespace BBM }) .addComponent([](WAL::Entity &entity, WAL::Wal &) { - gameState.nextScene = BBM::GameState::SceneID::GameScene; + gameState.nextScene = BBM::GameState::SceneID::LobbyScene; }); auto &settings = scene->addEntity("settings button") .addComponent(1920 / 2.5, 1080 - 360, 0) diff --git a/sources/Runner/PauseMenuScene.cpp b/sources/Runner/PauseMenuScene.cpp index ed674e3a..cf7d66c6 100644 --- a/sources/Runner/PauseMenuScene.cpp +++ b/sources/Runner/PauseMenuScene.cpp @@ -23,9 +23,8 @@ namespace BBM }; auto scene = std::make_shared(); + addMenuControl(*scene); scene->addEntity("Control entity") - .addComponent() - .addComponent() .addComponent("assets/musics/music_player_select.ogg") .addComponent(sounds); scene->addEntity("background") diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index 05ddb71e..6af5e04c 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -6,37 +6,35 @@ #include #include "System/Movable/MovableSystem.hpp" #include "System/Renderer/RenderSystem.hpp" -#include -#include +#include #include #include "System/Keyboard/KeyboardSystem.hpp" #include "System/Controllable/ControllableSystem.hpp" #include "System/Gamepad/GamepadSystem.hpp" #include +#include "Component/Renderer/Drawable2DComponent.hpp" #include "Runner.hpp" #include "Models/GameState.hpp" -#include #include #include #include #include #include +#include #include #include #include #include "System/Animation/AnimationsSystem.hpp" #include "Map/Map.hpp" #include "System/MenuControllable/MenuControllableSystem.hpp" -#include #include #include "System/Sound/PlayerSoundManagerSystem.hpp" #include "System/Sound/MenuSoundManagerSystem.hpp" #include "System/Gravity/GravitySystem.hpp" #include "System/BumperTimer/BumperTimerSystem.hpp" #include "System/Music/MusicSystem.hpp" - -namespace RAY3D = RAY::Drawables::Drawables3D; -namespace RAY2D = RAY::Drawables::Drawables2D; +#include "System/Lobby/LobbySystem.hpp" +#include "Component/Lobby/LobbyComponent.hpp" namespace BBM { @@ -44,6 +42,7 @@ namespace BBM void Runner::updateState(WAL::Wal &engine, GameState &state) { + auto &view = engine.getScene()->view(); if (RAY::Window::getInstance().shouldClose()) engine.shouldClose = true; if (gameState.currentScene == GameState::SceneID::GameScene || gameState.currentScene == GameState::SceneID::SplashScreen) { @@ -69,6 +68,7 @@ namespace BBM wal.addSystem() .addSystem() .addSystem() + .addSystem() .addSystem() .addSystem() .addSystem() @@ -96,15 +96,30 @@ namespace BBM .addSystem(window); } + void Runner::addMenuControl(WAL::Scene &scene) + { + scene.addEntity("Keyboard default control") + .addComponent() + .addComponent(); + scene.addEntity("Keyboard second control") + .addComponent() + .addComponent(ControllableComponent::Layout::KEYBOARD_1); + for (int i = 0; i < 4; i++) { + scene.addEntity("Gamepad controller") + .addComponent() + .addComponent(i); + } + } + void Runner::loadScenes() { gameState._loadedScenes[GameState::SceneID::MainMenuScene] = loadMainMenuScene(); - gameState._loadedScenes[GameState::SceneID::GameScene] = loadGameScene(); gameState._loadedScenes[GameState::SceneID::SettingsScene] = loadSettingsMenuScene(); gameState._loadedScenes[GameState::SceneID::PauseMenuScene] = loadPauseMenuScene(); gameState._loadedScenes[GameState::SceneID::TitleScreenScene] = loadTitleScreenScene(); gameState._loadedScenes[GameState::SceneID::CreditScene] = loadCreditScene(); gameState._loadedScenes[GameState::SceneID::SplashScreen] = loadSplashScreenScene(); + gameState._loadedScenes[GameState::SceneID::LobbyScene] = loadLobbyScene(); } int Runner::run() diff --git a/sources/Runner/Runner.hpp b/sources/Runner/Runner.hpp index b7d21729..dd225e1e 100644 --- a/sources/Runner/Runner.hpp +++ b/sources/Runner/Runner.hpp @@ -28,6 +28,8 @@ namespace BBM //! @brief init all raylib-related data & context static void enableRaylib(WAL::Wal &wal); + static void addMenuControl(WAL::Scene &scene); + //! @brief load all data related to title screen static std::shared_ptr loadTitleScreenScene(); @@ -46,6 +48,14 @@ namespace BBM //! @brief load all data related to credit screen static std::shared_ptr loadCreditScene(); + //! @brief load all data related to lobby screen + static std::shared_ptr loadLobbyScene(); + + //! @brief Create a player (without any controllable) and add it to the scene. + //! @param scene The scene where to player should reside. + //! @return A reference to the created player. + static WAL::Entity &createPlayer(WAL::Scene &scene); + //! @brief load all data related to splash screen static std::shared_ptr loadSplashScreenScene(); diff --git a/sources/Runner/SettingsMenuScene.cpp b/sources/Runner/SettingsMenuScene.cpp index 4d409aab..8883bbeb 100644 --- a/sources/Runner/SettingsMenuScene.cpp +++ b/sources/Runner/SettingsMenuScene.cpp @@ -24,9 +24,8 @@ namespace BBM {SoundComponent::JUMP, "assets/sounds/click.ogg"} }; + addMenuControl(*scene); scene->addEntity("Control entity") - .addComponent() - .addComponent() .addComponent("assets/musics/music_title.ogg") .addComponent(sounds); scene->addEntity("background") diff --git a/sources/Runner/SplashScreenScene.cpp b/sources/Runner/SplashScreenScene.cpp index 455a0e95..a22d20da 100644 --- a/sources/Runner/SplashScreenScene.cpp +++ b/sources/Runner/SplashScreenScene.cpp @@ -19,10 +19,9 @@ namespace BBM { auto scene = std::make_shared(); + addMenuControl(*scene); auto &splashComponent = scene->addEntity("animation component") - .addComponent() - .addComponent() - .addComponent(); + .addComponent(); auto &background = scene->addEntity("background") .addComponent(0, 0, 0) .addComponent(RAY::Vector2(), RAY::Vector2(1920, 1080)); diff --git a/sources/Runner/TitleScreenScene.cpp b/sources/Runner/TitleScreenScene.cpp index 0cbbf488..729434f3 100644 --- a/sources/Runner/TitleScreenScene.cpp +++ b/sources/Runner/TitleScreenScene.cpp @@ -22,9 +22,8 @@ namespace BBM {SoundComponent::JUMP, "assets/sounds/click.ogg"} }; auto scene = std::make_shared(); + addMenuControl(*scene); scene->addEntity("control") - .addComponent() - .addComponent() .addComponent(sounds) .addComponent("assets/musics/music_title.ogg"); scene->addEntity("background") diff --git a/sources/System/BombHolder/BombHolderSystem.cpp b/sources/System/BombHolder/BombHolderSystem.cpp index 6fe1055d..d67f16c7 100644 --- a/sources/System/BombHolder/BombHolderSystem.cpp +++ b/sources/System/BombHolder/BombHolderSystem.cpp @@ -44,7 +44,7 @@ namespace BBM return; wal.getScene()->scheduleNewEntity("explosion") .addComponent(position) - .addComponent(1s, [](WAL::Entity &explosion, WAL::Wal &wal) { + .addComponent(500ms, [](WAL::Entity &explosion, WAL::Wal &wal) { explosion.scheduleDeletion(); }) .addComponent("assets/bombs/explosion/explosion.glb", false, @@ -60,6 +60,12 @@ namespace BBM return; } } + for (auto &[entity, pos, _] : wal.getScene()->view>()) { + if (pos.position.round() == position) { + if (auto *health = entity.tryGetComponent()) + health->takeDmg(1); + } + } if (expansionDirections & ExpansionDirection::FRONT) { _dispatchExplosion(position + Vector3f{1, 0, 0}, wal, size - 1, ExpansionDirection::FRONT); } @@ -87,6 +93,14 @@ namespace BBM { this->_wal.getScene()->scheduleNewEntity("Bomb") .addComponent(position.round()) + .addComponent(1, [](WAL::Entity &entity, WAL::Wal &wal) { + // the bomb explode when hit + entity.scheduleDeletion(); + auto &pos = entity.getComponent(); + auto &bombDetails = entity.getComponent(); + BombHolderSystem::_dispatchExplosion(pos.position, wal, bombDetails.explosionRadius); + }) + .addComponent>() .addComponent(holder.damage, holder.explosionRadius, id) .addComponent(BombHolderSystem::explosionTimer, &BombHolderSystem::_bombExplosion) .addComponent( diff --git a/sources/System/Gamepad/GamepadSystem.cpp b/sources/System/Gamepad/GamepadSystem.cpp index 5dd30a34..623d5edd 100644 --- a/sources/System/Gamepad/GamepadSystem.cpp +++ b/sources/System/Gamepad/GamepadSystem.cpp @@ -30,7 +30,7 @@ namespace BBM }; for (auto key : keyPressedMap) - key.second = gamepad.isPressed(key.first); + key.second = gamepad.isDown(key.first); controllable.move.x = gamepad.getAxisValue(gamepadComponent.LeftStickX) * -1; controllable.move.y = gamepad.getAxisValue(gamepadComponent.LeftStickY) * -1; controllable.move.x -= static_cast(gamepad.isDown(gamepadComponent.keyRight)); diff --git a/sources/System/Lobby/LobbySystem.cpp b/sources/System/Lobby/LobbySystem.cpp new file mode 100644 index 00000000..9c020625 --- /dev/null +++ b/sources/System/Lobby/LobbySystem.cpp @@ -0,0 +1,173 @@ +// +// Created by Zoe Roux on 6/11/21. +// + +#include "System/Event/EventSystem.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "System/Lobby/LobbySystem.hpp" +#include "Component/Controllable/ControllableComponent.hpp" +#include "System/MenuControllable/MenuControllableSystem.hpp" +#include "Component/Tag/TagComponent.hpp" +#include +#include +#include +#include +#include +#include + +namespace RAY3D = RAY::Drawables::Drawables3D; + +namespace BBM +{ + std::array LobbySystem::_colors = { + "blue", + "red", + "green", +// "purple", TODO MISSING ICONS +// "cyan", + "yellow" + }; + + std::array LobbySystem::_rayColors = { + BLUE, + RED, + GREEN, + // PURPLE, + // SKYBLUE, + YELLOW + }; + + LobbySystem::LobbySystem(WAL::Wal &wal) + : System(wal) + {} + + void LobbySystem::_nextColor(WAL::ViewEntity &entity) + { + auto &lobby = entity.get(); + if (lobby.color != -1) + this->_colorTaken[lobby.color] = false; + do { + lobby.color++; + if (lobby.color >= this->_colorTaken.size()) + lobby.color = 0; + } while (this->_colorTaken[lobby.color]); + this->_colorTaken[lobby.color] = true; + entity.get().drawable = std::make_shared("assets/player/icons/" + _colors[lobby.color] + ".png"); + lobby.coloredTile.getComponent().drawable->setColor(_rayColors[lobby.color]); + } + + void LobbySystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &lobby = entity.get(); + + auto lastTick = std::chrono::steady_clock::now(); + if (lastTick - lobby.lastInput < std::chrono::milliseconds(150)) + return; + + if (lobby.layout == ControllableComponent::NONE) { + for (auto &[_, ctrl] : this->_wal.getScene()->view()) { + auto &controller = ctrl; + if (controller.jump) { + if (std::any_of(this->getView().begin(), this->getView().end(), [&controller](WAL::ViewEntity &view) { + return view.get().layout == controller.layout; + })) + return; + lobby.lastInput = lastTick; + lobby.color = -1; + this->_nextColor(entity); + lobby.layout = controller.layout; + controller.jump = false; + return; + } + } + } + + for (auto &[_, controller] : this->_wal.getScene()->view()) { + if (controller.layout != lobby.layout) + continue; + if (controller.jump && !lobby.ready) { + lobby.ready = true; + lobby.lastInput = lastTick; + controller.jump = false; + this->_wal.getSystem().now = lastTick; + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->use("assets/player/icons/ready.png"); + } + if (controller.bomb && !lobby.ready) { + lobby.lastInput = lastTick; + this->_nextColor(entity); + } + } + } + + void LobbySystem::onSelfUpdate() + { + auto &view = this->_wal.getScene()->view, Drawable2DComponent>(); + if (view.size() == 0) + return; + auto *texture = dynamic_cast(view.front().get().drawable.get()); + if (!texture) + return; + if (playersAreReady(*this->_wal.getScene())) + texture->setColor(WHITE); + else + texture->setColor(GRAY); + } + + bool LobbySystem::playersAreReady(WAL::Scene &scene) + { + auto &lobby = scene.view(); + return std::all_of(lobby.begin(), lobby.end(), [](WAL::ViewEntity &entity) { + auto &lobbyPlayer = entity.get(); + return lobbyPlayer.ready || lobbyPlayer.layout == ControllableComponent::NONE; + }); + } + + void LobbySystem::_addController(WAL::Entity &player, ControllableComponent::Layout layout) + { + switch (layout) { + case ControllableComponent::KEYBOARD_0: + case ControllableComponent::KEYBOARD_1: + player.addComponent(layout); + break; + case ControllableComponent::GAMEPAD_0: + player.addComponent(0); + break; + case ControllableComponent::GAMEPAD_1: + player.addComponent(1); + break; + case ControllableComponent::GAMEPAD_2: + player.addComponent(2); + break; + case ControllableComponent::GAMEPAD_3: + player.addComponent(3); + break; + default: + throw std::runtime_error("Invalid controller for a player."); + } + } + + void LobbySystem::switchToGame(WAL::Wal &wal) + { + auto scene = Runner::loadGameScene(); + int mapWidth = 16; + int mapHeight = 16; + int playerCount = 0; + + for (auto &[_, lobby] : wal.getScene()->view()) { + if (lobby.layout == ControllableComponent::NONE) + continue; + auto &player = Runner::createPlayer(*scene); + _addController(player, lobby.layout); + player.getComponent().position = Vector3f(mapWidth * (playerCount % 2), + 0, + mapHeight * ((playerCount + 1) % 2)); + 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; + } +} \ No newline at end of file diff --git a/sources/System/Lobby/LobbySystem.hpp b/sources/System/Lobby/LobbySystem.hpp new file mode 100644 index 00000000..b0a91bb3 --- /dev/null +++ b/sources/System/Lobby/LobbySystem.hpp @@ -0,0 +1,54 @@ +// +// Created by Zoe Roux on 6/11/21. +// + +#pragma once + +#include "System/System.hpp" +#include "Component/Lobby/LobbyComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" +#include "Entity/Entity.hpp" +#include +#include + +namespace BBM +{ + //! @brief A system to handle Health entities. + class LobbySystem : public WAL::System + { + private: + //! @brief Add a controller for the player. + static void _addController(WAL::Entity &player, ControllableComponent::Layout layout); + + void _nextColor(WAL::ViewEntity &entity); + + static std::array _colors; + + static std::array _rayColors; + + std::array _colorTaken = {}; + public: + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @inherit + void onSelfUpdate() override; + + //! @brief Check if every player is ready. + //! @param scene The lobby scene containing lobby players. + static bool playersAreReady(WAL::Scene &scene); + + //! @brief Inform the engine that the next scene should be the game scene and load it. + //! @param wal The engine. + static void switchToGame(WAL::Wal &wal); + + //! @brief A default constructor + explicit LobbySystem(WAL::Wal &wal); + //! @brief A Lobby system is copy constructable + LobbySystem(const LobbySystem &) = default; + //! @brief A default destructor + ~LobbySystem() override = default; + //! @brief A system is not assignable. + LobbySystem &operator=(const LobbySystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/MenuControllable/MenuControllableSystem.cpp b/sources/System/MenuControllable/MenuControllableSystem.cpp index 551c01dc..6dcc95e3 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.cpp +++ b/sources/System/MenuControllable/MenuControllableSystem.cpp @@ -4,7 +4,6 @@ #include #include "Component/Button/ButtonComponent.hpp" -#include "Component/Position/PositionComponent.hpp" #include "System/MenuControllable/MenuControllableSystem.hpp" #include "Component/Controllable/ControllableComponent.hpp" #include "Entity/Entity.hpp" @@ -12,12 +11,13 @@ namespace BBM { MenuControllableSystem::MenuControllableSystem(WAL::Wal &wal) - : System(wal), wal(wal), currentButton() + : System(wal), + _currentButton() {} - void MenuControllableSystem::updateCurrentButton(bool selected) + void MenuControllableSystem::_updateCurrentButton(bool selected, Vector2f move) { - auto buttonComponent = this->currentButton->getComponent(); + auto &buttonComponent = this->_currentButton->getComponent(); WAL::Entity *newButton = nullptr; if (move.y > 0 && buttonComponent._up) @@ -28,42 +28,38 @@ namespace BBM newButton = buttonComponent._right; if (move.x > 0 && buttonComponent._left) newButton = buttonComponent._left; + + if (newButton || selected) { + auto lastTick = std::chrono::steady_clock::now(); + if (lastTick - this->now < std::chrono::milliseconds(150)) + return; + this->now = lastTick; + } + if (newButton) { - this->currentButton->getComponent().onEvent(*this->currentButton, wal); - this->currentButton = newButton; - this->currentButton->getComponent().onEvent(*this->currentButton, wal); + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + this->_currentButton = newButton; + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); } if (selected) - this->currentButton->getComponent().onEvent(*this->currentButton, wal); + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); } void MenuControllableSystem::onFixedUpdate(WAL::ViewEntity &entity) { - auto lastTick = std::chrono::steady_clock::now(); auto &controllable = entity.get(); auto &buttons = _wal.getScene()->view(); - - if (lastTick - this->_now < std::chrono::milliseconds(100)) - return; - this->_now = lastTick; - move = controllable.move; - select = controllable.jump; - if (currentButton && currentButton->_scene.getID() != wal.getScene()->getID()) { - currentButton->getComponent().onEvent(*this->currentButton, wal); - currentButton = nullptr; + if (this->_currentButton && this->_currentButton->_scene.getID() != this->_wal.getScene()->getID()) { + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + this->_currentButton = nullptr; } - if (currentButton == nullptr && buttons.size()) { - currentButton = &(**buttons.begin()); - currentButton->getComponent().onEvent(*this->currentButton, wal); + if (this->_currentButton == nullptr && buttons.size()) { + this->_currentButton = &(*buttons.front()); + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); } - if (!currentButton) + if (!this->_currentButton) return; - this->updateCurrentButton(select); - } - - void MenuControllableSystem::onSelfUpdate(void) - { - + this->_updateCurrentButton(controllable.jump, controllable.move); } } \ No newline at end of file diff --git a/sources/System/MenuControllable/MenuControllableSystem.hpp b/sources/System/MenuControllable/MenuControllableSystem.hpp index 86e16130..0ad43a45 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.hpp +++ b/sources/System/MenuControllable/MenuControllableSystem.hpp @@ -14,41 +14,26 @@ namespace BBM class MenuControllableSystem : public WAL::System { private: - //! @brief reference to wal - WAL::Wal &wal; - //! @brief index of the current button selected - WAL::Entity *currentButton; - - //! @brief move vector - Vector2f move; - - //! @brief Select action - bool select = false; - - //! @brief Cancel action - bool cancel = false; + WAL::Entity *_currentButton; //! @brief update current button reference //! @param selected lets know if te new selected button is 'pressed' - void updateCurrentButton(bool selected); + void _updateCurrentButton(bool selected, Vector2f move); - //! @brief time (in mili second) since last check - std::chrono::time_point _now; public: - //! @inherit - void onSelfUpdate(void) override; - + //! @brief time (in millisecond) since last check + std::chrono::time_point now; //! @inherit void onFixedUpdate(WAL::ViewEntity &entities) override; //! @brief A default constructor - MenuControllableSystem(WAL::Wal &wal); + explicit MenuControllableSystem(WAL::Wal &wal); //! @brief A MenuControllable system is not copy constructable MenuControllableSystem(const MenuControllableSystem &) = delete; //! @brief A default destructor ~MenuControllableSystem() override = default; - //! @brief A MenuControllable system is assignable. - MenuControllableSystem &operator=(const MenuControllableSystem &) = default; + //! @brief A MenuControllable system is not assignable. + MenuControllableSystem &operator=(const MenuControllableSystem &) = delete; }; }