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 6beac4e5..dfb9d892 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,10 +10,19 @@ include_directories(bomberman sources) 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_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 sources/Runner/Runner.hpp + sources/Map/Map.cpp + sources/Map/Map.hpp sources/Component/Position/PositionComponent.cpp sources/Component/Position/PositionComponent.hpp sources/Component/Movable/MovableComponent.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/System/BombHolder/BombHolderSystem.cpp sources/System/BombHolder/BombHolderSystem.hpp sources/Component/Timer/TimerComponent.cpp @@ -64,8 +69,15 @@ set(SOURCES sources/System/Timer/TimerSystem.hpp sources/System/Event/EventSystem.cpp sources/System/Event/EventSystem.hpp + sources/Component/Animation/AnimationsComponent.cpp + sources/Component/Animation/AnimationsComponent.hpp + sources/System/Animation/AnimationsSystem.cpp + sources/System/Animation/AnimationsSystem.hpp + sources/Component/Collision/CollisionComponent.cpp + sources/Component/Collision/CollisionComponent.hpp + sources/System/Collision/CollisionSystem.hpp + sources/System/Collision/CollisionSystem.cpp ) - add_executable(bomberman sources/main.cpp ${SOURCES} @@ -81,6 +93,8 @@ add_executable(unit_tests EXCLUDE_FROM_ALL tests/EngineTests.cpp tests/CallbackTest.cpp tests/MoveTests.cpp +tests/ViewTest.cpp + tests/CollisionTest.cpp ) target_include_directories(unit_tests PUBLIC sources) target_link_libraries(unit_tests PUBLIC wal ray) diff --git a/README.md b/README.md index 18e93e7a..6bfa9002 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,13 @@ mkdir build cd build cmake .. cmake --build . +cd .. ``` Enjoy ! ```bash -./bomberman +./build/bomberman ``` diff --git a/assets/map/breakable_wall.mtl b/assets/map/breakable_wall.mtl new file mode 100644 index 00000000..86d5a0cf --- /dev/null +++ b/assets/map/breakable_wall.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/breakable_wall.obj b/assets/map/breakable_wall.obj new file mode 100644 index 00000000..144c9997 --- /dev/null +++ b/assets/map/breakable_wall.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/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/breakable_wall.mtl b/assets/map/bumper.mtl similarity index 100% rename from assets/wall/breakable_wall.mtl rename to assets/map/bumper.mtl diff --git a/assets/map/bumper.obj b/assets/map/bumper.obj new file mode 100644 index 00000000..519fef7e --- /dev/null +++ b/assets/map/bumper.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/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/map/floor.mtl b/assets/map/floor.mtl new file mode 100644 index 00000000..7925a729 --- /dev/null +++ b/assets/map/floor.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/floor.obj b/assets/map/floor.obj new file mode 100644 index 00000000..144c9997 --- /dev/null +++ b/assets/map/floor.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/floor.png b/assets/map/floor.png new file mode 100644 index 00000000..74624ea9 Binary files /dev/null and b/assets/map/floor.png differ 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/wall/breakable_wall.png b/assets/map/test.png similarity index 100% rename from assets/wall/breakable_wall.png rename to assets/map/test.png 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/player/blue.png b/assets/player/blue.png index d8cf2be5..bb40eb06 100644 Binary files a/assets/player/blue.png and b/assets/player/blue.png differ diff --git a/assets/wall/breakable_wall.obj b/assets/wall/breakable_wall.obj deleted file mode 100644 index 320cb55e..00000000 --- a/assets/wall/breakable_wall.obj +++ /dev/null @@ -1,338 +0,0 @@ -# Blender v2.92.0 OBJ File: '' -# www.blender.org -mtllib breakable_wall.mtl -o Cube.002 -v 0.404250 -0.428000 -0.404250 -v 0.404250 -0.428000 0.404250 -v -0.404250 -0.428000 0.404250 -v -0.404250 -0.428000 -0.404250 -v -0.404250 0.436000 0.404250 -v 0.404250 0.436000 0.404250 -v 0.404250 0.436000 -0.404250 -v -0.404250 0.436000 -0.404250 -v 0.432000 0.408250 -0.404250 -v 0.432000 0.408250 0.404250 -v 0.432000 -0.400250 0.404250 -v 0.432000 -0.400250 -0.404250 -v 0.404250 -0.500000 -0.404250 -v -0.404250 -0.500000 -0.404250 -v -0.404250 -0.500000 -0.504000 -v 0.404250 -0.500000 -0.504000 -v -0.404250 -0.500000 0.404250 -v 0.404250 -0.500000 0.404250 -v 0.404250 -0.500000 0.504000 -v -0.404250 -0.500000 0.504000 -v -0.404250 0.508000 -0.404250 -v 0.404250 0.508000 -0.404250 -v 0.404250 0.508000 -0.504000 -v -0.404250 0.508000 -0.504000 -v 0.404250 0.508000 0.404250 -v -0.404250 0.508000 0.404250 -v -0.404250 0.508000 0.504000 -v 0.404250 0.508000 0.504000 -v 0.504000 0.408250 -0.404250 -v 0.504000 -0.400250 -0.404250 -v 0.504000 -0.400250 -0.504000 -v 0.504000 0.408250 -0.504000 -v 0.504000 -0.400250 0.404250 -v 0.504000 0.408250 0.404250 -v 0.504000 0.408250 0.504000 -v 0.504000 -0.400250 0.504000 -v -0.504000 0.408250 0.404250 -v -0.504000 -0.400250 0.404250 -v -0.504000 -0.400250 0.504000 -v -0.504000 0.408250 0.504000 -v -0.504000 -0.400250 -0.404250 -v -0.504000 0.408250 -0.404250 -v -0.504000 0.408250 -0.504000 -v -0.504000 -0.400250 -0.504000 -v 0.404250 0.408250 0.504000 -v -0.404250 0.408250 0.504000 -v -0.404250 -0.400250 0.504000 -v 0.404250 -0.400250 0.504000 -v 0.504000 0.508000 -0.404250 -v 0.504000 0.508000 0.404250 -v 0.504000 -0.500000 0.404250 -v 0.504000 -0.500000 -0.404250 -v 0.404250 0.408250 -0.504000 -v -0.404250 0.408250 -0.504000 -v -0.404250 -0.400250 -0.504000 -v 0.404250 -0.400250 -0.504000 -v -0.504000 0.508000 -0.404250 -v -0.504000 0.508000 0.404250 -v -0.504000 -0.500000 0.404250 -v -0.504000 -0.500000 -0.404250 -v 0.504000 0.508000 -0.504000 -v 0.504000 -0.500000 -0.504000 -v 0.504000 -0.500000 0.504000 -v 0.504000 0.508000 0.504000 -v -0.504000 0.508000 0.504000 -v -0.504000 -0.500000 0.504000 -v -0.504000 -0.500000 -0.504000 -v -0.504000 0.508000 -0.504000 -v -0.404250 0.408250 0.432000 -v 0.404250 0.408250 0.432000 -v -0.404250 -0.400250 0.432000 -v 0.404250 -0.400250 0.432000 -v 0.404250 0.408250 -0.432000 -v -0.404250 0.408250 -0.432000 -v 0.404250 -0.400250 -0.432000 -v -0.404250 -0.400250 -0.432000 -v -0.432000 0.408250 0.404250 -v -0.432000 -0.400250 0.404250 -v -0.432000 0.408250 -0.404250 -v -0.432000 -0.400250 -0.404250 -vt 0.287300 0.056300 -vt 0.287300 0.282400 -vt 0.061200 0.282400 -vt 0.061200 0.056300 -vt 0.621800 0.620900 -vt 0.395400 0.620900 -vt 0.395400 0.394400 -vt 0.621800 0.394400 -vt 0.299200 0.394400 -vt 0.299200 0.620900 -vt 0.072700 0.620900 -vt 0.072700 0.394400 -vt 0.287300 0.036100 -vt 0.061200 0.036100 -vt 0.061200 0.008200 -vt 0.287300 0.008200 -vt 0.061200 0.302500 -vt 0.287300 0.302500 -vt 0.287300 0.330400 -vt 0.061200 0.330400 -vt 0.621800 0.374200 -vt 0.395400 0.374200 -vt 0.395400 0.346300 -vt 0.621800 0.346300 -vt 0.395400 0.641000 -vt 0.621800 0.641000 -vt 0.621800 0.669000 -vt 0.395400 0.669000 -vt 0.299200 0.374200 -vt 0.072700 0.374200 -vt 0.072700 0.346300 -vt 0.299200 0.346300 -vt 0.072700 0.641000 -vt 0.299200 0.641000 -vt 0.299200 0.669000 -vt 0.072700 0.669000 -vt 0.718100 0.641000 -vt 0.944500 0.641000 -vt 0.944500 0.669000 -vt 0.718100 0.669000 -vt 0.944500 0.374200 -vt 0.718100 0.374200 -vt 0.718100 0.346300 -vt 0.944500 0.346300 -vt 0.395400 0.696900 -vt 0.621800 0.696900 -vt 0.621800 0.963700 -vt 0.621800 0.991700 -vt 0.395400 0.991700 -vt 0.395400 0.963700 -vt 0.347300 0.394400 -vt 0.347300 0.620900 -vt 0.319300 0.620900 -vt 0.319300 0.394400 -vt 0.052500 0.394400 -vt 0.052500 0.620900 -vt 0.024600 0.620600 -vt 0.024600 0.394300 -vt 0.395400 0.318300 -vt 0.621800 0.318300 -vt 0.621800 0.051500 -vt 0.395400 0.051500 -vt 0.395400 0.023600 -vt 0.621800 0.023600 -vt 0.670000 0.394400 -vt 0.697900 0.394400 -vt 0.697900 0.620900 -vt 0.670000 0.620900 -vt 0.992600 0.620900 -vt 0.964700 0.620900 -vt 0.964700 0.394400 -vt 0.992600 0.394400 -vt 0.319300 0.366500 -vt 0.347300 0.366500 -vt 0.052500 0.366500 -vt 0.024600 0.366500 -vt 0.052500 0.648800 -vt 0.024600 0.648800 -vt 0.319300 0.648800 -vt 0.347300 0.648800 -vt 0.697900 0.648800 -vt 0.670000 0.648800 -vt 0.964700 0.648800 -vt 0.992600 0.648800 -vt 0.964700 0.366500 -vt 0.992600 0.366500 -vt 0.697900 0.366500 -vt 0.670000 0.366500 -vt 0.335400 0.282600 -vt 0.307500 0.282400 -vt 0.307500 0.056300 -vt 0.335400 0.056300 -vt 0.013200 0.282400 -vt 0.013200 0.056300 -vt 0.041100 0.056300 -vt 0.041100 0.282400 -vt 0.642000 0.620900 -vt 0.642000 0.394400 -vt 0.375200 0.394400 -vt 0.375200 0.620900 -vt 0.670000 0.717100 -vt 0.670000 0.943500 -vt 0.642000 0.943500 -vt 0.642000 0.717100 -vt 0.347300 0.717100 -vt 0.375200 0.717100 -vt 0.375200 0.943500 -vt 0.347300 0.943500 -vt 0.347300 0.298200 -vt 0.347300 0.071700 -vt 0.375200 0.071700 -vt 0.375200 0.298200 -vt 0.670000 0.071700 -vt 0.670000 0.298200 -vt 0.642000 0.298200 -vt 0.642000 0.071700 -vt 0.315200 0.008200 -vt 0.315200 0.036100 -vt 0.033300 0.008200 -vt 0.033300 0.036100 -vt 0.033300 0.302500 -vt 0.033300 0.330400 -vt 0.315200 0.302500 -vt 0.315200 0.330400 -vt 0.649800 0.374200 -vt 0.649800 0.346300 -vt 0.367400 0.374200 -vt 0.367400 0.346300 -vt 0.367400 0.669000 -vt 0.367400 0.641000 -vt 0.649800 0.669000 -vt 0.649800 0.641000 -vt 0.649800 0.696900 -vt 0.367400 0.696900 -vt 0.367400 0.991700 -vt 0.367400 0.963700 -vt 0.649800 0.963700 -vt 0.649800 0.991700 -vt 0.367400 0.318300 -vt 0.649800 0.318300 -vt 0.649800 0.023600 -vt 0.649800 0.051500 -vt 0.367400 0.051500 -vt 0.367400 0.023600 -vt 0.621800 0.717100 -vt 0.395400 0.717100 -vt 0.621800 0.943500 -vt 0.395400 0.943500 -vt 0.395400 0.298200 -vt 0.621800 0.298200 -vt 0.395400 0.071700 -vt 0.621800 0.071700 -vt 0.718100 0.620900 -vt 0.944500 0.620900 -vt 0.718100 0.394400 -vt 0.944500 0.394400 -vn 0.0000 -1.0000 -0.0000 -vn 0.0000 1.0000 0.0000 -vn 1.0000 0.0000 0.0000 -vn -1.0000 0.0000 0.0000 -vn 0.0000 0.0000 1.0000 -vn 0.0000 0.0000 -1.0000 -vn -0.7071 0.0000 0.7071 -vn 0.7071 0.0000 0.7071 -vn -0.7071 0.0000 -0.7071 -vn 0.7071 0.0000 -0.7071 -vn 0.7071 -0.7071 0.0000 -vn -0.7071 -0.7071 0.0000 -vn 0.7071 0.7071 0.0000 -vn -0.7071 0.7071 0.0000 -vn 0.0000 -0.7071 0.7071 -vn 0.0000 0.7071 0.7071 -vn 0.0000 -0.7071 -0.7071 -vn 0.0000 0.7071 -0.7071 -usemtl Cube.001 -s 1 -f 1/1/1 2/2/1 3/3/1 4/4/1 -f 5/5/2 6/6/2 7/7/2 8/8/2 -f 9/9/3 10/10/3 11/11/3 12/12/3 -f 13/13/1 14/14/1 15/15/1 16/16/1 -f 17/17/1 18/18/1 19/19/1 20/20/1 -f 21/21/2 22/22/2 23/23/2 24/24/2 -f 25/25/2 26/26/2 27/27/2 28/28/2 -f 29/29/3 30/30/3 31/31/3 32/32/3 -f 33/33/3 34/34/3 35/35/3 36/36/3 -f 37/37/4 38/38/4 39/39/4 40/40/4 -f 41/41/4 42/42/4 43/43/4 44/44/4 -f 45/45/5 28/28/5 27/27/5 46/46/5 -f 47/47/5 20/48/5 19/49/5 48/50/5 -f 49/51/3 50/52/3 34/53/3 29/54/3 -f 30/55/3 33/56/3 51/57/3 52/58/3 -f 53/59/6 54/60/6 24/24/6 23/23/6 -f 55/61/6 56/62/6 16/63/6 15/64/6 -f 57/65/4 42/66/4 37/67/4 58/68/4 -f 59/69/4 38/70/4 41/71/4 60/72/4 -f 29/54/3 32/73/3 61/74/3 49/51/3 -f 31/75/3 30/55/3 52/58/3 62/76/3 -f 33/56/3 36/77/3 63/78/3 51/57/3 -f 35/79/3 34/53/3 50/52/3 64/80/3 -f 37/67/4 40/81/4 65/82/4 58/68/4 -f 39/83/4 38/70/4 59/69/4 66/84/4 -f 41/71/4 44/85/4 67/86/4 60/72/4 -f 43/87/4 42/66/4 57/65/4 68/88/4 -f 51/89/1 18/90/1 13/91/1 52/92/1 -f 59/93/1 60/94/1 14/95/1 17/96/1 -f 57/65/2 58/68/2 26/97/2 21/98/2 -f 50/52/2 49/51/2 22/99/2 25/100/2 -f 40/101/5 39/102/5 47/103/5 46/104/5 -f 35/105/5 45/106/5 48/107/5 36/108/5 -f 32/109/6 31/110/6 56/111/6 53/112/6 -f 44/113/6 43/114/6 54/115/6 55/116/6 -f 16/16/1 62/117/1 52/118/1 13/13/1 -f 67/119/1 15/15/1 14/14/1 60/120/1 -f 59/121/1 17/17/1 20/20/1 66/122/1 -f 18/18/1 51/123/1 63/124/1 19/19/1 -f 57/125/2 21/21/2 24/24/2 68/126/2 -f 22/22/2 49/127/2 61/128/2 23/23/2 -f 28/28/2 64/129/2 50/130/2 25/25/2 -f 65/131/2 27/27/2 26/26/2 58/132/2 -f 65/131/5 40/133/5 46/46/5 27/27/5 -f 45/45/5 35/134/5 64/129/5 28/28/5 -f 19/49/5 63/135/5 36/136/5 48/50/5 -f 39/137/5 66/138/5 20/48/5 47/47/5 -f 53/59/6 23/23/6 61/128/6 32/139/6 -f 43/140/6 68/126/6 24/24/6 54/60/6 -f 67/141/6 44/142/6 55/61/6 15/64/6 -f 16/63/6 56/62/6 31/143/6 62/144/6 -f 13/13/7 1/1/7 4/4/8 14/14/8 -f 18/90/9 2/2/9 1/1/7 13/91/7 -f 17/17/10 3/3/10 2/2/9 18/18/9 -f 14/95/8 4/4/8 3/3/10 17/96/10 -f 21/21/8 8/8/8 7/7/7 22/22/7 -f 26/97/10 5/5/10 8/8/8 21/98/8 -f 25/25/9 6/6/9 5/5/10 26/26/10 -f 22/99/7 7/7/7 6/6/9 25/100/9 -f 46/46/11 69/145/11 70/146/12 45/45/12 -f 47/103/13 71/147/13 69/145/11 46/104/11 -f 48/50/14 72/148/14 71/147/13 47/47/13 -f 45/106/12 70/146/12 72/148/14 48/107/14 -f 29/29/15 9/9/15 12/12/16 30/30/16 -f 34/53/17 10/10/17 9/9/15 29/54/15 -f 33/33/18 11/11/18 10/10/17 34/34/17 -f 30/55/16 12/12/16 11/11/18 33/56/18 -f 53/59/12 73/149/12 74/150/11 54/60/11 -f 56/111/14 75/151/14 73/149/12 53/112/12 -f 55/61/13 76/152/13 75/151/14 56/62/14 -f 54/115/11 74/150/11 76/152/13 55/116/13 -f 37/37/17 77/153/17 78/154/18 38/38/18 -f 42/66/15 79/155/15 77/153/17 37/67/17 -f 41/41/16 80/156/16 79/155/15 42/42/15 -f 38/70/18 78/154/18 80/156/16 41/71/16 -f 76/152/6 74/150/6 73/149/6 75/151/6 -f 78/154/4 77/153/4 79/155/4 80/156/4 -f 72/148/5 70/146/5 69/145/5 71/147/5 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/CMakeLists.txt b/lib/Ray/CMakeLists.txt index 17d97db0..d713eb1e 100644 --- a/lib/Ray/CMakeLists.txt +++ b/lib/Ray/CMakeLists.txt @@ -56,6 +56,7 @@ set(HEADERS sources/Model/ModelAnimations.hpp sources/Vector/Vector2.hpp sources/Vector/Vector3.hpp + sources/Utils/Cache.hpp ) set(SRC diff --git a/lib/Ray/sources/Drawables/Image.cpp b/lib/Ray/sources/Drawables/Image.cpp index d7c357df..9676bc95 100644 --- a/lib/Ray/sources/Drawables/Image.cpp +++ b/lib/Ray/sources/Drawables/Image.cpp @@ -10,11 +10,11 @@ #include "Drawables/2D/Rectangle.hpp" namespace RAY { - std::unordered_map> Image::_ImageCache; + Cache<::Image> Image::_imagesCache(LoadImage, UnloadImage); Image::Image(const std::string &filename): Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE), - _image(fetchImageInCache(filename)) + _image(_imagesCache.fetch(filename)) { this->_dimensions = Vector2(this->_image->width, this->_image->height); } @@ -35,17 +35,6 @@ namespace RAY { return this->_image.get(); } - std::shared_ptr<::Image> Image::fetchImageInCache(const std::string &path) - { - if (Image::_ImageCache.find(path) == Image::_ImageCache.end()) - Image::_ImageCache.emplace(path, std::shared_ptr<::Image>( - new ::Image(LoadImage(path.c_str())), [](::Image *p) { - UnloadImage(*p); - delete p; - })); - return _ImageCache[path]; - } - void Image::draw(Drawables::ADrawable2D &drawable) { drawable.drawOn(*this); diff --git a/lib/Ray/sources/Drawables/Image.hpp b/lib/Ray/sources/Drawables/Image.hpp index 6f6355bf..840be518 100644 --- a/lib/Ray/sources/Drawables/Image.hpp +++ b/lib/Ray/sources/Drawables/Image.hpp @@ -11,8 +11,7 @@ #include #include #include "Texture.hpp" -#include -#include +#include "Utils/Cache.hpp" #include "Drawables/2D/Rectangle.hpp" namespace RAY @@ -50,10 +49,8 @@ namespace RAY private: //! @brief Image, really, that's just it... std::shared_ptr<::Image> _image; - //! @brief, look through cache to see if a model using same file - std::shared_ptr<::Image>fetchImageInCache(const std::string &path); - static std::unordered_map> _ImageCache; + static Cache<::Image> _imagesCache; INTERNAL: diff --git a/lib/Ray/sources/Drawables/Texture.cpp b/lib/Ray/sources/Drawables/Texture.cpp index b2691a23..befe8579 100644 --- a/lib/Ray/sources/Drawables/Texture.cpp +++ b/lib/Ray/sources/Drawables/Texture.cpp @@ -9,40 +9,22 @@ namespace RAY { + Cache<::Texture> Texture::_texturesCache(LoadTexture, UnloadTexture); + Texture::Texture(const std::string &filename): - _texture(LoadTexture(filename.c_str())), + _texture(_texturesCache.fetch(filename)), _resourcePath(filename) { } - Texture::Texture(const Texture &texture): - _texture(LoadTexture(texture._resourcePath.c_str())), - _resourcePath(texture._resourcePath) - { - } - Texture::Texture(const Image &image): - _texture(LoadTextureFromImage(image)), + _texture(std::make_shared<::Texture>(LoadTextureFromImage(image))), _resourcePath() { } - - Texture &Texture::operator=(const Texture &other) - { - UnloadTexture(this->_texture); - this->_resourcePath = other._resourcePath; - this->_texture = LoadTexture(this->_resourcePath.c_str()); - return *this; - } - - Texture::~Texture() - { - UnloadTexture(this->_texture); - } - Texture::operator ::Texture() const { - return this->_texture; + return *this->_texture; } } diff --git a/lib/Ray/sources/Drawables/Texture.hpp b/lib/Ray/sources/Drawables/Texture.hpp index e087275d..6fb2be66 100644 --- a/lib/Ray/sources/Drawables/Texture.hpp +++ b/lib/Ray/sources/Drawables/Texture.hpp @@ -10,6 +10,7 @@ #include #include +#include "Utils/Cache.hpp" namespace RAY { @@ -21,24 +22,27 @@ namespace RAY Texture(const std::string &filename); //! @brief A texture is copy constructable - Texture(const Texture &); + Texture(const Texture &) = default; //! @brief A textrue can be loaded from an image Texture(const Image &); //! @brief An texture is assignable - Texture &operator=(const Texture &); + Texture &operator=(const Texture &) = default; - //! @brief Texture destructor, will unload ressources - ~Texture(); + //! @brief Texture destructor, will not unload ressources + ~Texture() = default; protected: private: //! @brief Texture, really, that's just it... - ::Texture _texture; + std::shared_ptr<::Texture> _texture; + //! @brief path to the file the texture is loaded from std::string _resourcePath; + static Cache<::Texture> _texturesCache; + INTERNAL: //! @return libray Texture struct operator ::Texture() const; 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/Font.cpp b/lib/Ray/sources/Font.cpp index 00711def..c4288463 100644 --- a/lib/Ray/sources/Font.cpp +++ b/lib/Ray/sources/Font.cpp @@ -7,16 +7,14 @@ #include "Font.hpp" +RAY::Cache<::Font> RAY::Font::_fontsCache(LoadFont, UnloadFont); + RAY::Font::Font(const std::string &filename): - _font(LoadFont(filename.c_str())) + _font(_fontsCache.fetch(filename)) { } -RAY::Font::Font() +RAY::Font::Font(): + _font(std::make_shared<::Font>()) { } - -RAY::Font::~Font() -{ - UnloadFont(this->_font); -} diff --git a/lib/Ray/sources/Font.hpp b/lib/Ray/sources/Font.hpp index 1ad65a1e..a403dcb3 100644 --- a/lib/Ray/sources/Font.hpp +++ b/lib/Ray/sources/Font.hpp @@ -10,6 +10,7 @@ #include #include +#include "Utils/Cache.hpp" namespace RAY { @@ -29,13 +30,15 @@ namespace RAY //! @brief An font is assignable Font &operator=(const Font &) = default; - //! @brief Unload font at destruction - ~Font(); + //! @brief Default destructor + ~Font() = default; protected: private: //! @brief Font, really, that's just it... - ::Font _font; + std::shared_ptr<::Font> _font; + + static Cache<::Font> _fontsCache; }; } diff --git a/lib/Ray/sources/Model/Model.cpp b/lib/Ray/sources/Model/Model.cpp index 8554a40c..aab5fdc6 100644 --- a/lib/Ray/sources/Model/Model.cpp +++ b/lib/Ray/sources/Model/Model.cpp @@ -12,15 +12,16 @@ namespace RAY::Drawables::Drawables3D { - std::unordered_map> Model::_modelsCache; + RAY::Cache<::Model> Model::_modelsCache(LoadModel, UnloadModel); + Model::Model(const std::string &filename, std::optional> texture, + const RAY::Vector3 &scale, const RAY::Vector3 &position, const RAY::Vector3 &rotationAxis, - float rotationAngle, - const RAY::Vector3 &scale) + float rotationAngle) : ADrawable3D(position, WHITE), - _model(fetchModelInCache(filename)), + _model(_modelsCache.fetch(filename)), _rotationAxis(rotationAxis), _rotationAngle(rotationAngle), _scale(scale) @@ -105,15 +106,4 @@ namespace RAY::Drawables::Drawables3D { { DrawModelEx(*this->_model, this->_position, this->_rotationAxis, this->_rotationAngle, this->_scale, this->_color); } - - std::shared_ptr<::Model> Model::fetchModelInCache(const std::string &path) - { - if (Model::_modelsCache.find(path) == Model::_modelsCache.end()) - Model::_modelsCache.emplace(path, std::shared_ptr<::Model>( - new ::Model(LoadModel(path.c_str())), [](::Model *p) { - UnloadModel(*p); - delete p; - })); - return _modelsCache[path]; - } } \ No newline at end of file diff --git a/lib/Ray/sources/Model/Model.hpp b/lib/Ray/sources/Model/Model.hpp index 47689edb..7a7e3fdf 100644 --- a/lib/Ray/sources/Model/Model.hpp +++ b/lib/Ray/sources/Model/Model.hpp @@ -14,8 +14,7 @@ #include #include #include -#include -#include +#include "Utils/Cache.hpp" namespace RAY::Drawables::Drawables3D { //! @brief Basic 3D Model type @@ -28,10 +27,10 @@ namespace RAY::Drawables::Drawables3D { //! @param filePath: path to file to load Model(const std::string &filePath, 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, - const RAY::Vector3 &scale = RAY::Vector3(1, 1, 1)); + float rotationAngle = 0); //! @brief Create an model, loading a file //! @param mesh: mesh to load @@ -91,10 +90,8 @@ namespace RAY::Drawables::Drawables3D { float _rotationAngle; //! @brief Scale of the shape RAY::Vector3 _scale; - //! @brief, look through cache to see if a model using same file - std::shared_ptr<::Model>fetchModelInCache(const std::string &path); - static std::unordered_map> _modelsCache; + static RAY::Cache<::Model> _modelsCache; INTERNAL: //! @brief A RAY Model is cast-able in libray's model diff --git a/lib/Ray/sources/Model/ModelAnimations.cpp b/lib/Ray/sources/Model/ModelAnimations.cpp index 224b9979..6d41832d 100644 --- a/lib/Ray/sources/Model/ModelAnimations.cpp +++ b/lib/Ray/sources/Model/ModelAnimations.cpp @@ -7,18 +7,16 @@ #include "Model/ModelAnimations.hpp" +RAY::Cache<::ModelAnimation> RAY::ModelAnimations::_animationsCache(LoadModelAnimations, UnloadModelAnimations); + RAY::ModelAnimations::ModelAnimations(const std::string &filePath): - _animationsPtr(LoadModelAnimations(filePath.c_str(), &this->_animationCount)) + _animationsPtr(_animationsCache.fetch(filePath, &this->_animationCount)), + _filePath(filePath) { ::ModelAnimation *ptr = this->_animationsPtr.get(); for (int i = 0; i < this->_animationCount; i++) - this->_animations.push_back(RAY::ModelAnimation(ptr[i])); -} - -RAY::ModelAnimations::~ModelAnimations() -{ - UnloadModelAnimations(this->_animationsPtr.release(), this->_animationCount); + this->_animations.emplace_back(ptr[i]); } RAY::ModelAnimation &RAY::ModelAnimations::operator[](int index) @@ -31,3 +29,22 @@ size_t RAY::ModelAnimations::getAnimationsCount() const return this->_animationCount; } +std::string RAY::ModelAnimations::getFilePath() const +{ + return this->_filePath; +} + +const RAY::ModelAnimation &RAY::ModelAnimations::at(int index) const +{ + return this->_animations.at(index); +} + +const RAY::ModelAnimation &RAY::ModelAnimations::operator[](int index) const +{ + return this->_animations[index]; +} + +RAY::ModelAnimation &RAY::ModelAnimations::at(int index) +{ + return this->_animations.at(index); +} diff --git a/lib/Ray/sources/Model/ModelAnimations.hpp b/lib/Ray/sources/Model/ModelAnimations.hpp index cad0d038..2b99e1d7 100644 --- a/lib/Ray/sources/Model/ModelAnimations.hpp +++ b/lib/Ray/sources/Model/ModelAnimations.hpp @@ -11,6 +11,7 @@ #include "Model/ModelAnimation.hpp" #include #include +#include "Utils/Cache.hpp" namespace RAY { //! @brief A Holder for Model Animations @@ -20,30 +21,47 @@ namespace RAY { //! @param filePath Path to the file containing animations ModelAnimations(const std::string &filePath); - //! @brief Only single entity can hold these animations pointers - ModelAnimations(const ModelAnimations &) = delete; + //! @brief default copy ctor + ModelAnimations(const ModelAnimations &) = default; - //! @brief Unloads all animations - ~ModelAnimations(); + //! @brief Default constructor + ~ModelAnimations() = default; - //! @brief Only single entity can hold these animations pointers - ModelAnimations &operator=(const ModelAnimations &) = delete; + //! @brief Default assignment operator + ModelAnimations &operator=(const ModelAnimations &) = default; //! @brief Castin Object to raw model animation pointer ModelAnimation &operator[](int index); + //! @brief std [] const + const ModelAnimation &operator[](int index) const; + + //! @brief std at const + const ModelAnimation &at(int index) const; + + //! @brief std at + ModelAnimation &at(int index); + //! @return the number of loaded animations size_t getAnimationsCount() const; + //! @brief Get the creation file + std::string getFilePath() const; + private: //! @brief Holds the pointer returned by the loading function - std::unique_ptr<::ModelAnimation> _animationsPtr; + std::shared_ptr<::ModelAnimation> _animationsPtr; //! @brief A holder for animations std::vector _animations; //! @brief the number of loaded animations int _animationCount; + + //! @brief The file where the animations were loaded (used to create a copy of this class) + const std::string _filePath; + + static Cache<::ModelAnimation> _animationsCache; }; } diff --git a/lib/Ray/sources/Utils/Cache.hpp b/lib/Ray/sources/Utils/Cache.hpp new file mode 100644 index 00000000..7f041853 --- /dev/null +++ b/lib/Ray/sources/Utils/Cache.hpp @@ -0,0 +1,85 @@ +/* +** EPITECH PROJECT, 2021 +** Bomberman +** File description: +** Cache +*/ + +#pragma once +#include +#include +#include + +namespace RAY { + //! @brief A templated class used to cache ressources, indexed with a string + template + class Cache { + public: + //! @brief + Cache(std::function dataLoader, std::function dataUnloader): + _dataLoader(dataLoader), _dataUnloader(dataUnloader) + {}; + + //! @brief Default destructor, will destroy ray's data + ~Cache() = default; + + //! @brief default copy constructor + Cache(const Cache &) = default; + + //! @brief a cache is assignable + Cache &operator=(const Cache &) = default; + + //! @param path path of the file + //! @return a newly loaded ressource if it hasn't be previously loaded, or one from cache + std::shared_ptrfetch(const std::string &path) + { + if (this->_cache.find(path) == this->_cache.end()) + this->_cache.emplace(path, std::shared_ptr( + new T(this->_dataLoader(path.c_str())), [this](T *p) { + this->_dataUnloader(*p); + delete p; + })); + return _cache[path]; + }; + private: + //! @brief function to call to load data + std::function _dataLoader; + + //! @brief function to call when the ray data will be unloaded + std::function _dataUnloader; + + //! @brief map storing shared ptr of caches + std::unordered_map> _cache; + }; + + template<> + class Cache<::ModelAnimation> { + public: + Cache(std::function<::ModelAnimation *(const char *, int *)> dataLoader, std::functiondataUnloader): + _dataLoader(dataLoader), _dataUnloader(dataUnloader) + {}; + std::shared_ptr<::ModelAnimation> fetch(const std::string &path, int *counter) + { + if (this->_cache.find(path) != this->_cache.end()) + return this->_cache[path]; + + ::ModelAnimation *animations = this->_dataLoader(path.c_str(), counter); + unsigned int animCount = *counter; + + this->_cache.emplace(path, std::shared_ptr<::ModelAnimation>( + animations, [this, animCount](::ModelAnimation *p) { + this->_dataUnloader(p, animCount); + })); + return this->_cache[path]; + }; + private: + //! @brief function to call to load data + std::function<::ModelAnimation *(const char *, int *)> _dataLoader; + + //! @brief function to call when the ray data will be unloaded + std::function _dataUnloader; + + //! @brief map storing shared ptr of caches + std::unordered_map> _cache; + }; +} 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..9c30796f 100644 --- a/lib/wal/CMakeLists.txt +++ b/lib/wal/CMakeLists.txt @@ -7,7 +7,6 @@ add_library(wal sources/Entity/Entity.hpp sources/Component/Component.hpp sources/System/System.hpp - sources/Wal.cpp sources/Wal.hpp sources/Scene/Scene.cpp sources/Scene/Scene.hpp @@ -15,8 +14,10 @@ add_library(wal sources/Exception/WalError.hpp sources/Entity/Entity.cpp sources/Component/Component.cpp - sources/System/System.cpp sources/Models/Callback.hpp + sources/View/View.hpp + sources/System/ISystem.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.cpp b/lib/wal/sources/Entity/Entity.cpp index 17ebd6c2..d9cd550c 100644 --- a/lib/wal/sources/Entity/Entity.cpp +++ b/lib/wal/sources/Entity/Entity.cpp @@ -3,6 +3,7 @@ // #include "Entity/Entity.hpp" +#include "Scene/Scene.hpp" #include #include @@ -10,18 +11,20 @@ namespace WAL { unsigned Entity::nextID = 0; - Entity::Entity(std::string name) + Entity::Entity(Scene &scene, std::string name) : _uid(Entity::nextID++), + _scene(scene), _name(std::move(name)) { } Entity::Entity(const Entity &other) : _uid(Entity::nextID++), + _scene(other._scene), _name(other._name), _disabled(other._disabled) { for (const auto &cmp : other._components) - this->addComponent(*cmp); + this->addComponent(*cmp.second); } unsigned Entity::getUid() const @@ -46,34 +49,35 @@ namespace WAL Entity &Entity::addComponent(const Component &component) { - if (this->hasComponent(typeid(component), false)) - throw DuplicateError("A component of the type \"" + std::string(typeid(component).name()) + "\" already exists."); - this->_components.emplace_back(component.clone(*this)); + const std::type_index &type = typeid(component); + if (this->hasComponent(type, false)) + throw DuplicateError("A component of the type \"" + std::string(type.name()) + "\" already exists."); + this->_components.emplace(type, component.clone(*this)); + this->_scene._componentAdded(*this, type); return *this; } bool Entity::hasComponent(const std::type_info &type, bool skipDisabled) const { - auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) { - return typeid(*cmp) == type; - }); - if (existing == this->_components.end()) - return false; - if (skipDisabled) - return !(*existing)->isDisabled(); - return true; + return this->hasComponent(static_cast(type), skipDisabled); } bool Entity::hasComponent(const std::type_index &type, bool skipDisabled) const { - auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) { - return std::type_index(typeid(*cmp)) == type; - }); - if (existing == this->_components.end()) + auto cmp = this->_components.find(type); + if (cmp == this->_components.end()) return false; - if (skipDisabled) - return !(*existing)->isDisabled(); - return true; + return !cmp->second->isDisabled(); + } + + void Entity::_componentAdded(const std::type_index &type) + { + this->_scene._componentAdded(*this, type); + } + + void Entity::_componentRemoved(const std::type_index &type) + { + this->_scene._componentRemoved(*this, type); } bool Entity::shouldDelete() const diff --git a/lib/wal/sources/Entity/Entity.hpp b/lib/wal/sources/Entity/Entity.hpp index 2321934d..43aecb33 100644 --- a/lib/wal/sources/Entity/Entity.hpp +++ b/lib/wal/sources/Entity/Entity.hpp @@ -5,14 +5,17 @@ #pragma once #include -#include +#include #include #include #include "Component/Component.hpp" #include "Exception/WalError.hpp" +#include "Models/TypeHolder.hpp" namespace WAL { + class Scene; + //! @brief An entity of the WAL's ECS. class Entity { @@ -26,10 +29,20 @@ namespace WAL //! @brief Has this entity been scheduled for deletion? bool _shouldDelete; //! @brief The list of the components of this entity - std::vector> _components = {}; + std::unordered_map> _components = {}; //! @brief This ID will be the one of the next entity created. static unsigned nextID; + + //! @brief Callback called when a component is added + //! @param type The type of component + void _componentAdded(const std::type_index &type); + //! @brief Callback called when a component is removed + //! @param type The type of component + void _componentRemoved(const std::type_index &type); + protected: + //! @brief A reference to the ECS. + Scene &_scene; public: //! @brief Get the ID of the entity. unsigned getUid() const; @@ -47,17 +60,55 @@ namespace WAL void scheduleDeletion(); //! @brief Get a component of a specific type + //! @tparam The type of the component //! @throw NotFoundError if the component could not be found + //! @return The component of the requested type. template T &getComponent() { - const std::type_info &type = typeid(T); - auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) { - return typeid(*cmp) == type; - }); + T *ret = this->tryGetComponent(); + if (ret == nullptr) + throw NotFoundError("No component could be found with the type \"" + std::string(typeid(T).name()) + "\"."); + return *ret; + } + + //! @brief Get a component of a specific type or null if not found. + //! @tparam The type of the component + //! @return The component or nullptr if not found. + template + T *tryGetComponent() + { + const std::type_index &type = typeid(T); + auto existing = this->_components.find(type); if (existing == this->_components.end()) - throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\"."); - return *static_cast(existing->get()); + return nullptr; + return static_cast(existing->second.get()); + } + + //! @brief Get a component of a specific type + //! @tparam The type of the component + //! @throw NotFoundError if the component could not be found + //! @return The component of the requested type. + template + const T &getComponent() const + { + const T *ret = this->tryGetComponent(); + if (ret == nullptr) + throw NotFoundError("No component could be found with the type \"" + std::string(typeid(T).name()) + "\"."); + return *ret; + } + + //! @brief Get a component of a specific type or null if not found. + //! @tparam The type of the component + //! @return The component or nullptr if not found. + template + const T *tryGetComponent() const + { + const std::type_index &type = typeid(T); + auto existing = this->_components.find(type); + if (existing == this->_components.end()) + return nullptr; + return static_cast(existing->second.get()); } //! @brief Check if this entity has a component. @@ -83,12 +134,14 @@ namespace WAL //! @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 + template Entity &addComponent(Types &&...params) { - if (this->hasComponent(false)) - throw DuplicateError("A component of the type \"" + std::string(typeid(T).name()) + "\" already exists."); - this->_components.push_back(std::make_unique(*this, std::forward(params)...)); + const std::type_index &type = typeid(T); + if (this->hasComponent(type)) + throw DuplicateError("A component of the type \"" + std::string(type.name()) + "\" already exists."); + this->_components[type] = std::make_unique(*this, TypeHolder()..., std::forward(params)...); + this->_componentAdded(type); return *this; } @@ -103,17 +156,16 @@ namespace WAL Entity &removeComponent() { const std::type_info &type = typeid(T); - auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) { - return typeid(*cmp) == type; - }); + auto existing = this->_components.find(type); if (existing == this->_components.end()) throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\"."); this->_components.erase(existing); + this->_componentRemoved(type); return *this; } //! @brief A default constructor - explicit Entity(std::string name); + explicit Entity(Scene &wal, std::string name); //! @brief An entity is copyable Entity(const Entity &); //! @brief An entity is movable. diff --git a/lib/wal/sources/Models/Callback.hpp b/lib/wal/sources/Models/Callback.hpp index be2c092f..2c988db4 100644 --- a/lib/wal/sources/Models/Callback.hpp +++ b/lib/wal/sources/Models/Callback.hpp @@ -24,10 +24,14 @@ namespace WAL //! @brief Add a method to be called when this callback is invoked. //! @param callback The list of arguments of the callback method //! @return A unique ID for this callback. That can be used to remove the callback later. - int addCallback(std::function callback) + template + int addCallback(Func callback) { int id = this->_nextID++; - this->_functions[id] = std::move(callback); + if constexpr(std::is_same_v>) + this->_functions[id] = std::move(callback); + else + this->_functions[id] = std::function(callback); return id; } @@ -53,10 +57,14 @@ namespace WAL //! @brief A default assignment operator Callback &operator=(const Callback &) = default; - //! @brief Implicitly transform a function into a callback. - Callback(std::function callback) // NOLINT(google-explicit-constructor) + //! @brief Implicitly transform a callable into a callback. + template + Callback(Func callback) // NOLINT(google-explicit-constructor) { this->addCallback(callback); } }; + + template + static constexpr Callback EmptyCallback; } // namespace WAL \ No newline at end of file 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/Scene/Scene.cpp b/lib/wal/sources/Scene/Scene.cpp index 3c07f3c8..c4e610cf 100644 --- a/lib/wal/sources/Scene/Scene.cpp +++ b/lib/wal/sources/Scene/Scene.cpp @@ -3,15 +3,62 @@ // #include "Scene.hpp" +#include namespace WAL { - std::vector &Scene::getEntities() + int Scene::_nextID = 0; + + std::list &Scene::getEntities() { return this->_entities; } + Scene &Scene::operator=(const Scene &) { return *this; } + + Entity &Scene::addEntity(const std::string &name) + { + return this->_entities.emplace_back(*this, name); + } + + void Scene::_componentAdded(Entity &entity, const std::type_index &type) + { + for (auto &view : this->_views) { + if (std::find(view->getTypes().begin(), view->getTypes().end(), type) == view->getTypes().end()) + continue; + bool valid = std::all_of(view->getTypes().begin(), view->getTypes().end(), [&entity](const auto &type){ + return entity.hasComponent(type); + }); + if (valid) + view->emplace_back(entity); + } + } + + void Scene::_componentRemoved(const Entity &entity, const std::type_index &type) + { + for (auto &view : this->_views) { + if (std::find(view->getTypes().begin(), view->getTypes().end(), type) == view->getTypes().end()) + continue; + view->erase(entity); + } + } + + void Scene::_entityRemoved(const Entity &entity) + { + for (auto &view : this->_views) + view->erase(entity); + } + + void Scene::deleteMarkedEntities() + { + this->_entities.remove_if([this](auto &entity) { + if (!entity.shouldDelete()) + return false; + this->_entityRemoved(entity); + return true; + }); + } } // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/Scene/Scene.hpp b/lib/wal/sources/Scene/Scene.hpp index bddf1e5c..4dfc5ad8 100644 --- a/lib/wal/sources/Scene/Scene.hpp +++ b/lib/wal/sources/Scene/Scene.hpp @@ -6,7 +6,9 @@ #pragma once #include +#include #include +#include #include "Entity/Entity.hpp" namespace WAL @@ -15,20 +17,51 @@ namespace WAL class Scene { private: + static int _nextID; + //! @brief An ID representing this scene. + int _id = _nextID++; + //! @brief The list of registered entities - std::vector _entities = {}; + std::list _entities = {}; + //! @brief The list of cached views to update. + std::vector> _views = {}; + + //! @brief Notify this scene that a component has been added to the given entity. + //! @param entity The entity with the new component + //! @param type The type of the component added. + void _componentAdded(Entity &entity, const std::type_index &type); + //! @brief Notify this scene that a component has been removed to the given entity. + //! @param entity The entity with the removed component + //! @param type The type of the component removed. + void _componentRemoved(const Entity &entity, const std::type_index &type); + //! @brief Remove an entity from every views. + //! @param entity The entity to remove. + void _entityRemoved(const Entity &entity); public: //! @brief Get the list of entities. - std::vector &getEntities(); + std::list &getEntities(); - //! @brief Add a new entity to the scene, you can use this method with the same arguments as the entity's constructor. - //! @return The current scene is returned to allow you to chain call. - template - Entity &addEntity(Params &&...params) + //! @brief Add a new entity to the scene. + //! @param name The name of the created entity. + //! @return The created entity is returned. + Entity &addEntity(const std::string &name); + + template + View &view() { - return this->_entities.emplace_back(std::forward(params)...); + static std::unordered_map>> cache; + auto existing = cache.find(this->_id); + if (existing != cache.end() && !existing->second.expired()) + return *existing->second.lock(); + auto view = std::make_shared>(this->_entities); + this->_views.emplace_back(view); + cache.emplace(this->_id, view); + return *view; } + //! @brief Delete entities marked as deleted. + void deleteMarkedEntities(); + //! @brief A default constructor Scene() = default; //! @brief A scene is copy constructable @@ -38,5 +71,7 @@ namespace WAL //! @brief A scene is assignable Scene &operator=(const Scene &); Scene(Scene &&) = default; + + friend Entity; }; } // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/System/ISystem.hpp b/lib/wal/sources/System/ISystem.hpp new file mode 100644 index 00000000..ab8dc3f3 --- /dev/null +++ b/lib/wal/sources/System/ISystem.hpp @@ -0,0 +1,32 @@ +// +// Created by Zoe Roux on 2021-06-04. +// + + +#pragma once + +#include "Entity/Entity.hpp" +#include "View/View.hpp" +#include + +namespace WAL +{ + //! @brief A base class that represent a system. + class ISystem + { + public: + //! @brief Update the whole system (every entities that this system is responsible can be updated. + //! @param dtime The delta time since the last call to this method. + virtual void update(std::chrono::nanoseconds dtime) = 0; + + //! @brief An alternative of update that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up. + //! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding. + virtual void fixedUpdate() = 0; + + //! @brief Get a view containing every entity this system should update. + virtual IView &getView() = 0; + + //! @brief A virtual default destructor. + virtual ~ISystem() = default; + }; +} \ No newline at end of file diff --git a/lib/wal/sources/System/System.cpp b/lib/wal/sources/System/System.cpp deleted file mode 100644 index 0dd69f30..00000000 --- a/lib/wal/sources/System/System.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Zoe Roux on 5/17/21. -// - -#include "System.hpp" -#include -#include - -namespace WAL -{ - System::System(std::vector dependencies) - : _dependencies(std::move(dependencies)) - {} - - void System::onUpdate(Entity &entity, std::chrono::nanoseconds dtime) - {} - - void System::onFixedUpdate(Entity &entity) - {} - - void System::onSelfUpdate() - {} - - const std::vector &System::getDependencies() const - { - return this->_dependencies; - } -} // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/System/System.hpp b/lib/wal/sources/System/System.hpp index 59c82c4a..58f49970 100644 --- a/lib/wal/sources/System/System.hpp +++ b/lib/wal/sources/System/System.hpp @@ -6,40 +6,71 @@ #include #include +#include +#include #include "Entity/Entity.hpp" +#include "Wal.hpp" +#include "View/View.hpp" +#include "ISystem.hpp" +#include namespace WAL { //! @brief A base system of WAL - class System + //! @tparam Dependencies The list of dependencies this system has. + template + class System : public ISystem { - private: - //! @brief The list of dependencies of this system - std::vector _dependencies = {}; public: //! @brief A virtual, default, destructor - virtual ~System() = default; + ~System() override = default; //! @brief A system can be moved - System(System &&) = default; + System(System &&) noexcept = default; - //! @brief Get the name of the component corresponding to this system. - const std::vector &getDependencies() const; + //! @brief Get a view of all entities containing every dependencies of this system. + View &getView() override + { + return this->_wal.scene->template view(); + } //! @brief Update the corresponding component of the given entity //! @param entity The entity to update. //! @param dtime The delta time. - virtual void onUpdate(Entity &entity, std::chrono::nanoseconds dtime); + virtual void onUpdate(ViewEntity &entity, std::chrono::nanoseconds dtime) {} //! @brief An alternative of onUpdate that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up. //! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding. //! @param entity The entity to update. - virtual void onFixedUpdate(Entity &entity); + virtual void onFixedUpdate(ViewEntity &entity) {} //! @brief A method called after all entities that this system manage has been updated. - virtual void onSelfUpdate(); + virtual void onSelfUpdate() {} + + + //! @brief Update the whole system (every entities that this system is responsible can be updated. + //! @param dtime The delta time since the last call to this method. + void update(std::chrono::nanoseconds dtime) final + { + for (auto &entity : this->getView()) + this->onUpdate(entity, dtime); + this->onSelfUpdate(); + } + + //! @brief An alternative of update that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up. + //! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding. + void fixedUpdate() final + { + for (auto &entity : this->getView()) + this->onFixedUpdate(entity); + } protected: + //! @brief A reference to the ECS. + Wal &_wal; + //! @brief A system can't be instantiated, it should be derived. - explicit System(std::vector dependencies); + explicit System(Wal &wal) + : _wal(wal) + {} //! @brief A system can't be instantiated, it should be derived. System(const System &) = default; //! @brief A system can't be instantiated, it should be derived. diff --git a/lib/wal/sources/View/View.hpp b/lib/wal/sources/View/View.hpp new file mode 100644 index 00000000..15b31e09 --- /dev/null +++ b/lib/wal/sources/View/View.hpp @@ -0,0 +1,222 @@ +// +// Created by Zoe Roux on 2021-06-03. +// + + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "Entity/Entity.hpp" + +namespace WAL +{ + template + class ViewEntity + { + private: + std::tuple, std::reference_wrapper...> &_value; + public: + explicit ViewEntity(std::tuple, std::reference_wrapper...> &value) + : _value(value) + {} + + Entity *operator->() + { + return &(std::get<0>(this->_value).get()); + } + + Entity &operator*() + { + return std::get<0>(this->_value); + } + + operator Entity &() + { + return std::get<0>(this->_value); + } + + template + T &get() + { + return std::get>(this->_value); + } + + template + auto &get() + { + return std::get(this->_value); + } + }; + + template + class ViewIterator + { + private: + It _it; + std::optional> _entity; + + public: + ViewEntity &operator*() + { + if (!this->_entity) + this->_entity.emplace(*this->_it); + return *this->_entity; + } + + ViewEntity *operator->() + { + if (!this->_entity) + this->_entity =(*this->_it); + return &this->_entity; + } + + ViewIterator &operator++() + { + this->_it++; + this->_entity = std::nullopt; + return *this; + } + + ViewIterator operator++(int) + { + ViewIterator copy = *this; + this->_it++; + this->_entity = std::nullopt; + return *this; + } + + bool operator==(const ViewIterator &other) const + { + return this->_it == other._it; + } + + bool operator!=(const ViewIterator &other) const + { + return !this->operator==(other); + } + + explicit ViewIterator(It current) + : _it(current), + _entity(std::nullopt) + {} + }; + + //! @brief A basic view used to manipulate view without knowing their type at compile time. + class IView + { + public: + //! @brief The list of types that every entity of the view has. + virtual const std::vector &getTypes() const = 0; + + virtual void emplace_back(Entity &) = 0; + + virtual void erase(const Entity &) = 0; + + //! @brief A default destructor + virtual ~IView() = default; + }; + + //! @brief A view allowing one to easily access entities containing a set list of component. + //! A view is always updated and only references to entities are kept. + template + class View : public IView + { + private: + using entity_type = std::tuple, std::reference_wrapper...>; + + //! @brief The list of entities in the view. + std::vector _entities = {}; + //! @brief The list of types that every entity of the view has. + std::vector _types = {}; + public: + using iterator = ViewIterator::iterator, Components...>; + + iterator begin() + { + return iterator(this->_entities.begin()); + } + + iterator end() + { + return iterator(this->_entities.end()); + } + + std::size_t size() const + { + return this->_entities.size(); + } + + ViewEntity front() + { + return *iterator(this->_entities.begin()); + } + + ViewEntity back() + { + return *iterator(--this->_entities.end()); + } + + const std::vector &getTypes() const override + { + return this->_types; + } + + void emplace_back(Entity &entity) override + { + auto tuple = std::make_tuple(entity.tryGetComponent()...); + if (std::apply([](const auto *...component) {return ((component == nullptr) || ...);}, tuple)) + return; + std::apply([&](auto *...component) { + this->_entities.emplace_back(entity, *component...); + }, tuple); + } + + void erase(const Entity &entity) override + { + this->_entities.erase(std::remove_if(this->_entities.begin(), this->_entities.end(), [&entity](const auto &ref){ + return &std::get<0>(ref).get() == &entity; + })); + } + + //! @brief Construct a view from a list of entities. + //! Those entities are never copied but references to them are kept internally. + explicit View(std::list &scene) + { + this->_types = {typeid(Components)...}; + for (auto &entity : scene) + this->emplace_back(entity); + } + + //! @brief Copying a view is not possible since a view must be managed by a scene. + View(const View &) = delete; + //! @brief A default destructor + ~View() override = default; + //! @brief A view is not assignable. + View &operator=(const View &) = delete; + }; +} + +namespace std +{ + template + struct tuple_size<::WAL::ViewEntity> + : public std::integral_constant + {}; + + template + struct tuple_element<0, ::WAL::ViewEntity> + { + using type = WAL::Entity &; + }; + + template + struct tuple_element> + { + using type = typename std::tuple_element>::type; + }; +} \ No newline at end of file diff --git a/lib/wal/sources/Wal.cpp b/lib/wal/sources/Wal.cpp deleted file mode 100644 index 875e3bd8..00000000 --- a/lib/wal/sources/Wal.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by Zoe Roux on 2021-05-14. -// - -#include -#include -#include "Wal.hpp" - -namespace WAL -{ - std::chrono::nanoseconds Wal::timestep = std::chrono::milliseconds(8); - - void Wal::_update(std::chrono::nanoseconds dtime) - { - auto &entities = this->scene->getEntities(); - - for (auto &system : this->_systems) { - for (auto &entity : entities) { - if (!Wal::_hasDependencies(entity, *system)) - continue; - system->onUpdate(entity, dtime); - } - system->onSelfUpdate(); - } - } - - void Wal::_fixedUpdate() - { - auto &entities = this->scene->getEntities(); - - for (auto &system : this->_systems) { - for (auto &entity : entities) { - if (!Wal::_hasDependencies(entity, *system)) - continue; - system->onFixedUpdate(entity); - } - } - } - - bool Wal::_hasDependencies(const Entity &entity, const System &system) - { - // 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); - }); - } -} // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index 9c40d1da..b9c39aa9 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -10,38 +10,84 @@ #include #include #include "Exception/WalError.hpp" -#include "Scene/Scene.hpp" -#include "Entity/Entity.hpp" -#include "System/System.hpp" +#include "System/ISystem.hpp" #include "Models/Callback.hpp" +#include "Scene/Scene.hpp" + +#if defined(PLATFORM_WEB) +#include +#endif namespace WAL { + class Entity; + //! @brief The main WAL class, it is used to setup and run the ECS. class Wal { private: //! @brief The list of registered systems - std::vector> _systems = {}; + std::vector> _systems = {}; - //! @brief Call the onUpdate of every system with every component - void _update(std::chrono::nanoseconds dtime); + //! @brief Start the game loop + //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) + //! @param state An initial game state. If not specified, it will be defaulted. + //! @tparam T A type used to track your game state. It must be default constructable. + template + void _run(const Callback &callback, T state = T()) + { + auto lastTick = std::chrono::steady_clock::now(); + std::chrono::nanoseconds fBehind(0); - //! @brief Call the onFixedUpdate of every system with every component - void _fixedUpdate(); + while (!this->shouldClose) { + auto now = std::chrono::steady_clock::now(); + std::chrono::nanoseconds dtime = now - lastTick; + fBehind += dtime; + lastTick = now; - //! @brief Check if an entity met a system's dependencies. - //! @param entity The entity to check - //! @param system The system that will list dependencies - //! @return True if all dependencies are met, false otherwise. - static bool _hasDependencies(const Entity &entity, const System &system); + while (fBehind > Wal::timestep) { + fBehind -= Wal::timestep; + for (auto &system : this->_systems) + system->fixedUpdate(); + } + for (auto &system : this->_systems) + system->update(dtime); + auto &entities = this->scene->getEntities(); + this->scene->deleteMarkedEntities(); + callback(*this, state); + } + } + +#if defined(PLATFORM_WEB) + template + static void _runIteration(void *param) + { + static auto [wal, callback, state] = *reinterpret_cast &, T &> *>(param); + 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; + for (auto &system : wal._systems) + system->fixedUpdate(); + } + for (auto &system : wal._systems) + system->update(dtime); + wal.scene->deleteMarkedEntities(); + callback(wal, state); + } +#endif public: //! @brief The scene that contains entities. std::shared_ptr scene; //! @brief True if the engine should close after the end of the current tick. bool shouldClose = false; //! @brief The time between each fixed update. - static std::chrono::nanoseconds timestep; + static constexpr std::chrono::nanoseconds timestep = std::chrono::milliseconds(32); //! @brief Create a new system in place. //! @return The wal instance used to call this function is returned. This allow method chaining. @@ -54,7 +100,7 @@ namespace WAL }); if (existing != this->_systems.end()) throw DuplicateError("A system of the type \"" + std::string(type.name()) + "\" already exists."); - this->_systems.push_back(std::make_unique(std::forward(params)...)); + this->_systems.push_back(std::make_unique(*this, std::forward(params)...)); return *this; } @@ -101,17 +147,6 @@ namespace WAL return *this; } - //! @brief Start the game loop - //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) - //! @param state An initial game state. If not specified, it will be defaulted. - //! @tparam T A type used to track your game state. It must be default constructable. - template - void run(const std::function &callback, T state = T()) - { - Callback update(callback); - return this->run(update, state); - } - //! @brief Start the game loop //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) //! @param state An initial game state. If not specified, it will be defaulted. @@ -119,26 +154,12 @@ namespace WAL template void run(const Callback &callback, T state = T()) { - auto lastTick = std::chrono::steady_clock::now(); - std::chrono::nanoseconds fBehind(0); - - while (!this->shouldClose) { - auto now = std::chrono::steady_clock::now(); - std::chrono::nanoseconds dtime = now - lastTick; - fBehind += dtime; - lastTick = now; - - while (fBehind > Wal::timestep) { - fBehind -= Wal::timestep; - this->_fixedUpdate(); - } - this->_update(dtime); - auto &entities = this->scene->getEntities(); - entities.erase(std::remove_if(entities.begin(), entities.end(), [](auto &entity) { - return entity.shouldDelete(); - }), entities.end()); - callback(*this, state); - } + #if defined(PLATFORM_WEB) + std::tuple &, T &> iterationParams(*this, callback, state); + return emscripten_set_main_loop_arg((em_arg_callback_func)_runIteration, (void *)&iterationParams, 0, 1); + #else + return this->_run(callback, state); + #endif } //! @brief A default constructor diff --git a/sources/Component/Animation/AnimationsComponent.cpp b/sources/Component/Animation/AnimationsComponent.cpp new file mode 100644 index 00000000..4461cc8e --- /dev/null +++ b/sources/Component/Animation/AnimationsComponent.cpp @@ -0,0 +1,71 @@ +// +// Created by cbihan on 01/06/2021. +// + +#include "AnimationsComponent.hpp" +#include "Entity/Entity.hpp" +#include "Model/ModelAnimations.hpp" + +namespace BBM +{ + AnimationsComponent::AnimationsComponent(WAL::Entity &entity, RAY::ModelAnimations modelAnimation, int animIndex, bool play) + : WAL::Component(entity), + _modelAnimation(std::move(modelAnimation)), + _currentAnimIndex(animIndex), + _animDisabled(play) + { + this->_modelAnimation[this->_currentAnimIndex].setFrameCounter(0); + } + + WAL::Component *AnimationsComponent::clone(WAL::Entity &entity) const + { + return new AnimationsComponent(entity, + RAY::ModelAnimations(this->_modelAnimation.getFilePath()), + this->_currentAnimIndex); + } + + size_t AnimationsComponent::getCurrentAnimFrameCounter() const + { + return this->_modelAnimation.at(this->_currentAnimIndex).getFrameCounter(); + } + + RAY::ModelAnimation AnimationsComponent::getCurrentModelAnim() + { + return this->_modelAnimation[this->_currentAnimIndex]; + } + + void AnimationsComponent::setCurrentAnimFrameCounter(size_t animFrameCounter) + { + this->_modelAnimation[this->_currentAnimIndex].setFrameCounter(animFrameCounter); + } + + void AnimationsComponent::resetCurrentAnimFrameCounter() + { + this->_modelAnimation[this->_currentAnimIndex].setFrameCounter(0); + } + + size_t AnimationsComponent::getCurrentAnimIndex() const + { + return this->_currentAnimIndex; + } + + void AnimationsComponent::setAnimIndex(int animIndex) + { + this->_currentAnimIndex = animIndex % static_cast(this->_modelAnimation.getAnimationsCount()); + } + + void AnimationsComponent::incCurrentAnimFrameCounter() + { + this->_modelAnimation[this->_currentAnimIndex].incrementFrameCounter(); + } + + void AnimationsComponent::setAnimDisabled(bool disable) + { + this->_animDisabled = disable; + } + + bool AnimationsComponent::isAnimDisabled() const + { + return this->_animDisabled; + } +} \ No newline at end of file diff --git a/sources/Component/Animation/AnimationsComponent.hpp b/sources/Component/Animation/AnimationsComponent.hpp new file mode 100644 index 00000000..463f241f --- /dev/null +++ b/sources/Component/Animation/AnimationsComponent.hpp @@ -0,0 +1,63 @@ +// +// Created by cbihan on 01/06/2021. +// + +#pragma once + +#include +#include +#include +#include + +namespace BBM +{ + class AnimationsComponent : public WAL::Component + { + private: + //! @brief To get the animation data + RAY::ModelAnimations _modelAnimation; + //! @brief The index of the + int _currentAnimIndex; + //! @brief Bool allowing to play pause an animation + bool _animDisabled; + public: + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief get the current animation index + size_t getCurrentAnimIndex() const; + + //! @brief Set the animation index to use + void setAnimIndex(int animIndex); + + //! @brief get animation frame counter + size_t getCurrentAnimFrameCounter() const; + + //! @brief get the current + RAY::ModelAnimation getCurrentModelAnim(); + + //! @brief set the anim frame counter + void setCurrentAnimFrameCounter(size_t animFrameCounter); + + //! @brief Set the internal anim counter to 0 + void resetCurrentAnimFrameCounter(); + + //! @brief Increment the internal anim counter + void incCurrentAnimFrameCounter(); + + //! @brief Allow to play pause animations + void setAnimDisabled(bool disable); + + //! @brief To know if the animation will be updated or not + bool isAnimDisabled() const; + + //! @brief ctor entity and the path of the animation file + explicit AnimationsComponent(WAL::Entity &entity, RAY::ModelAnimations modelAnimation, int animIndex, bool play = true); + //! @brief copy ctor + AnimationsComponent(const AnimationsComponent &) = default; + //! @brief dtor + ~AnimationsComponent() override = default; + //! @brief assignment operator + AnimationsComponent &operator=(const AnimationsComponent &) = delete; + }; +} diff --git a/sources/Component/Collision/CollisionComponent.cpp b/sources/Component/Collision/CollisionComponent.cpp new file mode 100644 index 00000000..df727b2d --- /dev/null +++ b/sources/Component/Collision/CollisionComponent.cpp @@ -0,0 +1,34 @@ +// +// Created by Louis Auzuret on 2021-05-20. +// + +#include "Component/Collision/CollisionComponent.hpp" + + +namespace BBM +{ + CollisionComponent::CollisionComponent(WAL::Entity &entity) + : WAL::Component(entity) + { } + + WAL::Component *CollisionComponent::clone(WAL::Entity &entity) const + { + return new CollisionComponent(entity); + } + + CollisionComponent::CollisionComponent(WAL::Entity &entity, WAL::Callback onCollide, WAL::Callback onCollided, Vector3f bound) + : WAL::Component(entity), onCollide(onCollide), onCollided(onCollided), bound(bound) + { } + + CollisionComponent::CollisionComponent(WAL::Entity &entity, WAL::Callback onCollide, WAL::Callback onCollided, float boundSize) + : WAL::Component(entity), onCollide(onCollide), onCollided(onCollided), bound({boundSize, boundSize, boundSize}) + { } + + CollisionComponent::CollisionComponent(WAL::Entity &entity, Vector3f bound) + : WAL::Component(entity), onCollide(), onCollided(), bound(bound) + { } + + CollisionComponent::CollisionComponent(WAL::Entity &entity, float boundSize) + : WAL::Component(entity), onCollide(), onCollided(), bound({boundSize, boundSize, boundSize}) + { } +} \ No newline at end of file diff --git a/sources/Component/Collision/CollisionComponent.hpp b/sources/Component/Collision/CollisionComponent.hpp new file mode 100644 index 00000000..5bfe7e16 --- /dev/null +++ b/sources/Component/Collision/CollisionComponent.hpp @@ -0,0 +1,51 @@ +// +// Created by Louis Auzuret on 2021-05-20. +// + +#pragma once + +#include "Models/Callback.hpp" +#include "Models/Vector3.hpp" +#include "Component/Component.hpp" +#include "Entity/Entity.hpp" + +namespace BBM +{ + class CollisionComponent : public WAL::Component + { + private: + public: + //! @brief onCollide functions to be called + WAL::Callback onCollide; + //! @brief onCollided functions to be called + WAL::Callback onCollided; + //! @brief Bound size on all axis + Vector3f bound; + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief A component can't be instantiated, it should be derived. + explicit CollisionComponent(WAL::Entity &entity); + + //! @brief Constructor with a WAL::Callback + CollisionComponent(WAL::Entity &entity, WAL::Callback onCollide, WAL::Callback onCollided,Vector3f bound); + + //! @brief Constructor with a WAL::Callback, same boundSize for all axis + CollisionComponent(WAL::Entity &entity, WAL::Callback onCollide, WAL::Callback onCollided, float boundSize = 0); + + //! @brief Constructor of collider with no callback + CollisionComponent(WAL::Entity &entity, Vector3f bound); + + //! @brief Constructor no callback, same boundSize for all axis + CollisionComponent(WAL::Entity &entity, float boundSize); + + //! @brief Default copy constructor + CollisionComponent(const CollisionComponent &) = default; + + //! @brief default destructor + ~CollisionComponent() override = default; + + //! @brief A component can't be assigned + CollisionComponent &operator=(const CollisionComponent &) = delete; + }; +} \ No newline at end of file diff --git a/sources/Component/Movable/MovableComponent.cpp b/sources/Component/Movable/MovableComponent.cpp index 4fc9bc0c..26a8fd11 100644 --- a/sources/Component/Movable/MovableComponent.cpp +++ b/sources/Component/Movable/MovableComponent.cpp @@ -19,4 +19,10 @@ namespace BBM { this->_acceleration += force; } + + const Vector3f &MovableComponent::getVelocity(void) const + { + return _velocity; + } + } // namespace WAL \ No newline at end of file diff --git a/sources/Component/Movable/MovableComponent.hpp b/sources/Component/Movable/MovableComponent.hpp index 7656a960..6fecf89e 100644 --- a/sources/Component/Movable/MovableComponent.hpp +++ b/sources/Component/Movable/MovableComponent.hpp @@ -18,10 +18,14 @@ namespace BBM //! @brief The velocity of the entity. Vector3f _velocity; public: + //! @brief Add an instant force to this entity. //! @param force The force to add to this entity's acceleration. The force is added instantly and in one go. void addForce(Vector3f force); + //! @brief Get velocity + const Vector3f &getVelocity(void) const; + //! @inherit WAL::Component *clone(WAL::Entity &entity) const override; @@ -35,5 +39,6 @@ namespace BBM MovableComponent &operator=(const MovableComponent &) = delete; friend class MovableSystem; + friend class MapGenerator; }; } // namespace WAL \ No newline at end of file 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/Component/Timer/TimerComponent.cpp b/sources/Component/Timer/TimerComponent.cpp index 020601d9..1695ee39 100644 --- a/sources/Component/Timer/TimerComponent.cpp +++ b/sources/Component/Timer/TimerComponent.cpp @@ -19,12 +19,6 @@ namespace BBM callback(callback) {} - TimerComponent::TimerComponent(WAL::Entity &entity, std::chrono::nanoseconds delay, std::function callback) - : WAL::Component(entity), - ringIn(delay), - callback(std::move(callback)) - {} - WAL::Component *TimerComponent::clone(WAL::Entity &entity) const { return new TimerComponent(entity, this->ringIn, this->callback); diff --git a/sources/Component/Timer/TimerComponent.hpp b/sources/Component/Timer/TimerComponent.hpp index 222a69b9..b0ad2454 100644 --- a/sources/Component/Timer/TimerComponent.hpp +++ b/sources/Component/Timer/TimerComponent.hpp @@ -26,8 +26,6 @@ namespace BBM TimerComponent(WAL::Entity &entity, std::chrono::nanoseconds delay); //! @brief Create a timer with a callback. TimerComponent(WAL::Entity &entity, std::chrono::nanoseconds delay, const WAL::Callback &callback); - //! @brief Create a timer with a function to call on ring. - TimerComponent(WAL::Entity &entity, std::chrono::nanoseconds delay, std::function callback); //! @brief A timer component is copy constructable TimerComponent(const TimerComponent &) = default; //! @brief A default destructor diff --git a/sources/Map/Map.cpp b/sources/Map/Map.cpp new file mode 100644 index 00000000..e71d2c34 --- /dev/null +++ b/sources/Map/Map.cpp @@ -0,0 +1,337 @@ +// +// Created by Tom Augier on 5/26/21. +// Edited by Benjamin Henry on 5/26/21. +// + +#include +#include "Map.hpp" +#include + +namespace RAY3D = RAY::Drawables::Drawables3D; + +namespace BBM +{ + void MapGenerator::wallCollide(WAL::Entity &entity, const WAL::Entity &wall) + { + auto *mov = entity.tryGetComponent(); + if (!mov) + return; + auto &pos = entity.getComponent(); + const auto &wallPos = wall.getComponent(); + auto diff = pos.position + mov->getVelocity() - wallPos.position; +// mov->_velocity = Vector3f(); + if (diff.x <= 0 && mov->_velocity.x < 0) + mov->_velocity.x = 0; + if (diff.x >= 0 && mov->_velocity.x > 0) + mov->_velocity.x = 0; + if (diff.z <= 0 && mov->_velocity.z < 0) + mov->_velocity.z = 0; + if (diff.z >= 0 && mov->_velocity.z > 0) + mov->_velocity.z = 0; + } + + 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) + { + 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(i, 0, j) + .addComponent(WAL::Callback(), &MapGenerator::wallCollide, .75) + .addComponent(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePng)); + } + } + } + } + + void MapGenerator::generateWall(int width, int height, std::shared_ptr scene) + { + 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(WAL::Callback(), &MapGenerator::wallCollide, .75) + .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(WAL::Callback(), &MapGenerator::wallCollide, .75) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(width + 3, 1, 1)); + scene->addEntity("Left Wall") + .addComponent(Vector3f(width + 1, 0, height / 2)) + .addComponent(WAL::Callback(), &MapGenerator::wallCollide, .75) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(1, 1, height + 1)); + scene->addEntity("Right Wall") + .addComponent(Vector3f(-1, 0, height / 2)) + .addComponent(WAL::Callback(), &MapGenerator::wallCollide, .75) + .addComponent(unbreakableObj, + std::make_pair(MAP_DIFFUSE, unbreakablePnj), + RAY::Vector3(1, 1, height + 1)); + } + + void MapGenerator::generateFloor(MapBlock map, int width, int height, std::shared_ptr scene) + { + 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(floorObj, + std::make_pair(MAP_DIFFUSE, floorPng)); + } + } + } + + void MapGenerator::createElement(Vector3f coords, std::shared_ptr scene, BlockType blockType) + { + std::map elements = { + {BREAKABLE, &createBreakable}, + {UNBREAKABLE, &createUnbreakable}, + {HOLE, &createHole}, + {FLOOR, &createFloor}, + {BUMPER, &createBumper}, + {STAIRS, &createStairs}, + {UPPERFLOOR, &createUpperFloor}, + }; + + try { + auto element = elements.at(blockType); + element(coords, scene); + } catch (std::exception const &err) { + return; + } + } + + 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(WAL::Callback(), &MapGenerator::wallCollide, .75) + .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(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(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(WAL::Callback(), &MapGenerator::wallCollide, .75) + .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(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, 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(stairsObj, std::make_pair(MAP_DIFFUSE, stairsPng)); + } + + 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); + } + + MapGenerator::BlockType MapGenerator::getRandomBlockType() + { + double rnd = static_cast(std::rand()) / RAND_MAX; + + if (rnd > 0.95) + return HOLE; + 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; + + if (rnd > 0.60) { + for (int i = 0; i < width + 1; i++) { + map[std::make_tuple(i, 1, height)] = map[std::make_tuple(i, 0, height)]; + map[std::make_tuple(i, 0, height)] = UPPERFLOOR; + 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 / 2 - width / 4; i < width / 2 + width / 4 + 1; i++) { + for (int j = height / 2 - height / 4; j < height / 2 + height / 4 + 1; j++) { + if (map[std::make_tuple(i, 0, j)] == FLOOR) + continue; + map[std::make_tuple(i, 1, j)] = map[std::make_tuple(i, 0, j)]; + map[std::make_tuple(i, 0, j)] = UPPERFLOOR; + } + } + 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; + } + + MapGenerator::MapBlock MapGenerator::createSpawner(MapBlock map, int width, int height) + { + map[std::make_tuple(0, 0, 0)] = SPAWNER; + map[std::make_tuple(width, 0, 0)] = SPAWNER; + map[std::make_tuple(0, 0, height)] = SPAWNER; + map[std::make_tuple(width, 0, height)] = SPAWNER; + + 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 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)) { + map[std::make_tuple(i, 0, j)] = NOTHING; + } 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++) + 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, MapBlock map, std::shared_ptr scene) + { + generateWall(width, height, scene); + 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 new file mode 100644 index 00000000..0e54ea4c --- /dev/null +++ b/sources/Map/Map.hpp @@ -0,0 +1,173 @@ +// +// Created by Tom Augier on 5/26/21. +// Edited by Benjamin Henry on 5/26/21. +// + + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "Component/Renderer/Drawable3DComponent.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 +{ + + class MapGenerator + { + private: + //! @brief Enum of the block available. + enum BlockType { + NOTHING, + BREAKABLE, + HOLE, + UPPERFLOOR, + FLOOR, + BUMPER, + STAIRS, + SPAWNER, + UNBREAKABLE + }; + + using MapElem = std::function scene)>; + using MapBlock = std::map, BlockType>; + + //! @brief Generate random block type + static BlockType getRandomBlockType(); + + //! @param map ASCII map + //! @param x x index on the block + //! @param z z index on the block + //! @param blockType blockType to compare with position + static bool isCloseToBlockType(std::map, BlockType> map, int x, int y, int z, BlockType blockType); + + //! @param width Width of the map + //! @param height Height of the map + //! @param scene Scene where the map is instanced + //! @brief Generate the unbreakable block of the map + static void generateUnbreakableBlock(int width, int height, std::shared_ptr scene); + + //! @param width Width of the map + //! @param height Height of the map + //! @param scene Scene where the map is instanced + //! @brief Generate the wall of the map + static void generateWall(int width, int height, std::shared_ptr scene); + + //! @param width Width of the map + //! @param height Height of the map + //! @param scene Scene where the map is instanced + //! @brief Generate the floor of the map + 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 + //! @brief Create element of the map + static void createElement(Vector3f coords, std::shared_ptr scene, BlockType blockType); + + //! @param coords coords of the element + //! @param scene Scene where the map is instanced + //! @brief Create breakable of the map + static void createBreakable(Vector3f coords, std::shared_ptr scene); + + //! @param coords coords of the element + //! @param scene Scene where the map is instanced + //! @brief Create unbreakable of the map + static void createUnbreakable(Vector3f coords, std::shared_ptr scene); + + //! @param coords coords of the element + //! @param scene Scene where the map is instanced + //! @brief Create hole of the map + static void createHole(Vector3f coords, std::shared_ptr scene); + + //! @param coords coords of the element + //! @param scene Scene where the map is instanced + //! @brief Create bumper of the map + static void createBumper(Vector3f coords, std::shared_ptr scene); + + //! @param coords coords of the element + //! @param scene Scene where the map is instanced + //! @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 + //! @brief Create stair of the map + static void createStairs(Vector3f coords, std::shared_ptr scene); + + //! @param map Map to load with block declared inside + //! @param width Width of the map + //! @param height Height of the map + //! @brief Generate map of block to be loaded + static MapBlock createSpawner(MapBlock map, int width, int height); + + //! @param map Map to load with block declared inside + //! @param width Width of the map + //! @param height Height of the map + //! @brief Generate 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: + static void wallCollide(WAL::Entity &entity, const WAL::Entity &wall); + + + //! @param width Width of the map + //! @param height Height of the map + //! @brief Generate map of block to be loaded + static MapBlock createMap(int width, int height); + + //! @param width Width of the map + //! @param height Height of the map + //! @param map Map to load with block declared inside + //! @param scene Scene where the map is instanced + //! @brief Generate the map + static void loadMap(int width, int height, MapBlock map, std::shared_ptr scene); + + }; +} // namespace BBM \ No newline at end of file diff --git a/sources/Models/Vector3.hpp b/sources/Models/Vector3.hpp index def6d322..d4ba7337 100644 --- a/sources/Models/Vector3.hpp +++ b/sources/Models/Vector3.hpp @@ -71,7 +71,13 @@ namespace BBM } template - Vector3 &operator*=(T2 d) + Vector3 operator-(const Vector3 &vec) const + { + return Vector3(this->x - vec.x, this->y - vec.y, this->z - vec.z); + } + + template + Vector3 &operator*=(const T2 d) { this->x *= d; this->y *= d; @@ -80,7 +86,7 @@ namespace BBM } template - Vector3 operator*(T2 d) const + Vector3 operator*(const T2 d) const { return Vector3(this->x * d, this->y * d, this->z * d); } @@ -166,6 +172,22 @@ namespace BBM { return RAY::Vector3(this->x, this->y, this->z); } + + static Vector3 min(Vector3 a, Vector3 b) + { + Vector3 min = { std::min(a.x, b.x), + std::min(a.y, b.y), + std::min(a.z, b.z)}; + return min; + } + + static Vector3 max(Vector3 a, Vector3 b) + { + Vector3 max = { std::max(a.x, b.x), + std::max(a.y, b.y), + std::max(a.z, b.z)}; + return max; + } }; typedef Vector3 Vector3f; diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index b31250d8..13009d4e 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -5,11 +5,9 @@ #include #include #include "System/Movable/MovableSystem.hpp" -#include "System/Renderer/RenderScreenSystem.hpp" -#include "System/Renderer/Render2DScreenSystem.hpp" -#include "System/Renderer/Renderer2DSystem.hpp" +#include "System/Renderer/RenderSystem.hpp" #include -#include +#include #include #include #include "System/Event/EventSystem.hpp" @@ -17,19 +15,23 @@ #include "System/Timer/TimerSystem.hpp" #include "Component/BombHolder/BombHolderComponent.hpp" #include "System/BombHolder/BombHolderSystem.hpp" -#include "System/Renderer/Renderer3DSystem.hpp" #include "System/Keyboard/KeyboardSystem.hpp" #include "System/Controllable/ControllableSystem.hpp" #include "Component/Movable/MovableComponent.hpp" #include "Component/Controllable/ControllableComponent.hpp" #include "Component/Keyboard/KeyboardComponent.hpp" #include "System/Gamepad/GamepadSystem.hpp" -#include "Models/Vector2.hpp" +#include +#include #include "Component/Renderer/CameraComponent.hpp" +#include "Component/Renderer/Drawable3DComponent.hpp" #include "Runner.hpp" #include "Models/GameState.hpp" +#include +#include "Component/Animation/AnimationsComponent.hpp" +#include "System/Animation/AnimationsSystem.hpp" +#include "Map/Map.hpp" -namespace RAY2D = RAY::Drawables::Drawables2D; namespace RAY3D = RAY::Drawables::Drawables3D; namespace BBM @@ -46,13 +48,14 @@ namespace BBM void addSystems(WAL::Wal &wal) { - wal.addSystem(wal) + wal.addSystem() .addSystem() .addSystem() .addSystem() - .addSystem(wal) + .addSystem() .addSystem() .addSystem() + .addSystem() .addSystem(); } @@ -60,34 +63,34 @@ namespace BBM { RAY::TraceLog::setLevel(LOG_WARNING); RAY::Window &window = RAY::Window::getInstance(600, 400, "Bomberman", FLAG_WINDOW_RESIZABLE); - - wal.addSystem>(); - - wal.addSystem(window) - .addSystem>(); - wal.addSystem(window); + wal.addSystem() + .addSystem(window); } std::shared_ptr loadGameScene() { auto scene = std::make_shared(); - scene->addEntity("cube") - .addComponent() - .addComponent>(Vector2f(), Vector2f(10, 10), RED) - .addComponent() - .addComponent() - .addComponent(); 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(RAY::ModelAnimations("assets/player/player.iqm"), 3) + .addComponent(1) .addComponent() .addComponent() .addComponent(1); scene->addEntity("camera") - .addComponent(0, 20, -5) - .addComponent(); + .addComponent(8, 20, 7) + .addComponent(Vector3f(8, 0, 8)); +// scene->addEntity("cube") +// .addComponent(5, 0, 5) +// .addComponent(Vector3f(-5, 0, -5), Vector3f(3, 3, 3), RED) +// .addComponent() +// .addComponent() +// .addComponent(WAL::Callback(), &MapGenerator::wallCollide, 3); + 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 new file mode 100644 index 00000000..5aaa4597 --- /dev/null +++ b/sources/System/Animation/AnimationsSystem.cpp @@ -0,0 +1,31 @@ +// +// Created by cbihan on 01/06/2021. +// + +#include +#include "AnimationsSystem.hpp" +#include "Component/Animation/AnimationsComponent.hpp" +#include "Model/Model.hpp" +#include "Component/Renderer/Drawable3DComponent.hpp" + +namespace BBM +{ + + AnimationsSystem::AnimationsSystem(WAL::Wal &wal) + : System(wal) + {} + + void AnimationsSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds) + { + auto &model = entity.get(); + auto &anim = entity.get(); + + if (anim.isDisabled()) + return; + 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/Animation/AnimationsSystem.hpp b/sources/System/Animation/AnimationsSystem.hpp new file mode 100644 index 00000000..6ace28d8 --- /dev/null +++ b/sources/System/Animation/AnimationsSystem.hpp @@ -0,0 +1,28 @@ +// +// Created by cbihan on 01/06/2021. +// + +#pragma once + +#include +#include "Component/Renderer/Drawable3DComponent.hpp" +#include "Component/Animation/AnimationsComponent.hpp" + +namespace BBM +{ + class AnimationsSystem : public WAL::System + { + public: + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds) override; + + //! @brief A default constructor + explicit AnimationsSystem(WAL::Wal &wal); + //! @brief A Controllable system is copy constructable + AnimationsSystem(const AnimationsSystem &) = default; + //! @brief A default destructor + ~AnimationsSystem() override = default; + //! @brief A system is not assignable. + AnimationsSystem &operator=(const AnimationsSystem &) = delete; + }; +} \ No newline at end of file diff --git a/sources/System/BombHolder/BombHolderSystem.cpp b/sources/System/BombHolder/BombHolderSystem.cpp index 2c289ce4..f09d2356 100644 --- a/sources/System/BombHolder/BombHolderSystem.cpp +++ b/sources/System/BombHolder/BombHolderSystem.cpp @@ -5,10 +5,7 @@ #include "Component/Timer/TimerComponent.hpp" #include "System/Event/EventSystem.hpp" #include "Component/Renderer/Drawable3DComponent.hpp" -#include "Component/Controllable/ControllableComponent.hpp" #include "BombHolderSystem.hpp" -#include "Component/Position/PositionComponent.hpp" -#include "Component/BombHolder/BombHolderComponent.hpp" #include "Component/Health/HealthComponent.hpp" using namespace std::chrono_literals; @@ -20,12 +17,7 @@ namespace BBM float BombHolderSystem::explosionRadius = 3; BombHolderSystem::BombHolderSystem(WAL::Wal &wal) - : WAL::System({ - typeid(PositionComponent), - typeid(BombHolderComponent), - typeid(ControllableComponent) - }), - _wal(wal) + : System(wal) {} void BombHolderSystem::_bombExplosion(WAL::Entity &bomb, WAL::Wal &wal) @@ -34,13 +26,13 @@ namespace BBM bomb.scheduleDeletion(); auto &bombPosition = bomb.getComponent(); wal.getSystem().dispatchEvent([&bombPosition](WAL::Entity &entity){ - if (!entity.hasComponent() || - !entity.hasComponent()) - return; - auto &position = entity.getComponent(); + auto *health = entity.tryGetComponent(); + auto *pos = entity.tryGetComponent(); - if (position.position.distance(bombPosition.position) <= BombHolderSystem::explosionRadius) - entity.getComponent().takeDmg(1); + if (!health || !pos) + return; + if (pos->position.distance(bombPosition.position) <= BombHolderSystem::explosionRadius) + health->takeDmg(1); }); } @@ -50,15 +42,15 @@ namespace BBM this->_wal.scene->addEntity("Bomb") .addComponent(position) .addComponent(BombHolderSystem::explosionTimer, &BombHolderSystem::_bombExplosion) - .addComponent>("assets/bombs/bomb.obj", + .addComponent("assets/bombs/bomb.obj", std::make_pair(MAP_DIFFUSE, "assets/bombs/bomb_normal.png")); } - void BombHolderSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) + void BombHolderSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) { - auto &holder = entity.getComponent(); - auto &position = entity.getComponent(); - auto &controllable = entity.getComponent(); + auto &holder = entity.get(); + auto &position = entity.get(); + auto &controllable = entity.get(); if (controllable.bomb && holder.bombCount > 0) { holder.bombCount--; diff --git a/sources/System/BombHolder/BombHolderSystem.hpp b/sources/System/BombHolder/BombHolderSystem.hpp index 83f80711..fd3d4e78 100644 --- a/sources/System/BombHolder/BombHolderSystem.hpp +++ b/sources/System/BombHolder/BombHolderSystem.hpp @@ -7,15 +7,16 @@ #include #include #include "Models/Vector3.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/BombHolder/BombHolderComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" namespace BBM { //! @brief The system that allow one to place bombs. - class BombHolderSystem : public WAL::System + class BombHolderSystem : public WAL::System { private: - //! @brief A reference to the engine to spawn new entities. - WAL::Wal &_wal; //! @brief Spawn a bomb at the specified position. void _spawnBomb(Vector3f position); @@ -28,7 +29,7 @@ namespace BBM static float explosionRadius; //! @inherit - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) override; + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; //! @brief A default constructor explicit BombHolderSystem(WAL::Wal &wal); diff --git a/sources/System/Collision/CollisionSystem.cpp b/sources/System/Collision/CollisionSystem.cpp new file mode 100644 index 00000000..6a3e36cd --- /dev/null +++ b/sources/System/Collision/CollisionSystem.cpp @@ -0,0 +1,46 @@ +// +// Created by Louis Auzuret on 5/20/21 +// + +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Component/Collision/CollisionComponent.hpp" +#include "System/Collision/CollisionSystem.hpp" +#include "Scene/Scene.hpp" + +namespace BBM +{ + CollisionSystem::CollisionSystem(WAL::Wal &wal) + : System(wal) + { } + + bool CollisionSystem::collide(Vector3f minA, Vector3f maxA, Vector3f minB, Vector3f maxB) + { + bool overlapX = (minA.x <= maxB.x && maxA.x >= minB.x) || (minB.x <= maxA.x && maxB.x >= minA.x); + bool overlapY = (minA.y <= maxB.y && maxA.y >= minB.y) || (minB.y <= maxA.y && maxB.y >= minA.y); + bool overlapZ = (minA.z <= maxB.z && maxA.z >= minB.z) || (minB.z <= maxA.z && maxB.z >= minA.z); + + return (overlapX && overlapY && overlapZ); + } + + void CollisionSystem::onFixedUpdate(WAL::ViewEntity &entity) + { + auto &posA = entity.get(); + auto &col = entity.get(); + Vector3f position = posA.position; + if (auto *movable = entity->tryGetComponent()) + position += movable->getVelocity(); + Vector3f minA = Vector3f::min(position, position + col.bound); + Vector3f maxA = Vector3f::max(position, position + col.bound); + for (auto &[other, posB, colB] : this->getView()) { + if (other.getUid() == entity->getUid()) + continue; + Vector3f minB = Vector3f::min(posB.position, posB.position + colB.bound); + Vector3f maxB = Vector3f::max(posB.position, posB.position + colB.bound); + if (collide(minA, maxA, minB, maxB)) { + col.onCollide(entity, other); + colB.onCollided(entity, other); + } + } + } +} \ No newline at end of file diff --git a/sources/System/Collision/CollisionSystem.hpp b/sources/System/Collision/CollisionSystem.hpp new file mode 100644 index 00000000..2c0f5491 --- /dev/null +++ b/sources/System/Collision/CollisionSystem.hpp @@ -0,0 +1,36 @@ + +// +// Created by Louis Auzuret on 5/20/21 +// + +#pragma once + +#include +#include "Wal.hpp" +#include "System/System.hpp" +#include "Models/Vector3.hpp" +#include "Component/Collision/CollisionComponent.hpp" +#include "Component/Position/PositionComponent.hpp" + +namespace BBM +{ + //! @brief A system to handle collisions. + class CollisionSystem : public WAL::System + { + public: + //! @inherit + void onFixedUpdate(WAL::ViewEntity &entity) override; + + //! @brief A default constructor + explicit CollisionSystem(WAL::Wal &wal); + //! @brief A Collision system is copy constructable + CollisionSystem(const CollisionSystem &) = default; + //! @brief A default destructor + ~CollisionSystem() override = default; + //! @brief A system is not assignable. + CollisionSystem &operator=(const CollisionSystem &) = delete; + + //! @brief check AABB collision + static bool collide(Vector3f minA, Vector3f maxA, Vector3f minB, Vector3f maxB); + }; +} \ No newline at end of file diff --git a/sources/System/Controllable/ControllableSystem.cpp b/sources/System/Controllable/ControllableSystem.cpp index 0a9c789c..f14c46b3 100644 --- a/sources/System/Controllable/ControllableSystem.cpp +++ b/sources/System/Controllable/ControllableSystem.cpp @@ -10,19 +10,14 @@ namespace BBM { - float ControllableSystem::speed = .25f; - - ControllableSystem::ControllableSystem() - : WAL::System({ - typeid(ControllableComponent), - typeid(MovableComponent) - }) + ControllableSystem::ControllableSystem(WAL::Wal &wal) + : System(wal) {} - void ControllableSystem::onFixedUpdate(WAL::Entity &entity) + void ControllableSystem::onFixedUpdate(WAL::ViewEntity &entity) { - auto &controllable = entity.getComponent(); - auto &movable = entity.getComponent(); + auto &controllable = entity.get(); + auto &movable = entity.get(); Vector2f move = controllable.move.normalized() * ControllableSystem::speed; movable.addForce(Vector3f(move.x, controllable.jump, move.y)); diff --git a/sources/System/Controllable/ControllableSystem.hpp b/sources/System/Controllable/ControllableSystem.hpp index fac4db08..25a9e837 100644 --- a/sources/System/Controllable/ControllableSystem.hpp +++ b/sources/System/Controllable/ControllableSystem.hpp @@ -5,27 +5,29 @@ #pragma once +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" #include "System/System.hpp" namespace BBM { //! @brief A system to handle Controllable entities. - class ControllableSystem : public WAL::System + class ControllableSystem : public WAL::System { public: //! @brief The speed applied to every controllable entities. - static float speed; + static constexpr const float speed = .25f; //! @inherit - void onFixedUpdate(WAL::Entity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor - ControllableSystem(); + explicit ControllableSystem(WAL::Wal &wal); //! @brief A Controllable system is copy constructable ControllableSystem(const ControllableSystem &) = default; //! @brief A default destructor ~ControllableSystem() override = default; - //! @brief A Controllable system is assignable. - ControllableSystem &operator=(const ControllableSystem &) = default; + //! @brief A system is not assignable. + ControllableSystem &operator=(const ControllableSystem &) = delete; }; } diff --git a/sources/System/Event/EventSystem.cpp b/sources/System/Event/EventSystem.cpp index e37e9f53..af20674f 100644 --- a/sources/System/Event/EventSystem.cpp +++ b/sources/System/Event/EventSystem.cpp @@ -6,8 +6,8 @@ namespace BBM { - EventSystem::EventSystem() - : WAL::System({}) + EventSystem::EventSystem(WAL::Wal &wal) + : System(wal) {} void EventSystem::dispatchEvent(const std::function &event) @@ -15,7 +15,7 @@ namespace BBM this->_events.emplace_back(event); } - void EventSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds) + void EventSystem::onUpdate(WAL::ViewEntity<> &entity, std::chrono::nanoseconds) { for (auto &event : this->_events) event(entity); diff --git a/sources/System/Event/EventSystem.hpp b/sources/System/Event/EventSystem.hpp index 0defda29..0a4c205f 100644 --- a/sources/System/Event/EventSystem.hpp +++ b/sources/System/Event/EventSystem.hpp @@ -10,7 +10,7 @@ namespace BBM { - class EventSystem : public WAL::System + class EventSystem : public WAL::System<> { private: //! @brief The list of events that occurred in the last update. @@ -20,12 +20,12 @@ namespace BBM void dispatchEvent(const std::function& event); //! @inherit - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) override; + void onUpdate(WAL::ViewEntity<> &entity, std::chrono::nanoseconds dtime) override; //! @inherit void onSelfUpdate() override; //! @brief A default constructor - EventSystem(); + explicit EventSystem(WAL::Wal &wal); //! @brief An event system is copy constructable. EventSystem(const EventSystem &) = default; //! @brief A default destructor diff --git a/sources/System/Gamepad/GamepadSystem.cpp b/sources/System/Gamepad/GamepadSystem.cpp index 5df6bd96..f6d67d99 100644 --- a/sources/System/Gamepad/GamepadSystem.cpp +++ b/sources/System/Gamepad/GamepadSystem.cpp @@ -13,17 +13,14 @@ using Gamepad = RAY::Controller::GamePad; namespace BBM { - GamepadSystem::GamepadSystem() - : WAL::System({ - typeid(GamepadComponent), - typeid(ControllableComponent) - }) + GamepadSystem::GamepadSystem(WAL::Wal &wal) + : System(wal) {} - void GamepadSystem::onFixedUpdate(WAL::Entity &entity) + void GamepadSystem::onFixedUpdate(WAL::ViewEntity &entity) { - const auto &gamepadComponent = entity.getComponent(); - auto &controllable = entity.getComponent(); + const auto &gamepadComponent = entity.get(); + auto &controllable = entity.get(); Gamepad gamepad(gamepadComponent.getID()); const std::map keyPressedMap = { diff --git a/sources/System/Gamepad/GamepadSystem.hpp b/sources/System/Gamepad/GamepadSystem.hpp index 9c8c705f..61efdd5e 100644 --- a/sources/System/Gamepad/GamepadSystem.hpp +++ b/sources/System/Gamepad/GamepadSystem.hpp @@ -6,23 +6,25 @@ #include "System/System.hpp" #include +#include "Component/Gamepad/GamepadComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" namespace BBM { //! @brief A system to handle Gamepad entities. - class GamepadSystem : public WAL::System + class GamepadSystem : public WAL::System { public: //! @inherit - void onFixedUpdate(WAL::Entity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor - GamepadSystem(); + explicit GamepadSystem(WAL::Wal &wal); //! @brief A Gamepad system is copy constructable GamepadSystem(const GamepadSystem &) = default; //! @brief A default destructor ~GamepadSystem() override = default; - //! @brief A Gamepad system is assignable. - GamepadSystem &operator=(const GamepadSystem &) = default; + //! @brief A system is not assignable. + GamepadSystem &operator=(const GamepadSystem &) = delete; }; } diff --git a/sources/System/GridCentered/GridCenteredSystem.cpp b/sources/System/GridCentered/GridCenteredSystem.cpp index 5dcca1a9..3c86175b 100644 --- a/sources/System/GridCentered/GridCenteredSystem.cpp +++ b/sources/System/GridCentered/GridCenteredSystem.cpp @@ -8,18 +8,14 @@ namespace BBM { - GridCenteredSystem::GridCenteredSystem() - : WAL::System({ - typeid(GridCenteredComponent), - typeid(MovableComponent), -// typeid(PositionComponent) - }) + GridCenteredSystem::GridCenteredSystem(WAL::Wal &wal) + : System(wal) {} - void GridCenteredSystem::onFixedUpdate(WAL::Entity &entity) + void GridCenteredSystem::onFixedUpdate(WAL::ViewEntity &entity) { - auto &grid = entity.getComponent(); - auto &movement = entity.getComponent(); + auto &grid = entity.get(); + auto &movement = entity.get(); // movement.addForce(grid.force * ) } } \ No newline at end of file diff --git a/sources/System/GridCentered/GridCenteredSystem.hpp b/sources/System/GridCentered/GridCenteredSystem.hpp index e84e65fb..6ab97339 100644 --- a/sources/System/GridCentered/GridCenteredSystem.hpp +++ b/sources/System/GridCentered/GridCenteredSystem.hpp @@ -5,22 +5,23 @@ #pragma once #include +#include "Component/Position/PositionComponent.hpp" namespace BBM { //! @brief The system handling GridCenteredComponent - class GridCenteredSystem : public WAL::System + class GridCenteredSystem : public WAL::System { public: - void onFixedUpdate(WAL::Entity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor - GridCenteredSystem(); + explicit GridCenteredSystem(WAL::Wal &wal); //! @brief A GridCenteredSystem is copyable. GridCenteredSystem(const GridCenteredSystem &) = default; //! @brief A default destructor ~GridCenteredSystem() override = default; - //! @brief A GridCenteredSystem is assignable - GridCenteredSystem &operator=(const GridCenteredSystem &) = default; + //! @brief A system is not assignable + GridCenteredSystem &operator=(const GridCenteredSystem &) = delete; }; } diff --git a/sources/System/Health/HealthSystem.cpp b/sources/System/Health/HealthSystem.cpp index 90bbfbb9..29e0db1f 100644 --- a/sources/System/Health/HealthSystem.cpp +++ b/sources/System/Health/HealthSystem.cpp @@ -10,15 +10,13 @@ namespace BBM { - HealthSystem::HealthSystem() - : WAL::System({ - typeid(HealthComponent) - }) + HealthSystem::HealthSystem(WAL::Wal &wal) + : System(wal) {} - void HealthSystem::onFixedUpdate(WAL::Entity &entity) + void HealthSystem::onFixedUpdate(WAL::ViewEntity &entity) { - auto &health = entity.getComponent(); + auto &health = entity.get(); if (health.getHealthPoint() == 0) health.onDeath(entity); diff --git a/sources/System/Health/HealthSystem.hpp b/sources/System/Health/HealthSystem.hpp index 15ca2062..f1cd2397 100644 --- a/sources/System/Health/HealthSystem.hpp +++ b/sources/System/Health/HealthSystem.hpp @@ -5,24 +5,25 @@ #pragma once +#include "Component/Health/HealthComponent.hpp" #include "System/System.hpp" namespace BBM { //! @brief A system to handle Health entities. - class HealthSystem : public WAL::System + class HealthSystem : public WAL::System { public: //! @inherit - void onFixedUpdate(WAL::Entity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor - HealthSystem(); + explicit HealthSystem(WAL::Wal &wal); //! @brief A Health system is copy constructable HealthSystem(const HealthSystem &) = default; //! @brief A default destructor ~HealthSystem() override = default; - //! @brief A Health system is assignable. - HealthSystem &operator=(const HealthSystem &) = default; + //! @brief A system is not assignable. + HealthSystem &operator=(const HealthSystem &) = delete; }; } diff --git a/sources/System/Keyboard/KeyboardSystem.cpp b/sources/System/Keyboard/KeyboardSystem.cpp index a6c5963b..740b9e3a 100644 --- a/sources/System/Keyboard/KeyboardSystem.cpp +++ b/sources/System/Keyboard/KeyboardSystem.cpp @@ -6,24 +6,20 @@ #include "KeyboardSystem.hpp" #include "Component/Keyboard/KeyboardComponent.hpp" #include "Component/Controllable/ControllableComponent.hpp" -#include "Entity/Entity.hpp" #include "Controllers/Keyboard.hpp" using Keyboard = RAY::Controller::Keyboard; namespace BBM { - KeyboardSystem::KeyboardSystem() - : WAL::System({ - typeid(KeyboardComponent), - typeid(ControllableComponent) - }) + KeyboardSystem::KeyboardSystem(WAL::Wal &wal) + : System(wal) {} - void KeyboardSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds) + void KeyboardSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds) { - const auto &keyboard = entity.getComponent(); - auto &controllable = entity.getComponent(); + const auto &keyboard = entity.get(); + auto &controllable = entity.get(); const std::map keyPressedMap = { {keyboard.keyJump, controllable.jump}, diff --git a/sources/System/Keyboard/KeyboardSystem.hpp b/sources/System/Keyboard/KeyboardSystem.hpp index 5aba771e..e95bfcda 100644 --- a/sources/System/Keyboard/KeyboardSystem.hpp +++ b/sources/System/Keyboard/KeyboardSystem.hpp @@ -7,23 +7,25 @@ #include "System/System.hpp" #include +#include "Component/Keyboard/KeyboardComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" namespace BBM { //! @brief A system to handle keyboard entities. - class KeyboardSystem : public WAL::System + class KeyboardSystem : public WAL::System { public: //! @inherit - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds) override; + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds) override; //! @brief A default constructor - KeyboardSystem(); + explicit KeyboardSystem(WAL::Wal &wal); //! @brief A keyboard system is copy constructable KeyboardSystem(const KeyboardSystem &) = default; //! @brief A default destructor ~KeyboardSystem() override = default; - //! @brief A keyboard system is assignable. - KeyboardSystem &operator=(const KeyboardSystem &) = default; + //! @brief A system is not assignable. + KeyboardSystem &operator=(const KeyboardSystem &) = delete; }; } diff --git a/sources/System/Movable/MovableSystem.cpp b/sources/System/Movable/MovableSystem.cpp index 1c439345..eff5a79a 100644 --- a/sources/System/Movable/MovableSystem.cpp +++ b/sources/System/Movable/MovableSystem.cpp @@ -8,17 +8,14 @@ namespace BBM { - MovableSystem::MovableSystem() - : WAL::System({ - typeid(MovableComponent), - typeid(PositionComponent) - }) + MovableSystem::MovableSystem(WAL::Wal &wal) + : System(wal) {} - void MovableSystem::onFixedUpdate(WAL::Entity &entity) + void MovableSystem::onFixedUpdate(WAL::ViewEntity &entity) { - auto &movable = entity.getComponent(); - auto &position = entity.getComponent(); + auto &movable = entity.get(); + auto &position = entity.get(); position.position += movable._velocity; movable._velocity = movable._acceleration; diff --git a/sources/System/Movable/MovableSystem.hpp b/sources/System/Movable/MovableSystem.hpp index 51a56ea9..e109da13 100644 --- a/sources/System/Movable/MovableSystem.hpp +++ b/sources/System/Movable/MovableSystem.hpp @@ -5,25 +5,27 @@ #pragma once +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Position/PositionComponent.hpp" #include "System/System.hpp" #include "Entity/Entity.hpp" namespace BBM { //! @brief A system to handle movable entities. This system update velocity based on accelerations and positions based on velocity. - class MovableSystem : public WAL::System + class MovableSystem : public WAL::System { public: //! @inherit - void onFixedUpdate(WAL::Entity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor - MovableSystem(); + explicit MovableSystem(WAL::Wal &wal); //! @brief A movable system is copy constructable MovableSystem(const MovableSystem &) = default; //! @brief A default destructor ~MovableSystem() override = default; - //! @brief A movable system is assignable. - MovableSystem &operator=(const MovableSystem &) = default; + //! @brief A system is not assignable. + MovableSystem &operator=(const MovableSystem &) = delete; }; } // namespace WAL 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 8eba847a..00000000 --- a/sources/System/Renderer/RenderScreenSystem.cpp +++ /dev/null @@ -1,34 +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) - {} - - 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/RenderScreenSystem.hpp b/sources/System/Renderer/RenderScreenSystem.hpp deleted file mode 100644 index e9b2ea85..00000000 --- a/sources/System/Renderer/RenderScreenSystem.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Created by cbihan on 26/05/2021. -// - -#pragma once - -#include "System/System.hpp" -#include "Camera/Camera2D.hpp" -#include "Window.hpp" - -namespace BBM -{ - class RenderScreenSystem : public WAL::System - { - //! @brief The window to render on - RAY::Window &_window; - - //! @brief The camera used to render. - RAY::Camera::Camera3D _camera; - public: - //! @brief A method called after all entities that this system manage has been updated. - //! @note render on screen here - void onSelfUpdate() override; - - //! @inherit - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) override; - - //! @brief ctor - explicit RenderScreenSystem(RAY::Window &window); - //! @brief Default copy ctor - RenderScreenSystem(const RenderScreenSystem &) = default; - //! @brief Default dtor - ~RenderScreenSystem() override = default; - //! @brief A render screen system can't be assigned. - RenderScreenSystem &operator=(const RenderScreenSystem &) = delete; - }; -} diff --git a/sources/System/Renderer/RenderSystem.cpp b/sources/System/Renderer/RenderSystem.cpp new file mode 100644 index 00000000..cdabb452 --- /dev/null +++ b/sources/System/Renderer/RenderSystem.cpp @@ -0,0 +1,54 @@ +// +// 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/ADrawable3D.hpp" + +namespace BBM +{ + RenderSystem::RenderSystem(WAL::Wal &wal, RAY::Window &window, bool debugMode) + : System(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 &[_, pos, drawable] : this->_wal.scene->view()) { + drawable.drawable->setPosition(pos.position); + drawable.drawable->drawOn(this->_window); + } + this->_window.unuseCamera(); + + // TODO sort entities based on the Z axis + for (auto &[_, pos, drawable] : this->_wal.scene->view()) { + 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::ViewEntity &entity, std::chrono::nanoseconds dtime) + { + const auto &pos = entity.get(); + const auto &cam = entity.get(); + _camera.setPosition(pos.position); + _camera.setTarget(cam.target); + } +} \ No newline at end of file diff --git a/sources/System/Renderer/RenderSystem.hpp b/sources/System/Renderer/RenderSystem.hpp new file mode 100644 index 00000000..e770de02 --- /dev/null +++ b/sources/System/Renderer/RenderSystem.hpp @@ -0,0 +1,48 @@ +// +// Created by cbihan on 26/05/2021. +// + +#pragma once + +#include "Component/Renderer/CameraComponent.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "System/System.hpp" +#include "Camera/Camera2D.hpp" +#include "Window.hpp" +#include "Wal.hpp" + +namespace BBM +{ + class RenderSystem : public WAL::System + { + + //! @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 + void onSelfUpdate() override; + + //! @inherit + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; + + //! @brief ctor + RenderSystem(WAL::Wal &wal, RAY::Window &window, bool debugMode = true); + //! @brief Default copy ctor + RenderSystem(const RenderSystem &) = default; + //! @brief Default dtor + ~RenderSystem() override = default; + //! @brief A render screen system can't be assigned. + 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/System/Timer/TimerSystem.cpp b/sources/System/Timer/TimerSystem.cpp index e1765a23..f6c82c2b 100644 --- a/sources/System/Timer/TimerSystem.cpp +++ b/sources/System/Timer/TimerSystem.cpp @@ -10,15 +10,12 @@ using namespace std::chrono_literals; namespace BBM { TimerSystem::TimerSystem(WAL::Wal &wal) - : WAL::System({ - typeid(TimerComponent) - }), - _wal(wal) + : System(wal) {} - void TimerSystem::onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) + void TimerSystem::onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) { - auto &timer = entity.getComponent(); + auto &timer = entity.get(); timer.ringIn -= dtime; if (timer.ringIn <= 0ns) { timer.setDisable(true); diff --git a/sources/System/Timer/TimerSystem.hpp b/sources/System/Timer/TimerSystem.hpp index f925dd82..c7b20bc2 100644 --- a/sources/System/Timer/TimerSystem.hpp +++ b/sources/System/Timer/TimerSystem.hpp @@ -6,17 +6,15 @@ #include #include +#include namespace BBM { - class TimerSystem : public WAL::System + class TimerSystem : public WAL::System { - private: - //! @brief The wal engine - WAL::Wal &_wal; public: //! @inherit - void onUpdate(WAL::Entity &entity, std::chrono::nanoseconds dtime) override; + void onUpdate(WAL::ViewEntity &entity, std::chrono::nanoseconds dtime) override; //! @brief A default constructor TimerSystem(WAL::Wal &); diff --git a/sources/main.cpp b/sources/main.cpp index 43dccd7d..bd13441a 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -9,45 +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 "System/Renderer/Renderer3DSystem.hpp" -#include "System/Renderer/Renderer2DSystem.hpp" -#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; -} - - - - void usage(const std::string &bin) { std::cout << "Bomberman." << std::endl @@ -62,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 diff --git a/tests/CallbackTest.cpp b/tests/CallbackTest.cpp index 534ca9f4..30d67e76 100644 --- a/tests/CallbackTest.cpp +++ b/tests/CallbackTest.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include "Entity/Entity.hpp" #include "Models/Callback.hpp" @@ -36,6 +38,7 @@ TEST_CASE("Callback multiple arguments", "[Callback]") callback.addCallback([](const std::string& str, int a, unsigned *value, Entity &entity) { throw std::runtime_error(""); }); - Entity entity("name"); + Scene scene; + Entity entity(scene, "name"); REQUIRE_THROWS_AS(callback("1", 0, nullptr, entity), std::runtime_error); } diff --git a/tests/CollisionTest.cpp b/tests/CollisionTest.cpp new file mode 100644 index 00000000..394b1ccc --- /dev/null +++ b/tests/CollisionTest.cpp @@ -0,0 +1,97 @@ +// +// Created by Louis Auzuret on 5/31/21. +// + +#include +#include "Entity/Entity.hpp" +#include "Component/Position/PositionComponent.hpp" +#include "Wal.hpp" + +#define private public +#include "System/Collision/CollisionSystem.hpp" +#include "System/Movable/MovableSystem.hpp" +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Collision/CollisionComponent.hpp" + +using namespace WAL; +using namespace BBM; + + +TEST_CASE("Collision test", "[Component][System]") +{ + Wal wal; + CollisionSystem collision(wal); + wal.scene = std::make_shared(); + wal.scene->addEntity("player") + .addComponent() + .addComponent([](Entity &actual, const Entity &) { + try { + auto &pos = actual.getComponent(); + pos.position.x = 1; + pos.position.y = 1; + pos.position.z = 1; + } catch (std::exception &e) {}; + }, [](Entity &, const Entity &){}, 5.0); + Entity &entity = wal.scene->getEntities().front(); + REQUIRE(entity.getComponent().position == Vector3f()); + + entity.getComponent().bound.x = 5; + entity.getComponent().bound.y = 5; + entity.getComponent().bound.z = 5; + + collision.update(std::chrono::nanoseconds(1)); + collision.fixedUpdate(); + REQUIRE(entity.getComponent().position.x == 0.0); + REQUIRE(entity.getComponent().position.y == 0.0); + REQUIRE(entity.getComponent().position.z == 0.0); + + wal.scene->addEntity("block") + .addComponent(2,2,2) + .addComponent(1); + Entity &player = wal.scene->getEntities().front(); + collision.update(std::chrono::nanoseconds(1)); + REQUIRE(player.hasComponent(typeid(PositionComponent))); + collision.fixedUpdate(); + REQUIRE(wal.scene->getEntities().size() == 2); + REQUIRE(player.hasComponent(typeid(PositionComponent))); + REQUIRE(player.getComponent().position.x == 1.0); + REQUIRE(player.getComponent().position.y == 1); + REQUIRE(player.getComponent().position.z == 1); +} + + +TEST_CASE("Collsion test with movable", "[Component][System]") +{ + Wal wal; + CollisionSystem collision(wal); + MovableSystem movable(wal); + wal.scene = std::make_shared(); + wal.scene->addEntity("player") + .addComponent() + .addComponent([](Entity &actual, const Entity &) {}, [](Entity &actual, const Entity &) {}, 5.0) + .addComponent(); + + wal.scene->addEntity("block") + .addComponent(0, 0, 0) + .addComponent([](Entity &actual, const Entity &){}, [](Entity &actual, const Entity &) { + try { + auto &mov = actual.getComponent(); + mov._velocity = Vector3f(); + } catch (std::exception &e) {}; + }, 1); + Entity &entity = wal.scene->getEntities().front(); + REQUIRE(entity.getComponent().position == Vector3f()); + + entity.getComponent().bound.x = 5; + entity.getComponent().bound.y = 5; + entity.getComponent().bound.z = 5; + + entity.getComponent().addForce({1, 1, 1}); + collision.update(std::chrono::nanoseconds(1)); + collision.fixedUpdate(); + movable.update(std::chrono::nanoseconds(1)); + movable.fixedUpdate(); + REQUIRE(entity.getComponent().position.x == 0.0); + REQUIRE(entity.getComponent().position.y == 0.0); + REQUIRE(entity.getComponent().position.z == 0.0); +} \ No newline at end of file diff --git a/tests/EngineTests.cpp b/tests/EngineTests.cpp index 804b6050..9e356adf 100644 --- a/tests/EngineTests.cpp +++ b/tests/EngineTests.cpp @@ -31,7 +31,7 @@ TEST_CASE("Create system", "[Engine][System]") TEST_CASE("Create system by reference", "[Engine][System]") { Wal wal; - MovableSystem system; + MovableSystem system(wal); wal.addSystem(system); REQUIRE_THROWS_AS(wal.addSystem(), DuplicateError); } \ No newline at end of file diff --git a/tests/EntityTests.cpp b/tests/EntityTests.cpp index f58fd0c1..3520f862 100644 --- a/tests/EntityTests.cpp +++ b/tests/EntityTests.cpp @@ -5,13 +5,16 @@ #include "Entity/Entity.hpp" #include "Component/Position/PositionComponent.hpp" #include +#include +#include using namespace WAL; using namespace BBM; TEST_CASE("Component", "[Entity]") { - Entity entity("Bob"); + Scene scene; + Entity entity(scene, "Bob"); entity.addComponent(2, 3, 4); SECTION("Check value") { @@ -31,13 +34,15 @@ TEST_CASE("Component", "[Entity]") TEST_CASE("ComponentNotFound", "[Entity]") { - Entity entity("Bob"); + Scene scene; + Entity entity(scene, "Bob"); REQUIRE_THROWS_AS(entity.getComponent(), NotFoundError); } TEST_CASE("Add component by reference", "[Entity]") { - Entity entity("Bob"); + Scene scene; + Entity entity(scene, "Bob"); PositionComponent component(entity, 4, 5, 6); REQUIRE(&entity.addComponent(component) == &entity); diff --git a/tests/MoveTests.cpp b/tests/MoveTests.cpp index cd37d22a..b19a68fc 100644 --- a/tests/MoveTests.cpp +++ b/tests/MoveTests.cpp @@ -4,13 +4,13 @@ #include "Entity/Entity.hpp" #include "Component/Position/PositionComponent.hpp" -#include "System/Movable/MovableSystem.hpp" -#include "System/Controllable/ControllableSystem.hpp" #include #include -#include #define private public +#include "System/Controllable/ControllableSystem.hpp" +#include "System/Movable/MovableSystem.hpp" +#include #include using namespace WAL; @@ -19,32 +19,33 @@ using namespace BBM; TEST_CASE("Move test", "[Component][System]") { - Scene scene; - scene.addEntity("player") + Wal wal; + wal.scene = std::make_shared(); + wal.scene->addEntity("player") .addComponent() .addComponent() .addComponent(); - Entity &entity = scene.getEntities()[0]; + Entity &entity = wal.scene->getEntities().front(); REQUIRE(entity.getComponent().position == Vector3f()); entity.getComponent().move = Vector2f(1, 1); - ControllableSystem controllable; - controllable.onUpdate(entity, std::chrono::nanoseconds(1)); - controllable.onFixedUpdate(entity); + ControllableSystem controllable(wal); + controllable.update(std::chrono::nanoseconds(1)); + controllable.fixedUpdate(); REQUIRE(entity.getComponent()._acceleration.x > 0); REQUIRE(entity.getComponent()._acceleration.z > 0); - MovableSystem movable; - movable.onUpdate(entity, std::chrono::nanoseconds(1)); - movable.onFixedUpdate(entity); + MovableSystem movable(wal); + movable.update(std::chrono::nanoseconds(1)); + movable.fixedUpdate(); REQUIRE(entity.getComponent()._velocity.x > 0); REQUIRE(entity.getComponent()._velocity.z > 0); REQUIRE(entity.getComponent()._acceleration.x == 0); REQUIRE(entity.getComponent()._acceleration.z == 0); - movable.onUpdate(entity, std::chrono::nanoseconds(1)); - movable.onFixedUpdate(entity); + movable.update(std::chrono::nanoseconds(1)); + movable.fixedUpdate(); REQUIRE(entity.getComponent().position.x > 0); REQUIRE(entity.getComponent().position.z > 0); diff --git a/tests/ViewTest.cpp b/tests/ViewTest.cpp new file mode 100644 index 00000000..569d42ad --- /dev/null +++ b/tests/ViewTest.cpp @@ -0,0 +1,126 @@ +// +// Created by Zoe Roux on 6/3/21. +// + +#include "Entity/Entity.hpp" +#include "Component/Position/PositionComponent.hpp" +#include +#include +#include + +using namespace WAL; +using namespace BBM; + +TEST_CASE("View creation", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent() + .addComponent(); + scene.addEntity("Box") + .addComponent(); + REQUIRE(scene.view().size() == 2); + REQUIRE(scene.view().size() == 1); + Entity &entity = *scene.getEntities().begin(); + Entity &firstView = scene.view().front(); + REQUIRE(&entity == &firstView); +} + +TEST_CASE("View update", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent() + .addComponent(); + auto &view = scene.view(); + auto &entity = scene.addEntity("Box") + .addComponent(); + REQUIRE(view.size() == 2); + entity.removeComponent(); + REQUIRE(view.size() == 1); +} + +TEST_CASE("View cache", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent() + .addComponent(); + auto &view = scene.view(); + REQUIRE(&view == &scene.view()); +} + +TEST_CASE("View cache switch", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent() + .addComponent(); + auto &view = scene.view(); + Scene scene2; + scene2.addEntity("box") + .addComponent(); + + REQUIRE(&view == &scene.view()); + REQUIRE(view.front()->getName() == "player"); + REQUIRE(scene2.view().front()->getName() == "box"); +} + +TEST_CASE("View entity iteration", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent() + .addComponent(); + scene.addEntity("Box") + .addComponent(); + int i = 0; + for (Entity &entity : scene.view()) { + if (i == 0) + REQUIRE(entity.getName() == "player"); + else + REQUIRE(entity.getName() == "Box"); + i++; + } + REQUIRE(i == 2); +} + +TEST_CASE("ViewEntity<> iteration", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent(1, 1, 1) + .addComponent(); + scene.addEntity("Box") + .addComponent(1, 1, 1); + int i = 0; + for (auto entity : scene.view()) { + if (i == 0) + REQUIRE(entity->getName() == "player"); + else + REQUIRE(entity->getName() == "Box"); + REQUIRE(entity.get().position == Vector3f(1, 1, 1)); + i++; + } + REQUIRE(i == 2); +} + +TEST_CASE("View [entity, component] iteration", "[View]") +{ + Scene scene; + scene.addEntity("player") + .addComponent(1, 1, 1) + .addComponent(); + scene.addEntity("Box") + .addComponent(1, 1, 1); + int i = 0; + for (auto &[entity, position] : scene.view()) { + if (i == 0) + REQUIRE(entity.getName() == "player"); + else + REQUIRE(entity.getName() == "Box"); + REQUIRE(position.position == Vector3f(1, 1, 1)); + i++; + } + REQUIRE(i == 2); +} \ No newline at end of file