diff --git a/.github/workflows/build_web.yml b/.github/workflows/build_web.yml new file mode 100644 index 00000000..2b9a2f3e --- /dev/null +++ b/.github/workflows/build_web.yml @@ -0,0 +1,20 @@ +name: Web Build (Emscripten) +on: [push, pull_request] + +jobs: + Build: + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - name: Exec + shell: bash + run: ./build_web.sh + - name: Check files creation + run: | + test -f build_web/bomberman.html + test -f build_web/bomberman.js + test -f build_web/bomberman.wasm + test -f build_web/bomberman.data diff --git a/.gitignore b/.gitignore index 42cd6b29..f93eff30 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ cmake-build-debug ./bomberman .vscode build/* -docs/* \ No newline at end of file +docs/* +emsdk/ +build_web/* +wasm-python.py \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f7499f20..f6f5ff40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,15 @@ include_directories(bomberman sources) add_subdirectory(${PROJECT_SOURCE_DIR}/lib/wal) add_subdirectory(${PROJECT_SOURCE_DIR}/lib/Ray) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") + +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_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_DISABLE_EXCEPTION_CATCHING --shell-file ../sources/wasm/frontend.html --preload-file ../assets") + set(CMAKE_EXECUTABLE_SUFFIX ".html") +endif () + set(SOURCES sources/Models/GameState.hpp sources/Runner/Runner.cpp @@ -46,16 +55,12 @@ set(SOURCES sources/System/GridCentered/GridCenteredSystem.cpp sources/System/GridCentered/GridCenteredSystem.hpp sources/Models/Vector2.hpp - sources/Component/Renderer/Drawable3DComponent.hpp sources/Component/Renderer/Drawable2DComponent.hpp - sources/System/Renderer/Renderer3DSystem.hpp - sources/System/Renderer/Renderer2DSystem.hpp - sources/System/Renderer/RenderScreenSystem.hpp - sources/System/Renderer/RenderScreenSystem.cpp + sources/Component/Renderer/Drawable3DComponent.hpp + sources/System/Renderer/RenderSystem.hpp + sources/System/Renderer/RenderSystem.cpp sources/Component/Renderer/CameraComponent.cpp sources/Component/Renderer/CameraComponent.hpp - sources/System/Renderer/Render2DScreenSystem.cpp - sources/System/Renderer/Render2DScreenSystem.hpp sources/Component/Animation/AnimationsComponent.cpp sources/Component/Animation/AnimationsComponent.hpp sources/System/Animation/AnimationsSystem.cpp @@ -69,7 +74,6 @@ set(SOURCES sources/System/Animator/AnimatorSystem.cpp sources/System/Animator/AnimatorSystem.hpp ) - add_executable(bomberman sources/main.cpp ${SOURCES} diff --git a/README.md b/README.md index 0d19b943..6bfa9002 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ mkdir build cd build cmake .. cmake --build . -cd - +cd .. ``` Enjoy ! diff --git a/assets/wall/breakable_wall.mtl b/assets/map/breakable_wall.mtl similarity index 100% rename from assets/wall/breakable_wall.mtl rename to assets/map/breakable_wall.mtl diff --git a/assets/wall/breakable_wall.obj b/assets/map/breakable_wall.obj similarity index 100% rename from assets/wall/breakable_wall.obj rename to assets/map/breakable_wall.obj diff --git a/assets/map/breakable_wall.png b/assets/map/breakable_wall.png new file mode 100644 index 00000000..db05f964 Binary files /dev/null and b/assets/map/breakable_wall.png differ diff --git a/assets/wall/floor.mtl b/assets/map/bumper.mtl similarity index 100% rename from assets/wall/floor.mtl rename to assets/map/bumper.mtl diff --git a/assets/wall/hole.obj b/assets/map/bumper.obj similarity index 100% rename from assets/wall/hole.obj rename to assets/map/bumper.obj diff --git a/assets/map/bumper.png b/assets/map/bumper.png new file mode 100644 index 00000000..a86b67f2 Binary files /dev/null and b/assets/map/bumper.png differ diff --git a/assets/wall/hole.mtl b/assets/map/floor.mtl similarity index 100% rename from assets/wall/hole.mtl rename to assets/map/floor.mtl diff --git a/assets/wall/floor.obj b/assets/map/floor.obj similarity index 100% rename from assets/wall/floor.obj rename to assets/map/floor.obj diff --git a/assets/wall/floor.png b/assets/map/floor.png similarity index 100% rename from assets/wall/floor.png rename to assets/map/floor.png diff --git a/assets/map/hole.mtl b/assets/map/hole.mtl new file mode 100644 index 00000000..f6f7ca22 --- /dev/null +++ b/assets/map/hole.mtl @@ -0,0 +1,13 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl floor +Ns 225.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 2 +map_Kd hole.png diff --git a/assets/map/hole.obj b/assets/map/hole.obj new file mode 100644 index 00000000..094da9d2 --- /dev/null +++ b/assets/map/hole.obj @@ -0,0 +1,54 @@ +# Blender v2.92.0 OBJ File: '' +# www.blender.org +mtllib upper_floor.mtl +o floor +v -0.500000 -0.499144 0.500854 +v -0.500000 -0.500854 -0.499144 +v 0.500000 -0.499144 0.500855 +v 0.500000 -0.500855 -0.499144 +v 0.500000 0.500854 0.499144 +v 0.500000 0.499144 -0.500854 +v -0.500000 0.500855 0.499144 +v -0.500000 0.499144 -0.500855 +vt 0.000977 0.667790 +vt 0.000977 0.333151 +vt 0.333659 0.667790 +vt 0.333659 0.333151 +vt 0.666341 0.667790 +vt 0.666341 0.333151 +vt 0.333659 0.667790 +vt 0.333659 1.002429 +vt 0.000977 0.667790 +vt 0.000977 1.002429 +vt 0.666341 0.667790 +vt 0.666341 1.002429 +vt 0.333659 0.667790 +vt 0.333659 1.002429 +vt 0.666341 0.333151 +vt 0.999024 0.333151 +vt 0.666341 0.667790 +vt 0.999024 0.667790 +vt 0.999024 1.002429 +vt 0.666341 1.002429 +vt 0.999024 0.667790 +vt 0.666341 0.667790 +vn -0.0000 -1.0000 0.0017 +vn 1.0000 -0.0000 0.0000 +vn 0.0000 1.0000 -0.0017 +vn -1.0000 0.0000 -0.0000 +vn 0.0000 -0.0017 -1.0000 +vn -0.0000 0.0017 1.0000 +usemtl floor +s 1 +f 1/1/1 2/2/1 3/3/1 +f 3/3/1 2/2/1 4/4/1 +f 3/3/2 4/4/2 5/5/2 +f 5/5/2 4/4/2 6/6/2 +f 5/7/3 6/8/3 7/9/3 +f 7/9/3 6/8/3 8/10/3 +f 7/11/4 8/12/4 1/13/4 +f 1/13/4 8/12/4 2/14/4 +f 2/15/5 8/16/5 4/17/5 +f 4/17/5 8/16/5 6/18/5 +f 7/19/6 1/20/6 5/21/6 +f 5/21/6 1/20/6 3/22/6 diff --git a/assets/map/hole.png b/assets/map/hole.png new file mode 100644 index 00000000..3a79a9e0 Binary files /dev/null and b/assets/map/hole.png differ diff --git a/assets/map/stairs.mtl b/assets/map/stairs.mtl new file mode 100644 index 00000000..7925a729 --- /dev/null +++ b/assets/map/stairs.mtl @@ -0,0 +1,12 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl Cube.001 +Ns 225.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 2 diff --git a/assets/map/stairs.obj b/assets/map/stairs.obj new file mode 100644 index 00000000..519fef7e --- /dev/null +++ b/assets/map/stairs.obj @@ -0,0 +1,61 @@ +# hole.obj +# + +mtllib hole.mtl +o hole + +v -0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 + +vt 0.000000 0.000000 +vt 0.333333 0.000000 +vt 0.666666 0.000000 +vt 1.000000 0.000000 +vt 0.000000 0.500000 +vt 0.333333 0.500000 +vt 0.666666 0.500000 +vt 1.000000 0.500000 +vt 0.000000 1.000000 +vt 0.333333 1.000000 +vt 0.666666 1.000000 +vt 1.000000 1.000000 + +vn 0.000000 0.000000 1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 + +g floor +usemtl floor +# Back +s 1 +f 1/1/1 2/4/1 3/9/1 +f 3/9/1 2/4/1 4/12/1 +# Top +s 2 +f 3/1/2 4/4/2 5/9/2 +f 5/9/2 4/4/2 6/12/2 +# Front +s 3 +f 5/1/3 6/4/3 7/9/3 +f 7/9/3 6/4/3 8/12/3 +# Bottom +s 4 +f 7/1/4 8/4/4 1/9/4 +f 1/9/4 8/4/4 2/12/4 +# Right +s 5 +f 2/1/5 8/4/5 4/9/5 +f 4/9/5 8/4/5 6/12/5 +# Left +s 6 +f 7/1/6 1/4/6 5/9/6 +f 5/9/6 1/4/6 3/12/6 \ No newline at end of file diff --git a/assets/map/stairs.png b/assets/map/stairs.png new file mode 100644 index 00000000..aa732ced Binary files /dev/null and b/assets/map/stairs.png differ diff --git a/assets/map/test.mtl b/assets/map/test.mtl new file mode 100644 index 00000000..86d5a0cf --- /dev/null +++ b/assets/map/test.mtl @@ -0,0 +1,54 @@ +# Blender v2.92.0 OBJ File: '' +# www.blender.org +mtllib breakable_wall.mtl +o cube +v -0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +vt 0.000000 0.000000 +vt 0.333333 0.000000 +vt 0.000000 0.500000 +vt 0.333333 0.500000 +vt 0.666666 1.000000 +vt 1.000000 1.000000 +vt 0.666666 0.500000 +vt 1.000000 0.500000 +vt 0.000000 1.000000 +vt 0.333333 1.000000 +vt 0.000000 0.500000 +vt 0.333333 0.500000 +vt 0.666666 0.000000 +vt 1.000000 0.000000 +vt 0.666666 0.500000 +vt 1.000000 0.500000 +vt 0.666666 0.500000 +vt 0.666666 1.000000 +vt 0.333333 0.000000 +vt 0.666666 0.000000 +vt 0.333333 0.500000 +vt 0.666666 0.500000 +vn 0.0000 -0.0000 1.0000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 0.0000 +vn -1.0000 0.0000 0.0000 +usemtl cube +s 1 +f 1/1/1 2/2/1 3/3/1 +f 3/3/1 2/2/1 4/4/1 +f 3/5/2 4/6/2 5/7/2 +f 5/7/2 4/6/2 6/8/2 +f 5/9/3 6/10/3 7/11/3 +f 7/11/3 6/10/3 8/12/3 +f 7/13/4 8/14/4 1/15/4 +f 1/15/4 8/14/4 2/16/4 +f 2/17/5 8/12/5 4/18/5 +f 4/18/5 8/12/5 6/10/5 +f 7/19/6 1/20/6 5/21/6 +f 5/21/6 1/20/6 3/22/6 diff --git a/assets/map/test.obj b/assets/map/test.obj new file mode 100644 index 00000000..144c9997 --- /dev/null +++ b/assets/map/test.obj @@ -0,0 +1,61 @@ +# floor.obj +# + +mtllib floor.mtl +o floor + +v -0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 + +vt 0.000000 0.000000 +vt 0.333333 0.000000 +vt 0.666666 0.000000 +vt 1.000000 0.000000 +vt 0.000000 0.500000 +vt 0.333333 0.500000 +vt 0.666666 0.500000 +vt 1.000000 0.500000 +vt 0.000000 1.000000 +vt 0.333333 1.000000 +vt 0.666666 1.000000 +vt 1.000000 1.000000 + +vn 0.000000 0.000000 1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 + +g floor +usemtl floor +# Back +s 1 +f 1/1/1 2/4/1 3/9/1 +f 3/9/1 2/4/1 4/12/1 +# Top +s 2 +f 3/1/2 4/4/2 5/9/2 +f 5/9/2 4/4/2 6/12/2 +# Front +s 3 +f 5/1/3 6/4/3 7/9/3 +f 7/9/3 6/4/3 8/12/3 +# Bottom +s 4 +f 7/1/4 8/4/4 1/9/4 +f 1/9/4 8/4/4 2/12/4 +# Right +s 5 +f 2/1/5 8/4/5 4/9/5 +f 4/9/5 8/4/5 6/12/5 +# Left +s 6 +f 7/1/6 1/4/6 5/9/6 +f 5/9/6 1/4/6 3/12/6 \ No newline at end of file diff --git a/assets/map/test.png b/assets/map/test.png new file mode 100644 index 00000000..bdbc5fda Binary files /dev/null and b/assets/map/test.png differ diff --git a/assets/wall/unbreakable_wall.mtl b/assets/map/unbreakable_wall.mtl similarity index 100% rename from assets/wall/unbreakable_wall.mtl rename to assets/map/unbreakable_wall.mtl diff --git a/assets/wall/unbreakable_wall.obj b/assets/map/unbreakable_wall.obj similarity index 100% rename from assets/wall/unbreakable_wall.obj rename to assets/map/unbreakable_wall.obj diff --git a/assets/wall/unbreakable_wall.png b/assets/map/unbreakable_wall.png similarity index 100% rename from assets/wall/unbreakable_wall.png rename to assets/map/unbreakable_wall.png diff --git a/assets/map/upper_floor.mtl b/assets/map/upper_floor.mtl new file mode 100644 index 00000000..47c30151 --- /dev/null +++ b/assets/map/upper_floor.mtl @@ -0,0 +1,13 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl floor +Ns 225.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 2 +map_Kd upper_floor.png diff --git a/assets/map/upper_floor.obj b/assets/map/upper_floor.obj new file mode 100644 index 00000000..094da9d2 --- /dev/null +++ b/assets/map/upper_floor.obj @@ -0,0 +1,54 @@ +# Blender v2.92.0 OBJ File: '' +# www.blender.org +mtllib upper_floor.mtl +o floor +v -0.500000 -0.499144 0.500854 +v -0.500000 -0.500854 -0.499144 +v 0.500000 -0.499144 0.500855 +v 0.500000 -0.500855 -0.499144 +v 0.500000 0.500854 0.499144 +v 0.500000 0.499144 -0.500854 +v -0.500000 0.500855 0.499144 +v -0.500000 0.499144 -0.500855 +vt 0.000977 0.667790 +vt 0.000977 0.333151 +vt 0.333659 0.667790 +vt 0.333659 0.333151 +vt 0.666341 0.667790 +vt 0.666341 0.333151 +vt 0.333659 0.667790 +vt 0.333659 1.002429 +vt 0.000977 0.667790 +vt 0.000977 1.002429 +vt 0.666341 0.667790 +vt 0.666341 1.002429 +vt 0.333659 0.667790 +vt 0.333659 1.002429 +vt 0.666341 0.333151 +vt 0.999024 0.333151 +vt 0.666341 0.667790 +vt 0.999024 0.667790 +vt 0.999024 1.002429 +vt 0.666341 1.002429 +vt 0.999024 0.667790 +vt 0.666341 0.667790 +vn -0.0000 -1.0000 0.0017 +vn 1.0000 -0.0000 0.0000 +vn 0.0000 1.0000 -0.0017 +vn -1.0000 0.0000 -0.0000 +vn 0.0000 -0.0017 -1.0000 +vn -0.0000 0.0017 1.0000 +usemtl floor +s 1 +f 1/1/1 2/2/1 3/3/1 +f 3/3/1 2/2/1 4/4/1 +f 3/3/2 4/4/2 5/5/2 +f 5/5/2 4/4/2 6/6/2 +f 5/7/3 6/8/3 7/9/3 +f 7/9/3 6/8/3 8/10/3 +f 7/11/4 8/12/4 1/13/4 +f 1/13/4 8/12/4 2/14/4 +f 2/15/5 8/16/5 4/17/5 +f 4/17/5 8/16/5 6/18/5 +f 7/19/6 1/20/6 5/21/6 +f 5/21/6 1/20/6 3/22/6 diff --git a/assets/map/upper_floor.png b/assets/map/upper_floor.png new file mode 100644 index 00000000..307706a5 Binary files /dev/null and b/assets/map/upper_floor.png differ diff --git a/assets/wall/breakable_wall.png b/assets/wall/breakable_wall.png deleted file mode 100644 index 8e18cca8..00000000 Binary files a/assets/wall/breakable_wall.png and /dev/null differ diff --git a/assets/wall/hole.png b/assets/wall/hole.png deleted file mode 100644 index fe9ee288..00000000 Binary files a/assets/wall/hole.png and /dev/null differ diff --git a/build_web.sh b/build_web.sh new file mode 100755 index 00000000..b5975bba --- /dev/null +++ b/build_web.sh @@ -0,0 +1,11 @@ +#! /bin/bash +EMSDK_PATH=./emsdk +if [[ ! -d ./emsdk ]]; then + git clone https://github.com/emscripten-core/emsdk.git +fi +./emsdk/emsdk install latest +./emsdk/emsdk activate latest +source ./emsdk/emsdk_env.sh +mkdir -p build_web +emcmake cmake -S . -B build_web -DPLATFORM=Web && +cmake --build build_web \ No newline at end of file diff --git a/lib/Ray/sources/Exceptions/RayError.hpp b/lib/Ray/sources/Exceptions/RayError.hpp index 52068b22..f700ac17 100644 --- a/lib/Ray/sources/Exceptions/RayError.hpp +++ b/lib/Ray/sources/Exceptions/RayError.hpp @@ -9,6 +9,7 @@ #define RAYERROR_HPP_ #include +#include namespace RAY::Exception { //! @brief base exception class for RAY lib diff --git a/lib/Ray/sources/Window.cpp b/lib/Ray/sources/Window.cpp index 11acdab7..df332bb6 100644 --- a/lib/Ray/sources/Window.cpp +++ b/lib/Ray/sources/Window.cpp @@ -108,10 +108,14 @@ void RAY::Window::clear(RAY::Color color) ClearBackground(color); } -void RAY::Window::draw() +void RAY::Window::beginDrawing() +{ + BeginDrawing(); +} + +void RAY::Window::endDrawing() { EndDrawing(); - BeginDrawing(); } void RAY::Window::useCamera(RAY::Camera::Camera2D &camera) @@ -168,3 +172,13 @@ void RAY::Window::setIcon(RAY::Image &img) { SetWindowIcon(img); } + +void RAY::Window::drawFPS(const RAY::Vector2 &position) +{ + DrawFPS(position.x, position.y); +} + +bool RAY::Window::isReady() const +{ + return IsWindowReady(); +} \ No newline at end of file diff --git a/lib/Ray/sources/Window.hpp b/lib/Ray/sources/Window.hpp index 94c2ad80..f3c507b0 100644 --- a/lib/Ray/sources/Window.hpp +++ b/lib/Ray/sources/Window.hpp @@ -102,8 +102,10 @@ namespace RAY { NONE, }; - //! @brief Draw the content of the buffer on the screen. - void draw(); + //! @brief Setup canvas (framebuffer) to start drawing + void beginDrawing(); + //! @brief End canvas drawing and swap buffers (double buffering) + void endDrawing(); //! @brief Initialize 2D mode with custom camera (2D) void useCamera(Camera::Camera2D &camera); @@ -131,6 +133,11 @@ namespace RAY { //! @brief Draw a 3d mesh with material and transform void draw(const Mesh &mesh, const Material &material, const Matrix &transform); + //! @brief Draws current FPS on the frame + void drawFPS(const Vector2 &position); + //! @return true if the window's context has been correctly initialized + bool isReady() const; + private: //! @brief Creates window, and opens it if openNow is set to true diff --git a/lib/raylib/Findraylib.cmake b/lib/raylib/Findraylib.cmake index 4baf8bd8..d836183b 100644 --- a/lib/raylib/Findraylib.cmake +++ b/lib/raylib/Findraylib.cmake @@ -14,6 +14,9 @@ if (NOT raylib_FOUND) SET(FETCHCONTENT_QUIET NO) FetchContent_Populate(raylib) SET(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + if (EMSCRIPTEN) + SET(PLATFORM Web) + endif() ADD_SUBDIRECTORY(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR}) SET(raylib_FOUND TRUE) endif() diff --git a/lib/wal/CMakeLists.txt b/lib/wal/CMakeLists.txt index e8cd8655..d216b9f3 100644 --- a/lib/wal/CMakeLists.txt +++ b/lib/wal/CMakeLists.txt @@ -17,6 +17,6 @@ add_library(wal sources/Component/Component.cpp sources/System/System.cpp sources/Models/Callback.hpp -) + sources/Models/TypeHolder.hpp) target_include_directories(wal PUBLIC sources) \ No newline at end of file diff --git a/lib/wal/sources/Entity/Entity.hpp b/lib/wal/sources/Entity/Entity.hpp index 8e157c6e..b64bfb82 100644 --- a/lib/wal/sources/Entity/Entity.hpp +++ b/lib/wal/sources/Entity/Entity.hpp @@ -10,6 +10,7 @@ #include #include "Component/Component.hpp" #include "Exception/WalError.hpp" +#include "Models/TypeHolder.hpp" namespace WAL { @@ -83,6 +84,18 @@ namespace WAL return *this; } + //! @brief Add a component to this entity. The component is constructed in place. + //! @throw DuplicateError is thrown if a component with the same type already exist. + //! @return This entity is returned + template + Entity &addComponent(Types &&...params) + { + if (this->hasComponent()) + throw DuplicateError("A component of the type \"" + std::string(typeid(T).name()) + "\" already exists."); + this->_components.push_back(std::make_unique(*this, TypeHolder(), std::forward(params)...)); + return *this; + } + //! @brief Copy a component to this entity. //! @return This entity is returned. Entity &addComponent(const Component &component); diff --git a/lib/wal/sources/Models/TypeHolder.hpp b/lib/wal/sources/Models/TypeHolder.hpp new file mode 100644 index 00000000..45057ed1 --- /dev/null +++ b/lib/wal/sources/Models/TypeHolder.hpp @@ -0,0 +1,13 @@ +// +// Created by Zoe Roux on 2021-06-02. +// + + +#pragma once + +namespace WAL +{ + //! @brief A class only used to specify template arguments. + template + class TypeHolder {}; +} \ No newline at end of file diff --git a/lib/wal/sources/Wal.cpp b/lib/wal/sources/Wal.cpp index 875e3bd8..371c5774 100644 --- a/lib/wal/sources/Wal.cpp +++ b/lib/wal/sources/Wal.cpp @@ -41,8 +41,10 @@ namespace WAL { // TODO use an hashmap to cache results. const auto &dependency = system.getDependencies(); - return std::ranges::all_of(dependency.begin(), dependency.end(), [&entity](const auto &dependency) { - return entity.hasComponent(dependency); - }); + for (const auto &dependency : system.getDependencies()) { + if (!entity.hasComponent(dependency)) + return false; + } + return true; } } // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index 50a87188..3785081a 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -15,6 +15,10 @@ #include "System/System.hpp" #include "Models/Callback.hpp" +#if defined(PLATFORM_WEB) +#include +#endif + namespace WAL { //! @brief The main WAL class, it is used to setup and run the ECS. @@ -109,7 +113,13 @@ namespace WAL void run(const std::function &callback, T state = T()) { Callback update(callback); + + #if defined(PLATFORM_WEB) + std::tuple iterationParams(this, &update, &state); + return emscripten_set_main_loop_arg((em_arg_callback_func)runIteration, (void *)&iterationParams, 0, 1); + #else return this->run(update, state); + #endif } //! @brief Start the game loop @@ -137,6 +147,30 @@ namespace WAL } } + #if defined(PLATFORM_WEB) + template + static void runIteration(void *param) + { + static auto iterationParams = reinterpret_cast *, T *> *>(param); + static const Callback callback = *((Callback *)std::get<1>(*iterationParams)); + static T *state = (T *)std::get<2>(*iterationParams); + static Wal *wal = (Wal *)std::get<0>(*iterationParams); + static auto lastTick = std::chrono::steady_clock::now(); + static std::chrono::nanoseconds fBehind(0); + + auto now = std::chrono::steady_clock::now(); + std::chrono::nanoseconds dtime = now - lastTick; + fBehind += dtime; + lastTick = now; + while (fBehind > Wal::timestep) { + fBehind -= Wal::timestep; + wal->_fixedUpdate(); + } + wal->_update(dtime); + callback(*wal, *state); + } + #endif + //! @brief A default constructor Wal() = default; //! @brief A WAL can't be copy constructed diff --git a/sources/Component/Renderer/Drawable2DComponent.hpp b/sources/Component/Renderer/Drawable2DComponent.hpp index 63aaaf2b..227eacd6 100644 --- a/sources/Component/Renderer/Drawable2DComponent.hpp +++ b/sources/Component/Renderer/Drawable2DComponent.hpp @@ -4,36 +4,37 @@ #pragma once +#include #include "Component/Component.hpp" #include "Drawables/ADrawable2D.hpp" +#include "Model/Model.hpp" namespace BBM { - template class Drawable2DComponent : public WAL::Component { public: //! @brief The type of the component - T member; + std::shared_ptr drawable; - //! ctor - Drawable2DComponent(WAL::Entity &entity, T member) + //! @brief ctor + Drawable2DComponent(WAL::Entity &entity, std::shared_ptr drawable) : WAL::Component(entity), - member(std::move(member)) + drawable(std::move(drawable)) {} //! ctor - template - explicit Drawable2DComponent(WAL::Entity &entity, Params &&...params) + template + explicit Drawable2DComponent(WAL::Entity &entity, WAL::TypeHolder, Params &&...params) : WAL::Component(entity), - member(std::forward(params)...) + drawable(new T(std::forward(params)...)) {} //! @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->member); + return new Drawable2DComponent(entity, this->drawable); } //! @brief Default copy ctor @@ -42,7 +43,5 @@ namespace BBM ~Drawable2DComponent() override = default; //! @brief Default assignment operator Drawable2DComponent &operator=(const Drawable2DComponent &) = delete; - - }; } \ No newline at end of file diff --git a/sources/Component/Renderer/Drawable3DComponent.hpp b/sources/Component/Renderer/Drawable3DComponent.hpp index e4f85321..5a04da07 100644 --- a/sources/Component/Renderer/Drawable3DComponent.hpp +++ b/sources/Component/Renderer/Drawable3DComponent.hpp @@ -4,37 +4,37 @@ #pragma once +#include #include "Component/Component.hpp" #include "Drawables/ADrawable3D.hpp" #include "Model/Model.hpp" namespace BBM { - template class Drawable3DComponent : public WAL::Component { public: //! @brief The type of the component - T member; + std::shared_ptr drawable; //! @brief ctor - Drawable3DComponent(WAL::Entity &entity, T member) + Drawable3DComponent(WAL::Entity &entity, std::shared_ptr drawable) : WAL::Component(entity), - member(std::move(member)) + drawable(std::move(drawable)) {} //! ctor - template - explicit Drawable3DComponent(WAL::Entity &entity, Params &&...params) + template + explicit Drawable3DComponent(WAL::Entity &entity, WAL::TypeHolder, Params &&...params) : WAL::Component(entity), - member(std::forward(params)...) + drawable(new T(std::forward(params)...)) {} //! @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 Drawable3DComponent(entity, this->member); + return new Drawable3DComponent(entity, this->drawable); } //! @brief Default copy ctor diff --git a/sources/Map/Map.cpp b/sources/Map/Map.cpp index c90609f4..6c2dc83c 100644 --- a/sources/Map/Map.cpp +++ b/sources/Map/Map.cpp @@ -8,19 +8,32 @@ namespace RAY3D = RAY::Drawables::Drawables3D; namespace BBM -{ +{ + const std::string MapGenerator::assetsPath = "./assets/"; + const std::string MapGenerator::wallAssetsPath = MapGenerator::assetsPath + "map/"; + const std::string MapGenerator::imageExtension = ".png"; + const std::string MapGenerator::objExtension = ".obj"; + const std::string MapGenerator::breakableWallPath = MapGenerator::wallAssetsPath + "breakable_wall"; + const std::string MapGenerator::unbreakableWallPath = MapGenerator::wallAssetsPath + "unbreakable_wall"; + const std::string MapGenerator::floorPath = MapGenerator::wallAssetsPath + "floor"; + const std::string MapGenerator::secondFloorPath = MapGenerator::wallAssetsPath + "upper_floor"; + const std::string MapGenerator::stairsPath = MapGenerator::wallAssetsPath + "stairs"; + const std::string MapGenerator::bumperPath = MapGenerator::wallAssetsPath + "bumper"; + const std::string MapGenerator::holePath = MapGenerator::wallAssetsPath + "hole"; + void MapGenerator::generateUnbreakableBlock(int width, int height, std::shared_ptr scene) { - std::string unbreakableObj = "assets/wall/unbreakable_wall.obj"; - std::string unbreakablePnj = "assets/wall/unbreakable_wall.png"; + static const std::string UnbreakableObj = unbreakableWallPath + objExtension; + static const std::string UnbreakablePng = unbreakableWallPath + imageExtension; for (int i = 0; i < width + 1; i++) { for (int j = 0; j < height + 1; j++) { if (!(i % 2) && !(j % 2)) { scene->addEntity("Unbreakable Wall") .addComponent(Vector3f(i, 0, j)) - //.addComponent(1) - .addComponent>(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj)); + //.addComponent(1) + .addComponent(UnbreakableObj, + std::make_pair(MAP_DIFFUSE, UnbreakablePng)); } } } @@ -28,44 +41,62 @@ namespace BBM void MapGenerator::generateWall(int width, int height, std::shared_ptr scene) { - std::string unbreakableObj = "assets/wall/unbreakable_wall.obj"; - std::string unbreakablePnj = "assets/wall/unbreakable_wall.png"; + static const std::string unbreakableObj = unbreakableWallPath + objExtension; + static const std::string unbreakablePnj = unbreakableWallPath + imageExtension; scene->addEntity("Bottom Wall") .addComponent(Vector3f((width + 1) / 2, 0, -1)) - //.addComponent(1) - .addComponent>(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(width + 3, 1, 1)); + //.addComponent(1) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(width + 3, 1, 1)); scene->addEntity("Upper Wall") .addComponent(Vector3f((width + 1) / 2, 0, height + 1)) - //.addComponent(1) - .addComponent>(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(width + 3, 1, 1)); + //.addComponent(1) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(width + 3, 1, 1)); scene->addEntity("Left Wall") - .addComponent(Vector3f(width + 1, 0, (height + 1) / 2)) - //.addComponent(1) - .addComponent>(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(1, 1, height + 3)); + .addComponent(Vector3f(width + 1, 0, height / 2)) + //.addComponent(1) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(1, 1, height + 1)); scene->addEntity("Right Wall") - .addComponent(Vector3f(-1, 0, (height + 1) / 2)) - //.addComponent(1) - .addComponent>(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(1, 1, height + 3)); + .addComponent(Vector3f(-1, 0, height / 2)) + //.addComponent(1) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(1, 1, height + 1)); } - void MapGenerator::generateFloor(int width, int height, std::shared_ptr scene) + void MapGenerator::generateFloor(MapBlock map, int width, int height, std::shared_ptr scene) { - scene->addEntity("Floor") - .addComponent(Vector3f(width / 2, -1, height / 2)) - //.addComponent(1) - .addComponent>("assets/wall/floor.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/floor.png"), RAY::Vector3(width + 2, 0, height + 2)); + static const std::string floorObj = floorPath + objExtension; + static const std::string floorPng = floorPath + imageExtension; + + for (int i = 0; i < width + 1; i++) { + for (int j = 0; j < height + 1; j++) { + if (map[std::make_tuple(i, 0, j)] != HOLE && map[std::make_tuple(i, -1, j)] != BUMPER) + scene->addEntity("Unbreakable Wall") + .addComponent(Vector3f(i, -1, j)) + //.addComponent(1) + .addComponent(floorObj, + std::make_pair(MAP_DIFFUSE, floorPng)); + } + } } void MapGenerator::createElement(Vector3f coords, std::shared_ptr scene, BlockType blockType) { std::map elements = { - {BREAKABLE, &createBreakable}, + {BREAKABLE, &createBreakable}, {UNBREAKABLE, &createUnbreakable}, - {HOLE, &createHole}, - {FLOOR, &createFloor}, - /* {BUMPER, &createBumper}, - {STAIRS, &createStairs} */ + {HOLE, &createHole}, + {FLOOR, &createFloor}, + {BUMPER, &createBumper}, + {STAIRS, &createStairs}, + {UPPERFLOOR, &createUpperFloor}, }; try { @@ -78,103 +109,145 @@ namespace BBM void MapGenerator::createBreakable(Vector3f coords, std::shared_ptr scene) { + static const std::string breakableObj = breakableWallPath + objExtension; + static const std::string breakablePng = breakableWallPath + imageExtension; + scene->addEntity("Breakable Block") .addComponent(coords) .addComponent(1) - //.addComponent(1) - .addComponent>("assets/wall/breakable_wall.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/breakable_wall.png")); + //.addComponent(1) + .addComponent(breakableObj, std::make_pair(MAP_DIFFUSE, breakablePng)); } void MapGenerator::createFloor(Vector3f coords, std::shared_ptr scene) { + static const std::string floorObj = floorPath + objExtension; + static const std::string floorPng = floorPath + imageExtension; + scene->addEntity("Floor") .addComponent(Vector3f(coords)) - //.addComponent(1) - .addComponent>("assets/wall/floor.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/floor.png")); + //.addComponent(1) + .addComponent(floorObj, std::make_pair(MAP_DIFFUSE, floorPng)); } + void MapGenerator::createUpperFloor(Vector3f coords, std::shared_ptr scene) + { + static const std::string floorObj = secondFloorPath + objExtension; + static const std::string floorPng = secondFloorPath + imageExtension; + + scene->addEntity("Upper Floor") + .addComponent(Vector3f(coords)) + //.addComponent(1) + .addComponent(floorObj, std::make_pair(MAP_DIFFUSE, floorPng)); + } + + void MapGenerator::createUnbreakable(Vector3f coords, std::shared_ptr scene) { + static const std::string UnbreakableObj = unbreakableWallPath + objExtension; + static const std::string UnbreakablePng = unbreakableWallPath + imageExtension; + scene->addEntity("Unbreakable Block") .addComponent(coords) - //.addComponent(1) - .addComponent>("assets/wall/unbreakable_wall.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/unbreakable_wall.png")); + //.addComponent(1) + .addComponent(UnbreakableObj, + std::make_pair(MAP_DIFFUSE, UnbreakablePng)); } void MapGenerator::createHole(Vector3f coords, std::shared_ptr scene) { + static const std::string holeObj = holePath + objExtension; + static const std::string holePng = holePath + imageExtension; + scene->addEntity("Hole Block") .addComponent(Vector3f(coords.x, coords.y - 1, coords.z)) - .addComponent>("assets/wall/hole.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/hole.png")); - /* .addComponent([](const WAL::Entity &entity, WAL::Entity &other) { - if (other.hasComponent()) { - auto &health = other.getComponent(); - health.takeDmg(health.getHealthPoint()); - } - }); */ + .addComponent(holeObj, std::make_pair(MAP_DIFFUSE, holePng)); + /*.addComponent([](WAL::Entity &other, const WAL::Entity &entity) { + if (other.hasComponent()) { + auto &health = other.getComponent(); + health.takeDmg(health.getHealthPoint()); + } + }, [](WAL::Entity &other, const WAL::Entity &entity){}); */ } void MapGenerator::createBumper(Vector3f coords, std::shared_ptr scene) { + static const std::string bumperObj = bumperPath + objExtension; + static const std::string bumperPng = bumperPath + imageExtension; + scene->addEntity("Bumper Block") - .addComponent(Vector3f(coords.x, coords.y - 1, coords.z)) - .addComponent>("assets/wall/bumper_block.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/bumper_block.png")); - /* .addComponent([](const WAL::Entity &entity, WAL::Entity &other) { - if (other.hasComponent()) { - auto &movable = other.getComponent(); - movable.addForce(Vector3f(0, 5, 0)); - } - } */ + .addComponent(Vector3f(coords.x, coords.y, coords.z)) + .addComponent(bumperObj, std::make_pair(MAP_DIFFUSE, bumperPng)); + /* .addComponent([](const WAL::Entity &entity, WAL::Entity &other) { + if (other.hasComponent()) { + auto &movable = other.getComponent(); + movable.addForce(Vector3f(0, 5, 0)); + } + }); */ } void MapGenerator::createStairs(Vector3f coords, std::shared_ptr scene) { + static const std::string stairsObj = stairsPath + objExtension; + static const std::string stairsPng = stairsPath + imageExtension; + scene->addEntity("Stairs Block") .addComponent(coords) - //.addComponent(1) - .addComponent>("assets/wall/stairs_block.obj", std::make_pair(MAP_DIFFUSE, "assets/wall/stairs_block.png")); + //.addComponent(1) + .addComponent(stairsObj, std::make_pair(MAP_DIFFUSE, stairsPng)); } - bool MapGenerator::isCloseToBlockType(std::map, BlockType> map, int x, int y, int z, BlockType blockType) + bool MapGenerator::isCloseToBlockType(std::map, BlockType> map, int x, int y, int z, + BlockType blockType) { return (map[std::make_tuple(x - 1, y, z)] == blockType || - map[std::make_tuple(x + 1, y, z)] == blockType || - map[std::make_tuple(x, y, z + 1)] == blockType || - map[std::make_tuple(x, y, z - 1)] == blockType); + map[std::make_tuple(x + 1, y, z)] == blockType || + map[std::make_tuple(x, y, z + 1)] == blockType || + map[std::make_tuple(x, y, z - 1)] == blockType); } MapGenerator::BlockType MapGenerator::getRandomBlockType() - { - double rnd = static_cast(std::rand())/RAND_MAX; - + { + double rnd = static_cast(std::rand()) / RAND_MAX; + if (rnd > 0.95) return HOLE; - if (rnd > 0.10) + if (rnd > 0.25) return BREAKABLE; return NOTHING; } MapGenerator::MapBlock MapGenerator::createHeight(MapBlock map, int width, int height) { - double rnd = static_cast(std::rand())/RAND_MAX; + double rnd = static_cast(std::rand()) / RAND_MAX; if (rnd > 0.60) { - for (int i = 0; i < width; i++) { + for (int i = 0; i < width + 1; i++) { map[std::make_tuple(i, 1, height)] = map[std::make_tuple(i, 0, height)]; - map[std::make_tuple(i, 0, height)] = FLOOR; - } - for (int j = 0; j < height; j++) { - map[std::make_tuple(width, 1, j)] = map[std::make_tuple(width, 0, j)]; - map[std::make_tuple(width, 0, j)] = FLOOR; + map[std::make_tuple(i, 0, height)] = UPPERFLOOR; + map[std::make_tuple(i, 1, 0)] = map[std::make_tuple(i, 0, 0)]; + map[std::make_tuple(i, 0, 0)] = UPPERFLOOR; } + map[std::make_tuple(0, 0, height - 1)] = STAIRS; + map[std::make_tuple(0, 0, 1)] = STAIRS; + map[std::make_tuple(width, 0, height - 1)] = STAIRS; + map[std::make_tuple(width, 0, 1)] = STAIRS; + map[std::make_tuple(width / 2, -1, height - 1)] = BUMPER; + map[std::make_tuple(width / 2, -1, 1)] = BUMPER; } if (rnd > 0.30) { - for (int i = width - width/4; i < width + width/4 + 1; i++) { - for (int j = height - height/4; j < height + height/4 + 1; j++) { + for (int i = width / 2 - width / 4; i < width / 2 + width / 4 + 1; i++) { + for (int j = height / 2 - height / 4; j < height / 2 + height / 4 + 1; j++) { + if (map[std::make_tuple(i, 0, j)] == FLOOR) + continue; map[std::make_tuple(i, 1, j)] = map[std::make_tuple(i, 0, j)]; - map[std::make_tuple(i, 0, j)] = FLOOR; + map[std::make_tuple(i, 0, j)] = UPPERFLOOR; } } + map[std::make_tuple(width / 2 - width / 8, 0, height / 2 + height / 4 + 1)] = STAIRS; + map[std::make_tuple(width / 2 + width / 8, 0, height / 2 - height / 4 - 1)] = STAIRS; + map[std::make_tuple(width / 2 - width / 4 - 1, 0, height / 2 - height / 8)] = STAIRS; + map[std::make_tuple(width / 2 + width / 4 + 1, 0, height / 2 + height / 8)] = STAIRS; } return map; } @@ -189,50 +262,58 @@ namespace BBM return map; } + MapGenerator::MapBlock MapGenerator::cleanBreakable(MapBlock map, int width, int height) + { + for (int i = 0; i < width + 1; i++) + for (int j = 0; j < height; j++) { + if (map[std::make_tuple(i, 0, j)] == BREAKABLE && isCloseToBlockType(map, i, 0, j, STAIRS)) + map[std::make_tuple(i, 0, j)] = NOTHING; + if (map[std::make_tuple(i, 0, j)] == BREAKABLE && map[std::make_tuple(i, -1, j)] == BUMPER) + map[std::make_tuple(i, 0, j)] = NOTHING; + } + return (map); + } + MapGenerator::MapBlock MapGenerator::createMap(int width, int height) { MapBlock map; width = width % 2 ? width + 1 : width; height = height % 2 ? height + 1 : height; - for (int i = 0; i < width; i++) { + for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) map[std::make_tuple(i, 0, j)] = NOTHING; - } map = createSpawner(map, width, height); for (int i = 0; i < width + 1; i++) { for (int j = 0; j < height + 1; j++) { if (map[std::make_tuple(i, 0, j)] == SPAWNER) continue; - if (isCloseToBlockType(map, i , 0, j, SPAWNER)) + if (isCloseToBlockType(map, i, 0, j, SPAWNER)) { map[std::make_tuple(i, 0, j)] = NOTHING; - else + } else { map[std::make_tuple(i, 0, j)] = getRandomBlockType(); + } if (map[std::make_tuple(i, 0, j)] == UNBREAKABLE && isCloseToBlockType(map, i, 0, j, UNBREAKABLE)) map[std::make_tuple(i, 0, j)] = BREAKABLE; } } - for (int i = 0; i < width + 1; i++) { - for (int j = 0; j < height + 1; j++) { + for (int i = 0; i < width + 1; i++) + for (int j = 0; j < height + 1; j++) if (!((i + 1) % 2) && !((j + 1) % 2)) map[std::make_tuple(i, 0, j)] = UNBREAKABLE; - } - } map = createHeight(map, width, height); + map = cleanBreakable(map, width, height); return (map); } - void MapGenerator::loadMap(int width, int height, std::map, - BlockType> map, std::shared_ptr scene) + void MapGenerator::loadMap(int width, int height, MapBlock map, std::shared_ptr scene) { generateWall(width, height, scene); - generateFloor(width, height, scene); - for (int x = 0; x < width + 1; x++) { - for (int z = 0; z < height + 1; z++) { - for (int y = 0; y < 1 + 1; y++) + generateFloor(map, width, height, scene); + for (int x = 0; x < width + 1; x++) + for (int z = 0; z < height + 1; z++) + for (int y = -1; y < 1 + 1; y++) createElement(Vector3f(x, y, z), scene, map[std::make_tuple(x, y, z)]); - } - } } } // namespace BBM \ No newline at end of file diff --git a/sources/Map/Map.hpp b/sources/Map/Map.hpp index 962ce7ce..f08f25bd 100644 --- a/sources/Map/Map.hpp +++ b/sources/Map/Map.hpp @@ -14,12 +14,13 @@ #include #include #include "Component/Renderer/Drawable3DComponent.hpp" -#include "System/Renderer/Renderer3DSystem.hpp" +#include "System/Renderer/RenderSystem.hpp" #include "Scene/Scene.hpp" #include "Model/Model.hpp" #include "Component/Component.hpp" #include "Component/Position/PositionComponent.hpp" #include "Component/Health/HealthComponent.hpp" +#include "Component/Collision/CollisionComponent.hpp" #include "Component/Movable/MovableComponent.hpp" namespace BBM @@ -33,6 +34,7 @@ namespace BBM NOTHING, BREAKABLE, HOLE, + UPPERFLOOR, FLOOR, BUMPER, STAIRS, @@ -68,7 +70,7 @@ namespace BBM //! @param height Height of the map //! @param scene Scene where the map is instanced //! @brief Generate the floor of the map - static void generateFloor(int width, int height, std::shared_ptr scene); + static void generateFloor(MapBlock map, int width, int height, std::shared_ptr scene); //! @param coords coords of the element //! @param scene Scene where the map is instanced @@ -97,9 +99,14 @@ namespace BBM //! @param coords coords of the element //! @param scene Scene where the map is instanced - //! @brief Create bumper of the map + //! @brief Create floor of the map static void createFloor(Vector3f coords, std::shared_ptr scene); + //! @param coords coords of the element + //! @param scene Scene where the map is instanced + //! @brief Create upper floor of the map + static void createUpperFloor(Vector3f coords, std::shared_ptr scene); + //! @param coords coords of the element //! @param scene Scene where the map is instanced @@ -118,6 +125,34 @@ namespace BBM //! @brief Generate height for the map static MapBlock createHeight(MapBlock map, int width, int height); + //! @param map Map to load with block declared inside + //! @param width Width of the map + //! @param height Height of the map + //! @brief Clean breakable on stairs, bumpers, etc.. + static MapBlock cleanBreakable(MapBlock map, int width, int height); + + + static const std::string assetsPath; + + static const std::string wallAssetsPath; + + static const std::string imageExtension; + + static const std::string objExtension; + + static const std::string unbreakableWallPath; + + static const std::string breakableWallPath; + + static const std::string floorPath; + + static const std::string stairsPath; + + static const std::string bumperPath; + + static const std::string secondFloorPath; + + static const std::string holePath; public: diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index 8ab5827a..5e0449e9 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -4,15 +4,13 @@ #include #include -#include -#include -#include -#include +#include "System/Movable/MovableSystem.hpp" +#include "System/Renderer/RenderSystem.hpp" #include +#include #include #include #include -#include #include #include #include @@ -23,6 +21,8 @@ #include #include "Models/Vector2.hpp" #include "Component/Renderer/CameraComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Component/Renderer/Drawable3DComponent.hpp" #include "Runner.hpp" #include "Models/GameState.hpp" #include @@ -51,6 +51,8 @@ namespace BBM { wal.addSystem() .addSystem() + .addSystem() + .addSystem() .addSystem() .addSystem(wal) .addSystem(); @@ -60,15 +62,7 @@ namespace BBM { RAY::TraceLog::setLevel(LOG_WARNING); RAY::Window &window = RAY::Window::getInstance(600, 400, "Bomberman", FLAG_WINDOW_RESIZABLE); - - wal.addSystem>(); - wal.addSystem>(); - wal.addSystem(); - wal.addSystem(); - - wal.addSystem(window) - .addSystem>(); - wal.addSystem(window); + wal.addSystem(wal, window); } std::shared_ptr loadGameScene() @@ -76,11 +70,11 @@ namespace BBM auto scene = std::make_shared(); scene->addEntity("player") .addComponent() - .addComponent>("assets/player/player.iqm", std::make_pair(MAP_DIFFUSE, "assets/player/blue.png")) + .addComponent("assets/player/player.iqm", std::make_pair(MAP_DIFFUSE, "assets/player/blue.png")) .addComponent() .addComponent() .addComponent() - .addComponent(RAY::ModelAnimations("assets/player/player.iqm"), 1) + .addComponent(RAY::ModelAnimations("assets/player/player.iqm"), 3) .addComponent(2) .addComponent() .addComponent(1, [](WAL::Entity &entity) { @@ -89,7 +83,7 @@ namespace BBM }); scene->addEntity("cube") .addComponent(-5, 0, -5) - .addComponent>(Vector3f(-5, 0, -5), Vector3f(3, 3, 3), RED) + .addComponent(Vector3f(-5, 0, -5), Vector3f(3, 3, 3), RED) .addComponent() .addComponent() .addComponent([](WAL::Entity &, const WAL::Entity &){}, @@ -103,7 +97,7 @@ namespace BBM scene->addEntity("camera") .addComponent(8, 20, 7) .addComponent(Vector3f(8, 0, 8)); - std::srand(std::time(NULL)); + std::srand(std::time(nullptr)); MapGenerator::loadMap(16, 16, MapGenerator::createMap(16, 16), scene); return scene; } diff --git a/sources/System/Animation/AnimationsSystem.cpp b/sources/System/Animation/AnimationsSystem.cpp index 3400cf10..cce35719 100644 --- a/sources/System/Animation/AnimationsSystem.cpp +++ b/sources/System/Animation/AnimationsSystem.cpp @@ -13,7 +13,7 @@ namespace BBM AnimationsSystem::AnimationsSystem() : WAL::System({ - typeid(Drawable3DComponent), + typeid(Drawable3DComponent), typeid(AnimationsComponent) }) { @@ -21,12 +21,15 @@ namespace BBM void AnimationsSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds) { - auto &model = entity.getComponent>(); + auto &model = entity.getComponent(); auto &anim = entity.getComponent(); if (anim.isDisabled()) return; - model.member.setAnimation(anim.getCurrentModelAnim()); - anim.incCurrentAnimFrameCounter(); + auto modelPtr = std::dynamic_pointer_cast(model.drawable); + if (modelPtr) { + modelPtr->setAnimation(anim.getCurrentModelAnim()); + anim.incCurrentAnimFrameCounter(); + } } } \ No newline at end of file diff --git a/sources/System/Animator/AnimatorSystem.cpp b/sources/System/Animator/AnimatorSystem.cpp index 874dba08..a9dd38c4 100644 --- a/sources/System/Animator/AnimatorSystem.cpp +++ b/sources/System/Animator/AnimatorSystem.cpp @@ -31,11 +31,13 @@ namespace BBM const std::vector> moveDiag = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; const std::vector rotationAngle = {0.0f, 45.0f, 90.0f, 135.0f, 180.0f, 225.0f, 270.0f, 315.0f}; const auto &controllable = entity.getComponent(); - auto &model = entity.getComponent>(); + auto drawable = entity.getComponent().drawable.get(); auto &animation = entity.getComponent(); + auto anim = dynamic_cast(drawable); for (int i = 0; i != moveDiag.size(); i++) { if (controllable.move.x == moveDiag[i][0] && controllable.move.y == moveDiag[i][1]) { - model.member.setRotationAngle(rotationAngle[i]); + if (anim) + anim->setRotationAngle(rotationAngle[i]); animation.setAnimIndex(0); return; } diff --git a/sources/System/Collision/CollisionSystem.hpp b/sources/System/Collision/CollisionSystem.hpp index c4c2de25..b3d78b55 100644 --- a/sources/System/Collision/CollisionSystem.hpp +++ b/sources/System/Collision/CollisionSystem.hpp @@ -8,6 +8,7 @@ #include #include "Wal.hpp" #include "System/System.hpp" +#include "Models/Vector3.hpp" namespace BBM { diff --git a/sources/System/Renderer/Render2DScreenSystem.cpp b/sources/System/Renderer/Render2DScreenSystem.cpp deleted file mode 100644 index 938d107f..00000000 --- a/sources/System/Renderer/Render2DScreenSystem.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Zoe Roux on 5/27/21. -// - -#include "Render2DScreenSystem.hpp" - -namespace BBM -{ - Render2DScreenSystem::Render2DScreenSystem(RAY::Window &window) - : WAL::System({}), - _window(window), - _camera(RAY::Vector2(10, 10), RAY::Vector2(), 0) - {} - - void Render2DScreenSystem::onSelfUpdate() - { - this->_window.useCamera(this->_camera); - } -} \ No newline at end of file diff --git a/sources/System/Renderer/Render2DScreenSystem.hpp b/sources/System/Renderer/Render2DScreenSystem.hpp deleted file mode 100644 index 12adaf34..00000000 --- a/sources/System/Renderer/Render2DScreenSystem.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zoe Roux on 5/27/21. -// - -#pragma once - -#include -#include - -namespace BBM -{ - class Render2DScreenSystem : public WAL::System - { - //! @brief The window to render on - RAY::Window &_window; - - //! @brief The camera used to render. - RAY::Camera::Camera2D _camera; - public: - //! @brief A method called after all entities that this system manage has been updated. - //! @note render on screen here - void onSelfUpdate() override; - - //! @brief ctor - explicit Render2DScreenSystem(RAY::Window &window); - //! @brief Default copy ctor - Render2DScreenSystem(const Render2DScreenSystem &) = default; - //! @brief Default dtor - ~Render2DScreenSystem() override = default; - //! @brief A render screen system can't be assigned. - Render2DScreenSystem &operator=(const Render2DScreenSystem &) = delete; - }; -} \ No newline at end of file diff --git a/sources/System/Renderer/RenderScreenSystem.cpp b/sources/System/Renderer/RenderScreenSystem.cpp deleted file mode 100644 index c85e6971..00000000 --- a/sources/System/Renderer/RenderScreenSystem.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Created by Zoe Roux on 5/27/21. -// - -#include "RenderScreenSystem.hpp" -#include "Component/Renderer/CameraComponent.hpp" -#include "Component/Position/PositionComponent.hpp" - -namespace BBM -{ - RenderScreenSystem::RenderScreenSystem(RAY::Window &window) - : WAL::System({ - typeid(CameraComponent), - typeid(PositionComponent) - }), - _window(window), - _camera(Vector3f(), Vector3f(), Vector3f(0, 1, 0), 50, CAMERA_PERSPECTIVE) - { - this->_window.setFPS(60); - } - - void RenderScreenSystem::onSelfUpdate() - { - this->_window.draw(); - this->_window.clear(); - this->_window.useCamera(this->_camera); - } - - void RenderScreenSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) - { - const auto &pos = entity.getComponent(); - const auto &cam = entity.getComponent(); - _camera.setPosition(pos.position); - _camera.setTarget(cam.target); - } -} \ No newline at end of file diff --git a/sources/System/Renderer/RenderSystem.cpp b/sources/System/Renderer/RenderSystem.cpp new file mode 100644 index 00000000..57f99b83 --- /dev/null +++ b/sources/System/Renderer/RenderSystem.cpp @@ -0,0 +1,71 @@ +// +// Created by Zoe Roux on 5/27/21. +// + +#include +#include "Models/Vector2.hpp" +#include "RenderSystem.hpp" +#include "Component/Renderer/CameraComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Renderer/Drawable2DComponent.hpp" +#include "Drawables/ADrawable2D.hpp" +#include "Drawables/ADrawable3D.hpp" + +namespace BBM +{ + RenderSystem::RenderSystem(WAL::Wal &wal, RAY::Window &window, bool debugMode) + : WAL::System({ + typeid(CameraComponent), + typeid(PositionComponent) + }), + _wal(wal), + _window(window), + _camera(Vector3f(), Vector3f(), Vector3f(0, 1, 0), 50, CAMERA_PERSPECTIVE), + _debugMode(debugMode) + { + this->_window.setFPS(this->FPS); + } + + void RenderSystem::onSelfUpdate() + { + this->_camera.update(); + this->_window.beginDrawing(); + this->_window.clear(); + + this->_window.useCamera(this->_camera); + for (auto &entity : this->_wal.scene->getEntities()) { + if (!entity.hasComponent() + || !entity.hasComponent()) + continue; + auto &drawable = entity.getComponent(); + auto &pos = entity.getComponent(); + + drawable.drawable->setPosition(pos.position); + drawable.drawable->drawOn(this->_window); + } + this->_window.unuseCamera(); + + // TODO sort entities based on the Z axis + for (auto &entity : this->_wal.scene->getEntities()) { + if (!entity.hasComponent() + || !entity.hasComponent()) + continue; + auto &drawable = entity.getComponent(); + auto &pos = entity.getComponent(); + + drawable.drawable->setPosition(Vector2f(pos.position.x, pos.position.y)); + drawable.drawable->drawOn(this->_window); + } + if (this->_debugMode) + this->_window.drawFPS(Vector2f()); + this->_window.endDrawing(); + } + + void RenderSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) + { + const auto &pos = entity.getComponent(); + const auto &cam = entity.getComponent(); + _camera.setPosition(pos.position); + _camera.setTarget(cam.target); + } +} \ No newline at end of file diff --git a/sources/System/Renderer/RenderScreenSystem.hpp b/sources/System/Renderer/RenderSystem.hpp similarity index 58% rename from sources/System/Renderer/RenderScreenSystem.hpp rename to sources/System/Renderer/RenderSystem.hpp index e9b2ea85..e3852944 100644 --- a/sources/System/Renderer/RenderScreenSystem.hpp +++ b/sources/System/Renderer/RenderSystem.hpp @@ -7,16 +7,27 @@ #include "System/System.hpp" #include "Camera/Camera2D.hpp" #include "Window.hpp" +#include "Wal.hpp" namespace BBM { - class RenderScreenSystem : public WAL::System + class RenderSystem : public WAL::System { + //! @brief The ECS to update. + WAL::Wal &_wal; + //! @brief The window to render on RAY::Window &_window; //! @brief The camera used to render. RAY::Camera::Camera3D _camera; + + //! @brief Defines if the debug informations must be displayed or not + bool _debugMode; + + //! @brief Window framerate limit + static constexpr short FPS = 60; + public: //! @brief A method called after all entities that this system manage has been updated. //! @note render on screen here @@ -26,12 +37,12 @@ namespace BBM void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) override; //! @brief ctor - explicit RenderScreenSystem(RAY::Window &window); + RenderSystem(WAL::Wal &wal, RAY::Window &window, bool debugMode = true); //! @brief Default copy ctor - RenderScreenSystem(const RenderScreenSystem &) = default; + RenderSystem(const RenderSystem &) = default; //! @brief Default dtor - ~RenderScreenSystem() override = default; + ~RenderSystem() override = default; //! @brief A render screen system can't be assigned. - RenderScreenSystem &operator=(const RenderScreenSystem &) = delete; + RenderSystem &operator=(const RenderSystem &) = delete; }; } diff --git a/sources/System/Renderer/Renderer2DSystem.hpp b/sources/System/Renderer/Renderer2DSystem.hpp deleted file mode 100644 index a1622c0d..00000000 --- a/sources/System/Renderer/Renderer2DSystem.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by cbihan on 24/05/2021. -// - -#pragma once - -#include -#include "System/System.hpp" -#include "Entity/Entity.hpp" -#include "Component/Position/PositionComponent.hpp" -#include "Component/Renderer/Drawable2DComponent.hpp" -#include "Window.hpp" - -namespace BBM -{ - template - class Renderer2DSystem : public WAL::System - { - private: - //! @brief The class to render - RAY::Window &_window; - public: - explicit Renderer2DSystem() - : WAL::System({typeid(PositionComponent), typeid(Drawable2DComponent)}), - _window(RAY::Window::getInstance()) - { - } - - //! @brief Update the corresponding component of the given entity - //! @param entity The entity to update. - //! @param dtime The delta time. - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds) override - { - auto &comp = entity.getComponent>(); - auto &pos = entity.getComponent(); - - comp.member.setPosition({pos.getX(), pos.getY()}); - comp.member.drawOn(this->_window); - } - - //! @brief default copy ctor - Renderer2DSystem(const Renderer2DSystem &) = default; - //! @brief default dtor - ~Renderer2DSystem() override = default; - //! @brief Default assignment operator - Renderer2DSystem &operator=(const Renderer2DSystem &) = delete; - }; -} \ No newline at end of file diff --git a/sources/System/Renderer/Renderer3DSystem.hpp b/sources/System/Renderer/Renderer3DSystem.hpp deleted file mode 100644 index 8dba98f6..00000000 --- a/sources/System/Renderer/Renderer3DSystem.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by cbihan on 24/05/2021. -// - -#pragma once - -#include -#include "System/System.hpp" -#include "Entity/Entity.hpp" -#include "Component/Position/PositionComponent.hpp" -#include "Component/Renderer/Drawable3DComponent.hpp" -#include "Window.hpp" - -namespace BBM -{ - template - class Renderer3DSystem : public WAL::System - { - private: - //! @brief The class to render - RAY::Window &_window; - public: - //! @brief ctor - explicit Renderer3DSystem() - : WAL::System({typeid(PositionComponent), typeid(Drawable3DComponent)}), - _window(RAY::Window::getInstance()) - {} - - //! @brief Update the corresponding component of the given entity - //! @param entity The entity to update. - //! @param dtime The delta time. - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds) override - { - auto &comp = entity.getComponent>(); - auto &pos = entity.getComponent(); - - comp.member.setPosition(static_cast(pos.position)); - comp.member.drawOn(this->_window); - } - - //! @brief Default copy ctor - Renderer3DSystem(const Renderer3DSystem &) = default; - //! @brief Default dtor - ~Renderer3DSystem() override = default; - //! @brief Default assignment operator - Renderer3DSystem &operator=(const Renderer3DSystem &) = delete; - }; -} \ No newline at end of file diff --git a/sources/main.cpp b/sources/main.cpp index cb4a0269..bd13441a 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -9,50 +9,6 @@ #include #include "Runner/Runner.hpp" -// Dependencies of the demo -#include "Camera/Camera3D.hpp" -#include "Controllers/Keyboard.hpp" -#include "Drawables/2D/Text.hpp" -#include "Drawables/Image.hpp" -#include "Drawables/3D/Grid.hpp" -#include "Drawables/Texture.hpp" -#include "Drawables/3D/Circle.hpp" -#include "Drawables/2D/Circle.hpp" -#include "Drawables/3D/Cube.hpp" -#include "Drawables/3D/Sphere.hpp" -#include "Model/Model.hpp" -#include "Model/ModelAnimations.hpp" -#include -#include -#include -#include -#include "Component/Renderer/Drawable3DComponent.hpp" -#include "Component/Renderer/Drawable2DComponent.hpp" -#include "System/Renderer/RenderScreenSystem.hpp" -#include "Vector/Vector3.hpp" -#include "Window.hpp" -#include "TraceLog.hpp" -#include "Wal.hpp" - -const std::vectortextures = { - "blue", "cyan", "green", "purple", "red", "yellow" -}; - -std::string get_full_path(const std::string &color) -{ - std::string path = "assets/player/"; - - path += color; - path += ".png"; - return path; -} - -int demo(void) -{ - - return (0); -} - void usage(const std::string &bin) { std::cout << "Bomberman." << std::endl @@ -67,6 +23,5 @@ int main(int argc, char **argv) usage(argv[0]); return 1; } - //return demo(); return BBM::run(); } diff --git a/sources/wasm/frontend.html b/sources/wasm/frontend.html new file mode 100644 index 00000000..2816e377 --- /dev/null +++ b/sources/wasm/frontend.html @@ -0,0 +1,147 @@ + + + + + + Emscripten-Generated Code + + + +
+
emscripten
+
Downloading...
+
+ +
+
+ +
+
+
+ Resize canvas + Lock/hide mouse pointer +     + +
+ +
+ + {{{ SCRIPT }}} + + \ No newline at end of file