diff --git a/CMakeLists.txt b/CMakeLists.txt index afefeb04..643fa719 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,8 +119,32 @@ 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 + sources/System/Gravity/GravitySystem.cpp + sources/Component/BumperTimer/BumperTimerComponent.hpp + sources/Component/BumperTimer/BumperTimerComponent.cpp + sources/System/BumperTimer/BumperTimerSystem.hpp + sources/System/BumperTimer/BumperTimerSystem.cpp sources/System/Bomb/BombSystem.cpp sources/System/Bomb/BombSystem.hpp + sources/Component/IntroAnimation/IntroAnimationComponent.hpp + sources/Component/IntroAnimation/IntroAnimationComponent.cpp + sources/System/IntroAnimation/IntroAnimationSystem.hpp + sources/System/IntroAnimation/IntroAnimationSystem.cpp + sources/Runner/SplashScreenScene.cpp + sources/Runner/TitleScreenScene.cpp + sources/Runner/MainMenuScene.cpp + sources/Runner/GameScene.cpp + sources/Runner/PauseMenuScene.cpp + sources/Runner/SettingsMenuScene.cpp + sources/Runner/CreditScene.cpp + sources/Runner/LobbyScene.cpp ) add_executable(bomberman diff --git a/assets/bombs/explosion/blast.png b/assets/bombs/explosion/blast.png new file mode 100644 index 00000000..037212f6 Binary files /dev/null and b/assets/bombs/explosion/blast.png differ diff --git a/assets/bombs/explosion/explosion.glb b/assets/bombs/explosion/explosion.glb new file mode 100644 index 00000000..065ed85c Binary files /dev/null and b/assets/bombs/explosion/explosion.glb differ 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/assets/sounds/splash_sound.ogg b/assets/sounds/splash_sound.ogg new file mode 100644 index 00000000..d9092e53 Binary files /dev/null and b/assets/sounds/splash_sound.ogg differ diff --git a/lib/Ray/sources/Drawables/2D/Rectangle.cpp b/lib/Ray/sources/Drawables/2D/Rectangle.cpp index 9f623bee..284e9b27 100644 --- a/lib/Ray/sources/Drawables/2D/Rectangle.cpp +++ b/lib/Ray/sources/Drawables/2D/Rectangle.cpp @@ -33,13 +33,47 @@ namespace RAY::Drawables::Drawables2D return *this; } - Rectangle &Rectangle::setDimensions(int x, int y) + Rectangle &Rectangle::setDimensions(float x, float y) { this->_dimensions.x = x; this->_dimensions.y = y; return *this; } + float Rectangle::getHeight(void) const + { + return this->_dimensions.y; + } + + float Rectangle::getWidth(void) const + { + return this->_dimensions.x; + } + + Rectangle &Rectangle::incrementWidth(float width) + { + this->_dimensions.x += width; + return *this; + } + + Rectangle &Rectangle::incrementHeight(float height) + { + this->_dimensions.y += height; + return *this; + } + + Rectangle &Rectangle::setWidth(float width) + { + this->_dimensions.x = width; + return *this; + } + + Rectangle &Rectangle::setHeight(float height) + { + this->_dimensions.y = height; + return *this; + } + void Rectangle::drawOn(RAY::Window &) { DrawRectangleV(this->_position, this->_dimensions, this->_color); diff --git a/lib/Ray/sources/Drawables/2D/Rectangle.hpp b/lib/Ray/sources/Drawables/2D/Rectangle.hpp index e0d32dff..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,16 +37,38 @@ 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); + //! @return the width of the rectangle + float getWidth(void) const; + + //! @return the height of the rectangle + float getHeight(void) const; + //! @brief set dimensions Rectangle &setDimensions(const Vector2 &dimensions); + //! @brief increment width of the rectangle + //! @param width incrementer + Rectangle &incrementWidth(float width); + + //! @brief increment height of the rectangle + //! @param height incrementer + Rectangle &incrementHeight(float height); + + //! @brief set rectangle's height + //! @param height height of the rectangle + Rectangle &setHeight(float height); + + //! @brief set rectangle's width + //! @param width width of the rectangle + Rectangle &setWidth(float width); + //! @brief set dimensions - Rectangle &setDimensions(int x, int y); + Rectangle &setDimensions(float x, float y); //! @brief Draw point on window virtual void drawOn(RAY::Window &) override; diff --git a/lib/Ray/sources/Drawables/3D/Cube.cpp b/lib/Ray/sources/Drawables/3D/Cube.cpp index 6f651a15..1af236d1 100644 --- a/lib/Ray/sources/Drawables/3D/Cube.cpp +++ b/lib/Ray/sources/Drawables/3D/Cube.cpp @@ -30,4 +30,9 @@ namespace RAY::Drawables::Drawables3D { DrawCubeV(this->_position, this->_dimensions, this->_color); } + + void Cube::drawWiresOn(RAY::Window &) + { + DrawCubeWiresV(this->_position, this->_dimensions, this->_debugColor); + } } \ No newline at end of file diff --git a/lib/Ray/sources/Drawables/3D/Cube.hpp b/lib/Ray/sources/Drawables/3D/Cube.hpp index d1fff6f9..96347a95 100644 --- a/lib/Ray/sources/Drawables/3D/Cube.hpp +++ b/lib/Ray/sources/Drawables/3D/Cube.hpp @@ -41,6 +41,9 @@ namespace RAY::Drawables::Drawables3D { //! @brief Draw circle on window void drawOn(RAY::Window &) override; + + //! @brief Draw cube's wires on window + void drawWiresOn(RAY::Window &) override; private: //! @brief Dimensions of the cube Vector3 _dimensions; diff --git a/lib/Ray/sources/Drawables/3D/Cylinder.cpp b/lib/Ray/sources/Drawables/3D/Cylinder.cpp index 64db931d..8e2ff386 100644 --- a/lib/Ray/sources/Drawables/3D/Cylinder.cpp +++ b/lib/Ray/sources/Drawables/3D/Cylinder.cpp @@ -52,4 +52,9 @@ namespace RAY::Drawables::Drawables3D { DrawCylinder(this->_position, this->_topRadius, this->_bottomRadius, this->_height, 0, this->_color); } + + void Cylinder::drawWiresOn(RAY::Window &) + { + DrawCylinderWires(this->_position, this->_topRadius, this->_bottomRadius, this->_height, 0, this->_debugColor); + } } \ No newline at end of file diff --git a/lib/Ray/sources/Drawables/3D/Cylinder.hpp b/lib/Ray/sources/Drawables/3D/Cylinder.hpp index dc09fb5d..32871514 100644 --- a/lib/Ray/sources/Drawables/3D/Cylinder.hpp +++ b/lib/Ray/sources/Drawables/3D/Cylinder.hpp @@ -55,6 +55,8 @@ namespace RAY::Drawables::Drawables3D { //! @brief Draw point on window void drawOn(RAY::Window &) override; + //! @brief Draw cylinder's wires on window + void drawWiresOn(RAY::Window &) override; private: //! @brief Radius of the cylinder float _topRadius; diff --git a/lib/Ray/sources/Drawables/3D/Sphere.cpp b/lib/Ray/sources/Drawables/3D/Sphere.cpp index 7d23fc48..f87c3fa5 100644 --- a/lib/Ray/sources/Drawables/3D/Sphere.cpp +++ b/lib/Ray/sources/Drawables/3D/Sphere.cpp @@ -30,4 +30,9 @@ namespace RAY::Drawables::Drawables3D { DrawSphere(this->_position, this->_radius, this->_color); } + + void Sphere::drawWiresOn(RAY::Window &) + { + DrawSphereWires(this->_position, this->_radius, 10, 10, this->_debugColor); + } } \ No newline at end of file diff --git a/lib/Ray/sources/Drawables/3D/Sphere.hpp b/lib/Ray/sources/Drawables/3D/Sphere.hpp index d053ccf9..24c31a8b 100644 --- a/lib/Ray/sources/Drawables/3D/Sphere.hpp +++ b/lib/Ray/sources/Drawables/3D/Sphere.hpp @@ -40,6 +40,9 @@ namespace RAY::Drawables::Drawables3D { //! @brief Draw point on window void drawOn(RAY::Window &) override; + //! @brief Draw sphere's wires on window + void drawWiresOn(RAY::Window &) override; + private: //! @brief Radius of the sphere int _radius; diff --git a/lib/Ray/sources/Drawables/ADrawable3D.cpp b/lib/Ray/sources/Drawables/ADrawable3D.cpp index 0fff69f8..2d7cfaf2 100644 --- a/lib/Ray/sources/Drawables/ADrawable3D.cpp +++ b/lib/Ray/sources/Drawables/ADrawable3D.cpp @@ -36,4 +36,18 @@ namespace RAY::Drawables this->_position = position; return *this; } + + void ADrawable3D::drawWiresOn(RAY::Window &) + {} + + const RAY::Color &ADrawable3D::getDebugColor(void) const + { + return this->_debugColor; + } + + ADrawable3D &ADrawable3D::setDebugColor(const Color &debugColor) + { + this->_debugColor = debugColor; + return *this; + } } \ No newline at end of file diff --git a/lib/Ray/sources/Drawables/ADrawable3D.hpp b/lib/Ray/sources/Drawables/ADrawable3D.hpp index cc989fed..58aa5359 100644 --- a/lib/Ray/sources/Drawables/ADrawable3D.hpp +++ b/lib/Ray/sources/Drawables/ADrawable3D.hpp @@ -30,12 +30,21 @@ namespace RAY::Drawables { //! @brief Draw drawble on window void drawOn(RAY::Window &) override = 0; + //! @brief Draw drawble's wires on window + virtual void drawWiresOn(RAY::Window &); + //! @return the color of the ADrawable const RAY::Color &getColor(void) const; - + //! @brief set color ADrawable3D &setColor(const RAY::Color &color); + //! @return the debug color of the ADrawable + const RAY::Color &getDebugColor(void) const; + + //! @brief set the debug color + ADrawable3D &setDebugColor(const RAY::Color &debugColor); + //! @return the position of the ADrawable virtual const RAY::Vector3 &getPosition(void) const; @@ -49,6 +58,9 @@ namespace RAY::Drawables { //! @brief Color of the ADrawable Color _color; + //! @brief Color of the ADrawable's Debug + Color _debugColor = GREEN; + }; }; 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/Model.cpp b/lib/Ray/sources/Model/Model.cpp index 9fd5b31e..fefa29ea 100644 --- a/lib/Ray/sources/Model/Model.cpp +++ b/lib/Ray/sources/Model/Model.cpp @@ -114,6 +114,20 @@ namespace RAY::Drawables::Drawables3D this->_color); } + void Model::drawWiresOn(RAY::Window &) + { + if (this->_model->meshCount) { + ::BoundingBox box = GetMeshBoundingBox(*this->_model->meshes); + box.min.x += this->_position.x; + box.min.y += this->_position.y; + box.min.z += this->_position.z; + box.max.x += this->_position.x; + box.max.y += this->_position.y; + box.max.z += this->_position.z; + DrawBoundingBox(box, this->_debugColor); + } + } + void Model::setShader(const RAY::Shader &shader) { this->_originalShader = this->_model->materials[0].shader; diff --git a/lib/Ray/sources/Model/Model.hpp b/lib/Ray/sources/Model/Model.hpp index d67706be..2bf6cf47 100644 --- a/lib/Ray/sources/Model/Model.hpp +++ b/lib/Ray/sources/Model/Model.hpp @@ -87,6 +87,9 @@ namespace RAY::Drawables::Drawables3D { void drawOn(RAY::Window &) override; + //! @brief Draw model's wires on window + void drawWiresOn(RAY::Window &) override; + private: //! @brief Raw data from raylib std::shared_ptr<::Model> _model; 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/BumperTimer/BumperTimerComponent.cpp b/sources/Component/BumperTimer/BumperTimerComponent.cpp new file mode 100644 index 00000000..1d661395 --- /dev/null +++ b/sources/Component/BumperTimer/BumperTimerComponent.cpp @@ -0,0 +1,17 @@ +// +// Created by Tom Augier on 2021-05-20. +// + +#include "BumperTimerComponent.hpp" + +namespace BBM +{ + BumperTimerComponent::BumperTimerComponent(WAL::Entity &entity) + : WAL::Component(entity) + {} + + WAL::Component *BumperTimerComponent::clone(WAL::Entity &entity) const + { + return new BumperTimerComponent(entity); + } +} \ No newline at end of file diff --git a/sources/Component/BumperTimer/BumperTimerComponent.hpp b/sources/Component/BumperTimer/BumperTimerComponent.hpp new file mode 100644 index 00000000..a0b8c958 --- /dev/null +++ b/sources/Component/BumperTimer/BumperTimerComponent.hpp @@ -0,0 +1,41 @@ +// +// Created by Tom Augier on 2021-05-20. +// + +#pragma once + +#include +#include "Component/Component.hpp" +#include "Entity/Entity.hpp" + +using namespace std::chrono_literals; + +namespace BBM +{ + class BumperTimerComponent : public WAL::Component + { + public: + + + bool _isReseting = false; + //! @brief The number of seconds of each rest. This variable is used to reset the nextReset value. + std::chrono::nanoseconds resetRate = 1500ms; + //! @brief The number of nanosecond before the next bumper reset for the player. + std::chrono::nanoseconds nextReset = resetRate; + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief Constructor + BumperTimerComponent(WAL::Entity &entity); + + //! @brief A BumperTimer component can't be instantiated, it should be derived. + BumperTimerComponent(const BumperTimerComponent &) = default; + + //! @brief default destructor + ~BumperTimerComponent() override = default; + + //! @brief A BumperTimer component can't be assigned + BumperTimerComponent &operator=(const BumperTimerComponent &) = delete; + }; +} \ No newline at end of file diff --git a/sources/Component/Controllable/ControllableComponent.hpp b/sources/Component/Controllable/ControllableComponent.hpp index 48df8db0..5b7d39ad 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 = .25f; + //! @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/Gravity/GravityComponent.cpp b/sources/Component/Gravity/GravityComponent.cpp new file mode 100644 index 00000000..a6ee1db4 --- /dev/null +++ b/sources/Component/Gravity/GravityComponent.cpp @@ -0,0 +1,17 @@ +// +// Created by Tom Augier on 2021-05-20. +// + +#include "GravityComponent.hpp" + +namespace BBM +{ + GravityComponent::GravityComponent(WAL::Entity &entity) + : WAL::Component(entity) + {} + + WAL::Component *GravityComponent::clone(WAL::Entity &entity) const + { + return new GravityComponent(entity); + } +} \ No newline at end of file diff --git a/sources/Component/Gravity/GravityComponent.hpp b/sources/Component/Gravity/GravityComponent.hpp new file mode 100644 index 00000000..59f7cc89 --- /dev/null +++ b/sources/Component/Gravity/GravityComponent.hpp @@ -0,0 +1,31 @@ +// +// Created by Tom Augier on 2021-05-20. +// + +#pragma once + +#include "Component/Component.hpp" +#include "Entity/Entity.hpp" + +namespace BBM +{ + class GravityComponent : public WAL::Component + { + public: + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief Constructor + GravityComponent(WAL::Entity &entity); + + //! @brief A Gravity component can't be instantiated, it should be derived. + GravityComponent(const GravityComponent &) = default; + + //! @brief default destructor + ~GravityComponent() override = default; + + //! @brief A Gravity component can't be assigned + GravityComponent &operator=(const GravityComponent &) = delete; + }; +} \ No newline at end of file diff --git a/sources/Component/IntroAnimation/IntroAnimationComponent.cpp b/sources/Component/IntroAnimation/IntroAnimationComponent.cpp new file mode 100644 index 00000000..261a168e --- /dev/null +++ b/sources/Component/IntroAnimation/IntroAnimationComponent.cpp @@ -0,0 +1,17 @@ +// +// Created by Zoe Roux on 5/24/21. +// + +#include "IntroAnimationComponent.hpp" + +namespace BBM +{ + IntroAnimationComponent::IntroAnimationComponent(WAL::Entity &entity) + : WAL::Component(entity) + {} + + WAL::Component *IntroAnimationComponent::clone(WAL::Entity &entity) const + { + return new IntroAnimationComponent(entity); + } +} \ No newline at end of file diff --git a/sources/Component/IntroAnimation/IntroAnimationComponent.hpp b/sources/Component/IntroAnimation/IntroAnimationComponent.hpp new file mode 100644 index 00000000..0def3a25 --- /dev/null +++ b/sources/Component/IntroAnimation/IntroAnimationComponent.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace BBM +{ + //! @brief A component to slowly center entities to the middle of their current block. + //! This allow flexibility in their movement will preventing them from getting stuck at every corner. + class IntroAnimationComponent : public WAL::Component + { + public: + unsigned int frameCounter = 0; + + enum animationSteps { + boxBlinking, + topLeftgrowing, + bottomRightGrowing, + lettersTyping, + fading, + prompt, + }; + + enum animationSteps currentStep = boxBlinking; + + //! @inherit + Component *clone(WAL::Entity &entity) const override; + + //! @brief Create a new, default IntroAnimationComponent. + //! @param entity The entity attached to this component. + explicit IntroAnimationComponent(WAL::Entity &entity); + //! @brief A IntroAnimationComponent is copy constructable + //! @param other The other IntroAnimationComponent to copy. + IntroAnimationComponent(const IntroAnimationComponent &other) = default; + //! @brief A default destructor + ~IntroAnimationComponent() override = default; + //! @brief A IntroAnimationComponent is not assignable + IntroAnimationComponent &operator=(const IntroAnimationComponent &) = delete; + }; +} 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/Map/Map.cpp b/sources/Map/Map.cpp index 3a054493..6a88c984 100644 --- a/sources/Map/Map.cpp +++ b/sources/Map/Map.cpp @@ -11,12 +11,39 @@ #include #include #include +#include namespace RAY3D = RAY::Drawables::Drawables3D; using namespace std::chrono_literals; namespace BBM { + void MapGenerator::bumperCollide(WAL::Entity &entity, + const WAL::Entity &wall, + CollisionComponent::CollidedAxis collidedAxis) + { + auto *movable = entity.tryGetComponent(); + auto *bumperTimer = entity.tryGetComponent(); + + if (!movable || !bumperTimer) + return; + if (!bumperTimer->_isReseting) { + movable->_velocity.y = 1.5; + bumperTimer->_isReseting = true; + } + } + + void MapGenerator::holeCollide(WAL::Entity &entity, + const WAL::Entity &wall, + CollisionComponent::CollidedAxis collidedAxis) + { + auto *health = entity.tryGetComponent(); + + if (!health) + return; + health->takeDmg(health->getHealthPoint()); + } + void MapGenerator::wallCollided(WAL::Entity &entity, const WAL::Entity &wall, CollisionComponent::CollidedAxis collidedAxis) @@ -53,6 +80,8 @@ namespace BBM return; wal.getScene()->scheduleNewEntity("Bonus") .addComponent(position) + .addComponent>() + .addComponent() .addComponent(1, [](WAL::Entity &entity, WAL::Wal &wal) { entity.scheduleDeletion(); }) @@ -107,9 +136,25 @@ namespace BBM static const std::string unbreakableObj = unbreakableWallPath + objExtension; static const std::string unbreakablePnj = unbreakableWallPath + imageExtension; + for (int i = 0; i < height + 1; i++) { + scene->addEntity("Bomb stopper") + .addComponent(-1, 0, i) + .addComponent>(); + scene->addEntity("Bomb stopper") + .addComponent(width + 1, 0, i) + .addComponent>(); + } + for (int i = 0; i < width + 1; i++) { + scene->addEntity("Bomb stopper") + .addComponent(i, 0, -1) + .addComponent>(); + scene->addEntity("Bomb stopper") + .addComponent(i, 0, height + 1) + .addComponent>(); + } + scene->addEntity("Bottom Wall") .addComponent(Vector3f((width + 1) / 2, 0, -1)) - .addComponent>() .addComponent( WAL::Callback(), &MapGenerator::wallCollided, Vector3f(-(width + 1) / 2 , 0.25, 0.25), Vector3f(width + 1, 2, 0.75)) @@ -118,7 +163,6 @@ namespace BBM RAY::Vector3(width + 3, 1, 1)); scene->addEntity("Upper Wall") .addComponent(Vector3f((width + 1) / 2, 0, height + 1)) - .addComponent>() .addComponent( WAL::Callback(), &MapGenerator::wallCollided, Vector3f(-(width + 1) / 2 , 0.25, 0.25), Vector3f(width + 1, 2, 0.75)) @@ -127,7 +171,6 @@ namespace BBM RAY::Vector3(width + 3, 1, 1)); scene->addEntity("Left Wall") .addComponent(Vector3f(width + 1, 0, height / 2)) - .addComponent>() .addComponent( WAL::Callback(), &MapGenerator::wallCollided, Vector3f(0.25, 0.25, -(height + 1) / 2 ), Vector3f(0.75, 2, height + 1)) @@ -152,7 +195,7 @@ namespace BBM for (int i = 0; i < width + 1; i++) { for (int j = 0; j < height + 1; j++) { if (map[std::make_tuple(i, 0, j)] != HOLE && map[std::make_tuple(i, -1, j)] != BUMPER) - scene->addEntity("Unbreakable Wall") + scene->addEntity("Ground") .addComponent(Vector3f(i, -1, j)) .addComponent(floorObj, false, std::make_pair(MAP_DIFFUSE, floorPng)); @@ -241,19 +284,16 @@ namespace BBM WAL::Entity &holeEntity = scene->addEntity("Hole Block"); holeEntity.addComponent(Vector3f(coords.x, coords.y - 1, coords.z)) - .addComponent>(); - + .addComponent>() + .addComponent( + WAL::Callback(), + &MapGenerator::holeCollide, Vector3f(0.25, 0.25, 0.25),Vector3f(0.75, 1.75, 0.75)); if (coords.y == 0) holeEntity.addComponent(holeObj, false, std::make_pair(MAP_DIFFUSE, holePng)); else holeEntity.addComponent(secondFloorObj, false, std::make_pair(MAP_DIFFUSE, secondFloorPng)); - /*.addComponent([](WAL::Entity &other, const WAL::Entity &entity) { - if (other.hasComponent()) { - auto &health = other.getComponent(); - health.takeDmg(health.getHealthPoint()); - } - }, [](WAL::Entity &other, const WAL::Entity &entity){}); */ + } void MapGenerator::createBumper(Vector3f coords, std::shared_ptr scene) @@ -264,13 +304,10 @@ namespace BBM scene->addEntity("Bumper Block") .addComponent(Vector3f(coords.x, coords.y, coords.z)) .addComponent>() - .addComponent(bumperObj, false, std::make_pair(MAP_DIFFUSE, bumperPng)); - /* .addComponent([](const WAL::Entity &entity, WAL::Entity &other) { - if (other.hasComponent()) { - auto &movable = other.getComponent(); - movable.addForce(Vector3f(0, 5, 0)); - } - }); */ + .addComponent(bumperObj, false, std::make_pair(MAP_DIFFUSE, bumperPng)) + .addComponent( + WAL::Callback(), + &MapGenerator::bumperCollide, Vector3f(0.25, 0.25, 0.25),Vector3f(0.75, 0.75, 0.75)); } bool MapGenerator::isCloseToBlockType(std::map, BlockType> map, int x, int y, int z, @@ -286,7 +323,7 @@ namespace BBM { double rnd = static_cast(std::rand()) / RAND_MAX; - if (rnd > 0.95) + if (rnd > 0.98) return HOLE; if (rnd > 0.25) return BREAKABLE; @@ -297,7 +334,7 @@ namespace BBM { double rnd = static_cast(std::rand()) / RAND_MAX; - if (rnd > 0.60) { + if (rnd > 0.01) { for (int i = 0; i < width + 1; i++) { map[std::make_tuple(i, 1, height)] = map[std::make_tuple(i, 0, height)]; map[std::make_tuple(i, 0, height)] = UPPERFLOOR; @@ -310,12 +347,10 @@ namespace BBM map[std::make_tuple(width, -1, 1)] = BUMPER; map[std::make_tuple(width / 2, -1, height - 1)] = BUMPER; map[std::make_tuple(width / 2, -1, 1)] = BUMPER; - } - if (rnd > 0.30) { + } + if (rnd > 0.01) { for (int i = width / 2 - width / 4; i < width / 2 + width / 4 + 1; i++) { for (int j = height / 2 - height / 4; j < height / 2 + height / 4 + 1; j++) { - if (map[std::make_tuple(i, 0, j)] == FLOOR) - continue; map[std::make_tuple(i, 1, j)] = map[std::make_tuple(i, 0, j)]; map[std::make_tuple(i, 0, j)] = UPPERFLOOR; } @@ -344,26 +379,60 @@ namespace BBM for (int j = 0; j < height; j++) { if (map[std::make_tuple(i, 0, j)] == BREAKABLE && map[std::make_tuple(i, -1, j)] == BUMPER) map[std::make_tuple(i, 0, j)] = NOTHING; + if (map[std::make_tuple(i, 1, j)] == BREAKABLE && isCloseToBlockType(map, i, -1, j, BUMPER)) + map[std::make_tuple(i, 1, j)] = NOTHING; } return (map); } - MapGenerator::MapBlock MapGenerator::createMap(int width, int height) + MapGenerator::MapBlock MapGenerator::createClassicUnbreakable(MapBlock map, int width, int height) + { + for (int i = 0; i < width + 1; i++) { + for (int j = 0; j < height + 1; j++) { + if (!((i + 1) % 2) && !((j + 1) % 2)) + map[std::make_tuple(i, 0, j)] = UNBREAKABLE; + } + } + return (map); + } + + MapGenerator::MapBlock MapGenerator::createLongClassicUnbreakable(MapBlock map, int width, int height) + { + int placedSpace = 0; + + for (int i = 1; i < width; i++) { + placedSpace = 0; + for (int j = 1; j < height; j++) { + if (!(j % 2)) + continue; + if (i < (width / 2 - width / 10) || i > (width / 2 + width / 10)) + map[std::make_tuple(i, 0, j)] = UNBREAKABLE; + else + placedSpace++; + } + } + return (map); + } + + + MapGenerator::MapBlock MapGenerator::createMap(int width, int height, bool isHeight, bool isNotClassic) { MapBlock map; width = width % 2 ? width + 1 : width; height = height % 2 ? height + 1 : height; - for (int i = 0; i < width; i++) - for (int j = 0; j < height; j++) + for (int i = 0; i < width + 1; i++) + for (int j = 0; j < height + 1; j++) { map[std::make_tuple(i, 0, j)] = NOTHING; + map[std::make_tuple(i, 1, j)] = NOTHING; + } map = createSpawner(map, width, height); for (int i = 0; i < width + 1; i++) { for (int j = 0; j < height + 1; j++) { if (map[std::make_tuple(i, 0, j)] == SPAWNER) continue; if (isCloseToBlockType(map, i, 0, j, SPAWNER)) { - map[std::make_tuple(i, 0, j)] = NOTHING; + map[std::make_tuple(i, isNotClassic ? -1 : 0, j)] = isNotClassic ? BUMPER : NOTHING; } else { map[std::make_tuple(i, 0, j)] = getRandomBlockType(); } @@ -371,17 +440,61 @@ namespace BBM map[std::make_tuple(i, 0, j)] = BREAKABLE; } } - for (int i = 0; i < width + 1; i++) - for (int j = 0; j < height + 1; j++) - if (!((i + 1) % 2) && !((j + 1) % 2)) - map[std::make_tuple(i, 0, j)] = UNBREAKABLE; - map = createHeight(map, width, height); + if (!isNotClassic) + map = createClassicUnbreakable(map, width, height); + else + map = createLongClassicUnbreakable(map, width, height); + if (isHeight) + map = createHeight(map, width, height); map = cleanBreakable(map, width, height); return (map); } + void MapGenerator::generateHeightCollision(MapBlock map, int width, int height, std::shared_ptr scene) + { + int floor = 2; + + for (int i = 0; i < width + 1; i++) { + if (map[std::make_tuple(i, 0, 0)] != UPPERFLOOR && map[std::make_tuple(i, 0, 0)] != HOLE + && map[std::make_tuple(i, 0, 0)] != BUMPER) { + floor -= 1; + break; + } + } + for (int i = width / 2 - width / 4; i < width / 2 + width / 4 + 1; i++) { + for (int j = height / 2 - height / 4; j < height / 2 + height / 4 + 1; j++) { + if (map[std::make_tuple(i, 0, j)] != UPPERFLOOR && map[std::make_tuple(i, 0, j)] != HOLE + && map[std::make_tuple(i, 0, j)] != BUMPER) { + floor -= 1; + break; + } + } + if (floor <= 0) + break; + } + if (floor >= 1) { + scene->addEntity("FloorBot Hitbox") + .addComponent(Vector3f(0, 0, 0)) + .addComponent( + WAL::Callback(), + &MapGenerator::wallCollided, Vector3f(0.25, 0.25, 0.25), Vector3f(width, 0.75, 0.75)); + scene->addEntity("FloorUp Hitbox") + .addComponent(Vector3f(0, 0, height)) + .addComponent( + WAL::Callback(), + &MapGenerator::wallCollided, Vector3f(0.25, 0.25, 0.25),Vector3f(width, 0.75, 0.75)); + } + if (floor >= 2) + scene->addEntity("Middle Hitbox") + .addComponent(Vector3f(width / 2 - width / 4, 0, height / 2 - height / 4)) + .addComponent( + WAL::Callback(), + &MapGenerator::wallCollided, Vector3f(0.25, 0.25, 0.25),Vector3f(width, 0.75, height / 2 + height / 4)); + } + void MapGenerator::loadMap(int width, int height, MapBlock map, const std::shared_ptr &scene) - { + { + generateHeightCollision(map, width, height, scene); generateWall(width, height, scene); generateFloor(map, width, height, scene); for (int x = 0; x < width + 1; x++) diff --git a/sources/Map/Map.hpp b/sources/Map/Map.hpp index 2545529e..8355576e 100644 --- a/sources/Map/Map.hpp +++ b/sources/Map/Map.hpp @@ -44,18 +44,29 @@ namespace BBM UNBREAKABLE }; + using MapElem = std::function scene)>; using MapBlock = std::map, BlockType>; + static void wallCollided(WAL::Entity &entity, + const WAL::Entity &wall, + CollisionComponent::CollidedAxis collidedAxis); + static void wallDestroyed(WAL::Entity &entity, WAL::Wal &wal); + + static void holeCollide(WAL::Entity &entity, const WAL::Entity &wall, CollisionComponent::CollidedAxis collidedAxis); - static void wallDestroyed(WAL::Entity &entity, WAL::Wal &wal); + + static void bumperCollide(WAL::Entity &entity, + const WAL::Entity &wall, + CollisionComponent::CollidedAxis collidedAxis); + //! @param width Width of the map //! @param height Height of the map //! @brief Generate map of block to be loaded - static MapBlock createMap(int width, int height); + static MapBlock createMap(int width, int height, bool isHeight = false, bool isNotClassic = false); //! @param width Width of the map //! @param height Height of the map @@ -129,6 +140,25 @@ namespace BBM //! @brief Create upper floor of the map static void createUpperFloor(Vector3f coords, std::shared_ptr scene); + //! @param width Width of the map + //! @param height Height of the map + //! @param scene Scene where the map is instanced + //! @brief Generate the height hitbox of the map + static void generateHeightCollision(MapBlock map, int width, int height, + std::shared_ptr scene); + + //! @param map Map to load with block declared inside + //! @param width Width of the map + //! @param height Height of the map + //! @brief Generate unbreakable block on the map + static MapBlock createClassicUnbreakable(MapBlock map, int width, int height); + + //! @param map Map to load with block declared inside + //! @param width Width of the map + //! @param height Height of the map + //! @brief Generate unbreakable block on map + static MapBlock createLongClassicUnbreakable(MapBlock map, int width, int height); + //! @param map Map to load with block declared inside //! @param width Width of the map //! @param height Height of the map diff --git a/sources/Models/GameState.hpp b/sources/Models/GameState.hpp index a899551f..bafc69ce 100644 --- a/sources/Models/GameState.hpp +++ b/sources/Models/GameState.hpp @@ -18,6 +18,7 @@ namespace BBM //! @brief The list of scenes available. enum SceneID { + SplashScreen, MainMenuScene, GameScene, SettingsScene, @@ -29,10 +30,10 @@ namespace BBM //! @brief The currently loaded scene - SceneID currentScene = TitleScreenScene; + SceneID currentScene = SplashScreen; //! @brief The next scene to load (if smae as currentScene, nothing to do) - SceneID nextScene = TitleScreenScene; + SceneID nextScene = SplashScreen; //! @brief The list of loaded scenes. std::unordered_map> _loadedScenes = {}; diff --git a/sources/Models/Vector3.hpp b/sources/Models/Vector3.hpp index a2266e07..8e8b4093 100644 --- a/sources/Models/Vector3.hpp +++ b/sources/Models/Vector3.hpp @@ -173,6 +173,11 @@ namespace BBM return Vector3(std::round(this->x), std::round(this->y), std::round(this->z)); } + [[nodiscard]] bool isNull() const + { + return this->x == 0 && this->y == 0 && this->z == 0; + } + operator RAY::Vector3() const requires(std::is_same_v) { return RAY::Vector3(this->x, this->y, this->z); diff --git a/sources/Runner/CreditScene.cpp b/sources/Runner/CreditScene.cpp new file mode 100644 index 00000000..d87e47be --- /dev/null +++ b/sources/Runner/CreditScene.cpp @@ -0,0 +1,72 @@ + +#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::loadCreditScene() + { + auto scene = std::make_shared(); + static const std::map sounds = { + {SoundComponent::JUMP, "assets/sounds/click.ogg"} + }; + + addMenuControl(*scene); + scene->addEntity("background") + .addComponent() + .addComponent("assets/plain_menu_background.png"); + + scene->addEntity("Control entity") + .addComponent("assets/musics/music_title.ogg") + .addComponent(sounds); + + auto &raylibLogo = scene->addEntity("raylib logo") + .addComponent(1920 / 4, 1080 / 1.75, 0) + .addComponent("assets/raylib.png"); + auto &raylibText = scene->addEntity("raylib text") + .addComponent(1920 / 4, 1080 / 2, 0) + .addComponent("Powered by:", 35, RAY::Vector2(), BLACK); + auto &otherRepoText = scene->addEntity("other repo text") + .addComponent(1920 / 4, 1080 / 4, 0) + .addComponent("Many Thanks to:", 35, RAY::Vector2(), BLACK); + auto &BriansRepo = scene->addEntity("thx brian") + .addComponent(1920 / 3.5, 1080 / 3.5, 0) + .addComponent("Brian Guitteny (and his team)", 35, RAY::Vector2(), BLACK); + auto &team = scene->addEntity("team") + .addComponent(1920 / 1.5, 1080 / 3.5, 0) + .addComponent("Team:\n Zoe Roux\n Clément Le Bihan\n Arthur Jamet\n Louis Auzuret\n Benjamin Henry\n Tom Augier", 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::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"); + }); + return scene; + } + +} \ No newline at end of file diff --git a/sources/Runner/GameScene.cpp b/sources/Runner/GameScene.cpp new file mode 100644 index 00000000..f7f0107e --- /dev/null +++ b/sources/Runner/GameScene.cpp @@ -0,0 +1,71 @@ +#include +#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/Animator/AnimatorComponent.hpp" +#include "Component/Animation/AnimationsComponent.hpp" +#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/Button/ButtonComponent.hpp" +#include "Drawables/2D/Text.hpp" +#include "Component/Gravity/GravityComponent.hpp" +#include "Component/BumperTimer/BumperTimerComponent.hpp" +#include "Model/Model.hpp" +#include "Map/Map.hpp" + +namespace RAY3D = RAY::Drawables::Drawables3D; + +namespace BBM +{ + std::shared_ptr Runner::loadGameScene() + { + auto scene = std::make_shared(); + 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"} + }; + + return scene.addEntity("player") + .addComponent() + .addComponent("assets/player/player.iqm", true) + .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}) + .addComponent() + .addComponent(soundPath) + .addComponent("assets/musics/music_battle.ogg") + .addComponent() + .addComponent() + .addComponent(1, [](WAL::Entity &entity, WAL::Wal &) { + auto &animation = entity.getComponent(); + animation.setAnimIndex(5); + }); + } +} \ 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 new file mode 100644 index 00000000..42067222 --- /dev/null +++ b/sources/Runner/MainMenuScene.cpp @@ -0,0 +1,118 @@ + +#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::loadMainMenuScene() + { + 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_title.ogg") + .addComponent(sounds); + scene->addEntity("background") + .addComponent() + .addComponent("assets/plain_menu_background.png"); + scene->addEntity("logo") + .addComponent(1920 / 3, 180, 0) + .addComponent("assets/logo_small.png"); + auto &play = scene->addEntity("play button") + .addComponent(1920 / 2.5, 1080 - 540, 0) + .addComponent("assets/buttons/button_new_game.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_new_game.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_new_game_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::LobbyScene; + }); + auto &settings = scene->addEntity("settings button") + .addComponent(1920 / 2.5, 1080 - 360, 0) + .addComponent("assets/buttons/button_settings.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_settings.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_settings_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::SettingsScene; + }); + auto &exit = scene->addEntity("exit button") + .addComponent(1920 / 2.5, 1080 - 180, 0) + .addComponent("assets/buttons/button_exit.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_exit.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_exit_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + wal.shouldClose = true; + }); + auto &credits = scene->addEntity("credit button") + .addComponent(1920 - 100, 1080 - 30, 0) + .addComponent("Credits", 20, RAY::Vector2(), BLACK) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); + + text->setColor(BLACK); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); + + text->setColor(ORANGE); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + gameState.nextScene = BBM::GameState::SceneID::CreditScene; + }); + play.getComponent().setButtonLinks(nullptr, &settings); + settings.getComponent().setButtonLinks(&play, &exit); + exit.getComponent().setButtonLinks(&settings, &credits, nullptr, &credits); + credits.getComponent().setButtonLinks(&exit, nullptr, &exit); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/PauseMenuScene.cpp b/sources/Runner/PauseMenuScene.cpp new file mode 100644 index 00000000..cf7d66c6 --- /dev/null +++ b/sources/Runner/PauseMenuScene.cpp @@ -0,0 +1,100 @@ + +#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::loadPauseMenuScene() + { + 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("pause text") + .addComponent(1920 / 2.5, 180, 0) + .addComponent("PAUSE", 120, RAY::Vector2(), ORANGE); + auto &play = scene->addEntity("play button") + .addComponent(1920 / 6.5, 1080 - 360, 0) + .addComponent("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.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_back_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::GameScene; + }); + auto &settings = scene->addEntity("settings button") + .addComponent(1920 / 2.5, 1080 - 360, 0) + .addComponent("assets/buttons/button_settings.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_settings.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_settings_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::SettingsScene; + }); + auto &exit = scene->addEntity("exit button") + .addComponent(1920 / 1.5, 1080 - 360, 0) + .addComponent("assets/buttons/button_exit.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_exit.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_exit_hovered.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; + }); + //needed material + //music + play.getComponent().setButtonLinks(nullptr, nullptr, nullptr, &settings); + settings.getComponent().setButtonLinks(nullptr, nullptr, &play, &exit); + exit.getComponent().setButtonLinks(nullptr, nullptr, &settings, nullptr); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index a3279b5d..cadb0b10 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -6,14 +6,10 @@ #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 "Component/Movable/MovableComponent.hpp" -#include "Component/Controllable/ControllableComponent.hpp" -#include "Component/Keyboard/KeyboardComponent.hpp" #include "System/Gamepad/GamepadSystem.hpp" #include #include "Component/Button/ButtonComponent.hpp" @@ -27,33 +23,27 @@ #include "Component/Renderer/Drawable2DComponent.hpp" #include "Runner.hpp" #include "Models/GameState.hpp" -#include #include #include #include #include #include -#include +#include +#include #include #include -#include -#include -#include "Component/Animation/AnimationsComponent.hpp" #include "System/Animation/AnimationsSystem.hpp" -#include "Component/Shaders/ShaderComponent.hpp" #include "Map/Map.hpp" #include "System/IAControllable/IAControllableSystem.hpp" #include "System/MenuControllable/MenuControllableSystem.hpp" -#include #include -#include "Component/Music/MusicComponent.hpp" -#include "Component/Sound/SoundComponent.hpp" #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 { @@ -61,13 +51,17 @@ 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) { + if (gameState.currentScene == GameState::SceneID::GameScene || gameState.currentScene == GameState::SceneID::SplashScreen) { for (auto &[_, component]: engine.getScene()->view()) { - if (component.pause) { + if (component.pause && gameState.currentScene == GameState::SceneID::GameScene) { gameState.nextScene = GameState::SceneID::PauseMenuScene; break; + } else if (gameState.currentScene == GameState::SceneID::SplashScreen && component.jump) { + gameState.nextScene = GameState::SceneID::TitleScreenScene; + break; } } } @@ -84,6 +78,7 @@ namespace BBM .addSystem() .addSystem() .addSystem() + .addSystem() .addSystem() .addSystem() .addSystem() @@ -96,6 +91,9 @@ namespace BBM .addSystem() .addSystem() .addSystem() + .addSystem() + .addSystem() + .addSystem() .addSystem(); } @@ -108,515 +106,30 @@ namespace BBM .addSystem(window); } - std::shared_ptr Runner::loadTitleScreenScene() + void Runner::addMenuControl(WAL::Scene &scene) { - static const std::map sounds = { - {SoundComponent::JUMP, "assets/sounds/click.ogg"} - }; - auto scene = std::make_shared(); - scene->addEntity("control") - .addComponent() - .addComponent() - .addComponent(sounds) - .addComponent("assets/musics/music_title.ogg"); - scene->addEntity("background") - .addComponent() - .addComponent("assets/plain_menu_background.png"); - scene->addEntity("logo") - .addComponent(320, 180, 0) - .addComponent("assets/logo_big.png"); - scene->addEntity("text_prompt") - .addComponent(1920 / 2.5, 1080 - 130, 0) - .addComponent("Press space", 70, RAY::Vector2(), BLACK) - .addComponent() - .addComponent() - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; - }); - return scene; - } - - std::shared_ptr Runner::loadMainMenuScene() - { - static const std::map sounds = { - {SoundComponent::JUMP, "assets/sounds/click.ogg"} - }; - auto scene = std::make_shared(); - - scene->addEntity("Control entity") - .addComponent() - .addComponent() - .addComponent("assets/musics/music_title.ogg") - .addComponent(sounds); - scene->addEntity("background") - .addComponent() - .addComponent("assets/plain_menu_background.png"); - scene->addEntity("logo") - .addComponent(1920 / 3, 180, 0) - .addComponent("assets/logo_small.png"); - auto &play = scene->addEntity("play button") - .addComponent(1920 / 2.5, 1080 - 540, 0) - .addComponent("assets/buttons/button_new_game.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_new_game.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_new_game_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - gameState.nextScene = BBM::GameState::SceneID::GameScene; - }); - auto &settings = scene->addEntity("settings button") - .addComponent(1920 / 2.5, 1080 - 360, 0) - .addComponent("assets/buttons/button_settings.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_settings.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_settings_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - gameState.nextScene = BBM::GameState::SceneID::SettingsScene; - }); - auto &exit = scene->addEntity("exit button") - .addComponent(1920 / 2.5, 1080 - 180, 0) - .addComponent("assets/buttons/button_exit.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_exit.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_exit_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - wal.shouldClose = true; - }); - auto &credits = scene->addEntity("credit button") - .addComponent(1920 - 100, 1080 - 30, 0) - .addComponent("Credits", 20, RAY::Vector2(), BLACK) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); - - text->setColor(BLACK); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); - - text->setColor(ORANGE); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - gameState.nextScene = BBM::GameState::SceneID::CreditScene; - }); - play.getComponent().setButtonLinks(nullptr, &settings); - settings.getComponent().setButtonLinks(&play, &exit); - exit.getComponent().setButtonLinks(&settings, &credits, nullptr, &credits); - credits.getComponent().setButtonLinks(&exit, nullptr, &exit); - return scene; - } - - std::shared_ptr Runner::loadPauseMenuScene() - { - static const std::map sounds = { - {SoundComponent::JUMP, "assets/sounds/click.ogg"} - }; - auto scene = std::make_shared(); - - scene->addEntity("Control entity") - .addComponent() - .addComponent() - .addComponent("assets/musics/music_player_select.ogg") - .addComponent(sounds); - scene->addEntity("background") - .addComponent() - .addComponent("assets/plain_menu_background.png"); - scene->addEntity("pause text") - .addComponent(1920 / 2.5, 180, 0) - .addComponent("PAUSE", 120, RAY::Vector2(), ORANGE); - auto &play = scene->addEntity("play button") - .addComponent(1920 / 6.5, 1080 - 360, 0) - .addComponent("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.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_back_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - gameState.nextScene = BBM::GameState::SceneID::GameScene; - }); - auto &settings = scene->addEntity("settings button") - .addComponent(1920 / 2.5, 1080 - 360, 0) - .addComponent("assets/buttons/button_settings.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_settings.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_settings_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - gameState.nextScene = BBM::GameState::SceneID::SettingsScene; - }); - auto &exit = scene->addEntity("exit button") - .addComponent(1920 / 1.5, 1080 - 360, 0) - .addComponent("assets/buttons/button_exit.png") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_exit.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_exit_hovered.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; - }); - //needed material - //music - play.getComponent().setButtonLinks(nullptr, nullptr, nullptr, &settings); - settings.getComponent().setButtonLinks(nullptr, nullptr, &play, &exit); - exit.getComponent().setButtonLinks(nullptr, nullptr, &settings, nullptr); - return scene; - } - - std::shared_ptr Runner::loadSettingsMenuScene() - { - auto scene = std::make_shared(); - static const std::map sounds = { - {SoundComponent::JUMP, "assets/sounds/click.ogg"} - }; - - scene->addEntity("Control entity") - .addComponent() - .addComponent() - .addComponent("assets/musics/music_title.ogg") - .addComponent(sounds); - scene->addEntity("background") - .addComponent() - .addComponent("assets/plain_menu_background.png"); - scene->addEntity("logo") - .addComponent(1920 / 3, 180, 0) - .addComponent("assets/logo_small.png"); - auto &music = scene->addEntity("music text") - .addComponent(1920 / 2.5, 1080 - 540, 0) - .addComponent("Music Volume", 70, RAY::Vector2(), BLACK) - .addComponent() - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); - - auto &musicUp = scene->addEntity("music up button") - .addComponent(1920 / 1.5, 1080 - 540, 0) - .addComponent("assets/buttons/button_plus.png") - .addComponent("assets/musics/music_title.ogg") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_plus.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - auto &component = entity.getComponent(); - - component.turnUpVolume(); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_plus_hovered.png"); - }); - - auto &musicDown = scene->addEntity("music down button") - .addComponent(1920 / 3, 1080 - 540, 0) - .addComponent("assets/buttons/button_minus.png") - .addComponent("assets/musics/music_title.ogg") - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_minus.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - auto &component = entity.getComponent(); - - component.turnDownVolume(); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_minus_hovered.png"); - }); - - auto &sound = scene->addEntity("sound text") - .addComponent(1920 / 2.5, 1080 - 360, 0) - .addComponent("Sound Volume", 70, RAY::Vector2(), BLACK) - .addComponent() - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); - - auto &soundUp = scene->addEntity("sound up button") - .addComponent(1920 / 1.5, 1080 - 360, 0) - .addComponent("assets/buttons/button_plus.png") - .addComponent(sounds) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - auto &component = entity.getComponent(); - - component.turnUpVolume(); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_plus.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_plus_hovered.png"); - }); - - auto &soundDown = scene->addEntity("sound down button") - .addComponent(1920 / 3, 1080 - 360, 0) - .addComponent("assets/buttons/button_minus.png") - .addComponent(sounds) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_minus.png"); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - auto &component = entity.getComponent(); - - component.turnDownVolume(); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - - texture->use("assets/buttons/button_minus_hovered.png"); - }); - - auto &debug = scene->addEntity("debug text") - .addComponent(1920 / 2.5, 1080 - 180, 0) - .addComponent("Debug Mode: 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("Debug Mode: On"); - wal.getSystem().setDebug(true); - } else { - text->setText("Debug Mode: Off"); - wal.getSystem().setDebug(false); - } - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) - .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); - 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"); - }); - //needed material - //music - //sound - - music.getComponent().setButtonLinks(nullptr, &sound, &musicDown, &musicUp); - musicDown.getComponent().setButtonLinks(&debug, &sound, nullptr, &music); - musicUp.getComponent().setButtonLinks(&debug, &sound, &music); - sound.getComponent().setButtonLinks(&music, &debug, &soundDown, &soundUp); - soundDown.getComponent().setButtonLinks(&music, &debug, nullptr, &sound); - soundUp.getComponent().setButtonLinks(&music, &debug, &sound); - debug.getComponent().setButtonLinks(&sound, &back, &back); - back.getComponent().setButtonLinks(&debug, nullptr, nullptr, &debug); - return scene; - } - - std::shared_ptr Runner::loadGameScene() - { - auto scene = std::make_shared(); - scene->addEntity("control") + scene.addEntity("Keyboard default control") .addComponent() .addComponent(); - 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"} - }; - scene->addEntity("player") - .addComponent() - .addComponent("assets/player/player.iqm", true, std::make_pair(MAP_DIFFUSE, "assets/player/blue.png")) + scene.addEntity("Keyboard second control") .addComponent() - .addComponent() - //.addComponent() - .addComponent("./ai_scripts/john.lua") - .addComponent("assets/shaders/glsl330/predator.fs") - .addComponent>() - //.addComponent(0) - .addComponent(RAY::ModelAnimations("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) { - 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; - } - - std::shared_ptr Runner::loadCreditScene() - { - auto scene = std::make_shared(); - static const std::map sounds = { - {SoundComponent::JUMP, "assets/sounds/click.ogg"} - }; - - scene->addEntity("background") - .addComponent() - .addComponent("assets/plain_menu_background.png"); - - scene->addEntity("Control entity") - .addComponent() - .addComponent() - .addComponent("assets/musics/music_title.ogg") - .addComponent(sounds); - - auto &raylibLogo = scene->addEntity("raylib logo") - .addComponent(1920 / 4, 1080 / 1.75, 0) - .addComponent("assets/raylib.png"); - auto &raylibText = scene->addEntity("raylib text") - .addComponent(1920 / 4, 1080 / 2, 0) - .addComponent("Powered by:", 35, RAY::Vector2(), BLACK); - auto &otherRepoText = scene->addEntity("other repo text") - .addComponent(1920 / 4, 1080 / 4, 0) - .addComponent("Many Thanks to:", 35, RAY::Vector2(), BLACK); - auto &BriansRepo = scene->addEntity("thx brian") - .addComponent(1920 / 3.5, 1080 / 3.5, 0) - .addComponent("Brian Guitteny (and his team)", 35, RAY::Vector2(), BLACK); - auto &team = scene->addEntity("team") - .addComponent(1920 / 1.5, 1080 / 3.5, 0) - .addComponent("Team:\n Zoe Roux\n Clément Le Bihan\n Arthur Jamet\n Louis Auzuret\n Benjamin Henry\n Tom Augier", 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::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"); - }); - return scene; + .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() @@ -626,7 +139,7 @@ namespace BBM Runner::addSystems(wal); Runner::enableRaylib(wal); Runner::loadScenes(); - wal.changeScene(Runner::gameState._loadedScenes[GameState::SceneID::TitleScreenScene]); + wal.changeScene(Runner::gameState._loadedScenes[GameState::SceneID::SplashScreen]); try { wal.run(Runner::updateState, Runner::gameState); diff --git a/sources/Runner/Runner.hpp b/sources/Runner/Runner.hpp index 6c42adfe..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,17 @@ 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(); + //! @brief loads all scenes in the game state static void loadScenes(); }; diff --git a/sources/Runner/SettingsMenuScene.cpp b/sources/Runner/SettingsMenuScene.cpp new file mode 100644 index 00000000..8883bbeb --- /dev/null +++ b/sources/Runner/SettingsMenuScene.cpp @@ -0,0 +1,211 @@ + +#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" +#include "System/Renderer/RenderSystem.hpp" + +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + std::shared_ptr Runner::loadSettingsMenuScene() + { + 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_title.ogg") + .addComponent(sounds); + scene->addEntity("background") + .addComponent() + .addComponent("assets/plain_menu_background.png"); + scene->addEntity("logo") + .addComponent(1920 / 3, 180, 0) + .addComponent("assets/logo_small.png"); + auto &music = scene->addEntity("music text") + .addComponent(1920 / 2.5, 1080 - 540, 0) + .addComponent("Music Volume", 70, RAY::Vector2(), BLACK) + .addComponent() + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(BLACK); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(ORANGE); + }); + + auto &musicUp = scene->addEntity("music up button") + .addComponent(1920 / 1.5, 1080 - 540, 0) + .addComponent("assets/buttons/button_plus.png") + .addComponent("assets/musics/music_title.ogg") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_plus.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto &component = entity.getComponent(); + + component.turnUpVolume(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_plus_hovered.png"); + }); + + auto &musicDown = scene->addEntity("music down button") + .addComponent(1920 / 3, 1080 - 540, 0) + .addComponent("assets/buttons/button_minus.png") + .addComponent("assets/musics/music_title.ogg") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_minus.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto &component = entity.getComponent(); + + component.turnDownVolume(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_minus_hovered.png"); + }); + + auto &sound = scene->addEntity("sound text") + .addComponent(1920 / 2.5, 1080 - 360, 0) + .addComponent("Sound Volume", 70, RAY::Vector2(), BLACK) + .addComponent() + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(BLACK); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(ORANGE); + }); + + auto &soundUp = scene->addEntity("sound up button") + .addComponent(1920 / 1.5, 1080 - 360, 0) + .addComponent("assets/buttons/button_plus.png") + .addComponent(sounds) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto &component = entity.getComponent(); + + component.turnUpVolume(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_plus.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_plus_hovered.png"); + }); + + auto &soundDown = scene->addEntity("sound down button") + .addComponent(1920 / 3, 1080 - 360, 0) + .addComponent("assets/buttons/button_minus.png") + .addComponent(sounds) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_minus.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto &component = entity.getComponent(); + + component.turnDownVolume(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_minus_hovered.png"); + }); + + auto &debug = scene->addEntity("debug text") + .addComponent(1920 / 2.5, 1080 - 180, 0) + .addComponent("Debug Mode: 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("Debug Mode: On"); + wal.getSystem().setDebug(true); + } else { + text->setText("Debug Mode: Off"); + wal.getSystem().setDebug(false); + } + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(BLACK); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + entity.getComponent().drawable->setColor(ORANGE); + }); + 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"); + }); + //needed material + //music + //sound + + music.getComponent().setButtonLinks(nullptr, &sound, &musicDown, &musicUp); + musicDown.getComponent().setButtonLinks(&debug, &sound, nullptr, &music); + musicUp.getComponent().setButtonLinks(&debug, &sound, &music); + sound.getComponent().setButtonLinks(&music, &debug, &soundDown, &soundUp); + soundDown.getComponent().setButtonLinks(&music, &debug, nullptr, &sound); + soundUp.getComponent().setButtonLinks(&music, &debug, &sound); + debug.getComponent().setButtonLinks(&sound, &back, &back); + back.getComponent().setButtonLinks(&debug, nullptr, nullptr, &debug); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/SplashScreenScene.cpp b/sources/Runner/SplashScreenScene.cpp new file mode 100644 index 00000000..a22d20da --- /dev/null +++ b/sources/Runner/SplashScreenScene.cpp @@ -0,0 +1,36 @@ + +#include +#include +#include "Runner.hpp" +#include "Component/Music/MusicComponent.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" +#include "Component/IntroAnimation/IntroAnimationComponent.hpp" + +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + std::shared_ptr Runner::loadSplashScreenScene() + { + auto scene = std::make_shared(); + + addMenuControl(*scene); + auto &splashComponent = scene->addEntity("animation component") + .addComponent(); + auto &background = scene->addEntity("background") + .addComponent(0, 0, 0) + .addComponent(RAY::Vector2(), RAY::Vector2(1920, 1080)); + auto &text = scene->addEntity("powered by text") + .addComponent(1920 / 2 - 200, 1080 / 2 - 180, 0) + .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); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/TitleScreenScene.cpp b/sources/Runner/TitleScreenScene.cpp new file mode 100644 index 00000000..729434f3 --- /dev/null +++ b/sources/Runner/TitleScreenScene.cpp @@ -0,0 +1,46 @@ + +#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::loadTitleScreenScene() + { + static const std::map sounds = { + {SoundComponent::JUMP, "assets/sounds/click.ogg"} + }; + auto scene = std::make_shared(); + addMenuControl(*scene); + scene->addEntity("control") + .addComponent(sounds) + .addComponent("assets/musics/music_title.ogg"); + scene->addEntity("background") + .addComponent() + .addComponent("assets/plain_menu_background.png"); + scene->addEntity("logo") + .addComponent(320, 180, 0) + .addComponent("assets/logo_big.png"); + scene->addEntity("text_prompt") + .addComponent(1920 / 2.5, 1080 - 130, 0) + .addComponent("Press space", 70, RAY::Vector2(), BLACK) + .addComponent() + .addComponent() + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; + }); + return scene; + } +} \ No newline at end of file diff --git a/sources/System/BombHolder/BombHolderSystem.cpp b/sources/System/BombHolder/BombHolderSystem.cpp index 6a5dac6e..6fe1055d 100644 --- a/sources/System/BombHolder/BombHolderSystem.cpp +++ b/sources/System/BombHolder/BombHolderSystem.cpp @@ -2,6 +2,7 @@ // Created by Zoe Roux on 5/31/21. // +#include #include #include "Component/Timer/TimerComponent.hpp" #include "System/Event/EventSystem.hpp" @@ -21,25 +22,37 @@ namespace BBM std::chrono::nanoseconds BombHolderSystem::explosionTimer = 2s; void BombHolderSystem::_bombCollide(WAL::Entity &entity, - const WAL::Entity &bomb, - CollisionComponent::CollidedAxis collidedAxis) + const WAL::Entity &bomb, + CollisionComponent::CollidedAxis collidedAxis) { auto &bombInfo = bomb.getComponent(); if (bombInfo.ignoreOwner && bombInfo.ownerID == entity.getUid()) return; - return MapGenerator::wallCollided( entity, bomb, collidedAxis); + return MapGenerator::wallCollided(entity, bomb, collidedAxis); } - BombHolderSystem::BombHolderSystem(WAL::Wal &wal) : System(wal) {} - void BombHolderSystem::_dispatchExplosion(Vector3f position, WAL::Wal &wal, int count) + void BombHolderSystem::_dispatchExplosion(const Vector3f &position, + WAL::Wal &wal, + int size, + ExpansionDirection expansionDirections) { - if (count <= 0) + if (size <= 0) return; - wal.getSystem().dispatchEvent([position, count](WAL::Wal &wal) { + wal.getScene()->scheduleNewEntity("explosion") + .addComponent(position) + .addComponent(1s, [](WAL::Entity &explosion, WAL::Wal &wal) { + explosion.scheduleDeletion(); + }) + .addComponent("assets/bombs/explosion/explosion.glb", false, + std::make_pair( + MAP_DIFFUSE, + "assets/bombs/explosion/blast.png" + )); + wal.getSystem().dispatchEvent([position, size, expansionDirections](WAL::Wal &wal) { for (auto &[entity, pos, _] : wal.getScene()->view>()) { if (pos.position.round() == position) { if (auto *health = entity.tryGetComponent()) @@ -47,10 +60,18 @@ namespace BBM return; } } - _dispatchExplosion(position + Vector3f(1, 0, 0), wal, count - 1); - _dispatchExplosion(position + Vector3f(-1, 0, 0), wal, count - 1); - _dispatchExplosion(position + Vector3f(0, 0, 1), wal, count - 1); - _dispatchExplosion(position + Vector3f(0, 0, -1), wal, count - 1); + if (expansionDirections & ExpansionDirection::FRONT) { + _dispatchExplosion(position + Vector3f{1, 0, 0}, wal, size - 1, ExpansionDirection::FRONT); + } + if (expansionDirections & ExpansionDirection::BACK) { + _dispatchExplosion(position + Vector3f{-1, 0, 0}, wal, size - 1, ExpansionDirection::BACK); + } + if (expansionDirections & ExpansionDirection::LEFT) { + _dispatchExplosion(position + Vector3f{0, 0, 1}, wal, size - 1, ExpansionDirection::LEFT); + } + if (expansionDirections & ExpansionDirection::RIGHT) { + _dispatchExplosion(position + Vector3f{0, 0, -1}, wal, size - 1, ExpansionDirection::RIGHT); + } }); } @@ -59,7 +80,7 @@ namespace BBM bomb.scheduleDeletion(); auto position = bomb.getComponent().position.round(); auto explosionRadius = bomb.getComponent().explosionRadius; - _dispatchExplosion(position, wal, 3 + (explosionRadius - 3)); + _dispatchExplosion(position, wal, explosionRadius); } void BombHolderSystem::_spawnBomb(Vector3f position, BombHolderComponent &holder, unsigned id) @@ -68,16 +89,21 @@ namespace BBM .addComponent(position.round()) .addComponent(holder.damage, holder.explosionRadius, id) .addComponent(BombHolderSystem::explosionTimer, &BombHolderSystem::_bombExplosion) - .addComponent(WAL::Callback(), - &BombHolderSystem::_bombCollide, 0.25, .75) + .addComponent( + WAL::Callback(), + &BombHolderSystem::_bombCollide, 0.25, .75) .addComponent("assets/bombs/bomb.obj", false, - std::make_pair(MAP_DIFFUSE, "assets/bombs/bomb_normal.png")); + std::make_pair( + MAP_DIFFUSE, + "assets/bombs/bomb_normal.png" + )); holder.damage = 1; holder.explosionRadius = 3; } - void BombHolderSystem::onUpdate(WAL::ViewEntity &entity, - std::chrono::nanoseconds dtime) + void + BombHolderSystem::onUpdate(WAL::ViewEntity &entity, + std::chrono::nanoseconds dtime) { auto &holder = entity.get(); auto &position = entity.get(); diff --git a/sources/System/BombHolder/BombHolderSystem.hpp b/sources/System/BombHolder/BombHolderSystem.hpp index 481d7697..c5631190 100644 --- a/sources/System/BombHolder/BombHolderSystem.hpp +++ b/sources/System/BombHolder/BombHolderSystem.hpp @@ -14,6 +14,22 @@ namespace BBM { + enum ExpansionDirection + { + UP = 1, + DOWN = 2, + LEFT = 4, + RIGHT = 8, + FRONT = 16, + BACK = 32 + }; + + //! @brief Ta avoid explicit casting + inline ExpansionDirection operator|(ExpansionDirection a, ExpansionDirection b) + { + return static_cast(static_cast(a) | static_cast(b)); + } + //! @brief The system that allow one to place bombs. class BombHolderSystem : public WAL::System { @@ -22,13 +38,23 @@ namespace BBM void _spawnBomb(Vector3f position, BombHolderComponent &holder, unsigned id); //! @brief Spawn a bomb at the specified position. - static void _dispatchExplosion(Vector3f position, WAL::Wal &, int count); + static void _dispatchExplosion(const Vector3f &position, + WAL::Wal &wal, + int size, + ExpansionDirection expansionDirections = ExpansionDirection::DOWN + | ExpansionDirection::UP + | ExpansionDirection::FRONT + | ExpansionDirection::BACK + | ExpansionDirection::LEFT + | ExpansionDirection::RIGHT); //! @brief The method triggered when the bomb explode. static void _bombExplosion(WAL::Entity &bomb, WAL::Wal &); //! @brief The method called when a player collide with a bomb. - static void _bombCollide(WAL::Entity &entity, const WAL::Entity &wall, BBM::CollisionComponent::CollidedAxis collidedAxis); + static void + _bombCollide(WAL::Entity &entity, const WAL::Entity &wall, BBM::CollisionComponent::CollidedAxis collidedAxis); + public: //! @brief The explosion time of new bombs. static std::chrono::nanoseconds explosionTimer; @@ -39,11 +65,14 @@ namespace BBM //! @brief A default constructor explicit BombHolderSystem(WAL::Wal &wal); + //! @brief A bomb holder system is copy constructable BombHolderSystem(const BombHolderSystem &) = default; + //! @brief A default destructor ~BombHolderSystem() override = default; + //! @brief A bomb holder system is not assignable. BombHolderSystem &operator=(const BombHolderSystem &) = delete; }; -} +} \ No newline at end of file diff --git a/sources/System/BumperTimer/BumperTimerSystem.cpp b/sources/System/BumperTimer/BumperTimerSystem.cpp new file mode 100644 index 00000000..36c8b93f --- /dev/null +++ b/sources/System/BumperTimer/BumperTimerSystem.cpp @@ -0,0 +1,25 @@ +// +// Created by Tom Augier on 2021-06-09. +// + +#include "BumperTimerSystem.hpp" + +namespace BBM +{ + BumperTimerSystem::BumperTimerSystem(WAL::Wal &wal) + : System(wal) + {} + + void BumperTimerSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &bumperTimer = entity.get(); + + if (bumperTimer._isReseting) { + bumperTimer.nextReset -= dtime; + if (bumperTimer.nextReset <= 0ns) { + bumperTimer.nextReset = bumperTimer.resetRate; + bumperTimer._isReseting = false; + } + } + } +} \ No newline at end of file diff --git a/sources/System/BumperTimer/BumperTimerSystem.hpp b/sources/System/BumperTimer/BumperTimerSystem.hpp new file mode 100644 index 00000000..d1bbe2e8 --- /dev/null +++ b/sources/System/BumperTimer/BumperTimerSystem.hpp @@ -0,0 +1,29 @@ +// +// Created by Tom Augier on 2021-06-09. +// + +#pragma once + +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/BumperTimer/BumperTimerComponent.hpp" +#include "System/System.hpp" + +namespace BBM +{ + //! @brief A system to handle BumperTimer entities. + class BumperTimerSystem : public WAL::System + { + public: + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + //! @brief A default constructor + explicit BumperTimerSystem(WAL::Wal &wal); + //! @brief A BumperTimer system is copy constructable + BumperTimerSystem(const BumperTimerSystem &) = default; + //! @brief A default destructor + ~BumperTimerSystem() override = default; + //! @brief A system is not assignable. + BumperTimerSystem &operator=(const BumperTimerSystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/Collision/CollisionSystem.cpp b/sources/System/Collision/CollisionSystem.cpp index f9d3b12f..8e96e541 100644 --- a/sources/System/Collision/CollisionSystem.cpp +++ b/sources/System/Collision/CollisionSystem.cpp @@ -22,7 +22,7 @@ namespace BBM return (overlapX && overlapY && overlapZ); } - void CollisionSystem::onFixedUpdate(WAL::ViewEntity &entity) + void CollisionSystem::onFixedUpdate(WAL::ViewEntity &entity) { unsigned int entityUid = entity->getUid(); auto &posA = entity.get(); @@ -32,8 +32,10 @@ namespace BBM Vector3f pointAy = pointA; Vector3f pointAz = pointA; - if (auto *movable = entity->tryGetComponent()) { - auto vel = movable->getVelocity(); + auto &movable = entity.get(); + const auto &vel = movable.getVelocity(); + + if (!vel.isNull()) { pointAx.x += vel.x; pointAy.y += vel.y; pointAz.z += vel.z; @@ -42,13 +44,21 @@ namespace BBM Vector3f minAx = Vector3f::min(pointAx, pointAx + colA.bound); Vector3f maxAx = Vector3f::max(pointAx, pointAx + colA.bound); - Vector3f minAy = Vector3f::min(pointAy, pointAy + colA.bound); - Vector3f maxAy = Vector3f::max(pointAy, pointAy + colA.bound); + Vector3f minAy; + Vector3f maxAy; - Vector3f minAz = Vector3f::min(pointAz, pointAz + colA.bound); - Vector3f maxAz = Vector3f::max(pointAz, pointAz + colA.bound); + Vector3f minAz; + Vector3f maxAz; - for (auto &[other, posB, colB] : this->getView()) { + if (!vel.isNull()) { + minAy = Vector3f::min(pointAy, pointAy + colA.bound); + maxAy = Vector3f::max(pointAy, pointAy + colA.bound); + + minAz = Vector3f::min(pointAz, pointAz + colA.bound); + maxAz = Vector3f::max(pointAz, pointAz + colA.bound); + } + + for (auto &[other, posB, colB] : this->_wal.getScene()->view()) { if (other.getUid() == entityUid) continue; @@ -59,13 +69,15 @@ namespace BBM Vector3f maxB = Vector3f::max(pointB, pointB + colB.bound); if (boxesCollide(minAx, maxAx, minB, maxB)) { - collidedAxis += CollisionComponent::CollidedAxis::X; + collidedAxis += vel.isNull() ? 7 : CollisionComponent::CollidedAxis::X; } - if (boxesCollide(minAy, maxAy, minB, maxB)) { - collidedAxis += CollisionComponent::CollidedAxis::Y; - } - if (boxesCollide(minAz, maxAz, minB, maxB)) { - collidedAxis += CollisionComponent::CollidedAxis::Z; + if (!vel.isNull()) { + if (boxesCollide(minAy, maxAy, minB, maxB)) { + collidedAxis += CollisionComponent::CollidedAxis::Y; + } + if (boxesCollide(minAz, maxAz, minB, maxB)) { + collidedAxis += CollisionComponent::CollidedAxis::Z; + } } if (collidedAxis) { colA.onCollide(entity, other, static_cast(collidedAxis)); diff --git a/sources/System/Collision/CollisionSystem.hpp b/sources/System/Collision/CollisionSystem.hpp index e1e75ede..d7d31595 100644 --- a/sources/System/Collision/CollisionSystem.hpp +++ b/sources/System/Collision/CollisionSystem.hpp @@ -10,16 +10,17 @@ #include "System/System.hpp" #include "Models/Vector3.hpp" #include "Component/Collision/CollisionComponent.hpp" +#include "Component/Movable/MovableComponent.hpp" #include "Component/Position/PositionComponent.hpp" namespace BBM { //! @brief A system to handle collisions. - class CollisionSystem : public WAL::System + class CollisionSystem : public WAL::System { public: //! @inherit - void onFixedUpdate(WAL::ViewEntity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor explicit CollisionSystem(WAL::Wal &wal); diff --git a/sources/System/Gamepad/GamepadSystem.cpp b/sources/System/Gamepad/GamepadSystem.cpp index ee4b8767..623d5edd 100644 --- a/sources/System/Gamepad/GamepadSystem.cpp +++ b/sources/System/Gamepad/GamepadSystem.cpp @@ -30,12 +30,12 @@ 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 -= gamepad.isDown(gamepadComponent.keyRight); - controllable.move.x += gamepad.isDown(gamepadComponent.keyLeft); - controllable.move.y += gamepad.isDown(gamepadComponent.keyUp); - controllable.move.y -= gamepad.isDown(gamepadComponent.keyDown); + controllable.move.x -= static_cast(gamepad.isDown(gamepadComponent.keyRight)); + controllable.move.x += static_cast(gamepad.isDown(gamepadComponent.keyLeft)); + controllable.move.y += static_cast(gamepad.isDown(gamepadComponent.keyUp)); + controllable.move.y -= static_cast(gamepad.isDown(gamepadComponent.keyDown)); } } \ No newline at end of file diff --git a/sources/System/Gravity/GravitySystem.cpp b/sources/System/Gravity/GravitySystem.cpp new file mode 100644 index 00000000..a61e4220 --- /dev/null +++ b/sources/System/Gravity/GravitySystem.cpp @@ -0,0 +1,21 @@ +// +// Created by Tom Augier on 2021-06-09. +// + +#include "GravitySystem.hpp" + +namespace BBM +{ + GravitySystem::GravitySystem(WAL::Wal &wal) + : System(wal) + {} + + void GravitySystem::onFixedUpdate(WAL::ViewEntity &entity) + { + auto &movable = entity.get(); + auto &position = entity.get(); + + if (position.getY() > 0) + movable.addForce(Vector3f(0, -0.1, 0)); + } +} \ No newline at end of file diff --git a/sources/System/Gravity/GravitySystem.hpp b/sources/System/Gravity/GravitySystem.hpp new file mode 100644 index 00000000..59963ac7 --- /dev/null +++ b/sources/System/Gravity/GravitySystem.hpp @@ -0,0 +1,30 @@ +// +// Created by Tom Augier on 2021-06-09. +// + +#pragma once + +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Gravity/GravityComponent.hpp" +#include "System/System.hpp" + +namespace BBM +{ + //! @brief A system to handle Gravity entities. + class GravitySystem : public WAL::System + { + public: + //! @inherit + void onFixedUpdate(WAL::ViewEntity &entity) override; + + //! @brief A default constructor + explicit GravitySystem(WAL::Wal &wal); + //! @brief A Gravity system is copy constructable + GravitySystem(const GravitySystem &) = default; + //! @brief A default destructor + ~GravitySystem() override = default; + //! @brief A system is not assignable. + GravitySystem &operator=(const GravitySystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/IntroAnimation/IntroAnimationSystem.cpp b/sources/System/IntroAnimation/IntroAnimationSystem.cpp new file mode 100644 index 00000000..887a11d8 --- /dev/null +++ b/sources/System/IntroAnimation/IntroAnimationSystem.cpp @@ -0,0 +1,103 @@ + +#include "Component/Button/ButtonComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "System/IntroAnimation/IntroAnimationSystem.hpp" +#include "Entity/Entity.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" +#include +#include +#include "Runner/Runner.hpp" +#include "Component/Music/MusicComponent.hpp" + +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + IntroAnimationSystem::IntroAnimationSystem(WAL::Wal &wal) + : System(wal), wal(wal) + {} + + void IntroAnimationSystem::onFixedUpdate(WAL::ViewEntity &entity) + { + static const RAY::Vector2 logoPos(1920 / 2 - 128, 1080 / 2 - 128); + auto &component = entity.get(); + auto scene = wal.getScene(); + RAY2D::Rectangle *rectangle = nullptr; + RAY2D::Text *text = nullptr; + static auto &rayText = scene->addEntity("raylibtext Rectangle") + .addComponent(1920 / 2 - 44, 1080 / 2 + 48, 0) + .addComponent("", 50, RAY::Vector2(), BLACK); + static auto &bottomRectangle = scene->addEntity("bottom Rectangle") + .addComponent(1920 / 2 - 128, 1080 / 2 - 128, 0) + .addComponent(logoPos, RAY::Vector2(16, 16), BLACK); + static auto &leftRectangle = scene->addEntity("left Rectangle") + .addComponent(1920 / 2 - 128, 1080 / 2 - 128, 0) + .addComponent(logoPos, RAY::Vector2(16, 16), BLACK); + static auto &rightRectangle = scene->addEntity("right Rectangle") + .addComponent(1920 / 2 - 128, 1080 / 2 - 128, 0) + .addComponent(logoPos, RAY::Vector2(16, 16), BLACK); + static auto &topRectangle = scene->addEntity("top Rectangle") + .addComponent(1920 / 2 - 128, 1080 / 2 - 128, 0) + .addComponent(logoPos, RAY::Vector2(16, 16), BLACK); + static short letterCounter = 0; + + switch (component.currentStep) + { + case IntroAnimationComponent::animationSteps::boxBlinking: + if ((component.frameCounter / 15) % 2) + topRectangle.getComponent().drawable->setColor(BLACK); + else + topRectangle.getComponent().drawable->setColor(WHITE); + if (component.frameCounter >= 60) { + component.currentStep = IntroAnimationComponent::animationSteps::topLeftgrowing; + component.frameCounter = -1; + topRectangle.getComponent().drawable->setColor(BLACK); + leftRectangle.getComponent().drawable->setColor(BLACK); + } + break; + case IntroAnimationComponent::animationSteps::topLeftgrowing: + rectangle = dynamic_cast(leftRectangle.getComponent().drawable.get()); + rectangle->incrementHeight(8); + rectangle = dynamic_cast(topRectangle.getComponent().drawable.get()); + rectangle->incrementWidth(8); + if (rectangle->getWidth() >= 256) { + component.currentStep = IntroAnimationComponent::animationSteps::bottomRightGrowing; + bottomRectangle.getComponent().position = Vector3f(1920 / 2 - 128, 1080 / 2 - 128 + 240, 0); + rightRectangle.getComponent().position = Vector3f(1920 / 2 - 128 + 240, 1080 / 2 - 128, 0); + } + break; + case IntroAnimationComponent::animationSteps::bottomRightGrowing: + rectangle = dynamic_cast(bottomRectangle.getComponent().drawable.get()); + rectangle->incrementWidth(8); + rectangle = dynamic_cast(rightRectangle.getComponent().drawable.get()); + rectangle->incrementHeight(8); + if (rectangle->getHeight() >= 256) { + component.currentStep = IntroAnimationComponent::animationSteps::lettersTyping; + component.frameCounter = 0; + } + break; + case IntroAnimationComponent::animationSteps::lettersTyping: + if ((component.frameCounter / 10) % 2) { + letterCounter++; + text = dynamic_cast(rayText.getComponent().drawable.get()); + if (letterCounter == 2) { + scene->addEntity("startup sound") + .addComponent("assets/sounds/splash_sound.ogg") + .getComponent().playMusic(); + } + text->setText(std::string("raylib").substr(0, letterCounter)); + } + if (component.frameCounter == 60) + Runner::gameState.nextScene = Runner::gameState.TitleScreenScene; + break; + default: + break; + } + component.frameCounter++; + } + + void IntroAnimationSystem::onSelfUpdate(void) + { + } +} \ No newline at end of file diff --git a/sources/System/IntroAnimation/IntroAnimationSystem.hpp b/sources/System/IntroAnimation/IntroAnimationSystem.hpp new file mode 100644 index 00000000..1a266443 --- /dev/null +++ b/sources/System/IntroAnimation/IntroAnimationSystem.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "Component/IntroAnimation/IntroAnimationComponent.hpp" +#include "System/System.hpp" + +namespace BBM +{ + //! @brief A system to handle Controllable entities in a menu. + class IntroAnimationSystem : public WAL::System + { + private: + //! @brief reference to wal + WAL::Wal &wal; + + public: + //! @inherit + void onSelfUpdate(void) override; + + //! @inherit + void onFixedUpdate(WAL::ViewEntity &entities) override; + + //! @brief A default constructor + IntroAnimationSystem(WAL::Wal &wal); + //! @brief A IntroAnimation system is not copy constructable + IntroAnimationSystem(const IntroAnimationSystem &) = delete; + //! @brief A default destructor + ~IntroAnimationSystem() override = default; + //! @brief A IntroAnimation system is assignable. + IntroAnimationSystem &operator=(const IntroAnimationSystem &) = default; + }; +} \ No newline at end of file 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; }; } diff --git a/sources/System/Renderer/RenderSystem.cpp b/sources/System/Renderer/RenderSystem.cpp index 07b64134..d21065c2 100644 --- a/sources/System/Renderer/RenderSystem.cpp +++ b/sources/System/Renderer/RenderSystem.cpp @@ -11,8 +11,8 @@ #include #include "Drawables/ADrawable3D.hpp" #include "Component/Shaders/ShaderComponent.hpp" - - +#include +#include "Models/Vector3.hpp" #include "Component/Collision/CollisionComponent.hpp" namespace BBM @@ -26,6 +26,20 @@ namespace BBM this->_window.setFPS(this->FPS); } + void RenderSystem::drawBoundingBox(const WAL::Entity &entity, const PositionComponent &posComponent, const Drawable3DComponent &drawable) const + { + auto *dimsComponent = entity.tryGetComponent(); + + //draws hitbox + if (dimsComponent) { + RAY::Drawables::Drawables3D::Cube boundingBox(posComponent.position, dimsComponent->bound, WHITE); + boundingBox.setDebugColor(RED); + boundingBox.drawWiresOn(this->_window); + } + //draws models contours + drawable.drawable->drawWiresOn(this->_window); + } + void RenderSystem::onSelfUpdate() { this->_camera.update(); @@ -42,6 +56,8 @@ namespace BBM drawable.drawable->drawOn(this->_window); if (modelShader) modelShader->model->resetShader(); + if (this->_debugMode) + this->drawBoundingBox(entity, pos, drawable); } this->_window.unuseCamera(); @@ -59,7 +75,7 @@ namespace BBM } } if (this->_debugMode) - this->_window.drawFPS(Vector2f()); + this->_window.drawFPS(Vector2f(10, 10)); this->_window.endDrawing(); } diff --git a/sources/System/Renderer/RenderSystem.hpp b/sources/System/Renderer/RenderSystem.hpp index e790a741..bff17267 100644 --- a/sources/System/Renderer/RenderSystem.hpp +++ b/sources/System/Renderer/RenderSystem.hpp @@ -6,6 +6,7 @@ #include "Component/Renderer/CameraComponent.hpp" #include "Component/Position/PositionComponent.hpp" +#include "Component/Renderer/Drawable3DComponent.hpp" #include "System/System.hpp" #include "Camera/Camera2D.hpp" #include "Window.hpp" @@ -39,6 +40,9 @@ namespace BBM //! @param debug true if debug mode should be enabled void setDebug(bool debug); + //! @param entity entity to draw bounding box of + void drawBoundingBox(const WAL::Entity &entity, const PositionComponent &posComponent, const Drawable3DComponent &drawable) const; + //! @brief ctor RenderSystem(WAL::Wal &wal, RAY::Window &window, bool debugMode = false); //! @brief Default copy ctor diff --git a/tests/CollisionTest.cpp b/tests/CollisionTest.cpp index bf5a31dc..6c0795c4 100644 --- a/tests/CollisionTest.cpp +++ b/tests/CollisionTest.cpp @@ -17,6 +17,8 @@ using namespace WAL; using namespace BBM; +// WARN THE COLLISION SYSTEM IS ONLY CHECKING/LOOPING ON MOVABLE ENTITIES + TEST_CASE("Collision test", "[Component][System]") { @@ -25,6 +27,7 @@ TEST_CASE("Collision test", "[Component][System]") wal.changeScene(std::make_shared()); wal.getScene()->addEntity("player") .addComponent() + .addComponent() .addComponent([](Entity &actual, const Entity &, int _) { try { auto &pos = actual.getComponent(); @@ -118,6 +121,7 @@ TEST_CASE("Collision test callbacks calls", "[Component][System]") wal.getScene()->addEntity("block") .addComponent(0, 0, 0) + .addComponent() .addComponent( [&nbCallbacksCalled](Entity &actual, const Entity &, int) { nbCallbacksCalled++; }, [&nbCallbacksCalled](Entity &actual, const Entity &, int) { @@ -156,6 +160,7 @@ TEST_CASE("Collision test callbacks args", "[Component][System]") wal.getScene()->addEntity("player") .addComponent() + .addComponent() .addComponent( [&nbCallbacksCalled](Entity &actual, const Entity &other, int) { nbCallbacksCalled++; @@ -170,6 +175,7 @@ TEST_CASE("Collision test callbacks args", "[Component][System]") wal.getScene()->addEntity("block") .addComponent(0, 0, 0) + .addComponent() .addComponent( [&nbCallbacksCalled](Entity &actual, const Entity &other, int) { nbCallbacksCalled++; @@ -193,6 +199,57 @@ TEST_CASE("Collision test callbacks args", "[Component][System]") REQUIRE(nbCallbacksCalled == 4); } +TEST_CASE("Collision test callbacks args with only one movable entity", "[Component][System]") +{ + int nbCallbacksCalled = 0; + Wal wal; + CollisionSystem collision(wal); + MovableSystem movable(wal); + + wal.changeScene(std::make_shared()); + + wal.getScene()->addEntity("player") + .addComponent() + .addComponent() + .addComponent( + [&nbCallbacksCalled](Entity &actual, const Entity &other, int) { + nbCallbacksCalled++; + REQUIRE(actual.getName() == "player"); + REQUIRE(other.getName() == "block"); + }, + [&nbCallbacksCalled](Entity &actual, const Entity &other, int) { + // lambda should not be called + nbCallbacksCalled++; + REQUIRE(other.getName() == "plfayer"); + REQUIRE(actual.getName() == "blofck"); + }, 0, 5.0); + + wal.getScene()->addEntity("block") + .addComponent(0, 0, 0) + .addComponent( + [&nbCallbacksCalled](Entity &actual, const Entity &other, int) { + // lambda should not be called + nbCallbacksCalled++; + REQUIRE(other.getName() == "playefr"); + REQUIRE(actual.getName() == "blocfk"); + }, + [&nbCallbacksCalled](Entity &actual, const Entity &other, int) { + nbCallbacksCalled++; + REQUIRE(actual.getName() == "player"); + REQUIRE(other.getName() == "block"); + }, 0, 1); + Entity &entity = wal.getScene()->getEntities().front(); + REQUIRE(entity.getComponent().position == Vector3f()); + + entity.getComponent().bound.x = 5; + entity.getComponent().bound.y = 5; + entity.getComponent().bound.z = 5; + + collision.update(std::chrono::nanoseconds(1)); + collision.fixedUpdate(); + REQUIRE(nbCallbacksCalled == 2); +} + TEST_CASE("Vector round", "[Vector]") { Vector3f v(1.3, 1.5, 1.7);