diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 9f352ac4..6c6d01e9 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -18,4 +18,9 @@ jobs: cmake --build . - name: CheckBinaryName shell: bash - run: test -f build/bomberman \ No newline at end of file + run: test -f build/bomberman + - name: Archive production artifact for Linux binary + uses: actions/upload-artifact@v1 + with: + name: BombermanLinux + path: build/bomberman \ No newline at end of file diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index a3a21944..6e6b3998 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -35,3 +35,8 @@ jobs: shell: bash if: matrix.name == 'Linux' run: test -f build/bomberman + - name: Archive production artifact for Windows binary + uses: actions/upload-artifact@v1 + with: + name: BombermanWindows.exe + path: build/Debug/bomberman.exe diff --git a/CMakeLists.txt b/CMakeLists.txt index 74f8a0b9..62587c04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,10 @@ add_subdirectory(${PROJECT_SOURCE_DIR}/lib/wal) add_subdirectory(${PROJECT_SOURCE_DIR}/lib/Ray) if (EMSCRIPTEN) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_DISABLE_EXCEPTION_CATCHING --shell-file ../sources/wasm/frontend.html --preload-file ../assets") - set(CMAKE_EXECUTABLE_SUFFIX ".html") + set(CMAKE_EXECUTABLE_SUFFIX ".html") endif () set(SOURCES @@ -151,12 +151,32 @@ set(SOURCES sources/Parser/Node.hpp sources/Utils/Utils.cpp sources/Utils/Utils.hpp + sources/Runner/HowToPlayScene.cpp + sources/Runner/ScoreScene.cpp + sources/System/Shaders/ShaderSystem.cpp + sources/System/Shaders/ShaderSystem.hpp + sources/System/Shaders/ShaderModelSystem.cpp + sources/System/Shaders/ShaderModelSystem.hpp + sources/System/Shaders/ShaderDrawable2DSystem.cpp + sources/System/Shaders/ShaderDrawable2DSystem.hpp + sources/Component/Shaders/Items/BombExplosionShaderComponent.cpp + sources/Component/Shaders/Items/BombExplosionShaderComponent.hpp + sources/Component/Shaders/Items/WhiteShaderComponent.cpp + sources/Component/Shaders/Items/WhiteShaderComponent.hpp + sources/System/Timer/TimerUISystem.hpp + sources/System/Timer/TimerUISystem.cpp + sources/System/Bonus/BonusUISystem.hpp + sources/System/Bonus/BonusUISystem.cpp + sources/Component/Color/ColorComponent.hpp + sources/Component/Color/ColorComponent.cpp + sources/Component/Stat/StatComponent.cpp + sources/Component/Stat/StatComponent.hpp ) add_executable(bomberman - sources/main.cpp - ${SOURCES} -) + sources/main.cpp + ${SOURCES} + ) target_include_directories(bomberman PUBLIC sources) target_link_libraries(bomberman PUBLIC wal ray) @@ -179,5 +199,5 @@ find_package(Catch2 QUIET) if (NOT Catch2_FOUND) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/lib/catch2) find_package(Catch2 REQUIRED) -endif() +endif () target_link_libraries(unit_tests PRIVATE Catch2::Catch2) diff --git a/assets/background_game.png b/assets/background_game.png new file mode 100644 index 00000000..22b4cd46 Binary files /dev/null and b/assets/background_game.png differ diff --git a/assets/buttons/button_htp.png b/assets/buttons/button_htp.png new file mode 100644 index 00000000..c54d0afd Binary files /dev/null and b/assets/buttons/button_htp.png differ diff --git a/assets/buttons/button_htp_hovered.png b/assets/buttons/button_htp_hovered.png new file mode 100644 index 00000000..227dcc7c Binary files /dev/null and b/assets/buttons/button_htp_hovered.png differ diff --git a/assets/buttons/cpu_add.png b/assets/buttons/cpu_add.png new file mode 100644 index 00000000..adf5167f Binary files /dev/null and b/assets/buttons/cpu_add.png differ diff --git a/assets/buttons/cpu_add_hovered.png b/assets/buttons/cpu_add_hovered.png new file mode 100644 index 00000000..51c828d9 Binary files /dev/null and b/assets/buttons/cpu_add_hovered.png differ diff --git a/assets/buttons/cpu_remove.png b/assets/buttons/cpu_remove.png new file mode 100644 index 00000000..cdec18dd Binary files /dev/null and b/assets/buttons/cpu_remove.png differ diff --git a/assets/buttons/cpu_remove_hovered.png b/assets/buttons/cpu_remove_hovered.png new file mode 100644 index 00000000..03d935bf Binary files /dev/null and b/assets/buttons/cpu_remove_hovered.png differ diff --git a/assets/game_background.png b/assets/game_background.png new file mode 100644 index 00000000..366ef882 Binary files /dev/null and b/assets/game_background.png differ diff --git a/assets/player/icons/ai.png b/assets/player/icons/ai.png index ccd108e6..7e069b3e 100644 Binary files a/assets/player/icons/ai.png and b/assets/player/icons/ai.png differ diff --git a/assets/player/ui/blue.png b/assets/player/ui/blue.png new file mode 100644 index 00000000..5243a306 Binary files /dev/null and b/assets/player/ui/blue.png differ diff --git a/assets/player/ui/green.png b/assets/player/ui/green.png new file mode 100644 index 00000000..2a24f76c Binary files /dev/null and b/assets/player/ui/green.png differ diff --git a/assets/player/ui/red.png b/assets/player/ui/red.png new file mode 100644 index 00000000..ad00d65c Binary files /dev/null and b/assets/player/ui/red.png differ diff --git a/assets/player/ui/yellow.png b/assets/player/ui/yellow.png new file mode 100644 index 00000000..a06c28ea Binary files /dev/null and b/assets/player/ui/yellow.png differ diff --git a/assets/shaders/alpha.fs b/assets/shaders/alpha.fs new file mode 100644 index 00000000..85f2c56c --- /dev/null +++ b/assets/shaders/alpha.fs @@ -0,0 +1,28 @@ +#version 330 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform float alpha; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord); + + // Convert texel color to grayscale using NTSC conversion weights + + texelColor.a = alpha; + + gl_FragColor = texelColor; + // Calculate final fragment color + //gl_FragColor = vec4(gray, gray, gray, texelColor.a); +} \ No newline at end of file diff --git a/assets/shaders/bomb.vs b/assets/shaders/bomb.vs new file mode 100644 index 00000000..26dd04b1 --- /dev/null +++ b/assets/shaders/bomb.vs @@ -0,0 +1,114 @@ +#version 100 + +// Classic Perlin 3D Noise +// by Stefan Gustavson +// +vec4 permute(vec4 x) { + return mod(((x * 34.0) + 1.0) * x, 289.0); +} +vec4 taylorInvSqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} +vec3 fade(vec3 t) { + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +float cnoise(vec3 P) { + vec3 Pi0 = floor(P); // Integer part for indexing + vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 + Pi0 = mod(Pi0, 289.0); + Pi1 = mod(Pi1, 289.0); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 / 7.0; + vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 / 7.0; + vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x, gy0.x, gz0.x); + vec3 g100 = vec3(gx0.y, gy0.y, gz0.y); + vec3 g010 = vec3(gx0.z, gy0.z, gz0.z); + vec3 g110 = vec3(gx0.w, gy0.w, gz0.w); + vec3 g001 = vec3(gx1.x, gy1.x, gz1.x); + vec3 g101 = vec3(gx1.y, gy1.y, gz1.y); + vec3 g011 = vec3(gx1.z, gy1.z, gz1.z); + vec3 g111 = vec3(gx1.w, gy1.w, gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform float frame; +uniform vec3 center; + +uniform float radius; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// NOTE: Add here your custom variables + +void main() { + // Send vertex attributes to fragment shader + fragPosition = vertexPosition + vertexPosition * vec3(cnoise(vec3(vertexNormal + vec3(frame))) * 0.5); + fragColor = vertexColor; + fragNormal = vertexNormal; + fragTexCoord = vertexTexCoord; + // Calculate final vertex position + gl_Position = mvp * vec4(fragPosition , radius); + //gl_Position = vec4(vertexNormal, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/explosion.fs b/assets/shaders/explosion.fs new file mode 100644 index 00000000..bd97a93d --- /dev/null +++ b/assets/shaders/explosion.fs @@ -0,0 +1,26 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; +varying vec3 fragNormal; +varying vec2 fragTexCoord; + +uniform sampler2D texture0; +uniform float alpha; + +void main() { + // Texel color fetching from texture sampler + + // NOTE: Implement here your fragment shader code + vec4 tmp; + tmp.rgb = texture2D(texture0, fragTexCoord).rgb; + + + tmp.a = alpha; + + gl_FragColor = tmp; + //gl_FragColor = vec4(fragColor.r, fragColor.g, fragColor.b, alpha); + +} \ No newline at end of file diff --git a/assets/shaders/explosion.vs b/assets/shaders/explosion.vs new file mode 100644 index 00000000..26dd04b1 --- /dev/null +++ b/assets/shaders/explosion.vs @@ -0,0 +1,114 @@ +#version 100 + +// Classic Perlin 3D Noise +// by Stefan Gustavson +// +vec4 permute(vec4 x) { + return mod(((x * 34.0) + 1.0) * x, 289.0); +} +vec4 taylorInvSqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} +vec3 fade(vec3 t) { + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +float cnoise(vec3 P) { + vec3 Pi0 = floor(P); // Integer part for indexing + vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 + Pi0 = mod(Pi0, 289.0); + Pi1 = mod(Pi1, 289.0); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 / 7.0; + vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 / 7.0; + vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x, gy0.x, gz0.x); + vec3 g100 = vec3(gx0.y, gy0.y, gz0.y); + vec3 g010 = vec3(gx0.z, gy0.z, gz0.z); + vec3 g110 = vec3(gx0.w, gy0.w, gz0.w); + vec3 g001 = vec3(gx1.x, gy1.x, gz1.x); + vec3 g101 = vec3(gx1.y, gy1.y, gz1.y); + vec3 g011 = vec3(gx1.z, gy1.z, gz1.z); + vec3 g111 = vec3(gx1.w, gy1.w, gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform float frame; +uniform vec3 center; + +uniform float radius; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// NOTE: Add here your custom variables + +void main() { + // Send vertex attributes to fragment shader + fragPosition = vertexPosition + vertexPosition * vec3(cnoise(vec3(vertexNormal + vec3(frame))) * 0.5); + fragColor = vertexColor; + fragNormal = vertexNormal; + fragTexCoord = vertexTexCoord; + // Calculate final vertex position + gl_Position = mvp * vec4(fragPosition , radius); + //gl_Position = vec4(vertexNormal, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/white.fs b/assets/shaders/white.fs new file mode 100644 index 00000000..cde80534 --- /dev/null +++ b/assets/shaders/white.fs @@ -0,0 +1,34 @@ +#version 330 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform float white; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord); + + if (white > texelColor.r) + texelColor.r = white; + if (white > texelColor.g) + texelColor.g = white; + if (white > texelColor.b) + texelColor.b = white; + + // Convert texel color to grayscale using NTSC conversion weights + //float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114)); + + gl_FragColor = texelColor; + // Calculate final fragment color + //gl_FragColor = vec4(gray, gray, gray, texelColor.a); +} \ No newline at end of file diff --git a/lib/Ray/CMakeLists.txt b/lib/Ray/CMakeLists.txt index 9a55f6be..11540070 100644 --- a/lib/Ray/CMakeLists.txt +++ b/lib/Ray/CMakeLists.txt @@ -57,6 +57,9 @@ set(HEADERS sources/Vector/Vector2.hpp sources/Vector/Vector3.hpp sources/Utils/Cache.hpp + sources/Meshes/AMesh.hpp + sources/Meshes/MeshSphere.hpp + sources/Shaders/Shaders.hpp ) set(SRC @@ -97,7 +100,10 @@ set(SRC sources/Model/ModelAnimations.cpp sources/Vector/Vector2.cpp sources/Vector/Vector3.cpp - sources/Shaders/Shaders.cpp sources/Shaders/Shaders.hpp) + sources/Shaders/Shaders.cpp + sources/Meshes/MeshSphere.cpp + sources/Meshes/AMesh.cpp + ) find_package(raylib QUIET) if (NOT raylib_FOUND) diff --git a/lib/Ray/sources/Drawables/2D/Rectangle.cpp b/lib/Ray/sources/Drawables/2D/Rectangle.cpp index 284e9b27..5ad4b674 100644 --- a/lib/Ray/sources/Drawables/2D/Rectangle.cpp +++ b/lib/Ray/sources/Drawables/2D/Rectangle.cpp @@ -12,8 +12,8 @@ namespace RAY::Drawables::Drawables2D { - Rectangle::Rectangle(const Vector2 &position, const Vector2 &dimensions, const Color &color) : - ADrawable2D(position, color), _dimensions(dimensions) + Rectangle::Rectangle(const Vector2 &position, const Vector2 &dimensions, const Color &color, float scale, float rotation) : + ADrawable2D(position, color, scale, rotation), _dimensions(dimensions) { } diff --git a/lib/Ray/sources/Drawables/2D/Rectangle.hpp b/lib/Ray/sources/Drawables/2D/Rectangle.hpp index 1a829ea2..7cd6caf8 100644 --- a/lib/Ray/sources/Drawables/2D/Rectangle.hpp +++ b/lib/Ray/sources/Drawables/2D/Rectangle.hpp @@ -11,76 +11,83 @@ #include #include "Drawables/ADrawable2D.hpp" -namespace RAY::Drawables::Drawables2D { +namespace RAY::Drawables::Drawables2D +{ //! @brief Rectangle in a two-dimensional space - class Rectangle: public ADrawable2D + class Rectangle : public ADrawable2D { - public: - //! @brief Rectangle constructor - //! @param position position of top-left point - //! @param dimensions dimensions of the rectangle - //! @param Color Color of the rectangle - Rectangle(const Vector2 &position, const Vector2 &dimensions, const Color &color = WHITE); + public: + //! @brief Rectangle constructor + //! @param position position of top-left point + //! @param dimensions dimensions of the rectangle + //! @param Color Color of the rectangle + Rectangle(const Vector2 &position, + const Vector2 &dimensions, + const Color &color = WHITE, + float scale = 1, + float rotation = 0); - //! @brief Rectangle constructor - //! @param x x-position of top-left point - //! @param y y-position of top-left point - //! @param width width of the rectangle - //! @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 Rectangle constructor + //! @param x x-position of top-left point + //! @param y y-position of top-left point + //! @param width width of the rectangle + //! @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; + //! @brief A default copy constructor + Rectangle(const Rectangle &) = default; - //! @brief A rectangle is assignable - Rectangle &operator=(const Rectangle &) = default; + //! @brief A rectangle is assignable + Rectangle &operator=(const Rectangle &) = default; - //! @brief A default destructor - ~Rectangle() override = default; + //! @brief A default destructor + ~Rectangle() override = default; - //! @return the dimensions of the rectangle - const Vector2 &getDimensions(void); + //! @return the dimensions of the rectangle + const Vector2 &getDimensions(void); - //! @return the width of the rectangle - float getWidth(void) const; + //! @return the width of the rectangle + float getWidth(void) const; - //! @return the height of the rectangle - float getHeight(void) const; + //! @return the height of the rectangle + float getHeight(void) const; - //! @brief set dimensions - Rectangle &setDimensions(const Vector2 &dimensions); + //! @brief set dimensions + Rectangle &setDimensions(const Vector2 &dimensions); - //! @brief increment width of the rectangle - //! @param width incrementer - Rectangle &incrementWidth(float width); + //! @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 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 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 rectangle's width + //! @param width width of the rectangle + Rectangle &setWidth(float width); - //! @brief set dimensions - Rectangle &setDimensions(float x, float y); + //! @brief set dimensions + Rectangle &setDimensions(float x, float y); - //! @brief Draw point on window - virtual void drawOn(RAY::Window &) override; - //! @brief Draw point on image - virtual void drawOn(RAY::Image &image) override; + //! @brief Draw point on window + virtual void drawOn(RAY::Window &) override; - protected: - //! @brief Diemnsions of the rectangle - Vector2 _dimensions; - - INTERNAL: - operator ::Rectangle() const; + //! @brief Draw point on image + virtual void drawOn(RAY::Image &image) override; + + protected: + //! @brief Diemnsions of the rectangle + Vector2 _dimensions; + + INTERNAL: + + operator ::Rectangle() const; }; }; diff --git a/lib/Ray/sources/Drawables/ADrawable2D.cpp b/lib/Ray/sources/Drawables/ADrawable2D.cpp index 0dd9804a..de5a0826 100644 --- a/lib/Ray/sources/Drawables/ADrawable2D.cpp +++ b/lib/Ray/sources/Drawables/ADrawable2D.cpp @@ -11,14 +11,20 @@ namespace RAY::Drawables { - ADrawable2D::ADrawable2D(const Vector2 &position, const RAY::Color &color) : - _position(position), _color(color) + ADrawable2D::ADrawable2D(const Vector2 &position, const RAY::Color &color, float scale, float rotation) : + _rotation(rotation), + _scale(scale), + _position(position), + _color(color) { } - ADrawable2D::ADrawable2D(int x, int y, const RAY::Color &color) : - _position(static_cast(x), static_cast(y)), _color(color) + ADrawable2D::ADrawable2D(int x, int y, const RAY::Color &color, float scale, float rotation) : + _rotation(rotation), + _scale(scale), + _position(static_cast(x), static_cast(y)), + _color(color) { } @@ -50,4 +56,14 @@ namespace RAY::Drawables this->_color = color; return *this; } + + float ADrawable2D::getScale() const + { + return this->_scale; + } + + void ADrawable2D::setScale(float scale) + { + this->_scale = scale; + } } \ No newline at end of file diff --git a/lib/Ray/sources/Drawables/ADrawable2D.hpp b/lib/Ray/sources/Drawables/ADrawable2D.hpp index f2364539..90988543 100644 --- a/lib/Ray/sources/Drawables/ADrawable2D.hpp +++ b/lib/Ray/sources/Drawables/ADrawable2D.hpp @@ -24,12 +24,12 @@ namespace RAY::Drawables { //! @brief ADrawable constructor //! @param poition position of top-left point //! @param Color Color of the color - ADrawable2D(const Vector2 &position, const RAY::Color &color); + ADrawable2D(const Vector2 &position, const RAY::Color &color, float scale = 1, float rotation = 0); //! @brief ADrawable constructor //! @param x x-position of top-left point //! @param y y-position of top-left point //! @param Color Color of the color - ADrawable2D(int x, int y, const RAY::Color &color); + ADrawable2D(int x, int y, const RAY::Color &color, float scale = 1, float rotation = 0); //! @brief A default copy constructor ADrawable2D(const ADrawable2D &) = default; @@ -58,7 +58,16 @@ namespace RAY::Drawables { //! @brief Draw drawble on image virtual void drawOn(RAY::Image &image) = 0; + //! @brief scale getter + float getScale() const; + //! @brief scale setters + void setScale(float scale); + protected: + //! @brief rotation + float _rotation = 0; + //! @brief scale + float _scale = 1; //! @brief Top-left position Vector2 _position; //! @brief Color of the ADrawable diff --git a/lib/Ray/sources/Drawables/Image.hpp b/lib/Ray/sources/Drawables/Image.hpp index 7963328d..0ababe08 100644 --- a/lib/Ray/sources/Drawables/Image.hpp +++ b/lib/Ray/sources/Drawables/Image.hpp @@ -21,7 +21,7 @@ namespace RAY public: //! @brief Create an image, 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 + //! @param lonely: should be set to true if the entity's loaded data must be independent from others Image(const std::string &filename, bool lonely = false); //! @brief A default copy constructor diff --git a/lib/Ray/sources/Drawables/Texture.cpp b/lib/Ray/sources/Drawables/Texture.cpp index ce16a6f1..ee017382 100644 --- a/lib/Ray/sources/Drawables/Texture.cpp +++ b/lib/Ray/sources/Drawables/Texture.cpp @@ -14,11 +14,11 @@ namespace RAY { Cache<::Texture> Texture::_texturesCache(LoadTexture, UnloadTexture); Texture::Texture() - : Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE) + : Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE, 0, 0) {} - Texture::Texture(const std::string &filename, bool lonely): - Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE), + Texture::Texture(const std::string &filename, bool lonely, float scale, float rotation): + Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE, scale, rotation), _texture(_texturesCache.fetch(filename, lonely)), _resourcePath(filename) { @@ -56,9 +56,12 @@ namespace RAY { { if (!this->_texture) return; + DrawTextureEx(*this, this->_position, this->_rotation, this->_scale, this->_color); + } - float scale = this->_dimensions.x / this->_texture->width; - - DrawTextureEx(*this, this->_position, 0, scale, this->_color); + void Texture::unload() + { + this->_texture = nullptr; + this->_resourcePath = ""; } } diff --git a/lib/Ray/sources/Drawables/Texture.hpp b/lib/Ray/sources/Drawables/Texture.hpp index 04518c57..fe7fe9f1 100644 --- a/lib/Ray/sources/Drawables/Texture.hpp +++ b/lib/Ray/sources/Drawables/Texture.hpp @@ -21,7 +21,7 @@ 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 - explicit Texture(const std::string &filename, bool lonely = false); + explicit Texture(const std::string &filename, bool lonely = false, float scale = 1, float rotation = 0); //! @brief Create an empty texture Texture(); @@ -44,6 +44,9 @@ namespace RAY //! @brief Load texture from file, lets one use one entity for multiple files Texture &use(const std::string &filename); + //! @brief Unload the current texture (calls to drawOn will no-op). + void unload(); + //! @return path of loaded texture const std::string &getResourcePath() const; diff --git a/lib/Ray/sources/Meshes/AMesh.cpp b/lib/Ray/sources/Meshes/AMesh.cpp new file mode 100644 index 00000000..9a76e90e --- /dev/null +++ b/lib/Ray/sources/Meshes/AMesh.cpp @@ -0,0 +1,13 @@ +// +// Created by cbihan on 16/06/2021. +// + +#include "AMesh.hpp" + +namespace RAY::Mesh +{ + std::shared_ptr<::Mesh> RAY::Mesh::AMesh::getRaylibMesh() const + { + return this->_raylibMesh; + } +} \ No newline at end of file diff --git a/lib/Ray/sources/Meshes/AMesh.hpp b/lib/Ray/sources/Meshes/AMesh.hpp new file mode 100644 index 00000000..278552ec --- /dev/null +++ b/lib/Ray/sources/Meshes/AMesh.hpp @@ -0,0 +1,28 @@ +// +// Created by cbihan on 16/06/2021. +// + +#pragma once + +#include +#include + +namespace RAY::Mesh +{ + class AMesh + { + protected: + std::shared_ptr<::Mesh> _raylibMesh; + + INTERNAL: + //! @brief getter for _raylibMesh + std::shared_ptr<::Mesh> getRaylibMesh() const; + + public: + + //! @brief dtor + virtual ~AMesh() = default; + + }; + +} \ No newline at end of file diff --git a/lib/Ray/sources/Meshes/MeshSphere.cpp b/lib/Ray/sources/Meshes/MeshSphere.cpp new file mode 100644 index 00000000..349787c0 --- /dev/null +++ b/lib/Ray/sources/Meshes/MeshSphere.cpp @@ -0,0 +1,16 @@ +// +// Created by cbihan on 16/06/2021. +// + +#include "MeshSphere.hpp" + +namespace RAY::Mesh +{ + MeshSphere::MeshSphere(float radius_arg, int rings_arg, int slices_arg) : + radius(radius_arg), + rings(rings_arg), + slices(slices_arg) + { + this->_raylibMesh = std::make_shared<::Mesh>(GenMeshSphere(radius_arg, rings_arg, slices_arg)); + } +} \ No newline at end of file diff --git a/lib/Ray/sources/Meshes/MeshSphere.hpp b/lib/Ray/sources/Meshes/MeshSphere.hpp new file mode 100644 index 00000000..b8aa1c75 --- /dev/null +++ b/lib/Ray/sources/Meshes/MeshSphere.hpp @@ -0,0 +1,35 @@ +// +// Created by cbihan on 16/06/2021. +// + +#pragma once + +#include +#include "AMesh.hpp" +#include + +namespace RAY::Mesh +{ + class MeshSphere : public AMesh + { + public: + //! @brief radius + float radius; + //! @brief rings + int rings; + //! @brief slices + int slices; + + + //! @brief ctor + MeshSphere(float radius_arg, int rings_arg, int slices_arg); + //! @brief copy ctor + MeshSphere(const MeshSphere &) = default; + //! @brief dtor + ~MeshSphere() = default; + //! @brief assignment operator + MeshSphere &operator=(const MeshSphere &) = default; + + }; + +} diff --git a/lib/Ray/sources/Model/Model.cpp b/lib/Ray/sources/Model/Model.cpp index c758ba00..b694fb4d 100644 --- a/lib/Ray/sources/Model/Model.cpp +++ b/lib/Ray/sources/Model/Model.cpp @@ -32,10 +32,20 @@ namespace RAY::Drawables::Drawables3D this->setTextureToMaterial(texture->first, texture->second); } - Model::Model(const Mesh &mesh) - : ADrawable3D({0, 0, 0}, WHITE), - _model(std::make_shared<::Model>(LoadModelFromMesh(mesh))) + Model::Model(const Mesh::AMesh &mesh, + std::optional> texture, + const RAY::Vector3 &scale, + const RAY::Vector3 &position, + const RAY::Vector3 &rotationAxis, + float rotationAngle) + : ADrawable3D(position, WHITE), + _model(std::make_shared<::Model>(LoadModelFromMesh(*mesh.getRaylibMesh()))), + _rotationAxis(rotationAxis), + _rotationAngle(rotationAngle), + _scale(scale) { + if (texture.has_value()) + this->setTextureToMaterial(texture->first, texture->second); } bool Model::unloadKeepMeshes() diff --git a/lib/Ray/sources/Model/Model.hpp b/lib/Ray/sources/Model/Model.hpp index 16616fb8..1d44352e 100644 --- a/lib/Ray/sources/Model/Model.hpp +++ b/lib/Ray/sources/Model/Model.hpp @@ -13,6 +13,7 @@ #include "Model/ModelAnimation.hpp" #include "Shaders/Shaders.hpp" #include +#include "Meshes/AMesh.hpp" #include #include #include "Utils/Cache.hpp" @@ -36,7 +37,12 @@ namespace RAY::Drawables::Drawables3D { //! @brief Create an model, loading a file //! @param mesh: mesh to load - Model(const Mesh &mesh); + Model(const Mesh::AMesh &mesh, + std::optional> texture = std::nullopt, + const RAY::Vector3 &scale = RAY::Vector3(1, 1, 1), + const RAY::Vector3 &position = {0, 0, 0}, + const RAY::Vector3 &rotationAxis = RAY::Vector3(0, 1, 0), + float rotationAngle = 0); //! @brief A copy constructor Model(const Model &model) = default; diff --git a/lib/Ray/sources/Shaders/Shaders.cpp b/lib/Ray/sources/Shaders/Shaders.cpp index 435b4f72..0def3c96 100644 --- a/lib/Ray/sources/Shaders/Shaders.cpp +++ b/lib/Ray/sources/Shaders/Shaders.cpp @@ -12,11 +12,12 @@ namespace RAY Cache<::Shader> Shader::_shadersCache(LoadShader, UnloadShader); - Shader::Shader(const std::string &vertexFile, const std::string &fragmentFile) + Shader::Shader(const std::string &vertexFile, const std::string &fragmentFile, bool lonely) : _vertexFile(vertexFile), _fragmentFile(fragmentFile), - _rayLibShader(_shadersCache.fetch(vertexFile, fragmentFile)) + _rayLibShader(_shadersCache.fetch(vertexFile, fragmentFile, lonely)) { + this->_rayLibShader->locs[SHADER_LOC_MAP_EMISSION] = GetShaderLocation(*this->_rayLibShader, "mask"); } const std::shared_ptr<::Shader> &Shader::getShaderPtr() const @@ -37,6 +38,19 @@ namespace RAY SetShaderValue(*this->_rayLibShader, this->_shaderIndexVars[varName], &value, SHADER_UNIFORM_FLOAT); } + void Shader::setShaderUniformVar(const std::string &varName, int value) + { + if (this->_shaderIndexVars.find(varName) == this->_shaderIndexVars.end()) { + int varShaderIndex = GetShaderLocation(*this->_rayLibShader, varName.c_str()); + + if (varShaderIndex < 0) { + throw Exception::WrongInputError("The loaded shader doesn't have a variable called: " + varName); + } + this->_shaderIndexVars[varName] = varShaderIndex; + } + SetShaderValue(*this->_rayLibShader, this->_shaderIndexVars[varName], &value, SHADER_UNIFORM_INT); + } + void Shader::BeginUsingCustomShader(Shader &shader) { BeginShaderMode(*shader.getShaderPtr()); diff --git a/lib/Ray/sources/Shaders/Shaders.hpp b/lib/Ray/sources/Shaders/Shaders.hpp index 529eea64..20231ea7 100644 --- a/lib/Ray/sources/Shaders/Shaders.hpp +++ b/lib/Ray/sources/Shaders/Shaders.hpp @@ -42,8 +42,14 @@ namespace RAY //! @note Throw if the var is not found void setShaderUniformVar(const std::string &varName, float value); + //! @brief The set var for float values + //! @note Throw if the var is not found + void setShaderUniformVar(const std::string &varName, int value); + + void setLocation(::ShaderLocationIndex, const std::string &name); + //! @brief ctor if no vertexfile in needed set it to nullptr - Shader(const std::string &vertexFile, const std::string &fragmentFile); + Shader(const std::string &vertexFile, const std::string &fragmentFile, bool lonely = false); //! @brief Default copy ctor Shader(const Shader &) = default; //! @brief dtor diff --git a/lib/Ray/sources/Utils/Cache.hpp b/lib/Ray/sources/Utils/Cache.hpp index beb1ff89..f7433c17 100644 --- a/lib/Ray/sources/Utils/Cache.hpp +++ b/lib/Ray/sources/Utils/Cache.hpp @@ -45,7 +45,7 @@ namespace RAY { this->_cache.emplace(path, std::vector>()); std::vector> &matchingDataVector = this->_cache.at(path); - if (matchingDataVector.size()) { + if (!matchingDataVector.empty()) { for (std::shared_ptr &i: matchingDataVector) { if (!lonely) return i; @@ -117,23 +117,34 @@ namespace RAY { _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) {}; - std::shared_ptr<::Shader> fetch(const std::string &vertexFile, const std::string &fragmentFile) + std::shared_ptr<::Shader> fetch(const std::string &vertexFile, const std::string &fragmentFile, bool lonely = false) { const std::string index = vertexFile + fragmentFile; if (vertexFile.empty() && fragmentFile.empty()) { throw RAY::Exception::WrongInputError(); } - if (this->_cache.find(index) != this->_cache.end()) - return this->_cache[index]; + if (!this->_cache.contains(index)) { + this->_cache.emplace(index, std::vector>()); + } + std::vector> &matchingDataVector = this->_cache.at(index); - this->_cache.emplace(index, std::shared_ptr<::Shader>( + if (!matchingDataVector.empty()) { + for (std::shared_ptr<::Shader> &i: matchingDataVector) { + if (!lonely) + return i; + if (lonely && i.use_count() == 1) + return i; + } + } + + matchingDataVector.emplace_back(std::shared_ptr<::Shader>( new ::Shader( this->_dataLoader(vertexFile.empty() ? nullptr : vertexFile.c_str(), fragmentFile.c_str())), [this](::Shader *p) { this->_dataUnloader(*p); })); - return this->_cache[index]; + return matchingDataVector.back(); }; private: //! @brief function to call to load data @@ -143,6 +154,6 @@ namespace RAY { std::function _dataUnloader; //! @brief map storing shared ptr of caches - std::unordered_map> _cache; + std::unordered_map>> _cache; }; } diff --git a/sources/Component/Color/ColorComponent.cpp b/sources/Component/Color/ColorComponent.cpp new file mode 100644 index 00000000..994f7f10 --- /dev/null +++ b/sources/Component/Color/ColorComponent.cpp @@ -0,0 +1,24 @@ +// +// +// + +#include "ColorComponent.hpp" + +namespace BBM +{ + + ColorComponent::ColorComponent(WAL::Entity &entity, RAY::Color color) + : Component(entity), + color(color) + {} + + ColorComponent::ColorComponent(WAL::Entity &entity, unsigned char r, unsigned char g, unsigned char b, unsigned char a) + : Component(entity), + color(r, g, b, a) + {} + + WAL::Component *ColorComponent::clone(WAL::Entity &entity) const + { + return new ColorComponent(entity, this->color); + } +} // namespace WAL \ No newline at end of file diff --git a/sources/Component/Color/ColorComponent.hpp b/sources/Component/Color/ColorComponent.hpp new file mode 100644 index 00000000..d75b5818 --- /dev/null +++ b/sources/Component/Color/ColorComponent.hpp @@ -0,0 +1,33 @@ +// +// +// + +#pragma once + +#include "Color.hpp" +#include "Component/Component.hpp" + +namespace BBM +{ + //! @brief A basic color component + class ColorComponent : public WAL::Component + { + public: + //! @brief Get the editable color of this entity + RAY::Color color; + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief Create a new ColorComponent at a certain color + ColorComponent(WAL::Entity &entity, RAY::Color color); + //! @brief Create a new ColorComponent at a certain color + ColorComponent(WAL::Entity &entity, unsigned char r, unsigned char g, unsigned char b, unsigned char a); + //! @brief A color component is copy constructable + ColorComponent(const ColorComponent &) = default; + //! @brief A default destructor + ~ColorComponent() override = default; + //! @brief A color component is not assignable + ColorComponent &operator=(const ColorComponent &) = delete; + }; +} // namespace WAL \ No newline at end of file diff --git a/sources/Component/Controllable/ControllableComponent.hpp b/sources/Component/Controllable/ControllableComponent.hpp index e6c2c644..f16de468 100644 --- a/sources/Component/Controllable/ControllableComponent.hpp +++ b/sources/Component/Controllable/ControllableComponent.hpp @@ -25,13 +25,14 @@ namespace BBM GAMEPAD_0, GAMEPAD_1, GAMEPAD_2, - GAMEPAD_3 + GAMEPAD_3, + AI }; //! @brief The X and Z abscis of the movement. Vector2f move; - //! @brief input value for jump - bool jump = false; + //! @brief input value to select + bool select = false; //! @brief input value for bomb bool bomb = false; //! @brief input value for pause diff --git a/sources/Component/Renderer/Drawable2DComponent.hpp b/sources/Component/Renderer/Drawable2DComponent.hpp index 227eacd6..c6f86044 100644 --- a/sources/Component/Renderer/Drawable2DComponent.hpp +++ b/sources/Component/Renderer/Drawable2DComponent.hpp @@ -14,27 +14,40 @@ namespace BBM class Drawable2DComponent : public WAL::Component { public: + //! @brief Tells the renderer to draw in a particular order + bool drawBefore3D = false; + //! @brief The type of the component std::shared_ptr drawable; //! @brief ctor - Drawable2DComponent(WAL::Entity &entity, std::shared_ptr drawable) + Drawable2DComponent(WAL::Entity &entity, std::shared_ptr drawable, bool drawBefore3D = false) : WAL::Component(entity), - drawable(std::move(drawable)) + drawable(std::move(drawable)), + drawBefore3D(drawBefore3D) {} //! ctor template explicit Drawable2DComponent(WAL::Entity &entity, WAL::TypeHolder, Params &&...params) : WAL::Component(entity), - drawable(new T(std::forward(params)...)) + drawable(new T(std::forward(params)...)), + drawBefore3D(false) + {} + + //! ctor + template + explicit Drawable2DComponent(WAL::Entity &entity, WAL::TypeHolder, bool drawBefore3D, Params &&...params) + : WAL::Component(entity), + drawable(new T(std::forward(params)...)), + drawBefore3D(drawBefore3D) {} //! @brief Clone a component for another or the same entity. //! @param entity The entity that owns the ne component. WAL::Component *clone(WAL::Entity &entity) const override { - return new Drawable2DComponent(entity, this->drawable); + return new Drawable2DComponent(entity, this->drawable, this->drawBefore3D); } //! @brief Default copy ctor diff --git a/sources/Component/Shaders/Items/BombExplosionShaderComponent.cpp b/sources/Component/Shaders/Items/BombExplosionShaderComponent.cpp new file mode 100644 index 00000000..c1ee13b6 --- /dev/null +++ b/sources/Component/Shaders/Items/BombExplosionShaderComponent.cpp @@ -0,0 +1,19 @@ +// +// Created by cbihan on 16/06/2021. +// + +#include "BombExplosionShaderComponent.hpp" + +namespace BBM +{ + + BombExplosionShaderComponent::BombExplosionShaderComponent(WAL::Entity &entity) : + Component(entity) + { + } + + WAL::Component *BombExplosionShaderComponent::clone(WAL::Entity &entity) const + { + return new BombExplosionShaderComponent(this->_entity); + } +} \ No newline at end of file diff --git a/sources/Component/Shaders/Items/BombExplosionShaderComponent.hpp b/sources/Component/Shaders/Items/BombExplosionShaderComponent.hpp new file mode 100644 index 00000000..99f214e7 --- /dev/null +++ b/sources/Component/Shaders/Items/BombExplosionShaderComponent.hpp @@ -0,0 +1,48 @@ +// +// Created by cbihan on 16/06/2021. +// + +#pragma once + +#include "Component/Component.hpp" +#include "Entity/Entity.hpp" +#include + +using namespace std::chrono_literals; + +namespace BBM +{ + class BombExplosionShaderComponent : public WAL::Component + { + public: + //! @brief Explosion radius + float explosionRadius = 4; + //! @brief to have the shader move by the time + float frameCounter = 0; + //! @brief Transparency + float alpha = 1; + + //! @brief max explosion radius + static constexpr float maxRadius = 1.2; + + //! @brief The clock to use + std::chrono::nanoseconds clock = 0ns; + + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief ctor + explicit BombExplosionShaderComponent(WAL::Entity &entity); + + //! @brief Default copy ctor + BombExplosionShaderComponent(const BombExplosionShaderComponent &) = default; + + //! @brief Default dtor + ~BombExplosionShaderComponent() override = default; + + //! @brief Default assignment operator + BombExplosionShaderComponent &operator=(const BombExplosionShaderComponent &) = delete; + }; + +} diff --git a/sources/Component/Shaders/Items/WhiteShaderComponent.cpp b/sources/Component/Shaders/Items/WhiteShaderComponent.cpp new file mode 100644 index 00000000..638ffc91 --- /dev/null +++ b/sources/Component/Shaders/Items/WhiteShaderComponent.cpp @@ -0,0 +1,18 @@ +// +// Created by cbihan on 16/06/2021. +// + +#include "WhiteShaderComponent.hpp" + +namespace BBM +{ + WhiteShaderComponent::WhiteShaderComponent(WAL::Entity &entity) : + Component(entity) + { + } + + WAL::Component *WhiteShaderComponent::clone(WAL::Entity &entity) const + { + return new WhiteShaderComponent(this->_entity); + } +} \ No newline at end of file diff --git a/sources/Component/Shaders/Items/WhiteShaderComponent.hpp b/sources/Component/Shaders/Items/WhiteShaderComponent.hpp new file mode 100644 index 00000000..6c969818 --- /dev/null +++ b/sources/Component/Shaders/Items/WhiteShaderComponent.hpp @@ -0,0 +1,45 @@ +// +// Created by cbihan on 16/06/2021. +// + +#pragma once + + +#include "Component/Component.hpp" +#include + +using namespace std::chrono_literals; + +namespace BBM +{ + class WhiteShaderComponent : public WAL::Component + { + public: + //! @brief Transparency + float whiteValue = 0; + + //! @brief used to increase & decrease white value + float balance = 1; + + //! @brief The clock to use + std::chrono::nanoseconds clock = 0ns; + + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief ctor + explicit WhiteShaderComponent(WAL::Entity &entity); + + //! @brief Default copy ctor + WhiteShaderComponent(const WhiteShaderComponent &) = default; + + //! @brief Default dtor + ~WhiteShaderComponent() override = default; + + //! @brief Default assignment operator + WhiteShaderComponent &operator=(const WhiteShaderComponent &) = delete; + }; + +} + diff --git a/sources/Component/Shaders/ShaderComponent.cpp b/sources/Component/Shaders/ShaderComponent.cpp index 0320864e..e6f51917 100644 --- a/sources/Component/Shaders/ShaderComponent.cpp +++ b/sources/Component/Shaders/ShaderComponent.cpp @@ -16,29 +16,38 @@ namespace BBM RAY::Shader &ShaderComponent::getShader() { - return this->_shader; + return this->shader; } - ShaderComponent::ShaderComponent(WAL::Entity &entity, const std::string &fragmentFilePath, const std::string &vertexFilePath) + ShaderComponent::ShaderComponent(WAL::Entity &entity, + const std::string &fragmentFilePath, + const std::string &vertexFilePath, + const WAL::Callback &onFixedUpdate, + bool lonely) : WAL::Component(entity), - _shader(vertexFilePath, fragmentFilePath), - _fragmentFilePath(fragmentFilePath), - _vertexFilePath(vertexFilePath) + shader(vertexFilePath, fragmentFilePath, lonely), + fragmentFilePath(fragmentFilePath), + vertexFilePath(vertexFilePath), + update(onFixedUpdate) { } std::string ShaderComponent::getFragmentFilePath() const { - return this->_fragmentFilePath; + return this->fragmentFilePath; } std::string ShaderComponent::getVertexFilePath() const { - return this->_vertexFilePath; + return this->vertexFilePath; } - ShaderComponentModel::ShaderComponentModel(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath) - : ShaderComponent(entity, std::move(fragmentFilePath), std::move(vertexFilePath)) + ShaderComponentModel::ShaderComponentModel(WAL::Entity &entity, + const std::string &fragmentFilePath, + const std::string &vertexFilePath, + const WAL::Callback &onFixedUpdate, + bool lonely) + : ShaderComponent(entity, fragmentFilePath, vertexFilePath, onFixedUpdate, lonely) { } @@ -50,8 +59,12 @@ namespace BBM throw std::runtime_error("No model available with a shader model component. This is unsupported."); } - ShaderComponentDrawable2D::ShaderComponentDrawable2D(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath) - : ShaderComponent(entity, std::move(fragmentFilePath), std::move(vertexFilePath)) + ShaderComponentDrawable2D::ShaderComponentDrawable2D(WAL::Entity &entity, + const std::string &fragmentFilePath, + const std::string &vertexFilePath, + const WAL::Callback &onFixedUpdate, + bool lonely) + : ShaderComponent(entity, fragmentFilePath, vertexFilePath, onFixedUpdate, lonely) { } } \ No newline at end of file diff --git a/sources/Component/Shaders/ShaderComponent.hpp b/sources/Component/Shaders/ShaderComponent.hpp index 51428de2..fe44a506 100644 --- a/sources/Component/Shaders/ShaderComponent.hpp +++ b/sources/Component/Shaders/ShaderComponent.hpp @@ -5,23 +5,29 @@ #pragma once #include +#include #include #include #include #include +#include +#include namespace BBM { class ShaderComponent : public WAL::Component { - private: - //! @brief The shader to be applied - RAY::Shader _shader; - //! @brief The path to the fragment file - std::string _fragmentFilePath; - //! @brief The path to the vertex file - std::string _vertexFilePath; public: + //! @brief The shader to be applied + RAY::Shader shader; + //! @brief The path to the fragment file + std::string fragmentFilePath; + //! @brief The path to the vertex file + std::string vertexFilePath; + + //! @brief the function called to update shaders vars + WAL::Callback update; + //! @brief getter for _shader RAY::Shader &getShader(); @@ -37,11 +43,18 @@ namespace BBM //! @brief ctor //! @note use empty string to omit a file - ShaderComponent(WAL::Entity &entity, const std::string& fragmentFilePath, const std::string& vertexFilePath = ""); + ShaderComponent(WAL::Entity &entity, + const std::string &fragmentFilePath, + const std::string &vertexFilePath = "", + const WAL::Callback &onFixedUpdate = WAL::Callback(), + bool lonely = false); + //! @brief Default copy ctor ShaderComponent(const ShaderComponent &) = default; + //! @brief Default dtor ~ShaderComponent() override = default; + //! @brief Default assignment operator ShaderComponent &operator=(const ShaderComponent &) = delete; }; @@ -55,11 +68,18 @@ namespace BBM //! @brief ctor //! @note use empty string to omit a file - ShaderComponentModel(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath = ""); + ShaderComponentModel(WAL::Entity &entity, + const std::string &fragmentFilePath, + const std::string &vertexFilePath = "", + const WAL::Callback &onFixedUpdate = WAL::Callback(), + bool lonely = false); + //! @brief Default copy ctor ShaderComponentModel(const ShaderComponentModel &) = default; + //! @brief Default dtor ~ShaderComponentModel() override = default; + //! @brief Default assignment operator ShaderComponentModel &operator=(const ShaderComponentModel &) = delete; }; @@ -69,11 +89,18 @@ namespace BBM public: //! @brief ctor //! @note use empty string to omit a file - ShaderComponentDrawable2D(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath = ""); + ShaderComponentDrawable2D(WAL::Entity &entity, + const std::string &fragmentFilePath, + const std::string &vertexFilePath = "", + const WAL::Callback &onFixedUpdate = WAL::Callback(), + bool lonely = false); + //! @brief Default copy ctor ShaderComponentDrawable2D(const ShaderComponentDrawable2D &) = default; + //! @brief Default dtor ~ShaderComponentDrawable2D() override = default; + //! @brief Default assignment operator ShaderComponentDrawable2D &operator=(const ShaderComponentDrawable2D &) = delete; }; diff --git a/sources/Component/Stat/StatComponent.cpp b/sources/Component/Stat/StatComponent.cpp new file mode 100644 index 00000000..2e20f6f6 --- /dev/null +++ b/sources/Component/Stat/StatComponent.cpp @@ -0,0 +1,19 @@ +// +// +// + +#include "StatComponent.hpp" + +namespace BBM +{ + + StatComponent::StatComponent(WAL::Entity &entity, WAL::Callback callback) + : Component(entity), + updater(callback) + {} + + WAL::Component *StatComponent::clone(WAL::Entity &entity) const + { + return new StatComponent(entity, this->updater); + } +} // namespace WAL \ No newline at end of file diff --git a/sources/Component/Stat/StatComponent.hpp b/sources/Component/Stat/StatComponent.hpp new file mode 100644 index 00000000..75f9733f --- /dev/null +++ b/sources/Component/Stat/StatComponent.hpp @@ -0,0 +1,33 @@ +// +// +// + +#pragma once + +#include "Component/Component.hpp" +#include "Models/Callback.hpp" +#include "Wal.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" + +namespace BBM +{ + //! @brief A Stat component which contains a text and a callback + class StatComponent : public WAL::Component + { + public: + //! @brief onEvent callback + WAL::Callback updater; + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief Create a new StatComponent with a callback + StatComponent(WAL::Entity &entity, WAL::Callback callback); + //! @brief A color component is copy constructable + StatComponent(const StatComponent &) = default; + //! @brief A default destructor + ~StatComponent() override = default; + //! @brief A color component is not assignable + StatComponent &operator=(const StatComponent &) = delete; + }; +} // namespace WAL \ No newline at end of file diff --git a/sources/Models/GameState.hpp b/sources/Models/GameState.hpp index cdc7eec7..ead456f2 100644 --- a/sources/Models/GameState.hpp +++ b/sources/Models/GameState.hpp @@ -27,6 +27,7 @@ namespace BBM ResumeLobbyScene, TitleScreenScene, CreditScene, + HowToPlayScene, ScoreScene, }; diff --git a/sources/Parser/ParserYaml.cpp b/sources/Parser/ParserYaml.cpp index 28817305..17ea622c 100644 --- a/sources/Parser/ParserYaml.cpp +++ b/sources/Parser/ParserYaml.cpp @@ -151,11 +151,16 @@ namespace BBM { _bonus = std::stringstream(); } - void ParserYAML::_loadPlayer(std::shared_ptr scene, std::vector lines, int &index) + void ParserYAML::_loadPlayer(std::shared_ptr scene, std::vector lines, int &index, int countPlayer) { std::string name; std::string tmpAssets; - static int countPlayer = 0; + std::map map = { + {"red", RED}, + {"blue", BLUE}, + {"yellow", YELLOW}, + {"green", GREEN} + }; for (; index != lines.size(); index++) { if (lines[index].find("max_bomb") != std::string::npos && !name.empty()) { @@ -185,10 +190,12 @@ namespace BBM { tmpAssets.find("ai.png") == std::string::npos) || !std::filesystem::exists(tmpAssets)) { throw (ParserError("Error with saved map: One asset is invalid.\n Loading default maps...")); } + auto start = tmpAssets.find_last_of("/") + 1; + auto color = map.at(tmpAssets.substr(start, tmpAssets.length() - start - 4)); auto resumeScene = Runner::gameState._loadedScenes[GameState::SceneID::ResumeLobbyScene]; auto &playerTile = resumeScene->addEntity("player tile") .addComponent(224 * (countPlayer + 1) + 200 * countPlayer, 1080 / 3, 0) - .addComponent(RAY::Vector2(224 * (countPlayer + 1) + 200 * countPlayer, 1080 / 3), RAY::Vector2(200, 200), RAY::Color(0, 0, 0, 0)); + .addComponent(RAY::Vector2(224 * (countPlayer + 1) + 200 * countPlayer, 1080 / 3), RAY::Vector2(200, 200), color); auto &playerLogo = resumeScene->addEntity("player") .addComponent(224 * (countPlayer + 1) + 200 * countPlayer, 1080 / 3, 0) .addComponent(tmpAssets.replace(tmpAssets.find("textures"), 8, "icons")); @@ -196,8 +203,6 @@ namespace BBM { .addComponent(224 * (countPlayer + 1) + 200 * countPlayer, 1080 / 3, 0) .addComponent(); playerLogo.addComponent(countPlayer, ready, playerTile); - Runner::addedPlayer++; - countPlayer++; } void ParserYAML::_loadPlayers(std::shared_ptr scene) @@ -205,6 +210,7 @@ namespace BBM { std::ifstream file("save/" + fileName + "_player.yml"); std::string line; std::vector lines; + int countPlayer = 0; if (!file.good()) throw (ParserError("File error")); @@ -214,8 +220,9 @@ namespace BBM { lines.push_back(line); } for (int index = 0; lines.size() != index; index++) { - _loadPlayer(scene, lines, index); + _loadPlayer(scene, lines, index, countPlayer); index--; + countPlayer++; } } diff --git a/sources/Parser/ParserYaml.hpp b/sources/Parser/ParserYaml.hpp index 36f0a4c4..5f50b7ac 100644 --- a/sources/Parser/ParserYaml.hpp +++ b/sources/Parser/ParserYaml.hpp @@ -67,7 +67,7 @@ namespace BBM { //!@param lines Lines of the file //!@param index index of the vector //!@brief add player into scene - static void _loadPlayer(std::shared_ptr scene, std::vector lines, int &index); + static void _loadPlayer(std::shared_ptr scene, std::vector lines, int &index, int countPlayer); //!@param scene Scene to update //!@param lines Lines of the file //!@param index index of the vector diff --git a/sources/Runner/GameScene.cpp b/sources/Runner/GameScene.cpp index a14bfea6..1a967149 100644 --- a/sources/Runner/GameScene.cpp +++ b/sources/Runner/GameScene.cpp @@ -17,17 +17,21 @@ #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 "Component/Renderer/Drawable2DComponent.hpp" +#include #include "Drawables/2D/Text.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Button/ButtonComponent.hpp" +#include "Drawables/Texture.hpp" #include "Component/Gravity/GravityComponent.hpp" #include "Component/BumperTimer/BumperTimerComponent.hpp" #include "Component/Timer/TimerComponent.hpp" #include "Model/Model.hpp" #include "Map/Map.hpp" #include "Component/Score/ScoreComponent.hpp" +#include "Drawables/2D/Text.hpp" namespace RAY3D = RAY::Drawables::Drawables3D; namespace RAY2D = RAY::Drawables::Drawables2D; @@ -43,7 +47,12 @@ namespace BBM scene->addEntity("Timer") .addComponent(std::chrono::minutes (3), [](WAL::Entity &, WAL::Wal &) { Runner::gameState.nextScene = GameState::ScoreScene; - }); + }) + .addComponent(1920 / 2 - 2 * 30, 30, 0) + .addComponent("", 60, RAY::Vector2(), ORANGE); + scene->addEntity("background image") + .addComponent(true, "assets/background_game.png", false) + .addComponent(); return scene; } @@ -64,7 +73,6 @@ namespace BBM .addComponent() .addComponent() .addComponent() -// .addComponent("assets/shaders/glsl330/predator.fs") .addComponent>() .addComponent("assets/player/player.iqm", 3) .addComponent(BBM::Vector3f{0.25, 0, 0.25}, BBM::Vector3f{.75, 2, .75}) diff --git a/sources/Runner/HowToPlayScene.cpp b/sources/Runner/HowToPlayScene.cpp new file mode 100644 index 00000000..cfb2cb7e --- /dev/null +++ b/sources/Runner/HowToPlayScene.cpp @@ -0,0 +1,81 @@ +#include +#include +#include "Runner.hpp" +#include +#include "Component/Music/MusicComponent.hpp" +#include "Component/Sound/SoundComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Keyboard/KeyboardComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Button/ButtonComponent.hpp" +#include "Drawables/2D/Text.hpp" + +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + std::shared_ptr Runner::loadHowToPlayScene() + { + auto scene = std::make_shared(); + static const std::map sounds = { + {SoundComponent::JUMP, "assets/sounds/click.ogg"} + }; + + addMenuControl(*scene); + scene->addEntity("Control entity") + .addComponent("assets/musics/music_player_select.ogg") + .addComponent(sounds); + scene->addEntity("background") + .addComponent() + .addComponent("assets/plain_menu_background.png"); + scene->addEntity("scene title text") + .addComponent(1920 / 3, 100, 0) + .addComponent("How To Play?", 120, RAY::Vector2(), ORANGE); + + scene->addEntity("select text") + .addComponent(1920 / 8, 1080 / 3, 0) + .addComponent("Select:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("select") + .addComponent(1920 / 7, 1080 / 2.5, 0) + .addComponent("Space/A Button", 35, RAY::Vector2(), BLACK); + scene->addEntity("change skin text") + .addComponent(1920 / 8, 1080 / 2, 0) + .addComponent("Change Skin/Drop Bomb:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("change skin") + .addComponent(1920 / 7, 1080 / 1.75, 0) + .addComponent("E/B Button", 35, RAY::Vector2(), BLACK); + scene->addEntity("move text") + .addComponent(1920 / 1.75, 1080 / 3, 0) + .addComponent("Move:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("move") + .addComponent(1920 / 1.75, 1080 / 2.5, 0) + .addComponent("Q-Z-S-D/Arrow/Joystick", 35, RAY::Vector2(), BLACK); + scene->addEntity("back text") + .addComponent(1920 / 1.75, 1080 / 2, 0) + .addComponent("Back/Pause:", 60, RAY::Vector2(), ORANGE); + scene->addEntity("back") + .addComponent(1920 / 1.75, 1080 / 1.75, 0) + .addComponent("Esc / Controller's Home button:", 35, RAY::Vector2(), BLACK); + auto &back = scene->addEntity("back to menu") + .addComponent(10, 1080 - 85, 0) + .addComponent("assets/buttons/button_back.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::LobbyScene; + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_back.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_back_hovered.png"); + }); + return scene; + } +} \ No newline at end of file diff --git a/sources/Runner/LobbyScene.cpp b/sources/Runner/LobbyScene.cpp index 54e45191..7254006e 100644 --- a/sources/Runner/LobbyScene.cpp +++ b/sources/Runner/LobbyScene.cpp @@ -44,94 +44,147 @@ namespace BBM .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>(); - - + .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; - }) + { + gameState.nextScene = BBM::GameState::SceneID::MainMenuScene; + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - texture->use("assets/buttons/button_back.png"); - }) + texture->use("assets/buttons/button_back.png"); + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); - texture->use("assets/buttons/button_back_hovered.png"); - }); + texture->use("assets/buttons/button_back_hovered.png"); + }); + auto &howToPlay = scene->addEntity("to to play") + .addComponent(1920 - 10 - 75, 1080 - 85, 0) + .addComponent("assets/buttons/button_htp.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::HowToPlayScene; + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_htp.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + RAY::Texture *texture = dynamic_cast(entity.getComponent().drawable.get()); + + texture->use("assets/buttons/button_htp_hovered.png"); + }); auto &lavaOption = scene->addEntity("lava option text") - .addComponent(1920 / 6, 2 * 1080 / 3, 0) + .addComponent(1920 / 6, 1.85 * 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()); + { + 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 - } - }) + if (text->getString().find("Off") != std::string::npos) { + text->setText("Lava: On"); + //do + } else { + text->setText("Lava: Off"); + //do + } + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) + { + entity.getComponent().drawable->setColor(BLACK); + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); + { + entity.getComponent().drawable->setColor(ORANGE); + }); auto &heightOption = scene->addEntity("Height option text") - .addComponent(1920 / 1.75, 2 * 1080 / 3, 0) + .addComponent(1920 / 6, 2.1 * 1080 / 3, 0) .addComponent("2nd Level: Off", 70, RAY::Vector2(), BLACK) .addComponent([](WAL::Entity &entity, WAL::Wal &wal) - { - RAY2D::Text *text = dynamic_cast(entity.getComponent().drawable.get()); + { + auto *text = dynamic_cast(entity.getComponent().drawable.get()); - if (text->getString().find("Off") != std::string::npos) { - text->setText("2nd Level: On"); - //do - } else { - text->setText("2nd Level: Off"); - //do - } - }) + if (text->getString().find("Off") != std::string::npos) { + text->setText("2nd Level: On"); + Runner::hasHeights = true; + } else { + text->setText("2nd Level: Off"); + Runner::hasHeights = false; + } + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(BLACK); - }) + { + entity.getComponent().drawable->setColor(BLACK); + }) .addComponent([](WAL::Entity &entity, WAL::Wal &) - { - entity.getComponent().drawable->setColor(ORANGE); - }); + { + entity.getComponent().drawable->setColor(ORANGE); + }); + + auto &aiMore = scene->addEntity("AI+") + .addComponent(1920 / 1.75, 1.85 * 1080 / 3, 0) + .addComponent("assets/buttons/cpu_add.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + wal.getSystem().addAI(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_add.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_add_hovered.png"); + }); + + auto &aiLess = scene->addEntity("AI-") + .addComponent(1920 / 1.75, 2.10 * 1080 / 3, 0) + .addComponent("assets/buttons/cpu_remove.png") + .addComponent([](WAL::Entity &entity, WAL::Wal &wal) + { + wal.getSystem().removeAI(); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_remove.png"); + }) + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + auto *texture = dynamic_cast(entity.getComponent().drawable.get()); + texture->use("assets/buttons/cpu_remove_hovered.png"); + }); for (int i = 0; i < 4; i++) { auto &playerTile = scene->addEntity("player tile") @@ -142,16 +195,20 @@ namespace BBM .addComponent("assets/player/icons/none.png"); auto &ready = scene->addEntity("ready") .addComponent(224 * (i + 1) + 200 * i, 1080 / 3, 0) - .addComponent(); + // todo check why it does this | hacky way to fix ready texture + .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); + play.getComponent().setButtonLinks(&lavaOption, &back, &back, &howToPlay); + howToPlay.getComponent().setButtonLinks(&play, nullptr, &play); back.getComponent().setButtonLinks(&play, nullptr, nullptr, &play); - lavaOption.getComponent().setButtonLinks(nullptr, &play, nullptr, &heightOption); - heightOption.getComponent().setButtonLinks(nullptr, &play, &lavaOption, nullptr); + lavaOption.getComponent().setButtonLinks(nullptr, &heightOption, nullptr, &aiMore); + heightOption.getComponent().setButtonLinks(&lavaOption, &play, nullptr, &aiLess); + aiMore.getComponent().setButtonLinks(nullptr, &aiLess, &lavaOption, nullptr); + aiLess.getComponent().setButtonLinks(&aiMore, &play, &heightOption, nullptr); return scene; } } \ No newline at end of file diff --git a/sources/Runner/ResumeLobbyScene.cpp b/sources/Runner/ResumeLobbyScene.cpp index 2d22d5fb..22c78f86 100644 --- a/sources/Runner/ResumeLobbyScene.cpp +++ b/sources/Runner/ResumeLobbyScene.cpp @@ -26,8 +26,6 @@ namespace RAY2D = RAY::Drawables::Drawables2D; namespace BBM { - int Runner::addedPlayer = 0; - std::shared_ptr Runner::loadResumeLobbyScene() { static const std::map sounds = { diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index 2a395fbd..4ed81f40 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -16,6 +16,7 @@ #include "Runner.hpp" #include "Models/GameState.hpp" #include +#include #include #include #include @@ -24,6 +25,9 @@ #include #include #include +#include "System/Shaders/ShaderSystem.hpp" +#include "System/Shaders/ShaderDrawable2DSystem.hpp" +#include "System/Shaders/ShaderModelSystem.hpp" #include "System/Animation/AnimationsSystem.hpp" #include "Map/Map.hpp" #include "System/MenuControllable/MenuControllableSystem.hpp" @@ -38,26 +42,25 @@ #include "System/Score/ScoreSystem.hpp" #include "System/EndCondition/EndConditionSystem.hpp" #include "Component/Lobby/LobbyComponent.hpp" +#include "System/Bonus/BonusUISystem.hpp" namespace BBM { GameState Runner::gameState; int Runner::mapWidth = 16; int Runner::mapHeight = 16; + bool Runner::hasHeights = false; void Runner::updateState(WAL::Wal &engine, GameState &state) { auto &view = engine.getScene()->view(); if (RAY::Window::getInstance().shouldClose()) engine.shouldClose = true; - if (gameState.currentScene == GameState::SceneID::GameScene || gameState.currentScene == GameState::SceneID::SplashScreen) { + if (gameState.currentScene == GameState::SceneID::GameScene) { for (auto &[_, component]: engine.getScene()->view()) { if (component.pause && gameState.currentScene == GameState::SceneID::GameScene) { gameState.nextScene = GameState::SceneID::PauseMenuScene; break; - } else if (gameState.currentScene == GameState::SceneID::SplashScreen && component.jump) { - gameState.nextScene = GameState::SceneID::TitleScreenScene; - break; } } } @@ -73,6 +76,7 @@ namespace BBM void Runner::addSystems(WAL::Wal &wal) { wal.addSystem() + .addSystem() .addSystem() .addSystem() .addSystem() @@ -81,6 +85,7 @@ namespace BBM .addSystem() .addSystem() .addSystem() + .addSystem() .addSystem() .addSystem() .addSystem() @@ -91,6 +96,9 @@ namespace BBM .addSystem() .addSystem() .addSystem() + .addSystem() + .addSystem() + .addSystem() .addSystem() .addSystem() .addSystem(); @@ -130,6 +138,7 @@ namespace BBM gameState._loadedScenes[GameState::SceneID::SplashScreen] = loadSplashScreenScene(); gameState._loadedScenes[GameState::SceneID::LobbyScene] = loadLobbyScene(); gameState._loadedScenes[GameState::SceneID::ResumeLobbyScene] = loadResumeLobbyScene(); + gameState._loadedScenes[GameState::SceneID::HowToPlayScene] = loadHowToPlayScene(); } int Runner::run() diff --git a/sources/Runner/Runner.hpp b/sources/Runner/Runner.hpp index d61c108d..77fb51db 100644 --- a/sources/Runner/Runner.hpp +++ b/sources/Runner/Runner.hpp @@ -9,15 +9,15 @@ namespace BBM { class Runner { - public: + public: + //! @brief Has the map heights or is it disabled? + static bool hasHeights; //! @brief the width of the map static int mapWidth; //! @brief the height of the map static int mapHeight; - static int addedPlayer; - //! @brief store current scenes informations static GameState gameState; //! @brief Start the game and run a Bomberman. @@ -69,6 +69,8 @@ namespace BBM //! @brief load all data related to splash screen static std::shared_ptr loadSplashScreenScene(); + //! @brief load how to play screen + static std::shared_ptr loadHowToPlayScene(); //! @brief load all data related to score scene screen //! @param gameScene scene containing players (to know the scores) static std::shared_ptr loadScoreScene(WAL::Scene &gameScene); diff --git a/sources/Runner/SplashScreenScene.cpp b/sources/Runner/SplashScreenScene.cpp index a22d20da..3d0cc1ae 100644 --- a/sources/Runner/SplashScreenScene.cpp +++ b/sources/Runner/SplashScreenScene.cpp @@ -30,7 +30,13 @@ namespace BBM .addComponent("powered by", 30, RAY::Vector2(), BLACK); auto &skipText = scene->addEntity("Press space to skip") .addComponent(1920 - 250, 1080 - 30, 0) - .addComponent("Press space to skip", 20, RAY::Vector2(), BLACK); + .addComponent("Press space to skip", 20, RAY::Vector2(), BLACK) + .addComponent() + .addComponent() + .addComponent([](WAL::Entity &entity, WAL::Wal &) + { + gameState.nextScene = BBM::GameState::SceneID::TitleScreenScene; + }); return scene; } } \ No newline at end of file diff --git a/sources/System/BombHolder/BombHolderSystem.cpp b/sources/System/BombHolder/BombHolderSystem.cpp index e7b385a1..0a69c435 100644 --- a/sources/System/BombHolder/BombHolderSystem.cpp +++ b/sources/System/BombHolder/BombHolderSystem.cpp @@ -11,8 +11,13 @@ #include "Component/Health/HealthComponent.hpp" #include #include +#include +#include "Component/Shaders/Items/BombExplosionShaderComponent.hpp" +#include +#include "Component/Shaders/ShaderComponent.hpp" #include "Component/Collision/CollisionComponent.hpp" #include "Component/Tag/TagComponent.hpp" +#include "Component/Shaders/Items/WhiteShaderComponent.hpp" using namespace std::chrono_literals; namespace RAY3D = RAY::Drawables::Drawables3D; @@ -44,10 +49,31 @@ namespace BBM return; wal.getScene()->scheduleNewEntity("explosion") .addComponent(position) + .addComponent() + .addComponent("assets/shaders/explosion.fs", "assets/shaders/explosion.vs", [](WAL::Entity &entity, WAL::Wal &wal, std::chrono::nanoseconds dtime) { + auto &ctx = entity.getComponent(); + auto &shader = entity.getComponent(); + + ctx.clock += dtime; + if (duration_cast(ctx.clock).count() <= 10) + return; + ctx.clock = 0ns; + ctx.explosionRadius -= 0.6; + if (ctx.explosionRadius < BombExplosionShaderComponent::maxRadius) { + ctx.explosionRadius = BombExplosionShaderComponent::maxRadius; + ctx.alpha -= 0.1; + // slow the explosion movement + ctx.frameCounter -= 0.1; + } + ctx.frameCounter += 0.2; + shader.shader.setShaderUniformVar("frame", ctx.frameCounter); + shader.shader.setShaderUniformVar("alpha", ctx.alpha); + shader.shader.setShaderUniformVar("radius", ctx.explosionRadius); + }) .addComponent(500ms, [](WAL::Entity &explosion, WAL::Wal &wal) { explosion.scheduleDeletion(); }) - .addComponent("assets/bombs/explosion/explosion.glb", false, + .addComponent(RAY::Mesh::MeshSphere(0.5, 16, 16), std::make_pair( MAP_DIFFUSE, "assets/bombs/explosion/blast.png" @@ -100,6 +126,33 @@ namespace BBM auto &bombDetails = entity.getComponent(); BombHolderSystem::_dispatchExplosion(pos.position, wal, bombDetails.explosionRadius); }) + .addComponent("assets/shaders/white.fs", "", [](WAL::Entity &entity, WAL::Wal &wal, std::chrono::nanoseconds dtime) { + auto &ctx = entity.getComponent(); + auto &shader = entity.getComponent(); + auto &timer = entity.getComponent(); + + if (ctx.whiteValue >= 1) + ctx.balance = -1; + if (ctx.whiteValue <= 0) + ctx.balance = 1; + auto nbMilliSec = duration_cast(timer.ringIn).count(); + + float step; + + if (nbMilliSec > 1000) { + step = 0.07; + } else if (nbMilliSec > 500) { + step = 0.15; + } else if (nbMilliSec > 100) { + step = 0.26; + } else { + step = 0.5; + } + + ctx.whiteValue += static_cast(step * ctx.balance); + shader.shader.setShaderUniformVar("white", ctx.whiteValue); + }) + .addComponent() .addComponent>() .addComponent(holder.damage, holder.explosionRadius, id) .addComponent(BombHolderSystem::explosionTimer, &BombHolderSystem::_bombExplosion) diff --git a/sources/System/Bonus/BonusUISystem.cpp b/sources/System/Bonus/BonusUISystem.cpp new file mode 100644 index 00000000..d6ac5598 --- /dev/null +++ b/sources/System/Bonus/BonusUISystem.cpp @@ -0,0 +1,17 @@ +// +// Created by hbenjamin on 09/06/2021. +// + +#include "BonusUISystem.hpp" + +namespace BBM +{ + BonusUISystem::BonusUISystem(WAL::Wal &wal) + : System(wal) + {} + + void BonusUISystem::onFixedUpdate(WAL::ViewEntity &entity) + { + entity.get().updater(entity.get()); + } +} \ No newline at end of file diff --git a/sources/System/Bonus/BonusUISystem.hpp b/sources/System/Bonus/BonusUISystem.hpp new file mode 100644 index 00000000..ddc6f95f --- /dev/null +++ b/sources/System/Bonus/BonusUISystem.hpp @@ -0,0 +1,32 @@ +// +// +// + +#pragma once + +#include "System/System.hpp" +#include "Wal.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Stat/StatComponent.hpp" + +namespace BBM +{ + //! @brief The system that allow the text of the ui to display current values + class BonusUISystem : public WAL::System + { + private: + public: + //! @inherit + void onFixedUpdate(WAL::ViewEntity &entity) override; + + //! @brief A default constructor + explicit BonusUISystem(WAL::Wal &wal); + //! @brief A bomb holder system is copy constructable + BonusUISystem(const BonusUISystem &) = default; + //! @brief A default destructor + ~BonusUISystem() override = default; + //! @brief A bomb holder system is not assignable. + BonusUISystem &operator=(const BonusUISystem &) = delete; + }; +} + diff --git a/sources/System/Gamepad/GamepadSystem.cpp b/sources/System/Gamepad/GamepadSystem.cpp index 623d5edd..7ff78016 100644 --- a/sources/System/Gamepad/GamepadSystem.cpp +++ b/sources/System/Gamepad/GamepadSystem.cpp @@ -24,7 +24,7 @@ namespace BBM Gamepad gamepad(gamepadComponent.getID()); const std::map keyPressedMap = { - {gamepadComponent.keyJump, controllable.jump}, + {gamepadComponent.keyJump, controllable.select}, {gamepadComponent.keyBomb, controllable.bomb}, {gamepadComponent.keyPause, controllable.pause} }; diff --git a/sources/System/Keyboard/KeyboardSystem.cpp b/sources/System/Keyboard/KeyboardSystem.cpp index 334b757a..8dbda5ab 100644 --- a/sources/System/Keyboard/KeyboardSystem.cpp +++ b/sources/System/Keyboard/KeyboardSystem.cpp @@ -22,7 +22,7 @@ namespace BBM auto &controllable = entity.get(); const std::map keyPressedMap = { - {keyboard.keyJump, controllable.jump}, + {keyboard.keyJump, controllable.select}, {keyboard.keyBomb, controllable.bomb}, {keyboard.keyPause, controllable.pause} }; diff --git a/sources/System/Lobby/LobbySystem.cpp b/sources/System/Lobby/LobbySystem.cpp index 463e68ab..b55ea90a 100644 --- a/sources/System/Lobby/LobbySystem.cpp +++ b/sources/System/Lobby/LobbySystem.cpp @@ -17,8 +17,13 @@ #include #include #include +#include +#include "Component/Color/ColorComponent.hpp" +#include "Component/Stat/StatComponent.hpp" +#include "Component/Bonus/PlayerBonusComponent.hpp" namespace RAY3D = RAY::Drawables::Drawables3D; +namespace RAY2D = RAY::Drawables::Drawables2D; namespace BBM { @@ -70,7 +75,7 @@ namespace BBM if (lobby.layout == ControllableComponent::NONE) { for (auto &[_, ctrl] : this->_wal.getScene()->view()) { auto &controller = ctrl; - if (controller.jump) { + if (controller.select) { if (std::any_of(this->getView().begin(), this->getView().end(), [&controller](WAL::ViewEntity &view) { return view.get().layout == controller.layout; })) @@ -79,7 +84,7 @@ namespace BBM lobby.color = -1; this->_nextColor(entity); lobby.layout = controller.layout; - controller.jump = false; + controller.select = false; return; } } @@ -88,10 +93,10 @@ namespace BBM for (auto &[_, controller] : this->_wal.getScene()->view()) { if (controller.layout != lobby.layout) continue; - if (controller.jump && !lobby.ready) { + if (controller.select && !lobby.ready) { lobby.ready = true; lobby.lastInput = lastTick; - controller.jump = false; + controller.select = false; this->_wal.getSystem().now = lastTick; auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); if (texture) @@ -104,6 +109,47 @@ namespace BBM } } + void LobbySystem::addAI() + { + for (auto entity : this->getView()) { + auto &lobby = entity.get(); + if (lobby.layout != ControllableComponent::NONE) + continue; + lobby.color = -1; + this->_nextColor(entity); + lobby.layout = ControllableComponent::AI; + lobby.ready = true; + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->use("assets/player/icons/ai.png"); + return; + } + } + + void LobbySystem::removeAI() + { + std::optional> last; + for (auto &entity : this->getView()) { + auto &lobby = entity.get(); + if (lobby.layout == ControllableComponent::AI) + last.emplace(entity); + } + if (!last) + return; + auto &entity = *last; + auto &lobby = entity.get(); + auto &drawable = entity.get(); + this->_colorTaken[lobby.color] = false; + lobby.color = -1; + lobby.layout = ControllableComponent::NONE; + lobby.ready = false; + drawable.drawable = std::make_shared("assets/player/icons/none.png"); + lobby.coloredTile.getComponent().drawable->setColor(RAY::Color(0, 0, 0, 0)); + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->unload(); + } + void LobbySystem::onSelfUpdate() { auto &view = this->_wal.getScene()->view, Drawable2DComponent>(); @@ -146,6 +192,9 @@ namespace BBM case ControllableComponent::GAMEPAD_3: player.addComponent(3); break; + case ControllableComponent::AI: +// throw std::runtime_error("Not implemented error"); + break; default: throw std::runtime_error("Invalid controller for a player."); } @@ -157,32 +206,100 @@ namespace BBM int mapWidth = 16; int mapHeight = 16; int playerCount = 0; + int playerID = 0; for (auto &[_, lobby] : wal.getScene()->view()) { + playerID++; if (lobby.layout == ControllableComponent::NONE) continue; auto &player = Runner::createPlayer(*scene); addController(player, lobby.layout); player.getComponent().position = Vector3f(mapWidth * (playerCount % 2), 0, - mapHeight * ((playerCount + 1) % 2)); + mapHeight * (!(playerCount % 3))); auto *model = dynamic_cast(player.getComponent().drawable.get()); model->setTextureToMaterial(MAP_DIFFUSE, "assets/player/textures/" + _colors[lobby.color] + ".png"); + std::string texturePath = "assets/player/ui/" + _colors[lobby.color] + ".png"; + int x = (playerID % 2 == 0) ? 1920 - 10 - 320 : 10; + int y = playerID > 2 ? 1080 - 10 - 248 : 10; + scene->addEntity("player color tile") + .addComponent(x, y - 2, 0) + .addComponent(x, y, 320, 248, _rayColors[lobby.color]); + scene->addEntity("player ui tile") + .addComponent(x, y, 0) + .addComponent(texturePath); + scene->addEntity("player hide fireup") + .addComponent(x + 220, y + 35, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const BombHolderComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(std::to_string(bonus->explosionRadius)); + }); + scene->addEntity("player hide bombup") + .addComponent(x + 220, y + 77, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const BombHolderComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(std::to_string(bonus->bombCount) + " / " + std::to_string(bonus->maxBombCount)); + }); + scene->addEntity("player hide speedup") + .addComponent(x + 220, y + 122, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const ControllableComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(std::to_string(static_cast(bonus->speed * 100))); + }); + scene->addEntity("player hide wall") + .addComponent(x + 220, y + 161, 0) + .addComponent("", 20, x, y, WHITE) + .addComponent([&player](Drawable2DComponent &drawble) { + const PlayerBonusComponent *bonus = player.tryGetComponent(); + + if (!bonus) + return; + RAY2D::Text *text = dynamic_cast(drawble.drawable.get()); + if (!text) + return; + text->setText(bonus->isNoClipOn ? "YES" : "NO"); + }); playerCount++; } Runner::gameState._loadedScenes[GameState::SceneID::GameScene] = scene; MapGenerator::loadMap(Runner::mapWidth, Runner::mapHeight, MapGenerator::createMap(Runner::mapWidth, Runner::mapHeight), scene); Runner::gameState.nextScene = BBM::GameState::SceneID::GameScene; + wal.getSystem().unloadLobby(); } void LobbySystem::resumeToGame(WAL::Wal &wal) { auto scene = Runner::gameState._loadedScenes[GameState::SceneID::GameScene]; int countPlayer = 0; + int i = 0; for (auto &[_, lobby] : wal.getScene()->view()) { if (lobby.layout == ControllableComponent::NONE) continue; + if (i < 4) + std::cout << i << std::endl; + i++; auto &player = Runner::createPlayer(*scene); player.setName(ParserYAML::playerName[countPlayer]); auto *position = player.tryGetComponent(); @@ -201,5 +318,33 @@ namespace BBM countPlayer++; } Runner::gameState.nextScene = BBM::GameState::SceneID::GameScene; + wal.getSystem().unloadLobbyFromResume(); + } + + void LobbySystem::unloadLobby() + { + this->_colorTaken.fill(false); + for (auto &[_, lobby, drawable] : this->getView()) { + lobby.layout = ControllableComponent::NONE; + lobby.ready = false; + lobby.color = -1; + drawable.drawable = std::make_shared("assets/player/icons/none.png"); + lobby.coloredTile.getComponent().drawable->setColor(RAY::Color(0, 0, 0, 0)); + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->unload(); + } + } + + void LobbySystem::unloadLobbyFromResume() + { + this->_colorTaken.fill(false); + for (auto &[_, lobby, drawable] : this->getView()) { + lobby.layout = ControllableComponent::NONE; + lobby.ready = false; + auto *texture = dynamic_cast(lobby.readyButton.getComponent().drawable.get()); + if (texture) + texture->unload(); + } } } \ No newline at end of file diff --git a/sources/System/Lobby/LobbySystem.hpp b/sources/System/Lobby/LobbySystem.hpp index f1d79833..8ca92a72 100644 --- a/sources/System/Lobby/LobbySystem.hpp +++ b/sources/System/Lobby/LobbySystem.hpp @@ -46,6 +46,18 @@ namespace BBM //! @param wal The engine. static void switchToGame(WAL::Wal &wal); + //! @brief Reset the lobby scene to it's default state. + void unloadLobby(); + + //! @brief Reset the resume lobby scene to it's default state. + void unloadLobbyFromResume(); + + //! @brief Add an AI to the game. + void addAI(); + + //! @brief Remove an AI from the game. + void removeAI(); + //! @brief A default constructor explicit LobbySystem(WAL::Wal &wal); //! @brief A Lobby system is copy constructable diff --git a/sources/System/MenuControllable/MenuControllableSystem.cpp b/sources/System/MenuControllable/MenuControllableSystem.cpp index 6dcc95e3..d3158774 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.cpp +++ b/sources/System/MenuControllable/MenuControllableSystem.cpp @@ -7,6 +7,12 @@ #include "System/MenuControllable/MenuControllableSystem.hpp" #include "Component/Controllable/ControllableComponent.hpp" #include "Entity/Entity.hpp" +#include "Drawables/Texture.hpp" +#include "Drawables/2D/Text.hpp" +#include "Controllers/Mouse.hpp" + +namespace RAYControl = RAY::Controller; +namespace RAY2D = RAY::Drawables::Drawables2D; namespace BBM { @@ -45,14 +51,41 @@ namespace BBM this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); } - void MenuControllableSystem::onFixedUpdate(WAL::ViewEntity &entity) + bool MenuControllableSystem::_mouseOnButton(WAL::ViewEntity &entity) const { - auto &controllable = entity.get(); - auto &buttons = _wal.getScene()->view(); + auto &positionComponent = entity.get(); + RAY::Vector2 rayMousePos = RAYControl::Mouse::getCursorPosition(); + RAY::Texture *texture = dynamic_cast(entity.get().drawable.get()); + RAY2D::Text *text = dynamic_cast(entity.get().drawable.get()); + Vector2f buttonPos(positionComponent.getX(), positionComponent.getY()); + Vector2f mousePos(rayMousePos.x, rayMousePos.y); + Vector2f dimensions; + + WAL::Entity *newButton = nullptr; + + if (texture) { + dimensions.x = texture->getDimensions().x; + dimensions.y = texture->getDimensions().y; + } else if (text) { + dimensions.y = text->getFontSize(); + dimensions.x = text->getString().size() * (text->getLetterSpacing() + text->getFontSize()); + } else + return false; + return ((buttonPos.x <= mousePos.x && mousePos.x <= buttonPos.x + dimensions.x) + && (buttonPos.y <= mousePos.y && mousePos.y <= buttonPos.y + dimensions.y)); + } + + void MenuControllableSystem::onSelfUpdate() + { + + auto &controllableView = this->_wal.getScene()->view(); + auto &buttons = _wal.getScene()->view(); + if (this->_currentButton && this->_currentButton->_scene.getID() != this->_wal.getScene()->getID()) { this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); this->_currentButton = nullptr; + return; } if (this->_currentButton == nullptr && buttons.size()) { this->_currentButton = &(*buttons.front()); @@ -60,6 +93,20 @@ namespace BBM } if (!this->_currentButton) return; - this->_updateCurrentButton(controllable.jump, controllable.move); + for (auto &[_, controllable]: controllableView) + if (controllable.move.x || controllable.move.y || controllable.select) { + this->_updateCurrentButton(controllable.select, controllable.move); + return; + } + for (auto &entity: buttons) { + if (_mouseOnButton(entity)) { + if (this->_currentButton) + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + this->_currentButton = &(*entity); + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + if (RAYControl::Mouse::isPressed(RAYControl::Mouse::Button::MOUSE_BUTTON_LEFT)) + this->_currentButton->getComponent().onEvent(*this->_currentButton, this->_wal); + } + } } } \ No newline at end of file diff --git a/sources/System/MenuControllable/MenuControllableSystem.hpp b/sources/System/MenuControllable/MenuControllableSystem.hpp index 0ad43a45..67254369 100644 --- a/sources/System/MenuControllable/MenuControllableSystem.hpp +++ b/sources/System/MenuControllable/MenuControllableSystem.hpp @@ -7,11 +7,14 @@ #include "Component/Controllable/ControllableComponent.hpp" #include "Models/Vector2.hpp" #include "System/System.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Button/ButtonComponent.hpp" namespace BBM { //! @brief A system to handle Controllable entities in a menu. - class MenuControllableSystem : public WAL::System + class MenuControllableSystem : public WAL::System<> { private: //! @brief index of the current button selected @@ -21,11 +24,13 @@ namespace BBM //! @param selected lets know if te new selected button is 'pressed' void _updateCurrentButton(bool selected, Vector2f move); + //! @return true if mouse on entity + bool _mouseOnButton(WAL::ViewEntity &entity) const; public: //! @brief time (in millisecond) since last check std::chrono::time_point now; //! @inherit - void onFixedUpdate(WAL::ViewEntity &entities) override; + void onSelfUpdate() override; //! @brief A default constructor explicit MenuControllableSystem(WAL::Wal &wal); diff --git a/sources/System/Renderer/RenderSystem.cpp b/sources/System/Renderer/RenderSystem.cpp index d21065c2..161bd2d8 100644 --- a/sources/System/Renderer/RenderSystem.cpp +++ b/sources/System/Renderer/RenderSystem.cpp @@ -46,6 +46,21 @@ namespace BBM this->_window.beginDrawing(); this->_window.clear(); + for (auto &[entity, pos, drawable] : this->_wal.getScene()->view()) { + if (!drawable.drawBefore3D) + continue; + auto *shader = entity.tryGetComponent(); + + if (shader) { + RAY::Shader::BeginUsingCustomShader(shader->getShader()); + } + drawable.drawable->setPosition(Vector2f(pos.position.x, pos.position.y)); + drawable.drawable->drawOn(this->_window); + if (shader) { + RAY::Shader::EndUsingCustomShader(); + } + } + this->_window.useCamera(this->_camera); for (auto &[entity, pos, drawable] : this->_wal.getScene()->view()) { auto *modelShader = entity.tryGetComponent(); @@ -63,6 +78,8 @@ namespace BBM // TODO sort entities based on the Z axis for (auto &[entity, pos, drawable] : this->_wal.getScene()->view()) { + if (drawable.drawBefore3D) + continue; auto *shader = entity.tryGetComponent(); if (shader) { diff --git a/sources/System/Shaders/ShaderDrawable2DSystem.cpp b/sources/System/Shaders/ShaderDrawable2DSystem.cpp new file mode 100644 index 00000000..c8e7ae8d --- /dev/null +++ b/sources/System/Shaders/ShaderDrawable2DSystem.cpp @@ -0,0 +1,20 @@ +// +// Created by cbihan on 15/06/2021. +// + +#include "ShaderDrawable2DSystem.hpp" + +namespace BBM +{ + ShaderDrawable2DSystem::ShaderDrawable2DSystem(WAL::Wal &wal) + : System(wal) + { + } + + void ShaderDrawable2DSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &shader = entity->getComponent(); + + shader.update(entity, this->_wal, dtime); + } +} \ No newline at end of file diff --git a/sources/System/Shaders/ShaderDrawable2DSystem.hpp b/sources/System/Shaders/ShaderDrawable2DSystem.hpp new file mode 100644 index 00000000..59d22534 --- /dev/null +++ b/sources/System/Shaders/ShaderDrawable2DSystem.hpp @@ -0,0 +1,29 @@ +// +// Created by cbihan on 15/06/2021. +// + +#pragma once + +#include "Component/Shaders/ShaderComponent.hpp" +#include "System/System.hpp" +#include "Wal.hpp" + +namespace BBM +{ + class ShaderDrawable2DSystem : public WAL::System + { + public: + + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @brief ctor + explicit ShaderDrawable2DSystem(WAL::Wal &wal); + //! @brief Default copy ctor + ShaderDrawable2DSystem(const ShaderDrawable2DSystem &) = default; + //! @brief Default dtor + ~ShaderDrawable2DSystem() override = default; + //! @brief A render screen system can't be assigned. + ShaderDrawable2DSystem &operator=(const ShaderDrawable2DSystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/Shaders/ShaderModelSystem.cpp b/sources/System/Shaders/ShaderModelSystem.cpp new file mode 100644 index 00000000..07baa38a --- /dev/null +++ b/sources/System/Shaders/ShaderModelSystem.cpp @@ -0,0 +1,20 @@ +// +// Created by cbihan on 15/06/2021. +// + +#include "ShaderModelSystem.hpp" + +namespace BBM +{ + ShaderModelSystem::ShaderModelSystem(WAL::Wal &wal) + : System(wal) + { + } + + void ShaderModelSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &shader = entity->getComponent(); + + shader.update(entity, this->_wal, dtime); + } +} \ No newline at end of file diff --git a/sources/System/Shaders/ShaderModelSystem.hpp b/sources/System/Shaders/ShaderModelSystem.hpp new file mode 100644 index 00000000..7680e88f --- /dev/null +++ b/sources/System/Shaders/ShaderModelSystem.hpp @@ -0,0 +1,29 @@ +// +// Created by cbihan on 15/06/2021. +// + +#pragma once + +#include "ShaderSystem.hpp" +#include "System/System.hpp" +#include "Wal.hpp" + +namespace BBM +{ + class ShaderModelSystem : public WAL::System + { + public: + + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @brief ctor + explicit ShaderModelSystem(WAL::Wal &wal); + //! @brief Default copy ctor + ShaderModelSystem(const ShaderModelSystem &) = default; + //! @brief Default dtor + ~ShaderModelSystem() override = default; + //! @brief A render screen system can't be assigned. + ShaderModelSystem &operator=(const ShaderModelSystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/Shaders/ShaderSystem.cpp b/sources/System/Shaders/ShaderSystem.cpp new file mode 100644 index 00000000..8a86e3b6 --- /dev/null +++ b/sources/System/Shaders/ShaderSystem.cpp @@ -0,0 +1,21 @@ +// +// Created by cbihan on 15/06/2021. +// + +#include "ShaderSystem.hpp" + + +namespace BBM +{ + ShaderSystem::ShaderSystem(WAL::Wal &wal) + : System(wal) + { + } + + void ShaderSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &shader = entity->getComponent(); + + shader.update(entity, this->_wal, dtime); + } +} \ No newline at end of file diff --git a/sources/System/Shaders/ShaderSystem.hpp b/sources/System/Shaders/ShaderSystem.hpp new file mode 100644 index 00000000..874505d0 --- /dev/null +++ b/sources/System/Shaders/ShaderSystem.hpp @@ -0,0 +1,28 @@ +// +// Created by cbihan on 15/06/2021. +// + +#pragma once + +#include "Component/Shaders/ShaderComponent.hpp" +#include "System/System.hpp" + +namespace BBM +{ + class ShaderSystem : public WAL::System + { + public: + + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @brief ctor + explicit ShaderSystem(WAL::Wal &wal); + //! @brief Default copy ctor + ShaderSystem(const ShaderSystem &) = default; + //! @brief Default dtor + ~ShaderSystem() override = default; + //! @brief A render screen system can't be assigned. + ShaderSystem &operator=(const ShaderSystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/Sound/MenuSoundManagerSystem.cpp b/sources/System/Sound/MenuSoundManagerSystem.cpp index c1261f32..7f3e57e4 100644 --- a/sources/System/Sound/MenuSoundManagerSystem.cpp +++ b/sources/System/Sound/MenuSoundManagerSystem.cpp @@ -20,7 +20,7 @@ namespace BBM { std::map soundIndex = { {controllable.move.x, SoundComponent::MOVE}, {controllable.move.y, SoundComponent::MOVE}, - {controllable.jump, SoundComponent::JUMP}, + {controllable.select, SoundComponent::JUMP}, }; for (auto &a : soundIndex) { if (a.first) { diff --git a/sources/System/Sound/PlayerSoundManagerSystem.cpp b/sources/System/Sound/PlayerSoundManagerSystem.cpp index dac45304..4068a5e3 100644 --- a/sources/System/Sound/PlayerSoundManagerSystem.cpp +++ b/sources/System/Sound/PlayerSoundManagerSystem.cpp @@ -19,9 +19,9 @@ namespace BBM { sound.setVolume(sound.volume); std::map soundIndex = { - {health.getHealthPoint() <= 0, SoundComponent::DEATH}, - {controllable.bomb, SoundComponent::BOMB}, - {controllable.jump, SoundComponent::JUMP}, + {health.getHealthPoint() <= 0, SoundComponent::DEATH}, + {controllable.bomb, SoundComponent::BOMB}, + {controllable.select, SoundComponent::JUMP}, {controllable.move.x != 0 || controllable.move.y != 0, SoundComponent::MOVE} }; for (auto &a : soundIndex) { diff --git a/sources/System/Timer/TimerSystem.cpp b/sources/System/Timer/TimerSystem.cpp index f6c82c2b..3760534c 100644 --- a/sources/System/Timer/TimerSystem.cpp +++ b/sources/System/Timer/TimerSystem.cpp @@ -4,6 +4,7 @@ #include "TimerSystem.hpp" #include "Component/Timer/TimerComponent.hpp" +#include "Drawables/2D/Text.hpp" using namespace std::chrono_literals; diff --git a/sources/System/Timer/TimerSystem.hpp b/sources/System/Timer/TimerSystem.hpp index c7b20bc2..2be1c1f7 100644 --- a/sources/System/Timer/TimerSystem.hpp +++ b/sources/System/Timer/TimerSystem.hpp @@ -7,6 +7,7 @@ #include #include #include +#include "Component/Renderer/Drawable2DComponent.hpp" namespace BBM { diff --git a/sources/System/Timer/TimerUISystem.cpp b/sources/System/Timer/TimerUISystem.cpp new file mode 100644 index 00000000..a1f4cfa4 --- /dev/null +++ b/sources/System/Timer/TimerUISystem.cpp @@ -0,0 +1,30 @@ +// +// Created by Zoe Roux on 5/31/21. +// + +#include "TimerUISystem.hpp" +#include "Component/Timer/TimerComponent.hpp" +#include "Drawables/2D/Text.hpp" + +using namespace std::chrono_literals; +namespace RAY2D = RAY::Drawables::Drawables2D; + +namespace BBM +{ + TimerUISystem::TimerUISystem(WAL::Wal &wal) + : System(wal) + {} + + void TimerUISystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + auto &timer = entity.get(); + RAY2D::Text *text = dynamic_cast(entity.get().drawable.get()); + + if (text) { + unsigned long second = std::chrono::duration_cast(timer.ringIn).count(); + unsigned long minutes = second / 60; + second = second % 60; + text->setText(std::to_string(minutes) + ":" + std::to_string(second)); + } + } +} \ No newline at end of file diff --git a/sources/System/Timer/TimerUISystem.hpp b/sources/System/Timer/TimerUISystem.hpp new file mode 100644 index 00000000..c21a0300 --- /dev/null +++ b/sources/System/Timer/TimerUISystem.hpp @@ -0,0 +1,29 @@ +// +// Created by Zoe Roux on 5/31/21. +// + +#pragma once + +#include +#include +#include +#include "Component/Renderer/Drawable2DComponent.hpp" + +namespace BBM +{ + class TimerUISystem : public WAL::System + { + public: + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @brief A default constructor + TimerUISystem(WAL::Wal &); + //! @brief A timer system is copy constructable. + TimerUISystem(const TimerUISystem &) = default; + //! @brief A default destructor + ~TimerUISystem() override = default; + //! @breief A timer system is assignable. + TimerUISystem &operator=(const TimerUISystem &) = default; + }; +}