├── documentation ├── .gitignore ├── EventLoop.md ├── Networking.md ├── TimeManager.md ├── doxygen │ ├── footer.html │ └── header.html ├── Architecture.md └── INSPIRATION.md ├── core ├── Random.cpp ├── scene │ ├── Scene.cpp │ ├── Component.cpp │ ├── Behaviour.cpp │ ├── ScriptableObject.cpp │ ├── ScriptedBehaviour.cpp │ ├── Scene.h │ ├── Object.cpp │ ├── SendMessageOptions.h │ ├── SceneForwards.h │ ├── Behaviour.h │ ├── Transform.h │ ├── Transform.cpp │ ├── GameObject.cpp │ ├── ScriptableObject.h │ ├── Object.h │ ├── GameObject.h │ └── HideFlags.h ├── datastructures │ ├── Grid2D.cpp │ ├── Tree.cpp │ ├── Vector.cpp │ ├── concepts.h │ ├── Grid2D.h │ ├── Vector.h │ └── Tree.h ├── memory │ └── Memory.h ├── math │ ├── Vector3.cpp │ ├── Vector4.h │ ├── Vector4.cpp │ ├── Vector3.h │ ├── Vector2.cpp │ ├── Point2D.cpp │ └── Point2D.h ├── script │ ├── Script.cpp │ ├── ScriptManager.cpp │ ├── Script.h │ └── ScriptManager.h ├── engine │ ├── EngineForwards.h │ ├── EngineSettings.h │ └── Engine.h ├── error │ └── NotImplemented.h ├── Random.h ├── WebRequest.cpp ├── Texture.h ├── Polygon.h ├── Texture.cpp ├── WebRequest.h ├── Window.h ├── Polygon.cpp └── CMakeLists.txt ├── examples ├── maze │ ├── Node.cpp │ ├── MazeGeneratorBase.cpp │ ├── MazeGeneratorBase.h │ ├── main.cpp │ ├── CMakeLists.txt │ ├── generators │ │ ├── RecursiveBacktrackerExample.h │ │ ├── PrimExample.h │ │ ├── HuntAndKillExample.h │ │ ├── PrimExample.cpp │ │ ├── RecursiveBacktrackerExample.cpp │ │ └── HuntAndKillExample.cpp │ ├── Node.h │ └── World.h ├── life │ ├── RuleBase.cpp │ ├── GameOfLifeTileSetEnum.h │ ├── rules │ │ ├── HexagonGameOfLife.cpp │ │ ├── JohnConway.cpp │ │ ├── JohnConway.h │ │ └── HexagonGameOfLife.h │ ├── RuleBase.h │ ├── main.cpp │ ├── CMakeLists.txt │ ├── Manager.h │ ├── World.h │ └── World.cpp ├── scenario │ ├── GeneratorBase.cpp │ ├── GeneratorBase.h │ ├── generators │ │ ├── RandomGenerator.h │ │ ├── ParticleGenerator.h │ │ └── RandomGenerator.cpp │ ├── main.cpp │ ├── Manager.h │ └── CMakeLists.txt ├── CMakeLists.txt ├── chess │ ├── WorldStateFwd.h │ ├── pieces │ │ ├── Pieces.h │ │ ├── Bishop.h │ │ ├── Queen.h │ │ ├── Knight.h │ │ ├── Rook.h │ │ ├── King.h │ │ ├── Pawn.h │ │ ├── Knight.cpp │ │ ├── Bishop.cpp │ │ ├── Rook.cpp │ │ ├── Queen.cpp │ │ └── King.cpp │ ├── Search.h │ ├── Heuristics.h │ ├── main.cpp │ ├── CMakeLists.txt │ └── Manager.h ├── catchthecat │ ├── Cat.h │ ├── Catcher.h │ ├── Agent.h │ ├── Catcher.cpp │ ├── Cat.cpp │ ├── Agent.cpp │ └── CMakeLists.txt ├── flocking │ ├── behaviours │ │ ├── CohesionRule.cpp │ │ ├── AlignmentRule.cpp │ │ ├── WindRule.cpp │ │ ├── AlignmentRule.h │ │ ├── CohesionRule.h │ │ ├── WindRule.h │ │ ├── SeparationRule.h │ │ ├── MouseInfluenceRule.h │ │ ├── BoundedAreaRule.h │ │ ├── SeparationRule.cpp │ │ ├── MouseInfluenceRule.cpp │ │ ├── FlockingRule.h │ │ ├── BoundedAreaRule.cpp │ │ └── FlockingRule.cpp │ ├── utils │ │ └── ImGuiExtra.h │ ├── main.cpp │ ├── CMakeLists.txt │ └── gameobjects │ │ ├── Boid.h │ │ ├── Pacticle.cpp │ │ ├── Pacticle.h │ │ ├── Boid.cpp │ │ └── World.h ├── hideandseeksquared │ ├── CMakeLists.txt │ ├── main.cpp │ ├── Manager.h │ ├── ShadowCastGridRecursive.h │ └── ShadowCastGridRecursive.cpp └── headless │ ├── CMakeLists.txt │ └── main.cpp ├── .releaserc.json ├── scripts ├── windows-build.bat ├── emscripten-build-and-run.sh ├── emscripten-install.sh ├── emscripten-install-permanent.sh ├── win-set-env-vars.bat └── emscripten-build.sh ├── modules ├── CMakeLists.txt └── time │ ├── Time.cpp │ ├── CMakeLists.txt │ ├── Time.h │ ├── TimeDefs.h │ ├── Timer.cpp │ └── Timer.h ├── external ├── chaiscript.cmake ├── v8.cmake ├── glm.cmake ├── threadpool.cmake ├── bullet.cmake ├── zlib.cmake ├── mbedtls.cmake ├── filament.cmake ├── cpr.cmake ├── curl.cmake ├── glew.cmake ├── cpm.cmake ├── quickjs.cmake ├── wasm.cmake ├── imgui.cmake ├── external.cmake └── sdl.cmake ├── editor ├── Editor.h ├── vtk.cmake ├── TopBar.h ├── main.cpp ├── gdcm.cmake ├── itk.cmake ├── TopBar.cpp ├── Editor.cpp └── CMakeLists.txt ├── codecov.yaml ├── docker-compose.yml ├── cmake ├── subdirlist.cmake └── tools.cmake ├── test ├── GameObjects.tests.cpp ├── NullRenderer.tests.cpp ├── Test.cpp └── CMakeLists.txt ├── html ├── index.html ├── index2.html ├── chess.html ├── life.html ├── maze.html ├── editor.html ├── flocking.html ├── scenario.html ├── catchthecat.html └── hideandseek.html ├── .clang-tidy ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── style.yml │ ├── windows.yml │ ├── osx.yml │ ├── linux.yml │ └── test.yml ├── .all-contributorsrc ├── .gitignore ├── .gitattributes ├── .cmake-format ├── .clang-format ├── CMakeLists.txt └── package.json /documentation/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /core/Random.cpp: -------------------------------------------------------------------------------- 1 | #include "Random.h" 2 | -------------------------------------------------------------------------------- /core/scene/Scene.cpp: -------------------------------------------------------------------------------- 1 | #include "Scene.h" 2 | -------------------------------------------------------------------------------- /examples/maze/Node.cpp: -------------------------------------------------------------------------------- 1 | #include "Node.h" 2 | -------------------------------------------------------------------------------- /core/scene/Component.cpp: -------------------------------------------------------------------------------- 1 | #include "Component.h" 2 | -------------------------------------------------------------------------------- /examples/life/RuleBase.cpp: -------------------------------------------------------------------------------- 1 | #include "RuleBase.h" 2 | -------------------------------------------------------------------------------- /core/datastructures/Grid2D.cpp: -------------------------------------------------------------------------------- 1 | #include "Grid2D.h" 2 | -------------------------------------------------------------------------------- /core/memory/Memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /examples/scenario/GeneratorBase.cpp: -------------------------------------------------------------------------------- 1 | #include "GeneratorBase.h" 2 | -------------------------------------------------------------------------------- /core/math/Vector3.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector3.h" 2 | #include "../Random.h" 3 | -------------------------------------------------------------------------------- /examples/maze/MazeGeneratorBase.cpp: -------------------------------------------------------------------------------- 1 | #include "MazeGeneratorBase.h" 2 | -------------------------------------------------------------------------------- /core/math/Vector4.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR4_H 2 | #define VECTOR4_H 3 | 4 | struct Vector4 {}; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": ["master", "main"], 3 | "repositoryUrl": "https://github.com/InfiniBrains/mobagen" 4 | } -------------------------------------------------------------------------------- /core/math/Vector4.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 24/04/22. 3 | // 4 | 5 | #include "Vector4.h" 6 | -------------------------------------------------------------------------------- /core/script/Script.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.04.26. 3 | // 4 | 5 | #include "Script.h" 6 | -------------------------------------------------------------------------------- /core/datastructures/Tree.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.04.28. 3 | // 4 | 5 | #include "Tree.h" 6 | -------------------------------------------------------------------------------- /core/scene/Behaviour.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.03.28. 3 | // 4 | 5 | #include "Behaviour.h" 6 | -------------------------------------------------------------------------------- /core/datastructures/Vector.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.10.25. 3 | // 4 | 5 | #include "Vector.h" 6 | -------------------------------------------------------------------------------- /core/engine/EngineForwards.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_ENGINE_FORWARDS_H_ 2 | #define MOBAGEN_ENGINE_FORWARDS_H_ 3 | 4 | class Engine; 5 | 6 | #endif -------------------------------------------------------------------------------- /core/scene/ScriptableObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.04.04. 3 | // 4 | 5 | #include "ScriptableObject.h" 6 | -------------------------------------------------------------------------------- /core/scene/ScriptedBehaviour.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.03.28. 3 | // 4 | 5 | #include "ScriptedBehaviour.h" 6 | -------------------------------------------------------------------------------- /scripts/windows-build.bat: -------------------------------------------------------------------------------- 1 | cmake -H. -Bbuild -G "Visual Studio 16 2019" -T ClangCL -DCMAKE_BUILD_TYPE=MinSizeRel 2 | cmake --build build --config MinSizeRel -------------------------------------------------------------------------------- /core/scene/Scene.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_ENGINE_SCENE_H_ 2 | #define MOBAGEN_ENGINE_SCENE_H_ 3 | 4 | class Scene {}; 5 | 6 | #endif // MOBAGEN_ENGINE_SCENE_H_ 7 | -------------------------------------------------------------------------------- /core/script/ScriptManager.cpp: -------------------------------------------------------------------------------- 1 | // #include "ScriptManager.h" 2 | // #include "quickjspp.hpp" 3 | // 4 | // void ScriptManager::Initialize() { 5 | // 6 | // } 7 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | subdirlist(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR}) 2 | 3 | foreach(subdir ${SUBDIRS}) 4 | add_subdirectory(${subdir}) 5 | endforeach() 6 | -------------------------------------------------------------------------------- /modules/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | subdirlist(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR}) 2 | 3 | foreach(subdir ${SUBDIRS}) 4 | add_subdirectory(${subdir}) 5 | endforeach() 6 | -------------------------------------------------------------------------------- /documentation/EventLoop.md: -------------------------------------------------------------------------------- 1 | # Job Scheduler 2 | 3 | EventLoop 4 | TaskQueue 5 | MicroTask 6 | 7 | # Multi thread 8 | 9 | Main thread 10 | Job/work/??? stealing -------------------------------------------------------------------------------- /examples/life/GameOfLifeTileSetEnum.h: -------------------------------------------------------------------------------- 1 | enum class GameOfLifeTileSetEnum { 2 | None = 0, // just to force everyone to implement the tileset 3 | Square = 1, 4 | Hexagon = 2, 5 | }; -------------------------------------------------------------------------------- /external/chaiscript.cmake: -------------------------------------------------------------------------------- 1 | CPMAddPackage(GITHUB_REPOSITORY ChaiScript/ChaiScript) 2 | find_package(ChaiScript REQUIRED) 3 | if(ChaiScript_ADDED) 4 | message(STATUS ChaiScript_ADDED) 5 | endif() 6 | -------------------------------------------------------------------------------- /core/scene/Object.cpp: -------------------------------------------------------------------------------- 1 | #include "Object.h" 2 | #include 3 | 4 | template std::vector Object::FindObjectsOfType() { 5 | auto typehash = typeid(T).hash_code(); 6 | return std::vector(); 7 | } -------------------------------------------------------------------------------- /core/script/Script.h: -------------------------------------------------------------------------------- 1 | // #ifndef MOBAGEN_SCRIPT_H 2 | // #define MOBAGEN_SCRIPT_H 3 | // 4 | // #include 5 | // 6 | // class Script { 7 | // 8 | // }; 9 | // 10 | // #endif // MOBAGEN_SCRIPT_H 11 | -------------------------------------------------------------------------------- /examples/chess/WorldStateFwd.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_WORLDSTATEFWD_H 2 | #define MOBAGEN_WORLDSTATEFWD_H 3 | 4 | struct WorldState; 5 | struct Move; 6 | struct Search; 7 | struct Heuristics; 8 | 9 | #endif // MOBAGEN_WORLDSTATEFWD_H 10 | -------------------------------------------------------------------------------- /examples/catchthecat/Cat.h: -------------------------------------------------------------------------------- 1 | #ifndef CAT_H 2 | #define CAT_H 3 | 4 | #include "Agent.h" 5 | 6 | class Cat : public Agent { 7 | public: 8 | explicit Cat() : Agent(){}; 9 | Point2D Move(World*) override; 10 | }; 11 | 12 | #endif // CAT_H 13 | -------------------------------------------------------------------------------- /examples/chess/pieces/Pieces.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_PIECES_H 2 | #define CHESS_PIECES_H 3 | 4 | #include "King.h" 5 | #include "Queen.h" 6 | #include "Rook.h" 7 | #include "Bishop.h" 8 | #include "Knight.h" 9 | #include "Pawn.h" 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /core/scene/SendMessageOptions.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_SENDMESSAGEOPTIONS_H 2 | #define MOBAGEN_SENDMESSAGEOPTIONS_H 3 | 4 | enum class SendMessageOptions : bool { 5 | RequireReceiver, 6 | DontRequireReceiver, 7 | }; 8 | #endif // MOBAGEN_SENDMESSAGEOPTIONS_H 9 | -------------------------------------------------------------------------------- /core/scene/SceneForwards.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_ENGINE_SCENEFORWARDS_H_ 2 | #define MOBAGEN_ENGINE_SCENEFORWARDS_H_ 3 | 4 | class Object; 5 | class Component; 6 | class GameObject; 7 | class Scene; 8 | class Transform; 9 | class ScriptableObject; 10 | 11 | #endif -------------------------------------------------------------------------------- /examples/life/rules/HexagonGameOfLife.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by atolstenko on 2/9/2023. 3 | // 4 | 5 | #include "HexagonGameOfLife.h" 6 | void HexagonGameOfLife::Step(World& world) {} 7 | int HexagonGameOfLife::CountNeighbors(World& world, Point2D point) { return 0; } 8 | -------------------------------------------------------------------------------- /examples/catchthecat/Catcher.h: -------------------------------------------------------------------------------- 1 | #ifndef CATCHER_H 2 | #define CATCHER_H 3 | 4 | #include "Agent.h" 5 | 6 | class Catcher : public Agent { 7 | public: 8 | explicit Catcher() : Agent(){}; 9 | Point2D Move(World*) override; 10 | }; 11 | 12 | #endif // CATCHER_H 13 | -------------------------------------------------------------------------------- /editor/Editor.h: -------------------------------------------------------------------------------- 1 | // #ifndef EDITOR_H 2 | // #define EDITOR_H 3 | // 4 | // #include "GameObject.h" 5 | // 6 | // class Editor: GameObject { 7 | // public: 8 | // explicit Editor(Engine *pEngine); 9 | // void OnGui(ImGuiContext *context) override; 10 | // }; 11 | // #endif -------------------------------------------------------------------------------- /core/scene/Behaviour.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_BEHAVIOUR_H 2 | #define MOBAGEN_BEHAVIOUR_H 3 | 4 | #include "Component.h" 5 | class Behaviour : public Component { 6 | public: 7 | bool enabled = true; 8 | bool isActiveAndEnabled = true; 9 | }; 10 | 11 | #endif // MOBAGEN_BEHAVIOUR_H 12 | -------------------------------------------------------------------------------- /external/v8.cmake: -------------------------------------------------------------------------------- 1 | string(TIMESTAMP BEFORE "%s") 2 | CPMAddPackage("gh:bnoordhuis/v8-cmake#8.9.255.20") 3 | include_directories(${v8-cmake_SOURCE_DIR}) 4 | string(TIMESTAMP AFTER "%s") 5 | math(EXPR DELTAv8-cmake "${AFTER} - ${BEFORE}") 6 | message(STATUS "v8-cmake TIME: ${DELTAv8-cmake}s") 7 | -------------------------------------------------------------------------------- /codecov.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "test" 3 | 4 | comment: 5 | require_changes: true 6 | 7 | codecov: 8 | require_ci_to_pass: no 9 | 10 | coverage: 11 | precision: 2 12 | round: down 13 | range: "80...100" 14 | status: 15 | project: 16 | default: 17 | threshold: 0.1% -------------------------------------------------------------------------------- /editor/vtk.cmake: -------------------------------------------------------------------------------- 1 | string(TIMESTAMP BEFORE "%s") 2 | CPMAddPackage( 3 | NAME VTK 4 | GITHUB_REPOSITORY Kitware/VTK 5 | GIT_TAG v9.2.2 6 | OPTIONS "BUILD_SHARED_LIBS OFF" 7 | ) 8 | string(TIMESTAMP AFTER "%s") 9 | math(EXPR DELTAVTK "${AFTER} - ${BEFORE}") 10 | message(STATUS "VTK TIME: ${DELTAVTK}s") 11 | -------------------------------------------------------------------------------- /examples/life/rules/JohnConway.cpp: -------------------------------------------------------------------------------- 1 | #include "JohnConway.h" 2 | 3 | // Reference: https://playgameoflife.com/info 4 | void JohnConway::Step(World& world) { 5 | // todo: implement 6 | } 7 | 8 | int JohnConway::CountNeighbors(World& world, Point2D point) { 9 | // todo: implement 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | emsdk: 4 | container_name: mobagen-emsdk 5 | image: emscripten/emsdk 6 | working_dir: /usr/src/mobagen 7 | ports: 8 | - "8000:8000" 9 | volumes: 10 | - .:/usr/src/mobagen 11 | command: ./scripts/emscripten-build-and-run.sh 12 | -------------------------------------------------------------------------------- /external/glm.cmake: -------------------------------------------------------------------------------- 1 | # GLM 2 | string(TIMESTAMP BEFORE "%s") 3 | CPMAddPackage( 4 | NAME GLM 5 | GITHUB_REPOSITORY g-truc/glm 6 | GIT_TAG 0.9.9.8 7 | ) 8 | include_directories(${GLM_SOURCE_DIR}) 9 | string(TIMESTAMP AFTER "%s") 10 | math(EXPR DELTAGLM "${AFTER} - ${BEFORE}") 11 | message(STATUS "GLM TIME: ${DELTAGLM}s") 12 | -------------------------------------------------------------------------------- /core/engine/EngineSettings.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_ENGINESETTINGS_H 2 | #define MOBAGEN_ENGINESETTINGS_H 3 | 4 | struct EngineSettings { 5 | bool debug : 1 = true; 6 | bool fullscreen : 1 = false; 7 | bool vsync : 1 = true; 8 | bool showWindow : 1 = true; 9 | bool headless : 1 = false; 10 | }; 11 | 12 | #endif // MOBAGEN_ENGINESETTINGS_H 13 | -------------------------------------------------------------------------------- /external/threadpool.cmake: -------------------------------------------------------------------------------- 1 | CPMAddPackage( 2 | NAME thread-pool 3 | GITHUB_REPOSITORY DeveloperPaul123/thread-pool 4 | GIT_TAG 0.5.1 5 | OPTIONS "TP_BUILD_TESTS OFF" "TP_BUILD_EXAMPLES OFF" "TP_BUILD_BENCHMARKS OFF" 6 | ) 7 | # find_package(dp::thread-pool REQUIRED) todo: test https://github.com/Ahajha/LMRTFY todo: test 8 | # thread pool functionality 9 | -------------------------------------------------------------------------------- /examples/catchthecat/Agent.h: -------------------------------------------------------------------------------- 1 | #ifndef AGENT_H 2 | #define AGENT_H 3 | #include "math/Point2D.h" 4 | #include 5 | 6 | class World; 7 | 8 | class Agent { 9 | public: 10 | explicit Agent() = default; 11 | 12 | virtual Point2D Move(World*) = 0; 13 | 14 | std::vector generatePath(World* w); 15 | }; 16 | 17 | #endif // AGENT_H 18 | -------------------------------------------------------------------------------- /core/error/NotImplemented.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_NOTIMPLEMENTED_H 2 | #define MOBAGEN_NOTIMPLEMENTED_H 3 | 4 | #include 5 | 6 | // Todo: use when it's available 7 | class NotImplemented : public std::logic_error { 8 | public: 9 | NotImplemented() : std::logic_error("Not yet implemented"){}; 10 | }; 11 | #endif // MOBAGEN_NOTIMPLEMENTED_H 12 | -------------------------------------------------------------------------------- /external/bullet.cmake: -------------------------------------------------------------------------------- 1 | # set(USE_MSVC_RUNTIME_LIBRARY_DLL ON) set(BUILD_SHARED_LIBS OFF) set(BUILD_UNIT_TESTS OFF CACHE 2 | # BOOL "Do not build unit tests for bullet.") set(BUILD_BULLET2_DEMOS OFF CACHE BOOL "no bullet2 3 | # demos.") set(BUILD_CPU_DEMOS OFF CACHE BOOL "no bullet demos.") set(BUILD_BULLET3 OFF CACHE BOOL 4 | # "no bullet 3.") add_subdirectory(bullet3) 5 | -------------------------------------------------------------------------------- /examples/chess/pieces/Bishop.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_BISHOP_H 2 | #define CHESS_BISHOP_H 3 | 4 | #include "../WorldState.h" 5 | #include 6 | struct Bishop { 7 | static unordered_set AttackMoves(WorldState& world, const Point2D& origin); 8 | static unordered_set CoverMoves(WorldState& world, const Point2D& origin); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /editor/TopBar.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_TOPBAR_H 2 | #define MOBAGEN_TOPBAR_H 3 | 4 | #include "scene/ScriptableObject.h" 5 | 6 | class TopBar : public ScriptableObject { 7 | private: 8 | bool enabled = true; 9 | 10 | public: 11 | explicit TopBar() : ScriptableObject(){}; 12 | 13 | void OnGui(ImGuiContext* context) override; 14 | }; 15 | 16 | #endif // MOBAGEN_TOPBAR_H 17 | -------------------------------------------------------------------------------- /scripts/emscripten-build-and-run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd $DIRECTORY/../ 6 | 7 | rm -rf bin-emscripten 8 | 9 | cd $DIRECTORY 10 | 11 | ./emscripten-build.sh 12 | 13 | cd $DIRECTORY/../bin-emscripten/bin 14 | 15 | echo hosting build at http://localhost:8000 16 | 17 | python3 -m http.server 18 | -------------------------------------------------------------------------------- /core/scene/Transform.h: -------------------------------------------------------------------------------- 1 | #ifndef TRANSFORM_H 2 | #define TRANSFORM_H 3 | 4 | #include "../math/Vector2.h" 5 | 6 | struct Transform { 7 | public: 8 | Vector2f rotation; // this is the vector pointing to the up 9 | Vector2f scale; 10 | Vector2f position; 11 | 12 | Transform(); 13 | Transform(Vector2f position, Vector2f scale, Vector2f rotation); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cmake/subdirlist.cmake: -------------------------------------------------------------------------------- 1 | macro(SUBDIRLIST result curdir) 2 | file( 3 | GLOB children CONFIGURE_DEPENDS 4 | RELATIVE ${curdir} 5 | ${curdir}/* 6 | ) 7 | set(dirlist "") 8 | foreach(child ${children}) 9 | if(IS_DIRECTORY ${curdir}/${child}) 10 | list(APPEND dirlist ${child}) 11 | endif() 12 | endforeach() 13 | set(${result} ${dirlist}) 14 | endmacro() 15 | -------------------------------------------------------------------------------- /examples/chess/pieces/Queen.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_QUEEN_H 2 | #define CHESS_QUEEN_H 3 | 4 | #include "../WorldState.h" 5 | #include 6 | struct Queen { 7 | static unordered_set AttackMoves(WorldState& world, const Point2D& origin); 8 | static unordered_set CoverMoves(WorldState& world, const Point2D& origin); 9 | }; 10 | 11 | #endif // MOBAGEN_QUEEN_H 12 | -------------------------------------------------------------------------------- /external/zlib.cmake: -------------------------------------------------------------------------------- 1 | # zlib 2 | string(TIMESTAMP BEFORE "%s") 3 | CPMAddPackage("gh:madler/zlib#v1.2.13") 4 | string(TIMESTAMP AFTER "%s") 5 | math(EXPR DELTAzlib "${AFTER} - ${BEFORE}") 6 | message(STATUS "zlib TIME: ${DELTAzlib}s") 7 | if(zlib_ADDED) 8 | include_directories(${zlib_SOURCE_DIR}/include) 9 | else() 10 | message(FATAL_ERROR "zlib not configured correctly") 11 | endif() 12 | -------------------------------------------------------------------------------- /examples/chess/pieces/Knight.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_KNIGHT_H 2 | #define CHESS_KNIGHT_H 3 | 4 | #include "../WorldState.h" 5 | #include 6 | struct Knight { 7 | static unordered_set AttackMoves(WorldState& world, const Point2D& origin); 8 | static unordered_set CoverMoves(WorldState& world, const Point2D& origin); 9 | }; 10 | 11 | #endif // CHESS_KNIGHT_H 12 | -------------------------------------------------------------------------------- /scripts/emscripten-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | echo $DIR 6 | 7 | git clone https://github.com/emscripten-core/emsdk.git $DIR/../external/emsdk/ 8 | 9 | $DIR/../external/emsdk/emsdk install latest 10 | $DIR/../external/emsdk/emsdk activate latest 11 | 12 | read -t 5 -p "I am going to wait for 5 seconds only ..." 13 | -------------------------------------------------------------------------------- /core/math/Vector3.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR3_H 2 | #define VECTOR3_H 3 | 4 | // 5 | // just a vector3 simple 6 | struct Vector3 { 7 | float x; 8 | float y; 9 | float z; 10 | 11 | Vector3() { 12 | x = 0; 13 | y = 0; 14 | z = 0; 15 | } 16 | 17 | Vector3(float x, float y, float z) { 18 | this->x = x; 19 | this->y = y; 20 | this->z = z; 21 | } 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /examples/catchthecat/Catcher.cpp: -------------------------------------------------------------------------------- 1 | #include "Catcher.h" 2 | #include "World.h" 3 | 4 | Point2D Catcher::Move(World* world) { 5 | auto side = world->getWorldSideSize() / 2; 6 | for (;;) { 7 | Point2D p = {Random::Range(-side, side), Random::Range(-side, side)}; 8 | auto cat = world->getCat(); 9 | if (cat.x != p.x && cat.y != p.y && !world->getContent(p)) return p; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/scene/Transform.cpp: -------------------------------------------------------------------------------- 1 | #include "Transform.h" 2 | 3 | Transform::Transform() { 4 | this->scale = Vector2f::identity(); 5 | this->position = Vector2f::zero(); 6 | this->rotation = Vector2f::zero(); 7 | } 8 | 9 | Transform::Transform(Vector2f position, Vector2f scale, Vector2f rotation) { 10 | this->position = position; 11 | this->scale = scale; 12 | this->rotation = rotation; 13 | } 14 | -------------------------------------------------------------------------------- /examples/chess/pieces/Rook.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_TOWER_H 2 | #define CHESS_TOWER_H 3 | 4 | #include "../WorldState.h" 5 | #include 6 | #include 7 | struct Rook { 8 | static unordered_set AttackMoves(WorldState& world, const Point2D& origin); 9 | static unordered_set CoverMoves(WorldState& world, const Point2D& origin); 10 | }; 11 | 12 | #endif // CHESS_TOWER_H 13 | -------------------------------------------------------------------------------- /examples/scenario/GeneratorBase.h: -------------------------------------------------------------------------------- 1 | #ifndef SCENARIOGENERATORBASE_H 2 | #define SCENARIOGENERATORBASE_H 3 | #include "math/ColorT.h" 4 | #include 5 | #include 6 | 7 | class ScenarioGeneratorBase { 8 | public: 9 | virtual std::vector Generate(int sideSize, float displacement = 0) = 0; 10 | virtual std::string GetName() = 0; 11 | }; 12 | 13 | #endif // SCENARIOGENERATORBASE_H 14 | -------------------------------------------------------------------------------- /scripts/emscripten-install-permanent.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | echo $DIR 6 | 7 | git clone https://github.com/emscripten-core/emsdk.git $DIR/../external/emsdk/ 8 | 9 | $DIR/../external/emsdk/emsdk install latest 10 | $DIR/../external/emsdk/emsdk activate latest --permanent 11 | 12 | read -t 5 -p "I am going to wait for 5 seconds only ..." 13 | -------------------------------------------------------------------------------- /core/scene/GameObject.cpp: -------------------------------------------------------------------------------- 1 | #include "GameObject.h" 2 | #include "../engine/Engine.h" 3 | 4 | GameObject::GameObject(Engine* pEngine) : engine(pEngine), Object() { 5 | // todo: use a scene manager approach to this 6 | // todo: this addition should be done only on the end of the frame. it should not be committed now. given this engine is still single threaded, it 7 | engine->gameObjectsToBeStarted.emplace(this); 8 | } 9 | -------------------------------------------------------------------------------- /external/mbedtls.cmake: -------------------------------------------------------------------------------- 1 | # mbedtls 2 | string(TIMESTAMP BEFORE "%s") 3 | CPMAddPackage("gh:Mbed-TLS/mbedtls#v3.3.0") 4 | string(TIMESTAMP AFTER "%s") 5 | math(EXPR DELTAmbedtls "${AFTER} - ${BEFORE}") 6 | message(STATUS "mbedtls TIME: ${DELTAmbedtls}s") 7 | if(mbedtls_ADDED) 8 | include_directories(${mbedtls_SOURCE_DIR}/include) 9 | else() 10 | message(FATAL_ERROR "mbedtls not configured correctly") 11 | endif() 12 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/CohesionRule.cpp: -------------------------------------------------------------------------------- 1 | #include "CohesionRule.h" 2 | #include "../gameobjects/Boid.h" 3 | 4 | Vector2f CohesionRule::computeForce(const std::vector& neighborhood, Boid* boid) { 5 | Vector2f cohesionForce; 6 | 7 | // todo: add your code here to make a force towards the center of mass 8 | // hint: iterate over the neighborhood 9 | 10 | // find center of mass 11 | 12 | return cohesionForce; 13 | } -------------------------------------------------------------------------------- /examples/scenario/generators/RandomGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_RANDOMSCENARIOGENERATOR_H 2 | #define MOBAGEN_RANDOMSCENARIOGENERATOR_H 3 | 4 | #include "../GeneratorBase.h" 5 | 6 | class RandomScenarioGenerator : public ScenarioGeneratorBase { 7 | public: 8 | std::vector Generate(int sideSize, float displacement = 0) override; 9 | std::string GetName() override; 10 | }; 11 | 12 | #endif // MOBAGEN_RANDOMSCENARIOGENERATOR_H 13 | -------------------------------------------------------------------------------- /examples/life/RuleBase.h: -------------------------------------------------------------------------------- 1 | #ifndef LIFE_RULEBASE_H 2 | #define LIFE_RULEBASE_H 3 | 4 | // reference https://playgameoflife.com/info 5 | 6 | #include "World.h" 7 | #include "GameOfLifeTileSetEnum.h" 8 | class RuleBase { 9 | public: 10 | virtual ~RuleBase() = default; 11 | virtual void Step(World& world) = 0; 12 | virtual std::string GetName() = 0; 13 | virtual GameOfLifeTileSetEnum GetTileSet() = 0; 14 | }; 15 | 16 | #endif // MOBAGEN_RULEBASE_H 17 | -------------------------------------------------------------------------------- /external/filament.cmake: -------------------------------------------------------------------------------- 1 | # https://github.com/google/filament.git SET(ENABLE_PCH OFF CACHE BOOL "ENABLE_PCH") 2 | set_property(GLOBAL PROPERTY SKIP_PRECOMPILE_HEADERS ON) 3 | set_property(GLOBAL PROPERTY DISABLE_PRECOMPILE_HEADERS ON) 4 | CPMAddPackage( 5 | GITHUB_REPOSITORY google/filament 6 | GIT_TAG v1.29.0 7 | OPTIONS "ENABLE_PCH OFF" "ENABLE_OPT OFF" 8 | ) 9 | find_package(filament REQUIRED) 10 | if(filament_ADDED) 11 | message(STATUS filament_ADDED) 12 | endif() 13 | -------------------------------------------------------------------------------- /test/GameObjects.tests.cpp: -------------------------------------------------------------------------------- 1 | // #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 2 | // 3 | // #include 4 | // #include "engine/Engine.h" 5 | // #include "scene/GameObject.h" 6 | // 7 | ////TEST_CASE("Test GameObjects") { 8 | //// auto engine = new Engine(); 9 | //// if (engine->Start("Test engine")) { 10 | //// new GameObject(engine); 11 | //// engine->Run(); 12 | //// } 13 | //// engine->Exit(); 14 | //// delete engine; 15 | //// engine = nullptr; 16 | ////} -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Editor demo
4 | Flocking demo
5 | Catch the cat demo
6 | Maze Generation demo
7 | Scenario Generation demo
8 | Game Of Life demo
9 | Chess demo
10 | Hide And Seek demo
11 | 12 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/AlignmentRule.cpp: -------------------------------------------------------------------------------- 1 | #include "AlignmentRule.h" 2 | #include "../gameobjects/Boid.h" 3 | 4 | Vector2f AlignmentRule::computeForce(const std::vector& neighborhood, Boid* boid) { 5 | // Try to match the heading of neighbors = Average velocity 6 | Vector2f averageVelocity = Vector2f::zero(); 7 | 8 | // todo: add your code here to align each boid in a neighborhood 9 | // hint: iterate over the neighborhood 10 | 11 | return Vector2f::normalized(averageVelocity); 12 | } -------------------------------------------------------------------------------- /modules/time/Time.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2024.06.11. 3 | // 4 | 5 | #include 6 | #include "TimeDefs.h" 7 | #include "Time.h" 8 | namespace MoBaGEn::TimeManager { 9 | Duration Time::GetElapsedTime() { return Now() - startTime(); } 10 | 11 | TimePoint Time::Now() { return std::chrono::high_resolution_clock::now(); } 12 | TimePoint Time::startTime() { 13 | static const auto time = Now(); 14 | return time; 15 | } 16 | } // namespace MoBaGEn::TimeManager -------------------------------------------------------------------------------- /examples/chess/pieces/King.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_KING_H 2 | #define CHESS_KING_H 3 | #include "../WorldState.h" 4 | #include 5 | 6 | struct King { 7 | static unordered_set AttackMoves(WorldState& world, const Point2D& origin); 8 | static unordered_set CoverMovesNaive(WorldState& world, const Point2D& origin); 9 | static auto FindKing(WorldState& state, PieceColor color) -> Point2D; 10 | static auto IsInCheck(WorldState& state, PieceColor color) -> int; 11 | }; 12 | 13 | #endif // MOBAGEN_KING_H 14 | -------------------------------------------------------------------------------- /editor/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "TopBar.h" 4 | #include 5 | 6 | // Main code 7 | int main(int, char**) { 8 | SDL_Log("Creating Engine"); 9 | auto engine = new Engine(); 10 | SDL_Log("Engine Created"); 11 | new TopBar(); 12 | 13 | SDL_Log("Starting Engine"); 14 | if (engine->Start("Editor")) { 15 | SDL_Log("Engine Started"); 16 | engine->Run(); 17 | } 18 | 19 | SDL_Log("Exiting Engine"); 20 | engine->Exit(); 21 | SDL_Log("Engine Exited"); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /examples/life/rules/JohnConway.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_JOHNCONWAY_H 2 | #define MOBAGEN_JOHNCONWAY_H 3 | #include "../RuleBase.h" 4 | 5 | class JohnConway : public RuleBase { 6 | public: 7 | explicit JohnConway() = default; 8 | ~JohnConway() override = default; 9 | std::string GetName() override { return "JohnConway"; } 10 | void Step(World& world) override; 11 | int CountNeighbors(World& world, Point2D point); 12 | GameOfLifeTileSetEnum GetTileSet() override { return GameOfLifeTileSetEnum::Square; }; 13 | }; 14 | 15 | #endif // MOBAGEN_JOHNCONWAY_H 16 | -------------------------------------------------------------------------------- /scripts/win-set-env-vars.bat: -------------------------------------------------------------------------------- 1 | :: Check privileges 2 | net file 1>NUL 2>NUL 3 | if not '%errorlevel%' == '0' ( 4 | powershell Start-Process -FilePath "%0" -ArgumentList "%cd%" -verb runas >NUL 2>&1 5 | exit /b 6 | ) 7 | 8 | :: Change directory with passed argument. Processes started with 9 | :: "runas" start with forced C:\Windows\System32 workdir 10 | cd /d %1 11 | 12 | cd ..\external\emsdk\ 13 | cmd /c emsdk.bat install latest 14 | timeout 3 15 | 16 | cmd /c emsdk.bat activate latest --system 17 | echo "restarting" 18 | timeout 10 19 | 20 | shutdown /r -------------------------------------------------------------------------------- /examples/maze/MazeGeneratorBase.h: -------------------------------------------------------------------------------- 1 | #ifndef MAZEGENERATORBASE_H 2 | #define MAZEGENERATORBASE_H 3 | 4 | #include 5 | 6 | class World; 7 | 8 | class MazeGeneratorBase { 9 | public: 10 | MazeGeneratorBase() = default; 11 | virtual std::string GetName() = 0; 12 | // Step should return true if it made changes in the world 13 | virtual bool Step(World* world) = 0; 14 | // Clears and resets all data from the generator 15 | virtual void Clear(World* world) = 0; 16 | virtual ~MazeGeneratorBase() = default; 17 | }; 18 | 19 | #endif // MAZEGENERATORBASE_H 20 | -------------------------------------------------------------------------------- /examples/catchthecat/Cat.cpp: -------------------------------------------------------------------------------- 1 | #include "Cat.h" 2 | #include "World.h" 3 | #include 4 | 5 | Point2D Cat::Move(World* world) { 6 | auto rand = Random::Range(0, 5); 7 | auto pos = world->getCat(); 8 | switch (rand) { 9 | case 0: 10 | return World::NE(pos); 11 | case 1: 12 | return World::NW(pos); 13 | case 2: 14 | return World::E(pos); 15 | case 3: 16 | return World::W(pos); 17 | case 4: 18 | return World::SW(pos); 19 | case 5: 20 | return World::SE(pos); 21 | default: 22 | throw "random out of range"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/hideandseeksquared/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB HIDEANDSEEK_INC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h 2 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 3 | ) 4 | 5 | file(GLOB HIDEANDSEEK_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 7 | ) 8 | 9 | install(FILES ${HIDEANDSEEK_INC} DESTINATION include/hideandseek) 10 | 11 | add_executable(hideandseek ${HIDEANDSEEK_SRC} ${HIDEANDSEEK_INC}) 12 | 13 | target_include_directories(hideandseek PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 14 | target_link_libraries(hideandseek PUBLIC SDL2-static IMGUI core) 15 | -------------------------------------------------------------------------------- /examples/chess/Search.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_SEARCH_H 2 | #define MOBAGEN_SEARCH_H 3 | 4 | #include "WorldState.h" 5 | 6 | struct Search { 7 | // todo: create your algorithm to calculate next move 8 | static Move NextMove(WorldState& state); 9 | /** 10 | * @param state world state 11 | * @param currentPlayer calculate the current turn possible moves 12 | * @return 13 | */ 14 | static auto ListPlacesKingCannotGo(WorldState& state, PieceColor turn) -> unordered_set; 15 | static auto ListMoves(WorldState& state, PieceColor turn) -> std::vector; 16 | }; 17 | 18 | #endif // MOBAGEN_SEARCH_H 19 | -------------------------------------------------------------------------------- /examples/headless/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file( 2 | GLOB 3 | HEADLESS_INC 4 | CONFIGURE_DEPENDS 5 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 7 | ) 8 | 9 | file( 10 | GLOB 11 | HEADLESS_SRC 12 | CONFIGURE_DEPENDS 13 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 14 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 15 | ) 16 | 17 | install(FILES ${HEADLESS_INC} DESTINATION include/headless) 18 | 19 | add_executable(headless ${HEADLESS_SRC} ${HEADLESS_INC}) 20 | 21 | target_include_directories(headless PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 22 | target_link_libraries(headless PUBLIC SDL2-static IMGUI core) -------------------------------------------------------------------------------- /documentation/Networking.md: -------------------------------------------------------------------------------- 1 | # HTTP 2 | 3 | In order to work with https, we would need a lib to provide ssl/tls/crypto implementations. Given that, the first lib that come into my mind is OpenSSL. 4 | 5 | OpenSSL have many issues. Ex.: in order to build it, we need to have Perl scripting... 6 | 7 | So we need to look for options. 8 | 9 | - LibreSSL provides same bindings and it is compatible with OpenSSL interfaces. So it could be a good option. 10 | - BoringSSL 11 | - mbedtls 12 | 13 | https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations 14 | 15 | https://www.amongbytes.com/post/201804-comparing-mbedtls-to-boringssl/ 16 | -------------------------------------------------------------------------------- /examples/chess/Heuristics.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_HEURISTICS_H 2 | #define MOBAGEN_HEURISTICS_H 3 | 4 | #include 5 | #include "WorldStateFwd.h" // forward is needed here to avoid collisions 6 | #include "math/Point2D.h" 7 | 8 | struct Heuristics { 9 | public: 10 | inline float Score() const { return score; }; 11 | static int MaterialScore(WorldState* state); 12 | 13 | private: 14 | // positive score means white is winning 15 | float score; 16 | 17 | static int distanceToCenter(Point2D location); 18 | 19 | public: 20 | static Heuristics BoardAnalysis(WorldState* state); 21 | }; 22 | 23 | #endif // MOBAGEN_HEURISTICS_H 24 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: "*, 3 | -abseil-*, 4 | -altera-*, 5 | -android-*, 6 | -fuchsia-*, 7 | -google-*, 8 | -llvm*, 9 | -modernize-use-trailing-return-type, 10 | -zircon-*, 11 | -readability-else-after-return, 12 | -readability-static-accessed-through-instance, 13 | -readability-avoid-const-params-in-decls, 14 | -cppcoreguidelines-non-private-member-variables-in-classes, 15 | -misc-non-private-member-variables-in-classes, 16 | " 17 | WarningsAsErrors: '' 18 | HeaderFilterRegex: '' 19 | FormatStyle: none 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/chess/pieces/Pawn.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_PAWN_H 2 | #define CHESS_PAWN_H 3 | 4 | #include "../WorldState.h" 5 | #include "Polygon.h" 6 | #include 7 | struct Pawn { 8 | public: 9 | static unordered_set PossibleMoves(WorldState& world, const Point2D& origin); 10 | static unordered_set AttackMoves(WorldState& world, const Point2D& origin); 11 | static unordered_set CoverMoves(WorldState& world, const Point2D& origin); 12 | static int CountDoubles(WorldState& world, const Point2D& origin); 13 | static bool IsIsolated(WorldState& world, const Point2D& origin); 14 | }; 15 | 16 | #endif // MOBAGEN_PAWN_H 17 | -------------------------------------------------------------------------------- /examples/life/rules/HexagonGameOfLife.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_EXAMPLES_LIFE_RULES_HEXAGONGAMEOFLIFE_H_ 2 | #define MOBAGEN_EXAMPLES_LIFE_RULES_HEXAGONGAMEOFLIFE_H_ 3 | 4 | #include "../RuleBase.h" 5 | class HexagonGameOfLife : public RuleBase { 6 | public: 7 | explicit HexagonGameOfLife() = default; 8 | ~HexagonGameOfLife() override = default; 9 | std::string GetName() override { return "Hexagon"; } 10 | void Step(World& world) override; 11 | int CountNeighbors(World& world, Point2D point); 12 | GameOfLifeTileSetEnum GetTileSet() override { return GameOfLifeTileSetEnum::Hexagon; }; 13 | }; 14 | 15 | #endif // MOBAGEN_EXAMPLES_LIFE_RULES_HEXAGONGAMEOFLIFE_H_ 16 | -------------------------------------------------------------------------------- /modules/time/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # set(BUILD_SHARED_LIBS FALSE) 2 | 3 | # todo: isolate interfaces in a folder so you can use other time implementations 4 | file( 5 | GLOB_RECURSE TIME_INC CONFIGURE_DEPENDS 6 | RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 7 | *.h *.hpp 8 | ) 9 | 10 | file( 11 | GLOB_RECURSE TIME_SRC CONFIGURE_DEPENDS 12 | RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 13 | *.c *.cpp 14 | ) 15 | 16 | set(TIME_INC_DIR 17 | ${CMAKE_CURRENT_SOURCE_DIR} 18 | CACHE PATH "TIME INCLUDE SOURCE PATH" 19 | ) 20 | 21 | add_library(time STATIC ${TIME_SRC} ${TIME_INC}) 22 | 23 | install(TARGETS time DESTINATION lib) 24 | install(FILES ${TIME_INC} DESTINATION include/time) 25 | -------------------------------------------------------------------------------- /external/cpr.cmake: -------------------------------------------------------------------------------- 1 | # cpr 2 | string(TIMESTAMP BEFORE "%s") 3 | set(CURL_CA_FALLBACK 4 | ON 5 | CACHE INTERNAL " " FORCE 6 | ) # Workaround for failing SSL requests 7 | CPMAddPackage( 8 | GITHUB_REPOSITORY libcpr/cpr 9 | GIT_TAG 1.10.1 10 | OPTIONS "CPR_ENABLE_SSL ON" "CPR_FORCE_MBEDTLS_BACKEND ON" "CURL_USE_MBEDTLS ON" 11 | ) 12 | string(TIMESTAMP AFTER "%s") 13 | math(EXPR DELTAcpr "${AFTER} - ${BEFORE}") 14 | message(STATUS "cpr TIME: ${DELTAcpr}s") 15 | if(cpr_ADDED) 16 | include_directories(${cpr_SOURCE_DIR}/include) 17 | include_directories(${cpr_BUILD_DIR}/cpr_generated_includes) 18 | else() 19 | message(FATAL_ERROR "cpr not configured correctly") 20 | endif() 21 | -------------------------------------------------------------------------------- /examples/maze/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "World.h" 4 | 5 | int main() { 6 | SDL_Log("Creating Engine"); 7 | auto engine = new Engine(); 8 | SDL_Log("Engine Created"); 9 | 10 | SDL_Log("Creating World Object"); 11 | new World(engine, 21); 12 | SDL_Log("World Created"); 13 | 14 | SDL_Log("Starting Engine"); 15 | if (engine->Start("Maze")) { 16 | SDL_Log("Engine Started"); 17 | SDL_Log("Running Engine"); 18 | engine->Run(); 19 | SDL_Log("Engine Stopped"); 20 | } 21 | 22 | SDL_Log("Exiting Engine"); 23 | engine->Exit(); 24 | delete engine; 25 | SDL_Log("Engine Exited"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/NullRenderer.tests.cpp: -------------------------------------------------------------------------------- 1 | // #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 2 | // 3 | // #include 4 | // #include "engine/Engine.h" 5 | // #include "scene/GameObject.h" 6 | // 7 | // class Quitter : public GameObject { 8 | // public: 9 | // explicit Quitter(Engine* pEngine) : GameObject(pEngine){}; 10 | // void Update(float time) override { engine->Exit(); } 11 | // }; 12 | // 13 | // TEST_CASE("Engine should run without Renderering") { 14 | // auto* engine = new Engine(); 15 | // if (engine->Start("Test engine")) { 16 | // new Quitter(engine); 17 | // engine->Run(); 18 | // } 19 | // engine->Exit(); 20 | // delete engine; 21 | // engine = nullptr; 22 | // } -------------------------------------------------------------------------------- /examples/flocking/behaviours/WindRule.cpp: -------------------------------------------------------------------------------- 1 | #include "WindRule.h" 2 | #include 3 | #include "../gameobjects/Boid.h" 4 | #include "../gameobjects/World.h" 5 | #include "engine/Engine.h" 6 | 7 | Vector2f WindRule::computeForce(const std::vector& neighborhood, Boid* boid) { 8 | // todo: add a wind force here 9 | // hint: use the windAngle variable 10 | return Vector2f::zero(); 11 | } 12 | 13 | bool WindRule::drawImguiRuleExtra() { 14 | ImGui::SetCurrentContext(world->engine->window->imGuiContext); 15 | bool valueHasChanged = false; 16 | 17 | if (ImGui::SliderAngle("Wind Direction", &windAngle, 0)) { 18 | valueHasChanged = true; 19 | } 20 | 21 | return valueHasChanged; 22 | } -------------------------------------------------------------------------------- /examples/flocking/utils/ImGuiExtra.h: -------------------------------------------------------------------------------- 1 | #ifndef IMGUIEXTRA_H 2 | #define IMGUIEXTRA_H 3 | 4 | #include 5 | #include 6 | #include "imgui.h" 7 | #include 8 | 9 | // Plot value over time 10 | // Pass FLT_MAX value to draw without adding a new value 11 | void PlotVar(const char* label, float value, float scale_min = FLT_MAX, float scale_max = FLT_MAX, std::size_t buffer_size = 120); 12 | 13 | // Call this periodically to discard old/unused data 14 | void PlotVarFlushOldEntries(); 15 | 16 | // Tooltip from imgui_demo 17 | void HelpMarker(const char* desc); 18 | 19 | void ImguiTooltip(const char* desc); 20 | 21 | // From Avoid/Doug Binks 22 | void SetupImGuiStyle(); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /modules/time/Time.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2024.06.11. 3 | // 4 | 5 | #ifndef MOBAGEN_TIME_H 6 | #define MOBAGEN_TIME_H 7 | 8 | #include "TimeDefs.h" 9 | 10 | namespace MoBaGEn::TimeManager { 11 | class Time { 12 | public: 13 | /** 14 | * @brief Get the current wall time 15 | * @return TimePoint 16 | */ 17 | static TimePoint Now(); 18 | 19 | private: 20 | static TimePoint startTime(); 21 | 22 | public: 23 | /** 24 | * @brief Get the Elapsed Time since the start of the program 25 | * @return Duration 26 | */ 27 | static Duration GetElapsedTime(); 28 | }; 29 | } // namespace MoBaGEn::TimeManager 30 | #endif // MOBAGEN_TIME_H 31 | -------------------------------------------------------------------------------- /examples/life/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "Manager.h" 4 | 5 | // Main code 6 | int main(int, char**) { 7 | SDL_Log("Creating Engine"); 8 | auto engine = new Engine(); 9 | SDL_Log("Engine Created"); 10 | 11 | SDL_Log("Creating World Object"); 12 | new Manager(engine); 13 | SDL_Log("World Created"); 14 | 15 | SDL_Log("Starting Engine"); 16 | if (engine->Start("Scenario")) { 17 | SDL_Log("Engine Started"); 18 | 19 | SDL_Log("Running Engine"); 20 | engine->Run(); 21 | SDL_Log("Engine Stopped"); 22 | } 23 | 24 | SDL_Log("Exiting Engine"); 25 | engine->Exit(); 26 | delete engine; 27 | SDL_Log("Engine Exited"); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /examples/chess/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "Manager.h" 4 | 5 | // Main code 6 | int main(int, char**) { 7 | SDL_Log("Creating Engine"); 8 | auto engine = new Engine(); 9 | SDL_Log("Engine Created"); 10 | 11 | SDL_Log("Starting Engine"); 12 | if (engine->Start("Scenario")) { 13 | SDL_Log("Engine Started"); 14 | 15 | SDL_Log("Creating World Object"); 16 | new Manager(engine); 17 | SDL_Log("World Created"); 18 | 19 | SDL_Log("Running Engine"); 20 | engine->Run(); 21 | SDL_Log("Engine Stopped"); 22 | } 23 | 24 | SDL_Log("Exiting Engine"); 25 | engine->Exit(); 26 | delete engine; 27 | SDL_Log("Engine Exited"); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /examples/scenario/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "Manager.h" 4 | 5 | // Main code 6 | int main(int, char**) { 7 | SDL_Log("Creating Engine"); 8 | auto engine = new Engine(); 9 | SDL_Log("Engine Created"); 10 | 11 | SDL_Log("Creating World Object"); 12 | new Manager(engine, 21); 13 | SDL_Log("World Created"); 14 | 15 | SDL_Log("Starting Engine"); 16 | if (engine->Start("Scenario")) { 17 | SDL_Log("Engine Started"); 18 | 19 | SDL_Log("Running Engine"); 20 | engine->Run(); 21 | SDL_Log("Engine Stopped"); 22 | } 23 | 24 | SDL_Log("Exiting Engine"); 25 | engine->Exit(); 26 | delete engine; 27 | SDL_Log("Engine Exited"); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /examples/hideandseeksquared/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "Manager.h" 4 | 5 | // Main code 6 | int main(int, char**) { 7 | SDL_Log("Creating Engine"); 8 | auto engine = new Engine(); 9 | SDL_Log("Engine Created"); 10 | 11 | SDL_Log("Creating World Object"); 12 | new Manager(engine); 13 | SDL_Log("World Created"); 14 | 15 | SDL_Log("Starting Engine"); 16 | if (engine->Start("Scenario")) { 17 | SDL_Log("Engine Started"); 18 | 19 | SDL_Log("Running Engine"); 20 | engine->Run(); 21 | SDL_Log("Engine Stopped"); 22 | } 23 | 24 | SDL_Log("Exiting Engine"); 25 | engine->Exit(); 26 | delete engine; 27 | SDL_Log("Engine Exited"); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /core/datastructures/concepts.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_CONCEPTS_H 2 | #define MOBAGEN_CONCEPTS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | concept HashableConcept = requires(T a) { 10 | { std::hash{}(a) } -> std::convertible_to; 11 | }; 12 | 13 | template 14 | concept IntegralConcept = std::integral; 15 | 16 | template 17 | concept FloatConcept = std::floating_point; 18 | 19 | template 20 | concept NumberConcept = std::integral || std::floating_point; 21 | 22 | template 23 | concept SortableConcept = requires(T a, T b) { 24 | { a < b } -> std::convertible_to; 25 | }; 26 | 27 | #endif // MOBAGEN_CONCEPTS_H 28 | -------------------------------------------------------------------------------- /examples/life/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file( 2 | GLOB 3 | LIFE_INC 4 | CONFIGURE_DEPENDS 5 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/rules/*.h 8 | ${CMAKE_CURRENT_SOURCE_DIR}/rules/*.hpp 9 | ) 10 | 11 | file( 12 | GLOB 13 | LIFE_SRC 14 | CONFIGURE_DEPENDS 15 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 16 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 17 | ${CMAKE_CURRENT_SOURCE_DIR}/rules/*.cpp 18 | ${CMAKE_CURRENT_SOURCE_DIR}/rules/*.c 19 | ) 20 | 21 | install(FILES ${LIFE_INC} DESTINATION include/life) 22 | 23 | add_executable(life ${LIFE_SRC} ${LIFE_INC}) 24 | 25 | target_include_directories(life PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 26 | target_link_libraries(life PUBLIC SDL2-static IMGUI core) 27 | -------------------------------------------------------------------------------- /core/Random.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOM_H 2 | #define RANDOM_H 3 | 4 | #include 5 | 6 | struct Random { 7 | // inclusive 8 | static float Range(float start, float end) { 9 | if (start == end) return start; 10 | std::random_device rd; // todo: random device is slow and the seed should be cached 11 | std::mt19937 mt(rd()); 12 | std::uniform_real_distribution dist(start, end); 13 | return dist(mt); 14 | } 15 | 16 | static int Range(int start, int end) { 17 | if (start == end) return start; 18 | std::random_device rd; // todo: random device is slow and the seed should be cached 19 | std::mt19937 rng(rd()); 20 | std::uniform_int_distribution dist(start, end); 21 | return dist(rng); 22 | } 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /examples/maze/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file( 2 | GLOB 3 | MAZE_INC 4 | CONFIGURE_DEPENDS 5 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.h 8 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.hpp 9 | ) 10 | 11 | file( 12 | GLOB 13 | MAZE_SRC 14 | CONFIGURE_DEPENDS 15 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 16 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 17 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.cpp 18 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.c 19 | ) 20 | 21 | install(FILES ${MAZE_INC} DESTINATION include/maze) 22 | 23 | add_executable(maze ${MAZE_SRC} ${MAZE_INC}) 24 | 25 | target_include_directories(maze PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 26 | target_link_libraries(maze PUBLIC SDL2-static IMGUI core) 27 | -------------------------------------------------------------------------------- /examples/flocking/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "gameobjects/World.h" 4 | 5 | // Reference https://github.com/boardtobits/flocking-algorithm 6 | 7 | // Main code 8 | int main(int, char**) { 9 | SDL_Log("Creating Engine"); 10 | auto engine = new Engine(); 11 | SDL_Log("Engine Created"); 12 | 13 | SDL_Log("Creating World Object"); 14 | new World(engine); 15 | SDL_Log("World Created"); 16 | 17 | SDL_Log("Starting Engine"); 18 | if (engine->Start("Flocking")) { 19 | SDL_Log("Engine Started"); 20 | 21 | SDL_Log("Running Engine"); 22 | engine->Run(); 23 | SDL_Log("Engine Stopped"); 24 | } 25 | 26 | SDL_Log("Exiting Engine"); 27 | engine->Exit(); 28 | SDL_Log("Engine Exited"); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /core/WebRequest.cpp: -------------------------------------------------------------------------------- 1 | // #include "WebRequest.h" 2 | // #ifndef __EMSCRIPTEN__ 3 | // # include "cpr/cpr.h" 4 | // #endif 5 | // 6 | //// ref.: see https://github.com/libcpr/cpr/blob/master/test/post_tests.cpp 7 | // WebRequest::WebRequest(std::string uri, WebRequestVerb verb = WebRequestVerb::GET, std::map headers = {}) { 8 | // #ifndef __EMSCRIPTEN__ 9 | // cpr::Payload payload{}; 10 | // cpr::Session session; 11 | // cpr::Header header; 12 | // session.SetVerifySsl(false); // todo: find a way to not pass verifyssl 13 | // for (auto pair : headers) header.emplace(pair.first, pair.second); 14 | // session.SetHeader(header); 15 | // cpr::Response r; 16 | // if (verb == WebRequestVerb::GET) { 17 | // r = session.Get(); 18 | // } 19 | // #endif 20 | // } 21 | -------------------------------------------------------------------------------- /documentation/TimeManager.md: -------------------------------------------------------------------------------- 1 | # Game loop and time management 2 | 3 | In a game engine we commonly have 2 types of time management for the game loop. One for fixed time step and another one for variable time step. Let's discuss the differences between them. 4 | 5 | ## Game loop with fixed time step 6 | 7 | In the fixed time step, we run things that expect to happen in a constant rate, such as rendering that follows the monitor refresh rate, or network sync update running 5 times per second. 8 | 9 | ## Game loop with variable time step 10 | 11 | In a variable time step, the game loop run as fast as the computer permits. This offers a smoothen experience to the user. 12 | 13 | ## Time manager 14 | 15 | The time manager is responsible for triggering the different game loops and managing time for the game. -------------------------------------------------------------------------------- /external/curl.cmake: -------------------------------------------------------------------------------- 1 | # curl 2 | string(TIMESTAMP BEFORE "%s") 3 | 4 | CPMAddPackage( 5 | GITHUB_REPOSITORY curl/curl 6 | # GIT_TAG curl-7_88_1 7 | GIT_TAG curl-7_80_0 8 | OPTIONS "CURL_USE_MBEDTLS ON" 9 | "CMAKE_USE_MBEDTLS ON" 10 | "MBEDTLS_INCLUDE_DIRS ${mbedtls_SOURCE_DIR}/include" 11 | "MBEDTLS_LIBRARY mbedtls" 12 | "MBEDX509_LIBRARY mbedcrypto" 13 | "MBEDCRYPTO_LIBRARY mbedx509" 14 | "BUILD_TESTING OFF" 15 | "CURL_CA_FALLBACK 1" 16 | ) 17 | string(TIMESTAMP AFTER "%s") 18 | math(EXPR DELTAcurl "${AFTER} - ${BEFORE}") 19 | message(STATUS "curl TIME: ${DELTAcurl}s") 20 | if(curl_ADDED) 21 | include_directories(${curl_SOURCE_DIR}/include) 22 | else() 23 | message(FATAL_ERROR "curl not configured correctly") 24 | endif() 25 | -------------------------------------------------------------------------------- /examples/chess/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file( 2 | GLOB 3 | CHESS_INC 4 | CONFIGURE_DEPENDS 5 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/pieces/*.h 8 | ${CMAKE_CURRENT_SOURCE_DIR}/pieces/*.hpp 9 | ) 10 | 11 | file( 12 | GLOB 13 | CHESS_SRC 14 | CONFIGURE_DEPENDS 15 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 16 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 17 | ${CMAKE_CURRENT_SOURCE_DIR}/pieces/*.cpp 18 | ${CMAKE_CURRENT_SOURCE_DIR}/pieces/*.c 19 | ) 20 | 21 | install(FILES ${CHESS_INC} DESTINATION include/chess) 22 | 23 | add_executable(chess ${CHESS_SRC} ${CHESS_INC}) 24 | 25 | target_include_directories(chess PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 26 | target_link_libraries(chess PUBLIC SDL2::SDL2 SDL2_image::SDL2_image-static IMGUI core) 27 | -------------------------------------------------------------------------------- /examples/life/Manager.h: -------------------------------------------------------------------------------- 1 | #ifndef LIFE_MANAGER_H 2 | #define LIFE_MANAGER_H 3 | 4 | #include "scene/GameObject.h" 5 | #include "RuleBase.h" 6 | #include "World.h" 7 | 8 | class Manager : GameObject { 9 | private: 10 | int sideSize = 13; 11 | World world; 12 | bool isSimulating = false; 13 | float accumulatedTime = 0; 14 | float timeBetweenSteps = 0.2f; 15 | void step(); 16 | void clear(); 17 | std::vector rules; 18 | int ruleId = 0; 19 | Point2D mousePositionToIndex(ImVec2& pos); 20 | 21 | public: 22 | explicit Manager(Engine* pEngine); 23 | ~Manager(); 24 | 25 | void Start() override; 26 | void OnGui(ImGuiContext* context) override; 27 | void OnDraw(SDL_Renderer* renderer) override; 28 | void Update(float deltaTime) override; 29 | }; 30 | 31 | #endif // MOBAGEN_MANAGER_H 32 | -------------------------------------------------------------------------------- /examples/maze/generators/RecursiveBacktrackerExample.h: -------------------------------------------------------------------------------- 1 | #ifndef RECURSIVEBACKTRACKER_H 2 | #define RECURSIVEBACKTRACKER_H 3 | 4 | #include "../MazeGeneratorBase.h" 5 | #include "math/Point2D.h" 6 | #include 7 | #include 8 | 9 | class RecursiveBacktrackerExample : public MazeGeneratorBase { 10 | private: 11 | std::vector stack; 12 | std::map> visited; // naive. not optimal 13 | Point2D randomStartPoint(World* world); 14 | std::vector getVisitables(World* w, const Point2D& p); 15 | 16 | public: 17 | RecursiveBacktrackerExample() = default; 18 | std::string GetName() override { return "Recursive Back-Tracker"; }; 19 | bool Step(World* world) override; 20 | void Clear(World* world) override; 21 | }; 22 | 23 | #endif // RECURSIVEBACKTRACKER_H 24 | -------------------------------------------------------------------------------- /examples/maze/generators/PrimExample.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_EXAMPLES_MAZE_GENERATORS_PRIMEXAMPLE_H_ 2 | #define MOBAGEN_EXAMPLES_MAZE_GENERATORS_PRIMEXAMPLE_H_ 3 | 4 | #include 5 | #include "../MazeGeneratorBase.h" 6 | #include "math/Point2D.h" 7 | #include 8 | 9 | class PrimExample : public MazeGeneratorBase { 10 | private: 11 | std::vector toBeVisited; 12 | bool initialized = false; 13 | std::vector getVisitables(World* w, const Point2D& p); 14 | std::vector getVisitedNeighbors(World* w, const Point2D& p); 15 | 16 | public: 17 | PrimExample() = default; 18 | std::string GetName() override { return "Prim"; }; 19 | bool Step(World* world) override; 20 | void Clear(World* world) override; 21 | }; 22 | 23 | #endif // MOBAGEN_EXAMPLES_MAZE_GENERATORS_PRIMEXAMPLE_H_ 24 | -------------------------------------------------------------------------------- /documentation/doxygen/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/maze/generators/HuntAndKillExample.h: -------------------------------------------------------------------------------- 1 | #ifndef HUNTANDKILLEXAMPLE_H 2 | #define HUNTANDKILLEXAMPLE_H 3 | 4 | #include "../MazeGeneratorBase.h" 5 | #include "math/Point2D.h" 6 | #include 7 | #include 8 | 9 | class HuntAndKillExample : public MazeGeneratorBase { 10 | private: 11 | std::vector stack; 12 | std::map> visited; // naive. not optimal 13 | Point2D randomStartPoint(World* world); 14 | std::vector getVisitables(World* w, const Point2D& p); 15 | std::vector getVisitedNeighbors(World* w, const Point2D& p); 16 | 17 | public: 18 | HuntAndKillExample() = default; 19 | std::string GetName() override { return "HuntAndKill"; }; 20 | bool Step(World* world) override; 21 | void Clear(World* world) override; 22 | }; 23 | 24 | #endif // HUNTANDKILLEXAMPLE_H 25 | -------------------------------------------------------------------------------- /modules/time/TimeDefs.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2024.06.11. 3 | // 4 | 5 | #ifndef MOBAGEN_TIMEDEFS_H 6 | #define MOBAGEN_TIMEDEFS_H 7 | 8 | #include 9 | 10 | namespace MoBaGEn::TimeManager { 11 | /** 12 | * @brief TimePoint is a type alias for std::chrono::time_point 13 | * @description rename std::chrono::time_point to TimePoint 14 | */ 15 | using TimePoint = std::chrono::time_point; 16 | 17 | /** 18 | * @brief Duration is a type alias for std::chrono::duration 19 | * @description rename std::chrono::duration to Duration 20 | */ 21 | using Duration = std::chrono::duration; 22 | } // namespace MoBaGEn::TimeManager 23 | 24 | #endif // MOBAGEN_TIMEDEFS_H 25 | -------------------------------------------------------------------------------- /core/script/ScriptManager.h: -------------------------------------------------------------------------------- 1 | // #ifndef MOBAGEN_SCRIPTMANAGER_H 2 | // #define MOBAGEN_SCRIPTMANAGER_H 3 | // 4 | // #include "quickjspp.hpp" 5 | // 6 | //// todo: generate bindings for quickjs. see https://github.com/ftk/quickjspp/tree/master/binding-generator 7 | // 8 | //// singleton 9 | // class ScriptManager { 10 | // public: 11 | // static ScriptManager& getInstance() { 12 | // static ScriptManager instance; 13 | // return instance; 14 | // } 15 | // ScriptManager(ScriptManager const&) = delete; 16 | // void operator=(ScriptManager const&) = delete; 17 | // ~ScriptManager() = default; 18 | // 19 | // // quickjs stuff 20 | // qjs::Runtime runtime; 21 | // qjs::Context context = qjs::Context(runtime); 22 | // 23 | // void Initialize(); 24 | // protected: 25 | // ScriptManager() = default; 26 | // }; 27 | // 28 | // #endif // MOBAGEN_SCRIPTMANAGER_H 29 | -------------------------------------------------------------------------------- /core/Texture.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_TEXTURE_H 2 | #define MOBAGEN_TEXTURE_H 3 | #include "math/Point2D.h" 4 | #include "SDL_render.h" 5 | #include "scene/Transform.h" 6 | #include 7 | 8 | // todo: make this a game object 9 | class Texture { 10 | private: 11 | SDL_Surface* surface = nullptr; 12 | SDL_Texture* texture = nullptr; 13 | 14 | public: 15 | Point2D dimensions; 16 | Vector2f scale = {1, 1}; 17 | Vector2f position = {0, 0}; 18 | 19 | public: 20 | Texture(){}; 21 | ~Texture(); 22 | 23 | void Draw(SDL_Renderer* renderer); 24 | void Draw(SDL_Renderer* renderer, Vector2f position, Vector2f scale); 25 | 26 | // todo: hide or wrap this sdl_renderer type 27 | // todo: use asset loader in order do not use strings here! 28 | static Texture* LoadSVGFromString(SDL_Renderer* renderer, const std::string& svgtxt); 29 | }; 30 | 31 | #endif // MOBAGEN_TEXTURE_H 32 | -------------------------------------------------------------------------------- /editor/gdcm.cmake: -------------------------------------------------------------------------------- 1 | # GLM 2 | string(TIMESTAMP BEFORE "%s") 3 | # todo: upgrade version to latest 4 | CPMAddPackage( 5 | NAME GDCM 6 | GITHUB_REPOSITORY malaterre/GDCM 7 | GIT_TAG v2.8.9 8 | OPTIONS "GDCM_BUILD_SHARED_LIBS OFF" 9 | "GDCM_DOCUMENTATION OFF" 10 | "GDCM_BUILD_DOCBOOK_MANPAGES OFF" 11 | "GDCM_BUILD_TESTING OFF" 12 | "GDCM_BUILD_APPLICATIONS OFF" 13 | "GDCM_BUILD_EXAMPLES OFF" 14 | "GDCM_WRAP_CSHARP OFF" 15 | "GDCM_WRAP_JAVA OFF" 16 | "GDCM_WRAP_PYTHON OFF" 17 | "GDCM_USE_PVRG OFF" 18 | ) 19 | include_directories( 20 | ${CMAKE_BINARY_DIR}/_deps/gdcm-build/Source/Common ${GDCM_SOURCE_DIR}/Source/Common 21 | ${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition 22 | ) 23 | string(TIMESTAMP AFTER "%s") 24 | math(EXPR DELTAGDCM "${AFTER} - ${BEFORE}") 25 | message(STATUS "GDCM TIME: ${DELTAGDCM}s") 26 | -------------------------------------------------------------------------------- /external/glew.cmake: -------------------------------------------------------------------------------- 1 | # GLEW 2 | string(TIMESTAMP BEFORE "%s") 3 | # todo: move this to cpm options 4 | set(ONLY_LIBS 5 | ON 6 | CACHE BOOL "cmake_ONLY_LIBS" 7 | ) 8 | set(glew-cmake_BUILD_SHARED 9 | OFF 10 | CACHE BOOL "Build the shared glew library" 11 | ) 12 | set(glew-cmake_BUILD_STATIC 13 | ON 14 | CACHE BOOL "Build the static glew library" 15 | ) 16 | set(glew-cmake_BUILD_SINGLE_CONTEXT 17 | ON 18 | CACHE BOOL "Build the single context glew library" 19 | ) 20 | set(glew-cmake_BUILD_MULTI_CONTEXT 21 | OFF 22 | CACHE BOOL "Build the multi context glew library" 23 | ) 24 | CPMAddPackage( 25 | NAME GLEW 26 | GITHUB_REPOSITORY Perlmint/glew-cmake 27 | GIT_TAG glew-cmake-2.2.0 28 | ) 29 | include_directories(${GLEW_SOURCE_DIR}/include) 30 | string(TIMESTAMP AFTER "%s") 31 | math(EXPR DELTAGLEW "${AFTER} - ${BEFORE}") 32 | message(STATUS "GLEW TIME: ${DELTAGLEW}s") 33 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/AlignmentRule.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_ALIGNMENTRULE_H 2 | #define MOBAGEN_ALIGNMENTRULE_H 3 | 4 | #include "FlockingRule.h" 5 | 6 | /* Steer toward average heading of local flockmates */ 7 | class AlignmentRule : public FlockingRule { 8 | public: 9 | explicit AlignmentRule(World* pWorld, float weight = 1., bool isEnabled = true) : FlockingRule(pWorld, Color::Yellow, weight, isEnabled) {} 10 | 11 | std::unique_ptr clone() override { return std::make_unique(*this); } 12 | 13 | const char* getRuleName() override { return "Alignment Rule"; } 14 | 15 | const char* getRuleExplanation() override { return "Steer to move in the same direction that nearby boids."; } 16 | 17 | virtual float getBaseWeightMultiplier() override { return 1.; } 18 | 19 | Vector2f computeForce(const std::vector& neighborhood, Boid* boid) override; 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /modules/time/Timer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2024.06.12. 3 | // 4 | 5 | #include "TimeDefs.h" 6 | #include "Time.h" 7 | #include "Timer.h" 8 | #include 9 | 10 | namespace MoBaGEn::TimeManager { 11 | Timer::Timer(bool startOnCreation) { 12 | if (startOnCreation) { 13 | Start(); 14 | } 15 | } 16 | 17 | void Timer::Start() { 18 | if (!m_running) { 19 | m_startTime = Time::Now(); 20 | m_running = true; 21 | } else { 22 | throw std::runtime_error("Timer already running"); 23 | } 24 | } 25 | 26 | Duration Timer::Stop() { 27 | if (m_running) { 28 | m_elapsedTime += Time::Now() - m_startTime; 29 | m_running = false; 30 | } 31 | return m_elapsedTime; 32 | } 33 | 34 | void Timer::Reset() { 35 | m_elapsedTime = Duration(0); 36 | Start(); 37 | } 38 | 39 | } // namespace MoBaGEn::TimeManager -------------------------------------------------------------------------------- /.github/workflows/style.yml: -------------------------------------------------------------------------------- 1 | name: Style 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | env: 12 | CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: cache 22 | uses: actions/cache@v2 23 | with: 24 | path: "**/cpm_modules" 25 | key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} 26 | 27 | - name: Install format dependencies 28 | run: pip3 install clang-format==14.0.6 cmake_format==0.6.11 pyyaml 29 | 30 | - name: configure 31 | run: cmake -S. -Bbuild -DENABLE_TEST_COVERAGE=ON -DENABLE_DOCUMENTATION=OFF 32 | 33 | - name: check style 34 | run: cmake --build build --target check-format -------------------------------------------------------------------------------- /core/math/Vector2.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector2.h" 2 | #include "../Random.h" 3 | 4 | template T& Vector2::operator[](const int& i) { 5 | if (i < 0 || i > 1) throw std::out_of_range("Out of Vector2 range\n"); 6 | return (i == 0) ? x : y; 7 | } 8 | 9 | template const T& Vector2::operator[](const int& i) const { 10 | if (i < 0 || i > 1) throw std::out_of_range("Out of Vector2 range\n"); 11 | return (i == 0) ? x : y; 12 | } 13 | 14 | template Vector2 Vector2::Random(T start, T end) { return {Random::Range(start, end), Random::Range(start, end)}; } 15 | 16 | template Vector2 Vector2::getVector2FromRadian(const T radian) { return {cos(radian), sin(radian)}; } 17 | 18 | template Vector2 Vector2::getVector2FromDegree(const T degree) { 19 | T radian = degree * ((T)M_PI / 180); 20 | return getVector2FromRadian(radian); 21 | } 22 | -------------------------------------------------------------------------------- /external/cpm.cmake: -------------------------------------------------------------------------------- 1 | # CPM REGION SET(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/external/ CACHE STRING "CPM_SOURCE_CACHE") 2 | set(CPM_DOWNLOAD_VERSION 0.38.2) 3 | if(CPM_SOURCE_CACHE) 4 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 5 | elseif(DEFINED ENV{CPM_SOURCE_CACHE}) 6 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 7 | else() 8 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 9 | endif() 10 | get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) 11 | if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) 12 | message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") 13 | file(DOWNLOAD 14 | https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 15 | ${CPM_DOWNLOAD_LOCATION} 16 | ) 17 | endif() 18 | include(${CPM_DOWNLOAD_LOCATION}) 19 | -------------------------------------------------------------------------------- /examples/scenario/Manager.h: -------------------------------------------------------------------------------- 1 | #ifndef SCENARIO_MANAGER_H 2 | #define SCENARIO_MANAGER_H 3 | 4 | #include "math/ColorT.h" 5 | #include "scene/GameObject.h" 6 | #include "GeneratorBase.h" 7 | #include 8 | 9 | // ref https://e2eml.school/transformers.html 10 | 11 | class Manager : public GameObject { 12 | private: 13 | float accumulatedTime = 0; 14 | int sideSize = 512; 15 | SDL_Texture* texture; 16 | bool isSimulating = false; 17 | 18 | std::vector generators; 19 | int generatorId = 0; 20 | 21 | void step(); 22 | 23 | public: 24 | ~Manager(); 25 | explicit Manager(Engine* engine, int size); 26 | 27 | void Start() override; 28 | void OnGui(ImGuiContext* context) override; 29 | void OnDraw(SDL_Renderer* renderer) override; 30 | void Update(float deltaTime) override; 31 | 32 | void Clear(); 33 | int GetSize() const; 34 | 35 | void SetPixels(std::vector& pixels); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "MoBaGEn", 3 | "projectOwner": "InfiniBrains", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": ["README.md"], 7 | "imageSize": 100, 8 | "commit": false, 9 | "contributorsPerLine": 4, 10 | "contributorsSortAlphabetically": false, 11 | "badgeTemplate": "[![All Contributors](https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg?style=flat-square)](#contributors)", 12 | "contributorTemplate": "\">\" width=\"<%= options.imageSize %>px;\" alt=\"\"/>
<%= contributor.name %>
", 13 | "types": { 14 | "custom": { 15 | "symbol": "🔭", 16 | "description": "A custom contribution type.", 17 | "link": "[<%= symbol %>](<%= url %> \"<%= description %>\")," 18 | } 19 | }, 20 | "linkToUsage": true, 21 | "skipCi": true, 22 | "contributors": [] 23 | } -------------------------------------------------------------------------------- /core/datastructures/Grid2D.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_GRID2D_H 2 | #define MOBAGEN_GRID2D_H 3 | 4 | #include "../math/Point2D.h" 5 | #include 6 | 7 | template struct Grid2D { 8 | private: 9 | int width = 0; 10 | int height = 0; 11 | std::vector data; 12 | 13 | public: 14 | Grid2D() = default; 15 | Grid2D(int width, int height) : width(width), height(height) { data.reserve(width * height); } 16 | ~Grid2D() { data.clear(); } 17 | 18 | T& operator()(int x, int y) { return data[x + y * width]; } 19 | const T& operator()(int x, int y) const { return data[x + y * width]; } 20 | 21 | T& operator()(const Point2D& pos) { return data[pos.x + pos.y * width]; } 22 | const T& operator()(const Point2D& pos) const { return data[pos.x + pos.y * width]; } 23 | 24 | void Resize(int width, int height) { 25 | this->width = width; 26 | this->height = height; 27 | data.resize(width * height); 28 | } 29 | }; 30 | 31 | #endif // MOBAGEN_GRID2D_H 32 | -------------------------------------------------------------------------------- /examples/maze/generators/PrimExample.cpp: -------------------------------------------------------------------------------- 1 | #include "PrimExample.h" 2 | #include "../World.h" 3 | #include "Random.h" 4 | 5 | bool PrimExample::Step(World* w) { 6 | int sideOver2 = w->GetSize() / 2; 7 | 8 | // todo: code this 9 | 10 | return true; 11 | } 12 | void PrimExample::Clear(World* world) { 13 | toBeVisited.clear(); 14 | initialized = false; 15 | } 16 | 17 | std::vector PrimExample::getVisitables(World* w, const Point2D& p) { 18 | auto sideOver2 = w->GetSize() / 2; 19 | std::vector visitables; 20 | auto clearColor = Color::DarkGray; 21 | 22 | // todo: code this 23 | 24 | return visitables; 25 | } 26 | 27 | std::vector PrimExample::getVisitedNeighbors(World* w, const Point2D& p) { 28 | std::vector deltas = {Point2D::UP, Point2D::DOWN, Point2D::LEFT, Point2D::RIGHT}; 29 | auto sideOver2 = w->GetSize() / 2; 30 | std::vector neighbors; 31 | 32 | // todo: code this 33 | 34 | return neighbors; 35 | } 36 | -------------------------------------------------------------------------------- /external/quickjs.cmake: -------------------------------------------------------------------------------- 1 | string(TIMESTAMP BEFORE "%s") 2 | CPMAddPackage( 3 | NAME quickjspp 4 | URL "https://github.com/ftk/quickjspp/archive/refs/heads/master.zip" 5 | OPTIONS "QUICKJSPP_BUILD_TESTS OFF" "BUILD_TESTING OFF" 6 | ) 7 | if(quickjspp_ADDED) 8 | # add_library(quickjspp STATIC) target_compile_definitions( quickjs PRIVATE 9 | # CONFIG_VERSION="v1.0.0" # hack to make it compile. it doesnt accept date as # version number ) 10 | # target_sources( quickjs PRIVATE ${quickjs_SOURCE_DIR}/quickjs.h 11 | # ${quickjs_SOURCE_DIR}/quickjs-libc.h ${quickjs_SOURCE_DIR}/quickjs.c 12 | # ${quickjs_SOURCE_DIR}/libregexp.c ${quickjs_SOURCE_DIR}/libunicode.c 13 | # ${quickjs_SOURCE_DIR}/libbf.c ${quickjs_SOURCE_DIR}/cutils.c 14 | # ${quickjs_SOURCE_DIR}/quickjs-libc.c ) 15 | include_directories(${quickjspp_SOURCE_DIR}) 16 | endif() 17 | string(TIMESTAMP AFTER "%s") 18 | math(EXPR DELTAquickjspp "${AFTER} - ${BEFORE}") 19 | message(STATUS "quickjspp TIME: ${DELTAquickjspp}s") 20 | -------------------------------------------------------------------------------- /examples/hideandseeksquared/Manager.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_MANAGERHIDEANDSEEK_H 2 | #define MOBAGEN_MANAGERHIDEANDSEEK_H 3 | 4 | #include "engine/EngineForwards.h" 5 | #include "scene/GameObject.h" 6 | #include "datastructures/Grid2D.h" 7 | #include "ShadowCastGridRecursive.h" 8 | 9 | // make it be a component instead a gameobject 10 | class Manager : public GameObject { 11 | int sideSize = 17; 12 | Grid2D grid; 13 | float enemyTickSize = 0.5f; 14 | float timeTimeRemaining = 0.5f; 15 | bool showHiddenObjects = true; 16 | 17 | public: 18 | explicit Manager(Engine* pEngine); 19 | 20 | void Start() override; 21 | void OnGui(ImGuiContext* context) override; 22 | void OnDraw(SDL_Renderer* renderer) override; 23 | void Update(float deltaTime) override; 24 | 25 | // helper functions 26 | Point2D screenSpaceToGridIndex(ImVec2& pos); 27 | void Reset(); 28 | 29 | // game logic 30 | void EnemyTick(); 31 | void ShadowCast(); 32 | }; 33 | 34 | #endif // MOBAGEN_MANAGER_H 35 | -------------------------------------------------------------------------------- /external/wasm.cmake: -------------------------------------------------------------------------------- 1 | string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) 2 | # set (WAMR_BUILD_PLATFORM "linux") set (WAMR_BUILD_TARGET "X86_64") 3 | set(WAMR_BUILD_INTERP 1) 4 | # set (WAMR_BUILD_FAST_INTERP 1) set (WAMR_BUILD_AOT 1) set (WAMR_BUILD_LIBC_BUILTIN 1) set 5 | # (WAMR_BUILD_LIBC_WASI 1) set (WAMR_BUILD_SIMD 1) set (WAMR_ROOT_DIR path/to/wamr/root) 6 | 7 | string(TIMESTAMP BEFORE "%s") 8 | CPMAddPackage( 9 | NAME wasm-micro-runtime 10 | GITHUB_REPOSITORY bytecodealliance/wasm-micro-runtime RECURSIVE YES 11 | GIT_TAG WAMR-1.1.2 12 | ) 13 | string(TIMESTAMP AFTER "%s") 14 | math(EXPR DELTAwasm "${AFTER} - ${BEFORE}") 15 | message(STATUS "wasm TIME: ${DELTAwasm}s") 16 | if(wasm-micro-runtime_ADDED) 17 | include_directories(${wasm-micro-runtime_SOURCE_DIR}/include) 18 | include(${wasm-micro-runtime_SOURCE_DIR}/build-scripts/runtime_lib.cmake) 19 | # add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) 20 | else() 21 | message(FATAL_ERROR "wasm not configured correctly") 22 | endif() 23 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/CohesionRule.h: -------------------------------------------------------------------------------- 1 | #ifndef COHESIONRULE_H 2 | #define COHESIONRULE_H 3 | 4 | #include "FlockingRule.h" 5 | 6 | class Boid; 7 | 8 | /* Steer to move toward center of mass of local flockmates */ 9 | class CohesionRule : public FlockingRule { 10 | public: 11 | explicit CohesionRule(World* pWorld, float weight = 1., bool isEnabled = true) : FlockingRule(pWorld, Color::Cyan, weight, isEnabled) {} 12 | 13 | std::unique_ptr clone() override { 14 | // Créer un pointeur concret en utilisant le constructeur abstrait parent 15 | return std::make_unique(*this); 16 | } 17 | 18 | const char* getRuleName() override { return "Cohesion Rule"; } 19 | 20 | const char* getRuleExplanation() override { return "Steer to move toward center of mass of nearby boids."; } 21 | 22 | virtual float getBaseWeightMultiplier() override { return 1.; } 23 | 24 | Vector2f computeForce(const std::vector& neighborhood, Boid* boid) override; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/WindRule.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDRULE_H 2 | #define WINDRULE_H 3 | 4 | #include "FlockingRule.h" 5 | 6 | class WindRule : public FlockingRule { 7 | private: 8 | float windAngle; 9 | 10 | public: 11 | explicit WindRule(World* pWorld, float weight = 1., float angle = 0, bool isEnabled = true) 12 | : FlockingRule(pWorld, Color::White, weight, isEnabled), windAngle(angle) {} 13 | 14 | WindRule(const WindRule& toCopy) : FlockingRule(toCopy) { windAngle = toCopy.windAngle; } 15 | 16 | std::unique_ptr clone() override { return std::make_unique(*this); } 17 | 18 | const char* getRuleName() override { return "Wind Force"; } 19 | 20 | const char* getRuleExplanation() override { return "Apply a constant force to all boids."; } 21 | 22 | virtual float getBaseWeightMultiplier() override { return 0.5; } 23 | 24 | Vector2f computeForce(const std::vector& neighborhood, Boid* boid) override; 25 | 26 | bool drawImguiRuleExtra() override; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /examples/life/World.h: -------------------------------------------------------------------------------- 1 | #ifndef LIFE_WORLD_H 2 | #define LIFE_WORLD_H 3 | 4 | #include "math/Point2D.h" 5 | #include 6 | 7 | struct World { 8 | private: 9 | // double buffer approach to avoid memory reallocation 10 | std::vector buffer[2]; 11 | int currentBufferId; 12 | int sideSize; 13 | inline std::vector& currentBuffer() { return buffer[currentBufferId % 2]; } 14 | inline std::vector& nextBuffer() { return buffer[(currentBufferId + 1) % 2]; } 15 | 16 | public: 17 | inline const int& SideSize() const { return sideSize; }; 18 | void Resize(int sideSize); 19 | // to be called at the end of the frame 20 | void SwapBuffers(); 21 | // todo: make it follow the standard at() function that returns the exactly element 22 | bool Get(Point2D point); 23 | // todo: make it follow the standard at() function that returns the exactly element 24 | void SetNext(Point2D point, bool value); 25 | void SetCurrent(Point2D point, bool value); 26 | void Randomize(); 27 | }; 28 | 29 | #endif // MOBAGEN_WORLD_H 30 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/SeparationRule.h: -------------------------------------------------------------------------------- 1 | #ifndef SEPARATIONRULE_H 2 | #define SEPARATIONRULE_H 3 | 4 | #include "FlockingRule.h" 5 | 6 | /* Steer to avoid local flockmates */ 7 | class SeparationRule : public FlockingRule { 8 | private: 9 | float desiredMinimalDistance = 10; 10 | 11 | public: 12 | explicit SeparationRule(World* pWorld, float desiredSeparation = 20., float weight = 1., bool isEnabled = true) 13 | : FlockingRule(pWorld, Color::Red, weight, isEnabled), desiredMinimalDistance(desiredSeparation) {} 14 | 15 | std::unique_ptr clone() override { return std::make_unique(*this); } 16 | 17 | const char* getRuleName() override { return "Separation Rule"; } 18 | 19 | const char* getRuleExplanation() override { return "Steer to avoid collision with nearby boids."; } 20 | 21 | virtual float getBaseWeightMultiplier() override { return 1.f; } 22 | 23 | Vector2f computeForce(const std::vector& neighborhood, Boid* boid) override; 24 | 25 | bool drawImguiRuleExtra() override; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /external/imgui.cmake: -------------------------------------------------------------------------------- 1 | # ImGui 2 | string(TIMESTAMP BEFORE "%s") 3 | CPMAddPackage( 4 | NAME IMGUI 5 | GIT_TAG v1.92.2b-docking 6 | GITHUB_REPOSITORY ocornut/imgui 7 | ) 8 | if(IMGUI_ADDED) 9 | add_library(IMGUI STATIC) 10 | 11 | target_sources( 12 | IMGUI 13 | PUBLIC ${IMGUI_SOURCE_DIR}/imgui_demo.cpp 14 | ${IMGUI_SOURCE_DIR}/imgui_draw.cpp 15 | ${IMGUI_SOURCE_DIR}/imgui_tables.cpp 16 | ${IMGUI_SOURCE_DIR}/imgui_widgets.cpp 17 | ${IMGUI_SOURCE_DIR}/imgui.cpp 18 | ${IMGUI_SOURCE_DIR}/backends/imgui_impl_sdlrenderer2.cpp 19 | ${IMGUI_SOURCE_DIR}/backends/imgui_impl_sdl2.cpp 20 | # ${IMGUI_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp 21 | ) 22 | target_include_directories( 23 | IMGUI 24 | PUBLIC ${IMGUI_SOURCE_DIR} 25 | PUBLIC ${IMGUI_SOURCE_DIR}/backends 26 | ) 27 | 28 | target_link_libraries(IMGUI PUBLIC SDL2-static ${CMAKE_DL_LIBS}) 29 | endif() 30 | string(TIMESTAMP AFTER "%s") 31 | math(EXPR DELTAIMGUI "${AFTER} - ${BEFORE}") 32 | message(STATUS "IMGUI TIME: ${DELTAIMGUI}s") 33 | -------------------------------------------------------------------------------- /examples/hideandseeksquared/ShadowCastGridRecursive.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_SHADOWCASTGRIDRECURSIVE_H 2 | #define MOBAGEN_SHADOWCASTGRIDRECURSIVE_H 3 | 4 | #include "datastructures/Grid2D.h" 5 | #include "math/Point2D.h" 6 | 7 | enum class SquareType : uint8_t { 8 | Empty = 0, 9 | Wall = 1, 10 | Player = 2, 11 | Enemy = 3, 12 | }; 13 | 14 | struct Square { 15 | public: 16 | bool visible : 1; 17 | SquareType type : 2; 18 | 19 | private: 20 | uint8_t _reserved : 5; 21 | }; 22 | 23 | // every node is a enum that holds WALL, FLOOR, ENEMY, PLAYER 24 | enum class Octant { 25 | NNE, 26 | ENE, 27 | ESE, 28 | SSE, 29 | SSW, 30 | WSW, 31 | WNW, 32 | NNW, 33 | }; 34 | 35 | // slope is a datastructure holding 2 floats, max and min, representing the max and min slope of the current recursion level 36 | struct Slope { 37 | float min; 38 | float max; 39 | }; 40 | 41 | // parameters: 42 | void ShadowCastGridRecursive(Grid2D& grid, Point2D& origin, int deepness, int maxDeepness, Octant octant, Slope slopeRange); 43 | 44 | #endif // MOBAGEN_SHADOWCASTGRIDRECURSIVE_H 45 | -------------------------------------------------------------------------------- /test/Test.cpp: -------------------------------------------------------------------------------- 1 | #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 2 | 3 | #include 4 | #include "engine/Engine.h" 5 | #include "scene/GameObject.h" 6 | // #include "cpr/cpr.h" 7 | 8 | class Quitter : public GameObject { 9 | public: 10 | Quitter(Engine* pEngine) : GameObject(pEngine){}; 11 | void Update(float time) override { engine->Exit(); } 12 | }; 13 | 14 | TEST_CASE("Start and Stop Engine") { 15 | auto engine = new Engine(); 16 | if (engine->Start("Test engine")) { 17 | new Quitter(engine); 18 | engine->Run(); 19 | } 20 | engine->Exit(); 21 | delete engine; 22 | engine = nullptr; 23 | // CHECK(Scheduler::Instance().RunningWorkersQuantity() == Scheduler::Instance().ConcurrencyLevel()); 24 | } 25 | // 26 | // TEST_CASE("Start and Stop Engine") { 27 | // cpr::Response r = cpr::Get(cpr::Url{"https://google.com"});//, cpr::VerifySsl(false)); 28 | // r.status_code; // 200 29 | // r.header["content-type"]; // application/json; charset=utf-8 30 | // r.text; // JSON text string 31 | // 32 | // CHECK(r.status_code == 200); 33 | //} -------------------------------------------------------------------------------- /core/scene/ScriptableObject.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_SCRIPTABLEOBJECT_H 2 | #define MOBAGEN_SCRIPTABLEOBJECT_H 3 | 4 | #include "../engine/Engine.h" 5 | #include "Object.h" 6 | // todo: this should be a scene object? 7 | class ScriptableObject : public Object { 8 | public: 9 | explicit ScriptableObject() : Object() { Engine::GetInstance()->AddScriptableObject(this); }; 10 | 11 | // messages 12 | virtual void Awake(){}; 13 | virtual void OnDestroy(){}; 14 | virtual void OnDisable(){}; 15 | virtual void OnEnable(){}; 16 | virtual void OnValidate(){}; 17 | virtual void Reset(){}; 18 | 19 | virtual void OnGui(ImGuiContext* context){}; // todo: if a scriptable object has a gui, it should be drawn in the editor this will require a huge 20 | // refactor of the editor 21 | 22 | // methods 23 | template 24 | requires std::is_base_of::value 25 | static T* CreateInstance(Engine* engine) { // todo: remove dependency of engine 26 | return new T(engine); 27 | } 28 | }; 29 | 30 | #endif // MOBAGEN_SCRIPTABLEOBJECT_H 31 | -------------------------------------------------------------------------------- /scripts/emscripten-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | mkdir -p "${DIRECTORY}"/../bin-emscripten/bin/ 6 | 7 | if which emcmake >/dev/null; then 8 | echo emsdk exists in path 9 | else 10 | echo installing emsdk 11 | ./emscripten-install.sh 12 | cd $DIRECTORY/../external/emsdk 13 | source ./emsdk_env.sh 14 | export EMSCRIPTEN=${EMSDK}/upstream/emscripten 15 | fi 16 | 17 | cd $DIRECTORY/../ 18 | 19 | pwd 20 | 21 | #cmake -DCMAKE_C_COMPILER=emcc -DCMAKE_CXX_COMPILER=em++ -DCMAKE_MAKE_PROGRAM=cmake -DCMAKE_C_ABI_COMPILED=ON -DCMAKE_CXX_ABI_COMPILED=ON -DCMAKE_CROSSCOMPILING=ON -DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_STATIC_LIBRARY_SUFFIX=".bc" -DCMAKE_SHARED_LIBRARY_SUFFIX=".bc" -DEMSCRIPTEN=1 -DCMAKE_BUILD_TYPE=MinSizeRel -H. -Bbuild 22 | 23 | cmake --version 24 | 25 | emcmake cmake --version 26 | 27 | emcmake cmake -DCMAKE_C_ABI_COMPILED=ON -DCMAKE_CXX_ABI_COMPILED=ON -DEMSCRIPTEN=1 -DCMAKE_BUILD_TYPE=MinSizeRel -H. -Bbin-emscripten 28 | 29 | cmake --build bin-emscripten/ --parallel -------------------------------------------------------------------------------- /core/scene/Object.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_ENGINE_OBJECT_H_ 2 | #define MOBAGEN_ENGINE_OBJECT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Object { 9 | public: 10 | const std::string& name() const { return _name; } 11 | void name(const std::string& name) { _name = name; } 12 | 13 | private: 14 | std::string _name; 15 | 16 | private: 17 | int _instanceId; // todo: initialize this properly 18 | 19 | public: 20 | // todo: make it const to protect from modification 21 | std::uint64_t instanceId() { return _instanceId; } 22 | 23 | // todo: equals comparison and attribution via copy or move ? 24 | public: 25 | Object(){}; // todo: implement copy and set internal variables 26 | 27 | public: 28 | // todo: mark to be deleted next frame 29 | static void Destroy(const Object& object){}; 30 | 31 | public: 32 | template static std::vector FindObjectsOfType(); 33 | 34 | public: 35 | static void DontDestroyOnLoad(const Object& object){}; 36 | 37 | public: 38 | std::string ToString() { return _name; }; 39 | }; 40 | 41 | #endif // MOBAGEN_ENGINE_OBJECT_H_ 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | .idea/ 31 | 32 | cmake-build* 33 | 34 | *.stackdump 35 | 36 | bin-emscripten/ 37 | 38 | build*/ 39 | 40 | .DS_Store 41 | 42 | node_modules 43 | 44 | package-lock.json 45 | 46 | ide/clion/ 47 | .vs/ 48 | 49 | # Build directories and binary files 50 | out/ 51 | cmake-*/ 52 | conan-cache/ 53 | 54 | # User spesific settings 55 | CMakeUserPresets.json 56 | 57 | # IDE files 58 | .vscode/ 59 | !.vscode/settings.json 60 | !.vscode/tasks.json 61 | !.vscode/launch.json 62 | !.vscode/extensions.json 63 | *.swp 64 | *~ 65 | _ReSharper* 66 | *.log 67 | 68 | # OS Generated Files 69 | .AppleDouble 70 | .LSOverride 71 | ._* 72 | .Spotlight-V100 73 | .Trashes 74 | .Trash-* 75 | $RECYCLE.BIN/ 76 | .TemporaryItems 77 | ehthumbs.db 78 | Thumbs.db 79 | 80 | external/*/ -------------------------------------------------------------------------------- /examples/scenario/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # GLM 2 | string(TIMESTAMP BEFORE "%s") 3 | CPMAddPackage( 4 | NAME GLM 5 | GITHUB_REPOSITORY g-truc/glm 6 | GIT_TAG master 7 | ) 8 | include_directories(${GLM_SOURCE_DIR}) 9 | string(TIMESTAMP AFTER "%s") 10 | math(EXPR DELTAGLM "${AFTER} - ${BEFORE}") 11 | message(STATUS "GLM TIME: ${DELTAGLM}s") 12 | 13 | file( 14 | GLOB 15 | SCENARIO_INC 16 | CONFIGURE_DEPENDS 17 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h 18 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 19 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.h 20 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.hpp 21 | ) 22 | 23 | file( 24 | GLOB 25 | SCENARIO_SRC 26 | CONFIGURE_DEPENDS 27 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 28 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 29 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.cpp 30 | ${CMAKE_CURRENT_SOURCE_DIR}/generators/*.c 31 | ) 32 | 33 | install(FILES ${SCENARIO_INC} DESTINATION include/scenario) 34 | 35 | add_executable(scenario ${SCENARIO_SRC} ${SCENARIO_INC}) 36 | 37 | target_include_directories(scenario PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 38 | target_link_libraries(scenario PUBLIC SDL2-static IMGUI core glm) 39 | -------------------------------------------------------------------------------- /core/Polygon.h: -------------------------------------------------------------------------------- 1 | #ifndef POLYGON_H 2 | #define POLYGON_H 3 | 4 | #include 5 | #include "math/Vector2.h" 6 | #include "scene/Transform.h" 7 | #include "math/Vector3.h" 8 | #include "math/ColorT.h" 9 | 10 | // naive approach to represent a polygon 11 | struct Polygon { 12 | public: 13 | Polygon() = default; 14 | explicit Polygon(std::vector points) : points(std::move(points)){}; 15 | std::vector points; 16 | 17 | // polygon points to be used in the draw functions 18 | std::vector getDrawablePoints(const Transform& transform); 19 | 20 | void Draw(SDL_Renderer* renderer, const Transform& transform, const Color32& color); 21 | void Draw(SDL_Renderer* renderer, const Vector2f& position, const Vector2f& scale, const Vector2f& rotation, const Color32& color); 22 | 23 | static void DrawLine(SDL_Renderer* renderer, const Vector2f& v1, const Vector2f& v2, const Color32& color); 24 | }; 25 | 26 | struct Circle : Polygon { 27 | explicit Circle(int sample); 28 | }; 29 | 30 | struct Square : Polygon { 31 | explicit Square(); 32 | }; 33 | 34 | struct Hexagon : Polygon { 35 | explicit Hexagon(); 36 | }; 37 | 38 | #endif // POLYGON_H 39 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | env: 12 | BUILD_TYPE: MinSizeRel 13 | CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules 14 | 15 | jobs: 16 | windows-native: 17 | runs-on: windows-2022 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | with: 22 | submodules: recursive 23 | 24 | - uses: actions/cache@v2 25 | with: 26 | path: "**/cpm_modules" 27 | key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} 28 | 29 | - name: Configure CMake 30 | shell: cmd 31 | run: cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=MinSizeRel -DENABLE_TEST_COVERAGE=OFF 32 | 33 | - name: Build 34 | shell: cmd 35 | run: cmake --build build --config MinSizeRel --parallel 36 | 37 | - name: Release 38 | uses: fnkr/github-action-ghr@v1.3 39 | if: startsWith(github.ref, 'refs/tags/') 40 | env: 41 | GHR_COMPRESS: zip 42 | GHR_PATH: build/ 43 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /examples/flocking/behaviours/MouseInfluenceRule.h: -------------------------------------------------------------------------------- 1 | #ifndef MOUSEINFLUENCERULE_H 2 | #define MOUSEINFLUENCERULE_H 3 | 4 | #include "FlockingRule.h" 5 | 6 | class MouseInfluenceRule : public FlockingRule { 7 | private: 8 | // If not avoiding, is attracted 9 | bool isRepulsive; 10 | 11 | public: 12 | explicit MouseInfluenceRule(World* pWorld, float weight = 1., bool isRepulsive_ = false, bool isEnabled = true) 13 | : FlockingRule(pWorld, Color::Magenta, weight, isEnabled), isRepulsive(isRepulsive_) {} 14 | 15 | MouseInfluenceRule(const MouseInfluenceRule& toCopy) : FlockingRule(toCopy) { isRepulsive = toCopy.isRepulsive; } 16 | 17 | std::unique_ptr clone() override { return std::make_unique(*this); } 18 | 19 | const char* getRuleName() override { return "Mouse Click Influence"; } 20 | 21 | const char* getRuleExplanation() override { return "Steer toward or away the mouse when clicked."; } 22 | 23 | virtual float getBaseWeightMultiplier() override { return 0.1; } 24 | 25 | Vector2f computeForce(const std::vector& neighborhood, Boid* boid) override; 26 | 27 | bool drawImguiRuleExtra() override; 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /examples/maze/Node.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_NODE_H 2 | #define MOBAGEN_NODE_H 3 | #include 4 | #include 5 | #include 6 | 7 | // the goal of this data structure is to interface with the world 8 | struct Node { 9 | public: 10 | Node() = default; 11 | Node(bool north, bool east, bool south, bool west) { 12 | data = ((uint8_t)north) | ((uint8_t)east << 1U) | ((uint8_t)south << 2U) | ((uint8_t)west << 3U); 13 | } 14 | 15 | private: 16 | uint8_t data; 17 | 18 | public: 19 | // todo: can you improve this? 20 | bool inline GetNorth() const { return data & 1U; }; 21 | bool inline GetEast() const { return data >> 1U & 1U; }; 22 | bool inline GetSouth() const { return data >> 2U & 1U; }; 23 | bool inline GetWest() const { return data >> 3U & 1U; }; 24 | 25 | // todo set 26 | // todo: can you improve this? 27 | void inline SetNorth(bool x) { data = (data & ~(1 << 0)) | x << 0; }; 28 | void inline SetEast(bool x) { data = (data & ~(1 << 1)) | x << 1; }; 29 | void inline SetSouth(bool x) { data = (data & ~(1 << 2)) | x << 2; }; 30 | void inline SetWest(bool x) { data = (data & ~(1 << 3)) | x << 3; }; 31 | }; 32 | 33 | #endif // MOBAGEN_NODE_H 34 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################### 2 | # Git Line Endings # 3 | ############################### 4 | 5 | * text=auto eol=lf 6 | *.sh text eol=lf 7 | *.{cmd,[cC][mM][dD]} text eol=crlf 8 | *.{bat,[bB][aA][tT]} text eol=crlf 9 | *.{vcxproj,vcxproj.filters} text eol=crlf 10 | 11 | ############################### 12 | # Git Large File System (LFS) # 13 | ############################### 14 | 15 | # Archives 16 | #*.7z filter=lfs diff=lfs merge=lfs -text 17 | #*.br filter=lfs diff=lfs merge=lfs -text 18 | #*.gz filter=lfs diff=lfs merge=lfs -text 19 | #*.tar filter=lfs diff=lfs merge=lfs -text 20 | #*.zip filter=lfs diff=lfs merge=lfs -text 21 | 22 | # Documents 23 | #*.pdf filter=lfs diff=lfs merge=lfs -text 24 | 25 | # Images 26 | #*.gif filter=lfs diff=lfs merge=lfs -text 27 | #*.ico filter=lfs diff=lfs merge=lfs -text 28 | #*.jpg filter=lfs diff=lfs merge=lfs -text 29 | #*.pdf filter=lfs diff=lfs merge=lfs -text 30 | #*.png filter=lfs diff=lfs merge=lfs -text 31 | #*.psd filter=lfs diff=lfs merge=lfs -text 32 | #*.webp filter=lfs diff=lfs merge=lfs -text 33 | 34 | # Fonts 35 | #*.woff2 filter=lfs diff=lfs merge=lfs -text 36 | 37 | # Other 38 | #*.exe filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /examples/flocking/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file( 2 | GLOB 3 | FLOCKING_INC 4 | CONFIGURE_DEPENDS 5 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/behaviours/*.h 8 | ${CMAKE_CURRENT_SOURCE_DIR}/behaviours/*.hpp 9 | ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.h 10 | ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.hpp 11 | ${CMAKE_CURRENT_SOURCE_DIR}/gameobjects/*.h 12 | ${CMAKE_CURRENT_SOURCE_DIR}/gameobjects/*.hpp 13 | ) 14 | 15 | file( 16 | GLOB 17 | FLOCKING_SRC 18 | CONFIGURE_DEPENDS 19 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 20 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 21 | ${CMAKE_CURRENT_SOURCE_DIR}/behaviours/*.cpp 22 | ${CMAKE_CURRENT_SOURCE_DIR}/behaviours/*.c 23 | ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.c 24 | ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.cpp 25 | ${CMAKE_CURRENT_SOURCE_DIR}/gameobjects/*.c 26 | ${CMAKE_CURRENT_SOURCE_DIR}/gameobjects/*.cpp 27 | ) 28 | 29 | install(FILES ${FLOCKING_INC} DESTINATION include/flocking) 30 | 31 | add_executable(flocking ${FLOCKING_SRC} ${FLOCKING_INC}) 32 | 33 | target_include_directories(flocking PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 34 | target_link_libraries(flocking PUBLIC SDL2-static IMGUI core) 35 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/BoundedAreaRule.h: -------------------------------------------------------------------------------- 1 | #ifndef BOUNDEDAREARULE_H 2 | #define BOUNDEDAREARULE_H 3 | 4 | #include "FlockingRule.h" 5 | 6 | class BoundedAreaRule : public FlockingRule { 7 | private: 8 | int desiredDistance; 9 | 10 | public: 11 | BoundedAreaRule(World* pWorld, int distanceFromBorder_, float weight = 1., bool isEnabled = true) 12 | : FlockingRule(pWorld, Color::Red.Light(), weight, isEnabled), desiredDistance(distanceFromBorder_) {} 13 | 14 | BoundedAreaRule(const BoundedAreaRule& toCopy) : FlockingRule(toCopy) { desiredDistance = toCopy.desiredDistance; } 15 | 16 | std::unique_ptr clone() override { return std::make_unique(*this); } 17 | 18 | const char* getRuleName() override { return "Bounded Windows"; } 19 | 20 | const char* getRuleExplanation() override { return "Steer to avoid the window's borders."; } 21 | 22 | virtual float getBaseWeightMultiplier() override { return 1.; } 23 | 24 | Vector2f computeForce(const std::vector& neighborhood, Boid* boid) override; 25 | 26 | bool drawImguiRuleExtra() override; 27 | 28 | virtual void draw(const Boid& boid, SDL_Renderer* renderer) const override; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /examples/maze/generators/RecursiveBacktrackerExample.cpp: -------------------------------------------------------------------------------- 1 | #include "../World.h" 2 | #include "Random.h" 3 | #include "RecursiveBacktrackerExample.h" 4 | #include 5 | bool RecursiveBacktrackerExample::Step(World* w) { 6 | // todo: implement this 7 | return false; 8 | } 9 | 10 | void RecursiveBacktrackerExample::Clear(World* world) { 11 | visited.clear(); 12 | stack.clear(); 13 | auto sideOver2 = world->GetSize() / 2; 14 | 15 | for (int i = -sideOver2; i <= sideOver2; i++) { 16 | for (int j = -sideOver2; j <= sideOver2; j++) { 17 | visited[i][j] = false; 18 | } 19 | } 20 | } 21 | 22 | Point2D RecursiveBacktrackerExample::randomStartPoint(World* world) { 23 | auto sideOver2 = world->GetSize() / 2; 24 | 25 | // todo: change this if you want 26 | for (int y = -sideOver2; y <= sideOver2; y++) 27 | for (int x = -sideOver2; x <= sideOver2; x++) 28 | if (!visited[y][x]) return {x, y}; 29 | return {INT_MAX, INT_MAX}; 30 | } 31 | 32 | std::vector RecursiveBacktrackerExample::getVisitables(World* w, const Point2D& p) { 33 | auto sideOver2 = w->GetSize() / 2; 34 | std::vector visitables; 35 | 36 | // todo: implement this 37 | 38 | return visitables; 39 | } 40 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/SeparationRule.cpp: -------------------------------------------------------------------------------- 1 | #include "SeparationRule.h" 2 | #include "../gameobjects/Boid.h" 3 | #include "../gameobjects/World.h" 4 | #include "engine/Engine.h" 5 | 6 | Vector2f SeparationRule::computeForce(const std::vector& neighborhood, Boid* boid) { 7 | // Try to avoid boids too close 8 | Vector2f separatingForce = Vector2f::zero(); 9 | 10 | // float desiredDistance = desiredMinimalDistance; 11 | // 12 | // // todo: implement a force that if neighbor(s) enter the radius, moves the boid away from it/them 13 | // if (!neighborhood.empty()) { 14 | // Vector2f position = boid->transform.position; 15 | // int countCloseFlockmates = 0; 16 | // // todo: find and apply force only on the closest mates 17 | // } 18 | 19 | separatingForce = Vector2f::normalized(separatingForce); 20 | 21 | return separatingForce; 22 | } 23 | 24 | bool SeparationRule::drawImguiRuleExtra() { 25 | ImGui::SetCurrentContext(world->engine->window->imGuiContext); 26 | bool valusHasChanged = false; 27 | 28 | if (ImGui::DragFloat("Desired Separation", &desiredMinimalDistance, 0.05f)) { 29 | valusHasChanged = true; 30 | } 31 | 32 | return valusHasChanged; 33 | } 34 | -------------------------------------------------------------------------------- /examples/hideandseeksquared/ShadowCastGridRecursive.cpp: -------------------------------------------------------------------------------- 1 | #include "ShadowCastGridRecursive.h" 2 | 3 | // reference: https://www.albertford.com/shadowcasting/ 4 | void ShadowCastGridRecursive(Grid2D& grid, Point2D& origin, int deepness, int maxDeepness, Octant octant, Slope slopeRange) { 5 | // return if max depth is reached 6 | if (deepness > maxDeepness) return; 7 | 8 | // return if the slope range is invalid 9 | if (slopeRange.min > slopeRange.max || slopeRange.min < 0 || slopeRange.max > 1) return; 10 | // for every octant, behave differently. 11 | 12 | // start the lower slope with the slopeRange.min 13 | // list all elements for the current level of deepness inside the slope range. to calculate the range, you will use origin, depth and octant 14 | // iterate over the list of elements looking for blocks: 15 | // If a block is found, then call visibility again with the new slope range from the current lower and the current block. 16 | // Search for the new lower slope, if the current block is not a wall, then the new lower slope is the current block's slope. 17 | // If the current block has slope of 1 call visibility again with the new slope range from the current lower and the current block. 18 | } -------------------------------------------------------------------------------- /editor/itk.cmake: -------------------------------------------------------------------------------- 1 | string(TIMESTAMP BEFORE "%s") 2 | CPMAddPackage( 3 | NAME ITX 4 | GITHUB_REPOSITORY InsightSoftwareConsortium/ITK 5 | GIT_TAG v5.3rc04 6 | OPTIONS "ITK_USE_CLANG_FORMAT OFF" "BUILD_DOC OFF" 7 | ) 8 | string(TIMESTAMP AFTER "%s") 9 | math(EXPR DELTAITK "${AFTER} - ${BEFORE}") 10 | message(STATUS "ITK TIME: ${DELTAITK}s") 11 | 12 | # todo: add gdcm source dir to the include path 13 | message(STATUS "ITK_SOURCE_DIR: ${ITK_SOURCE_DIR}") 14 | include_directories( 15 | ${ITK_SOURCE_DIR} 16 | ${ITKGDCM_SOURCE_DIR}/src/gdcm/Source/MediaStorageAndFileFormat 17 | ${ITKGDCM_SOURCE_DIR}/src/gdcm/Source/DataDictionary 18 | ${ITKGDCM_SOURCE_DIR}/src/gdcm/Source/Common 19 | ${ITKGDCM_SOURCE_DIR}/src/gdcm/Source/InformationObjectDefinition 20 | ${ITKGDCM_SOURCE_DIR}/src/gdcm/Source/MessageExchangeDefinition 21 | ${ITKGDCM_SOURCE_DIR}/src/gdcm/Source/DataStructureAndEncodingDefinition 22 | ${ITKGDCM_BINARY_DIR}/src/gdcm/Source/Common 23 | ) 24 | # C:\projects\mobagen\cmake-debug\_deps\itx-build\Modules\ThirdParty\GDCM\src\gdcm\Source\Common 25 | message(STATUS "ITKGDCM_SOURCE_DIR: ${ITKGDCM_SOURCE_DIR}") 26 | message(STATUS "ITKGDCM_BINARY_DIR: ${ITKGDCM_BINARY_DIR}") 27 | include_directories(${ITKGDCM_BINARY_DIR}) 28 | -------------------------------------------------------------------------------- /core/datastructures/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_VECTOR_H 2 | #define MOBAGEN_VECTOR_H 3 | /*** 4 | * 5 | * @brief This is just me trying to improve my skills dont use this as a vector replacement 6 | * 7 | * @tparam T data type to hold inside the container 8 | */ 9 | template struct Vector { 10 | private: 11 | T* buffer; 12 | // Constructors 13 | // default (1) 14 | // vector(); 15 | // explicit vector (const allocator_type& alloc); 16 | 17 | // fill (2) 18 | // explicit vector (size_type n, const allocator_type& alloc = allocator_type()); 19 | // vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type()); 20 | 21 | // range (3) 22 | // template vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); 23 | 24 | // copy (4) 25 | // vector (const vector& x);vector (const vector& x, const allocator_type& alloc); 26 | 27 | // move (5) 28 | // vector (vector&& x); 29 | // vector (vector&& x, const allocator_type& alloc); 30 | 31 | // initializer list (6) 32 | // vector (initializer_list il, const allocator_type& alloc = allocator_type()); 33 | 34 | ~Vector(); 35 | }; 36 | 37 | #endif // MOBAGEN_VECTOR_H 38 | -------------------------------------------------------------------------------- /html/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /core/math/Point2D.cpp: -------------------------------------------------------------------------------- 1 | #include "Point2D.h" 2 | #include 3 | 4 | const Point2D Point2D::UP = Point2D(0, -1); 5 | const Point2D Point2D::DOWN = Point2D(0, 1); 6 | const Point2D Point2D::LEFT = Point2D(-1, 0); 7 | const Point2D Point2D::RIGHT = Point2D(1, 0); 8 | const Point2D Point2D::INFINITE = Point2D(INT32_MAX, INT32_MAX); 9 | 10 | bool Point2D::operator==(const Point2D& rhs) const { return y == rhs.y && x == rhs.x; } 11 | 12 | bool Point2D::operator!=(const Point2D& rhs) const { return x != rhs.x || y != rhs.y; } 13 | 14 | Point2D& Point2D::operator=(const Point2D& rhs) { 15 | // Check for self-assignment 16 | if (this == &rhs) return *this; 17 | x = rhs.x; 18 | y = rhs.y; 19 | return *this; 20 | } 21 | 22 | Point2D Point2D::operator+(const Point2D& rhs) const { return {x + rhs.x, y + rhs.y}; } 23 | 24 | Point2D Point2D::operator-(const Point2D& rhs) const { return {x - rhs.x, y - rhs.y}; } 25 | std::string Point2D::to_string() { return "{" + std::to_string(x) + ", " + std::to_string(y) + "}"; } 26 | Point2D& Point2D::operator+=(const Point2D& rhs) { 27 | this->x += rhs.x; 28 | this->y += rhs.y; 29 | return *this; 30 | } 31 | Point2D& Point2D::operator-=(const Point2D& rhs) { 32 | this->x -= rhs.x; 33 | this->y -= rhs.y; 34 | return *this; 35 | } 36 | -------------------------------------------------------------------------------- /examples/chess/Manager.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_MANAGER_H 2 | #define CHESS_MANAGER_H 3 | 4 | #include "Texture.h" 5 | #include "WorldState.h" 6 | #include "math/ColorT.h" 7 | #include "engine/Engine.h" 8 | #include "scene/GameObject.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class Manager : GameObject { 15 | private: 16 | WorldState state; 17 | stack previousStates; 18 | Point2D selected = {INT32_MIN, INT32_MIN}; 19 | unordered_set validMoves; 20 | map piecePackedToTexture; 21 | PieceColor aiColor = PieceColor::Black; 22 | bool aiEnabled = false; 23 | 24 | public: 25 | double score; 26 | explicit Manager(Engine* pEngine); 27 | void Start() override; 28 | ~Manager(); 29 | void OnGui(ImGuiContext* context) override; 30 | void OnDraw(SDL_Renderer* renderer) override; 31 | void Update(float deltaTime) override; 32 | 33 | private: 34 | Point2D mousePositionToIndex(ImVec2& pos); 35 | unordered_set getMoves(PieceType t, Point2D point); 36 | void drawSquare(SDL_Renderer* renderer, Color32& color, SDL_Rect& rect); 37 | void drawPiece(SDL_Renderer* renderer, PieceData piece, Vector2f location, Vector2f scale); 38 | }; 39 | 40 | #endif // CHESS_MANAGER_H 41 | -------------------------------------------------------------------------------- /html/chess.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /html/life.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /html/maze.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/osx.yml: -------------------------------------------------------------------------------- 1 | name: OSX 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | env: 12 | BUILD_TYPE: MinSizeRel 13 | CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules 14 | 15 | jobs: 16 | osx-native: 17 | runs-on: macos-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | with: 22 | submodules: recursive 23 | 24 | - name: cache 25 | uses: actions/cache@v2 26 | with: 27 | path: "**/cpm_modules" 28 | key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} 29 | 30 | - uses: actions/setup-python@v4 31 | with: 32 | python-version: '3.10' 33 | 34 | - name: install dependencies 35 | run: | 36 | pip install jsonschema jinja2 37 | 38 | - name: Configure CMake 39 | run: cmake -Bbuild -H. -DCMAKE_BUILD_TYPE=MinSizeRel 40 | 41 | - name: Build 42 | run: cmake --build build/ --parallel 43 | 44 | - name: Release 45 | uses: fnkr/github-action-ghr@v1.3 46 | if: startsWith(github.ref, 'refs/tags/') 47 | env: 48 | GHR_COMPRESS: zip 49 | GHR_PATH: build/ 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /html/editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /html/flocking.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /html/scenario.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /html/catchthecat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /html/hideandseek.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /core/datastructures/Tree.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_TREE_H 2 | #define MOBAGEN_TREE_H 3 | #include "concepts.h" 4 | #include 5 | 6 | // binary tree 7 | // template struct BinaryTree { 8 | // struct Node { 9 | // T value; 10 | // Node* left = nullptr; 11 | // Node* right = nullptr; 12 | // explicit Node(T value) : value(value) {} 13 | // Node(T value, Node* left, Node* right) : value(value), left(left), right(right) {} 14 | // 15 | // ~Node() { 16 | // if (left) delete left; 17 | // if (right) delete right; 18 | // } 19 | // }; 20 | // 21 | // Node* root = nullptr; 22 | // 23 | // void Add(T value) { 24 | // if (!root) { 25 | // root = new Node(value); 26 | // return; 27 | // } 28 | // Node* current = root; 29 | // while (true) { 30 | // if (value < current->value) { 31 | // if (current->left != nullptr) { 32 | // current = current->left; 33 | // } else { 34 | // current->left = new Node(value); 35 | // break; 36 | // } 37 | // } else { 38 | // if (current->right != nullptr) { 39 | // current = current->right; 40 | // } else { 41 | // current->right = new Node(value); 42 | // break; 43 | // } 44 | // } 45 | // } 46 | // } 47 | //}; 48 | 49 | #endif // MOBAGEN_TREE_H 50 | -------------------------------------------------------------------------------- /examples/flocking/gameobjects/Boid.h: -------------------------------------------------------------------------------- 1 | #ifndef BOID_H 2 | #define BOID_H 3 | 4 | #include "../behaviours/FlockingRule.h" 5 | #include "Pacticle.h" 6 | #include "Polygon.h" 7 | 8 | class World; 9 | 10 | class Boid : public Particle { 11 | private: 12 | float detectionRadius = 100.; 13 | 14 | std::vector> rules; 15 | 16 | // Methods 17 | std::vector computeBoidNeighborhood(); 18 | 19 | Circle circle = Circle(12); 20 | World* world; 21 | 22 | public: 23 | // Member 24 | bool drawDebugRadius = true; 25 | bool drawDebugRules = true; 26 | Color32 circleColor = Color::Purple; 27 | 28 | // Constructor 29 | explicit Boid(Engine* pEngine, World* pWorld); 30 | 31 | // Getter - Setters 32 | void setFlockingRules(std::vector> const& newRules) { 33 | rules.clear(); 34 | 35 | // Clone the rules in newRules in the boid rules. 36 | for (auto& rule : newRules) { 37 | rules.push_back(rule->clone()); 38 | } 39 | } 40 | 41 | void setDetectionRadius(float newRadius) { detectionRadius = newRadius; } 42 | 43 | float getDetectionRadius() const { return detectionRadius; } 44 | 45 | void Update(float deltaTime) override; 46 | 47 | // Inherited via Drawable 48 | virtual void OnDraw(SDL_Renderer* renderer) override; 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /core/scene/GameObject.h: -------------------------------------------------------------------------------- 1 | #ifndef GAMEOBJECT_H 2 | #define GAMEOBJECT_H 3 | 4 | #include "SceneForwards.h" 5 | #include "../engine/EngineForwards.h" 6 | #include "imgui.h" 7 | #include "Transform.h" 8 | #include "Object.h" 9 | 10 | // todo: create a game list of game components of a game object 11 | class GameObject : public Object { 12 | public: 13 | // todo: make it private 14 | Transform transform; 15 | Engine* engine; 16 | 17 | public: 18 | // const Transform& Transform() const { return transform; } 19 | 20 | explicit GameObject(Engine* pEngine); 21 | 22 | // todo: move this to component. Revome from this class 23 | virtual void Start(){}; 24 | virtual void OnGui(ImGuiContext* context){}; 25 | virtual void OnDraw(SDL_Renderer* renderer){}; 26 | virtual void Update(float deltaTime){}; 27 | 28 | // make use of concepts here 29 | template std::vector GetComponents() { return {}; }; 30 | template std::vector GetComponentsInChildren() { return {}; }; 31 | template std::vector GetComponentsInParent() { return {}; }; 32 | template T* AddComponent() { return nullptr; }; 33 | 34 | static GameObject* Find(std::string name) { return nullptr; }; 35 | std::string tag; // todo: make it private 36 | bool CompareTag(std::string tag) { return tag == this->tag; } 37 | }; 38 | #endif -------------------------------------------------------------------------------- /examples/scenario/generators/ParticleGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_PARTICLEGENERATOR_H 2 | #define MOBAGEN_PARTICLEGENERATOR_H 3 | #define GLM_ENABLE_EXPERIMENTAL // to use glm::normal 4 | 5 | // reference: https://github.com/weigert/SimpleErosion 6 | #include "../GeneratorBase.h" 7 | #include 8 | #include 9 | class ParticleGenerator : public ScenarioGeneratorBase { 10 | private: 11 | // todo: improve this data structure to be more cache friendly 12 | float heights[2048][2048]; 13 | int sideSizeCached = 0; 14 | glm::vec3 surfaceNormal(int i, int j); 15 | std::vector heightsToColor(); 16 | void generateRandomHeights(); 17 | void Erode(float dt); 18 | float minVol = 0.01; 19 | float density = 1; 20 | float friction = 0.05; 21 | float depositionRate = 0.1; 22 | float evapRate = 0.001; 23 | float lastUpdate = 0; 24 | 25 | public: 26 | std::vector Generate(int sideSize, float displacement = 0) override; 27 | std::string GetName() override; 28 | }; 29 | 30 | struct Particle { 31 | // Construct Particle at Position 32 | Particle(glm::vec2 _pos) { pos = _pos; } 33 | 34 | glm::vec2 pos; 35 | glm::vec2 speed = glm::vec2(0.0); 36 | 37 | float volume = 1.0; // This will vary in time 38 | float sediment = 0.0; // Fraction of Volume that is Sediment! 39 | }; 40 | 41 | #endif // MOBAGEN_PARTICLEGENERATOR_H 42 | -------------------------------------------------------------------------------- /core/scene/HideFlags.h: -------------------------------------------------------------------------------- 1 | // ref https://docs.unity3d.com/ScriptReference/HideFlags.html 2 | // If you set hide flags to DontSaveInEditor, DontSaveInBuild or HideInHierarchy, this internally removes the object from the Unity Scene, as well as 3 | // from its current physics scene (this includes both 2D and 3D physics scenes). This also causes the object to trigger its OnDisable and OnEnable 4 | // calls. 5 | enum class HideFlags { 6 | // A normal, visible object. This is the default. 7 | None = 0, 8 | // The object will not appear in the hierarchy. 9 | HideInHierarchy = 1, 10 | // It is not possible to view it in the inspector. 11 | HideInInspector = 2, 12 | // The object will not be saved to the Scene in the editor. 13 | DontSaveInEditor = 4, 14 | // The object is not editable in the Inspector. 15 | NotEditable = 8, 16 | // The object will not be saved when building a player. 17 | DontSaveInBuild = 16, 18 | // The object will not be unloaded by Resources.UnloadUnusedAssets. 19 | DontUnloadUnusedAsset = 32, 20 | // The object will not be saved to the Scene. It will not be destroyed when a new Scene is loaded. It is a shortcut for HideFlags.DontSaveInBuild | 21 | // HideFlags.DontSaveInEditor | HideFlags.DontUnloadUnusedAsset. 22 | DontSave = 52, 23 | // The GameObject is not shown in the Hierarchy, not saved to Scenes, and not unloaded by Resources.UnloadUnusedAssets. 24 | HideAndDontSave = 128 25 | }; -------------------------------------------------------------------------------- /documentation/Architecture.md: -------------------------------------------------------------------------------- 1 | # Architecture 2 | 3 | ![Architecture](assets/architecture.svg) 4 | 5 | 6 | https://playground.diagram.codes/d/system-layers 7 | 8 | ``` 9 | V[Interfaces,glue,engine,editor] with label "Architecture" 10 | 11 | glue=H["Math","Containers &\nData Converters","Log",platform] with label "Glue" 12 | platform=H[mobile,desktop,web] with label "Platform Specific" 13 | 14 | mobile=H["android","ios"] with label "Mobile" 15 | desktop=H["win","osx","linux"] with label "Desktop" 16 | web=H["wasm"] with label "WEB" 17 | 18 | engine=H[orchestrator,rendering,physics,resource,animation,networking,gameplay] with label "Modules" 19 | rendering=V["GUI","Rendering","Shaders","Scripting","Materials"] with label "Graphics" 20 | 21 | physics=V["Particles","Collision","RigidBody","Constraints"] with label "Physics" 22 | animation=V["Skeleton","Poses","Clip","Skinning","Blending","Sprite"] with label "Animation" 23 | orchestrator=V["Time\nManager","Job\nScheduler","IO","Predict\nRollback", "Plugin\nManager"] with label "Orchestrator" 24 | 25 | gameplay=V["Scripting","Scene\nGraph","ECS","Events &\nMessaging","AI"] with label "Gameplay" 26 | networking=V["HTTPs","Real-Time"] with label "Networking" 27 | resource=V["Mesh","Audio","Video","Image","Text","Font","Binary","Prefab"] with label "Resource\nManager" 28 | 29 | editor=V[editor1] with label "Editor" 30 | editor1=H["Simulator","Visual Scripting","Scene Editor","Animator"] 31 | ``` 32 | -------------------------------------------------------------------------------- /core/Texture.cpp: -------------------------------------------------------------------------------- 1 | #include "Texture.h" 2 | #include "SDL_image.h" 3 | #include "SDL_surface.h" 4 | 5 | Texture* Texture::LoadSVGFromString(SDL_Renderer* renderer, const std::string& svgtxt) { 6 | auto tex = new Texture(); 7 | 8 | SDL_RWops* rw = SDL_RWFromConstMem(svgtxt.c_str(), svgtxt.size()); 9 | // todo: check if it is correct 10 | tex->surface = IMG_Load_RW(rw, 1); 11 | tex->texture = SDL_CreateTextureFromSurface(renderer, tex->surface); 12 | SDL_QueryTexture(tex->texture, nullptr, nullptr, &tex->dimensions.x, &tex->dimensions.y); 13 | return tex; 14 | } 15 | Texture::~Texture() { 16 | SDL_DestroyTexture(texture); 17 | // todo: destroy surface! 18 | // SDL_DestroySurface(surface); 19 | } 20 | void Texture::Draw(SDL_Renderer* renderer) { 21 | SDL_Rect rect; 22 | // todo: make rotation aware 23 | rect.w = dimensions.x * scale.x; 24 | rect.h = dimensions.y * scale.y; 25 | // to center 26 | rect.x = position.x - rect.w / 2.f; 27 | rect.y = position.y - rect.h / 2.f; 28 | SDL_RenderCopy(renderer, texture, nullptr, &rect); 29 | } 30 | void Texture::Draw(SDL_Renderer* renderer, Vector2f position, Vector2f scale) { 31 | SDL_Rect rect; 32 | // todo: make rotation aware 33 | rect.w = dimensions.x * scale.x; 34 | rect.h = dimensions.y * scale.y; 35 | // to center 36 | rect.x = position.x - rect.w / 2.f; 37 | rect.y = position.y - rect.h / 2.f; 38 | SDL_RenderCopy(renderer, texture, nullptr, &rect); 39 | } 40 | -------------------------------------------------------------------------------- /examples/maze/generators/HuntAndKillExample.cpp: -------------------------------------------------------------------------------- 1 | #include "HuntAndKillExample.h" 2 | #include "../World.h" 3 | #include "Random.h" 4 | #include 5 | bool HuntAndKillExample::Step(World* w) { 6 | // todo: code this 7 | return false; 8 | } 9 | void HuntAndKillExample::Clear(World* world) { 10 | visited.clear(); 11 | stack.clear(); 12 | auto sideOver2 = world->GetSize() / 2; 13 | 14 | for (int i = -sideOver2; i <= sideOver2; i++) { 15 | for (int j = -sideOver2; j <= sideOver2; j++) { 16 | visited[i][j] = false; 17 | } 18 | } 19 | } 20 | Point2D HuntAndKillExample::randomStartPoint(World* world) { 21 | // Todo: improve this if you want 22 | auto sideOver2 = world->GetSize() / 2; 23 | 24 | for (int y = -sideOver2; y <= sideOver2; y++) 25 | for (int x = -sideOver2; x <= sideOver2; x++) 26 | if (!visited[y][x]) return {x, y}; 27 | return {INT_MAX, INT_MAX}; 28 | } 29 | 30 | std::vector HuntAndKillExample::getVisitables(World* w, const Point2D& p) { 31 | auto sideOver2 = w->GetSize() / 2; 32 | std::vector visitables; 33 | 34 | // todo: code this 35 | 36 | return visitables; 37 | } 38 | std::vector HuntAndKillExample::getVisitedNeighbors(World* w, const Point2D& p) { 39 | std::vector deltas = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; 40 | auto sideOver2 = w->GetSize() / 2; 41 | std::vector neighbors; 42 | 43 | // todo: code this 44 | 45 | return neighbors; 46 | } 47 | -------------------------------------------------------------------------------- /.cmake-format: -------------------------------------------------------------------------------- 1 | format: 2 | tab_size: 2 3 | line_width: 100 4 | dangle_parens: true 5 | 6 | parse: 7 | additional_commands: 8 | cpmaddpackage: 9 | pargs: 10 | nargs: '*' 11 | flags: [] 12 | spelling: CPMAddPackage 13 | kwargs: &cpmaddpackagekwargs 14 | NAME: 1 15 | FORCE: 1 16 | VERSION: 1 17 | GIT_TAG: 1 18 | DOWNLOAD_ONLY: 1 19 | GITHUB_REPOSITORY: 1 20 | GITLAB_REPOSITORY: 1 21 | GIT_REPOSITORY: 1 22 | SVN_REPOSITORY: 1 23 | SVN_REVISION: 1 24 | SOURCE_DIR: 1 25 | DOWNLOAD_COMMAND: 1 26 | FIND_PACKAGE_ARGUMENTS: 1 27 | NO_CACHE: 1 28 | GIT_SHALLOW: 1 29 | URL: 1 30 | URL_HASH: 1 31 | URL_MD5: 1 32 | DOWNLOAD_NAME: 1 33 | DOWNLOAD_NO_EXTRACT: 1 34 | HTTP_USERNAME: 1 35 | HTTP_PASSWORD: 1 36 | OPTIONS: + 37 | cpmfindpackage: 38 | pargs: 39 | nargs: '*' 40 | flags: [] 41 | spelling: CPMFindPackage 42 | kwargs: *cpmaddpackagekwargs 43 | packageproject: 44 | pargs: 45 | nargs: '*' 46 | flags: [] 47 | spelling: packageProject 48 | kwargs: 49 | NAME: 1 50 | VERSION: 1 51 | NAMESPACE: 1 52 | INCLUDE_DIR: 1 53 | INCLUDE_DESTINATION: 1 54 | BINARY_DIR: 1 55 | COMPATIBILITY: 1 56 | VERSION_HEADER: 1 57 | DEPENDENCIES: + -------------------------------------------------------------------------------- /examples/flocking/behaviours/MouseInfluenceRule.cpp: -------------------------------------------------------------------------------- 1 | #include "MouseInfluenceRule.h" 2 | #include "../gameobjects/Boid.h" 3 | #include "../gameobjects/World.h" 4 | #include "engine/Engine.h" 5 | 6 | Vector2f MouseInfluenceRule::computeForce(const std::vector& neighborhood, Boid* boid) { 7 | ImGui::SetCurrentContext(world->engine->window->imGuiContext); 8 | // ImGuiIO& io = ImGui::GetIO(); 9 | // if (ImGui::IsMousePosValid() && io.MouseDown[0]) { 10 | // Vector2f mousePos(io.MousePos.x, io.MousePos.y); // todo: use this 11 | // Vector2f displacement = Vector2f::zero(); // todo: change this 12 | // float distance = 0; // todo: change this 13 | // 14 | // //The force is inversely proportional to distance 15 | // Vector2f force = Vector2f::zero(); // todo: change this 16 | // 17 | // if (isRepulsive) 18 | // force *= -1.f; 19 | // 20 | // return force; 21 | // } 22 | // else 23 | // return Vector2f::zero(); 24 | return Vector2f::zero(); 25 | } 26 | 27 | bool MouseInfluenceRule::drawImguiRuleExtra() { 28 | bool valueHasChanged = false; 29 | 30 | if (ImGui::RadioButton("Attractive", !isRepulsive)) { 31 | isRepulsive = false; 32 | valueHasChanged = true; 33 | } 34 | 35 | ImGui::SameLine(); 36 | if (ImGui::RadioButton("Repulsive", isRepulsive)) { 37 | isRepulsive = true; 38 | valueHasChanged = true; 39 | } 40 | 41 | return valueHasChanged; 42 | } -------------------------------------------------------------------------------- /core/math/Point2D.h: -------------------------------------------------------------------------------- 1 | #ifndef POINT2D_H 2 | #define POINT2D_H 3 | #include 4 | #include 5 | 6 | struct Point2D { 7 | public: 8 | Point2D(int x, int y) : x(x), y(y){}; 9 | Point2D() = default; 10 | int x, y; 11 | bool operator==(const Point2D& rhs) const; 12 | bool operator!=(const Point2D& rhs) const; 13 | Point2D& operator=(const Point2D& rhs); 14 | Point2D operator+(const Point2D& rhs) const; 15 | Point2D& operator+=(const Point2D& rhs); 16 | Point2D operator-(const Point2D& rhs) const; 17 | Point2D& operator-=(const Point2D& rhs); 18 | 19 | inline Point2D Up() const { return *this + UP; }; 20 | inline Point2D Left() const { return *this + LEFT; }; 21 | inline Point2D Right() const { return *this + RIGHT; }; 22 | inline Point2D Down() const { return *this + DOWN; }; 23 | 24 | const static Point2D UP; 25 | const static Point2D DOWN; 26 | const static Point2D LEFT; 27 | const static Point2D RIGHT; 28 | const static Point2D INFINITE; 29 | std::string to_string(); 30 | 31 | // for unordered set 32 | size_t operator()(const Point2D& p) const noexcept { return ((uint64_t)p.x) << 32 | (uint64_t)p.y; }; 33 | 34 | uint64_t hash(Point2D const& p) const noexcept { return ((uint64_t)p.x) << 32 | (uint64_t)p.y; } 35 | }; 36 | 37 | namespace std { 38 | template <> struct hash { 39 | std::size_t operator()(const Point2D& p) const noexcept { return p(p); } 40 | }; 41 | } // namespace std 42 | 43 | #endif // POINT2D_H 44 | -------------------------------------------------------------------------------- /core/WebRequest.h: -------------------------------------------------------------------------------- 1 | // #ifndef MOBAGEN_WEBREQUEST_H 2 | // #define MOBAGEN_WEBREQUEST_H 3 | // 4 | // #include 5 | // #include 6 | // #include 7 | // 8 | // enum class WebRequestVerb { GET, POST, PUT }; 9 | // 10 | // enum class ErrorCode { 11 | // OK = 0, 12 | // CONNECTION_FAILURE, 13 | // EMPTY_RESPONSE, 14 | // HOST_RESOLUTION_FAILURE, 15 | // INTERNAL_ERROR, 16 | // INVALID_URL_FORMAT, 17 | // NETWORK_RECEIVE_ERROR, 18 | // NETWORK_SEND_FAILURE, 19 | // OPERATION_TIMEDOUT, 20 | // PROXY_RESOLUTION_FAILURE, 21 | // SSL_CONNECT_ERROR, 22 | // SSL_LOCAL_CERTIFICATE_ERROR, 23 | // SSL_REMOTE_CERTIFICATE_ERROR, 24 | // SSL_CACERT_ERROR, 25 | // GENERIC_SSL_ERROR, 26 | // UNSUPPORTED_PROTOCOL, 27 | // REQUEST_CANCELLED, 28 | // TOO_MANY_REDIRECTS, 29 | // UNKNOWN_ERROR = 1000, 30 | // }; 31 | // 32 | // struct WebResponse { 33 | // public: 34 | // uint32_t status_code; 35 | // std::string text; 36 | // std::map header; 37 | // std::string url; 38 | // // todo: cookies 39 | // ErrorCode errorCode; 40 | // std::string ErrorMessage; 41 | // std::string raw_header{}; 42 | // std::string status_line{}; 43 | // std::string reason{}; 44 | // // todo: uploaded_bytes{}; 45 | // // todo: downloaded_bytes{}; 46 | // }; 47 | // 48 | // struct WebRequest { 49 | // WebRequest(std::string uri, WebRequestVerb verb, std::map headers); 50 | // }; 51 | // 52 | // #endif // MOBAGEN_WEBREQUEST_H 53 | -------------------------------------------------------------------------------- /examples/flocking/gameobjects/Pacticle.cpp: -------------------------------------------------------------------------------- 1 | #include "Pacticle.h" 2 | #include "Polygon.h" 3 | 4 | Particle::Particle(Engine* pEngine, float size, Color32 color) 5 | : GameObject(pEngine), velocity(Vector2f::zero()), circleSize(size), color(color), acceleration(Vector2f::zero()) { 6 | polygon.points = {{0, -2}, {1, 1}, {0, 0}, {-1, 1}}; 7 | transform.scale = {2, 2}; 8 | } 9 | 10 | // Public Methods 11 | void Particle::applyForce(Vector2f force) { acceleration += force; } 12 | 13 | void Particle::Update(const float deltaTime) { 14 | // Has a max acceleration per frame 15 | if (Vector2f::getMagnitude(acceleration) > maxAcceleration) acceleration = Vector2f::normalized(acceleration) * maxAcceleration; 16 | 17 | // Apply acceleration to velocity 18 | setVelocity(velocity + acceleration); 19 | resetAcceleration(); 20 | 21 | // constant speed never change || else only ceil the speed if wanted 22 | if (hasConstantSpeed || Vector2f::getMagnitude(velocity) > speed) setVelocity(Vector2f::normalized(velocity) * speed); 23 | 24 | transform.position += velocity * deltaTime; 25 | } 26 | 27 | void Particle::OnDraw(SDL_Renderer* renderer) { 28 | // todo: draw a circle or the ship? 29 | polygon.Draw(renderer, transform, color); 30 | 31 | if (drawAcceleration) { 32 | auto pos = getPosition(); 33 | Polygon::DrawLine(renderer, pos, pos + previousAcceleration * 2.f, Color::Purple); 34 | } 35 | } 36 | 37 | void Particle::resetAcceleration() { 38 | previousAcceleration = acceleration; 39 | acceleration = Vector2f::zero(); 40 | } -------------------------------------------------------------------------------- /editor/TopBar.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2023.04.04. 3 | // 4 | 5 | #include "TopBar.h" 6 | #include "imgui.h" 7 | 8 | void TopBar::OnGui(ImGuiContext* context) { 9 | ImGui::SetCurrentContext(context); 10 | if (ImGui::BeginMainMenuBar()) { 11 | if (ImGui::BeginMenu("File")) { 12 | if (ImGui::MenuItem("New", "Ctrl+N")) { 13 | } 14 | if (ImGui::MenuItem("Open", "Ctrl+O")) { 15 | } 16 | if (ImGui::MenuItem("Save", "Ctrl+S")) { 17 | } 18 | if (ImGui::MenuItem("Save As", "Ctrl+Shift+S")) { 19 | } 20 | ImGui::EndMenu(); 21 | } 22 | if (ImGui::BeginMenu("Edit")) { 23 | if (ImGui::MenuItem("Undo", "Ctrl+Z")) { 24 | } 25 | if (ImGui::MenuItem("Redo", "Ctrl+Y", false, false)) { 26 | } // Disabled item 27 | ImGui::Separator(); 28 | if (ImGui::MenuItem("Cut", "Ctrl+X")) { 29 | } 30 | if (ImGui::MenuItem("Copy", "Ctrl+C")) { 31 | } 32 | if (ImGui::MenuItem("Paste", "Ctrl+V")) { 33 | } 34 | ImGui::EndMenu(); 35 | } 36 | if (ImGui::BeginMenu("View")) { 37 | if (ImGui::MenuItem("Show/Hide Top Bar", "Ctrl+T")) { 38 | } 39 | if (ImGui::MenuItem("Show/Hide Left Bar", "Ctrl+L")) { 40 | } 41 | if (ImGui::MenuItem("Show/Hide Right Bar", "Ctrl+R")) { 42 | } 43 | ImGui::EndMenu(); 44 | } 45 | if (ImGui::BeginMenu("Help")) { 46 | if (ImGui::MenuItem("About")) { 47 | } 48 | ImGui::EndMenu(); 49 | } 50 | ImGui::EndMainMenuBar(); 51 | 52 | ImGui::ShowDemoWindow(&enabled); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | env: 12 | BUILD_TYPE: MinSizeRel 13 | 14 | jobs: 15 | linux-native: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | with: 21 | submodules: recursive 22 | 23 | - name: cache 24 | uses: actions/cache@v2 25 | with: 26 | key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} 27 | path: "**/cpm_modules" 28 | 29 | - uses: actions/setup-python@v4 30 | with: 31 | python-version: '3.10' 32 | 33 | - name: install dependencies 34 | run: | 35 | pip install jsonschema jinja2 36 | 37 | - name: Install dependencies 38 | run: | 39 | sudo apt update 40 | sudo apt install -y build-essential cmake mesa-common-dev libgl1-mesa-dev libx11-dev mesa-common-dev mesa-utils libgl-dev python3-distutils libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev 41 | 42 | - name: Configure CMake 43 | run: cmake -Bbuild -H. -DCMAKE_BUILD_TYPE=MinSizeRel 44 | 45 | - name: Build 46 | # run: cmake --build build/ --parallel 47 | run: cmake --build build/ 48 | 49 | - name: Release 50 | uses: fnkr/github-action-ghr@v1.3 51 | if: startsWith(github.ref, 'refs/tags/') 52 | env: 53 | GHR_COMPRESS: zip 54 | GHR_PATH: build/ 55 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /core/Window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "math/Point2D.h" 3 | #include "SDL_render.h" 4 | #include "SDL_video.h" 5 | #include "math/Vector2.h" 6 | #include 7 | #include 8 | 9 | #ifdef EMSCRIPTEN 10 | # include 11 | #endif 12 | 13 | class Window { 14 | // void init(void); 15 | 16 | // void tick(void); 17 | 18 | // void swapBuffer(void); 19 | 20 | // int poll_event(void); 21 | 22 | // int getWidth(void); 23 | 24 | // int getHeight(void); 25 | 26 | // getViewport(void) const; 27 | 28 | // getDisplaySize(void) const; 29 | 30 | // getDrawableSize(void) const; 31 | 32 | // static const char *getClipboardText(void* user_data); 33 | 34 | // static void setClipboardText(void* user_data, const char* text); 35 | 36 | // void makeCurrentContext(void) const; 37 | 38 | // Input *getInput(void); 39 | 40 | SDL_Window* getSDLWindow(void); 41 | 42 | // bool shouldQuit(void) const; 43 | 44 | // void drawCursor(bool enabled); 45 | 46 | // void setFullscreen(uint32_t flag); 47 | 48 | // void toggleFullscreen(void); 49 | 50 | public: 51 | explicit Window(std::string title); 52 | 53 | SDL_Window* sdlWindow; 54 | SDL_Renderer* sdlRenderer; 55 | ImGuiContext* imGuiContext; 56 | 57 | Point2D size(); 58 | void Update(); 59 | 60 | ~Window(); 61 | 62 | private: 63 | SDL_GLContext m_glContext; 64 | Point2D windowSize; 65 | // std::unique_ptr m_guiManager; 66 | 67 | // int m_width, m_height; 68 | 69 | // Input m_input; 70 | 71 | // bool m_quit; 72 | // bool m_fullscreen; 73 | }; 74 | -------------------------------------------------------------------------------- /examples/chess/pieces/Knight.cpp: -------------------------------------------------------------------------------- 1 | #include "Knight.h" 2 | unordered_set Knight::AttackMoves(WorldState& world, const Point2D& origin) { 3 | auto piece = world.PieceAtPosition(origin); 4 | if (piece.Piece() != PieceType::Knight) return {}; 5 | 6 | unordered_set moves; 7 | 8 | vector const deltas = {{-1, 2}, {1, 2}, {-2, 1}, {2, 1}, {-2, -1}, {2, -1}, {-1, -2}, {1, -2}}; 9 | for (auto delta : deltas) { 10 | auto sum = delta + origin; 11 | auto other = world.PieceAtPosition(sum); 12 | if (other.Piece() == PieceType::WRONG || // outside board 13 | ((uint8_t)other.Piece() < (uint8_t)PieceType::WRONG && other.Piece() != PieceType::NONE 14 | && other.Color() == piece.Color())) // same side piece 15 | continue; 16 | moves.insert(sum); 17 | } 18 | return moves; 19 | } 20 | unordered_set Knight::CoverMoves(WorldState& world, const Point2D& origin) { 21 | auto piece = world.PieceAtPosition(origin); 22 | if (piece.Piece() != PieceType::Knight) return {}; 23 | 24 | unordered_set moves; 25 | 26 | vector const deltas = {{-1, 2}, {1, 2}, {-2, 1}, {-2, 1}, {-2, -1}, {-2, -1}, {-1, -2}, {1, -2}}; 27 | for (auto delta : deltas) { 28 | auto sum = delta + origin; 29 | auto other = world.PieceAtPosition(sum); 30 | if (other.Piece() == PieceType::WRONG || // outside board 31 | ((uint8_t)other.Piece() < (uint8_t)PieceType::WRONG && other.Piece() != PieceType::NONE 32 | && other.Color() != piece.Color())) // other side piece 33 | continue; 34 | moves.insert(sum); 35 | } 36 | return moves; 37 | } 38 | -------------------------------------------------------------------------------- /modules/time/Timer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Alexandre Tolstenko Nogueira on 2024.06.12. 3 | // 4 | 5 | #ifndef MOBAGEN_TIMER_H 6 | #define MOBAGEN_TIMER_H 7 | 8 | #include "TimeDefs.h" 9 | #include "Time.h" 10 | 11 | namespace MoBaGEn::TimeManager { 12 | /** 13 | * @brief Timer class 14 | * @details A class to measure wall clock time 15 | */ 16 | class Timer { 17 | private: 18 | TimePoint m_startTime = Time::Now(); 19 | Duration m_elapsedTime = Duration(0); 20 | bool m_running = false; 21 | 22 | public: 23 | /** 24 | * @brief Construct a new Timer object, by default it starts the timer 25 | * @param startOnCreation Start the timer on creation 26 | */ 27 | explicit Timer(bool startOnCreation = true); 28 | ~Timer() = default; 29 | 30 | // delete all implicit copy and move constructors 31 | Timer(const Timer&) = delete; 32 | Timer(Timer&&) = delete; 33 | Timer& operator=(const Timer&) = delete; 34 | Timer& operator=(Timer&&) = delete; 35 | 36 | /** 37 | * @brief Start or resume the timer 38 | * @details It will update the start time and mark the timer as running 39 | */ 40 | void Start(); 41 | /** 42 | * @brief Stop or pause the timer 43 | * @return Duration The elapsed time since the timer started 44 | * @details It will update the elapsed time and mark the timer as not running, and return 45 | */ 46 | Duration Stop(); 47 | 48 | /** 49 | * @brief Reset the timer and restart it 50 | * @details It will reset the elapsed time to 0 and start the timer 51 | */ 52 | void Reset(); 53 | }; 54 | } // namespace MoBaGEn::TimeManager 55 | 56 | #endif // MOBAGEN_TIMER_H 57 | -------------------------------------------------------------------------------- /examples/catchthecat/Agent.cpp: -------------------------------------------------------------------------------- 1 | #include "Agent.h" 2 | #include 3 | #include 4 | #include 5 | #include "World.h" 6 | using namespace std; 7 | std::vector Agent::generatePath(World* w) { 8 | unordered_map cameFrom; // to build the flowfield and build the path 9 | queue frontier; // to store next ones to visit 10 | unordered_set frontierSet; // OPTIMIZATION to check faster if a point is in the queue 11 | unordered_map visited; // use .at() to get data, if the element dont exist [] will give you wrong results 12 | 13 | // bootstrap state 14 | auto catPos = w->getCat(); 15 | frontier.push(catPos); 16 | frontierSet.insert(catPos); 17 | Point2D borderExit = Point2D::INFINITE; // if at the end of the loop we dont find a border, we have to return random points 18 | 19 | while (!frontier.empty()) { 20 | // get the current from frontier 21 | // remove the current from frontierset 22 | // mark current as visited 23 | // getVisitableNeightbors(world, current) returns a vector of neighbors that are not visited, not cat, not block, not in the queue 24 | // iterate over the neighs: 25 | // for every neighbor set the cameFrom 26 | // enqueue the neighbors to frontier and frontierset 27 | // do this up to find a visitable border and break the loop 28 | } 29 | 30 | // if the border is not infinity, build the path from border to the cat using the camefrom map 31 | // if there isnt a reachable border, just return empty vector 32 | // if your vector is filled from the border to the cat, the first element is the catcher move, and the last element is the cat move 33 | return vector(); 34 | } 35 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # Use the Google style in this project. 2 | BasedOnStyle: Google 3 | 4 | AccessModifierOffset: -2 5 | 6 | AlignTrailingComments: true 7 | AllowAllParametersOfDeclarationOnNextLine: false 8 | AlwaysBreakTemplateDeclarations: No 9 | BreakBeforeBraces: Attach 10 | ColumnLimit: 150 11 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 12 | #IncludeBlocks: Preserve 13 | IndentPPDirectives: AfterHash 14 | IndentWidth: 2 15 | NamespaceIndentation: All 16 | BreakBeforeBinaryOperators: All 17 | BreakBeforeTernaryOperators: true 18 | 19 | SortIncludes: Never 20 | 21 | # Some folks prefer to write "int& foo" while others prefer "int &foo". The 22 | # Google Style Guide only asks for consistency within a project, we chose 23 | # "int& foo" for this project: 24 | DerivePointerAlignment: false 25 | PointerAlignment: Left 26 | 27 | #IncludeCategories: 28 | # # Matches common headers first, but sorts them after project includes 29 | # - Regex: '^\"google/cloud/internal/disable_deprecation_warnings.inc\"$' 30 | # Priority: -1 31 | # - Regex: '^\"google/cloud/(internal/|grpc_utils/|testing_util/|[^/]+\.h)' 32 | # Priority: 1000 33 | # - Regex: '^\"google/cloud/' # project includes should sort first 34 | # Priority: 500 35 | # - Regex: '^\"' 36 | # Priority: 1500 37 | # - Regex: '^' 44 | # Priority: 5000 45 | 46 | # Format raw string literals with a `pb` or `proto` tag as proto. 47 | RawStringFormats: 48 | - Language: TextProto 49 | Delimiters: 50 | - 'pb' 51 | - 'proto' 52 | BasedOnStyle: Google 53 | 54 | CommentPragmas: '(@copydoc)' -------------------------------------------------------------------------------- /examples/flocking/gameobjects/Pacticle.h: -------------------------------------------------------------------------------- 1 | #ifndef PACTICLE_H 2 | #define PACTICLE_H 3 | 4 | #include "scene/GameObject.h" 5 | #include "scene/Transform.h" 6 | #include "Polygon.h" 7 | 8 | class Particle : public GameObject { 9 | private: 10 | // Members 11 | bool hasConstantSpeed = false; 12 | float speed = 120.; 13 | float maxAcceleration = 10.; 14 | float circleSize; // todo: is this really needed? 15 | 16 | Vector2f acceleration; 17 | Vector2f previousAcceleration; // to draw Acc 18 | Polygon polygon; 19 | 20 | // Methods 21 | void resetAcceleration(); 22 | 23 | public: 24 | Vector2f velocity; // todo: make this private 25 | bool drawAcceleration = false; 26 | Color32 color; // todo: make this private 27 | 28 | // Constructor 29 | explicit Particle(Engine* pEngine, float size = 4.f, Color32 color = Color32::RandomColor(31, 255)); 30 | 31 | // Getter / Setters 32 | Transform getTransform() const { return transform; } 33 | 34 | Vector2f getPosition() const { return transform.position; } 35 | 36 | Vector2f getVelocity() const { return velocity; } 37 | 38 | void setPosition(Vector2f position) { transform.position = position; } 39 | 40 | void setVelocity(Vector2f velocity_) { 41 | velocity = velocity_; 42 | transform.rotation = velocity_.normalized(); 43 | } 44 | 45 | void setSpeed(float newSpeed) { speed = newSpeed; } 46 | 47 | void setMaxAcceleration(float newMaxAcceleration) { maxAcceleration = newMaxAcceleration; } 48 | 49 | void setHasConstantSpeed(bool hasConstantSpeed_) { hasConstantSpeed = hasConstantSpeed_; } 50 | 51 | // Methods 52 | void applyForce(Vector2f force); 53 | 54 | virtual void Update(float deltaTime) override; 55 | 56 | // Inherited via Drawable 57 | void OnDraw(SDL_Renderer* renderer) override; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/flocking/gameobjects/Boid.cpp: -------------------------------------------------------------------------------- 1 | #include "Boid.h" 2 | #include "World.h" 3 | 4 | std::vector Boid::computeBoidNeighborhood() { 5 | std::vector neighborhood; 6 | 7 | float detectionRadiusSquared = detectionRadius * detectionRadius; 8 | auto position = getPosition(); 9 | 10 | // We compare distance to squared distances to avoid doing square roots. 11 | // TODO: Optimize this! Move this to the world manager 12 | // Option 1. Locality Sensitive Hashing or Spatial hashing 13 | // Option 2. Quadtree or octree 14 | for (const auto& boid : world->boids) { 15 | if (boid != this) { 16 | float squareDistance = Vector2f::DistanceSquared(position, boid->getPosition()); 17 | 18 | // Verify if boid is close enough to be part of the neighborhood 19 | if (squareDistance <= detectionRadiusSquared) neighborhood.push_back(boid); 20 | } 21 | } 22 | 23 | return neighborhood; 24 | } 25 | 26 | Boid::Boid(Engine* pEngine, World* pWorld) : Particle(pEngine), world(pWorld) {} 27 | 28 | void Boid::Update(float deltaTime) { 29 | Particle::Update(deltaTime); 30 | std::vector neighborhood = computeBoidNeighborhood(); 31 | 32 | for (auto& rule : rules) { 33 | auto weightedForce = rule->computeWeightedForce(neighborhood, this); 34 | // std::cout << typeid(*rule).name() << " Force : " << Vector2f::getMagnitude(weightedForce) << std::endl; 35 | applyForce(weightedForce); 36 | } 37 | } 38 | 39 | void Boid::OnDraw(SDL_Renderer* renderer) { 40 | if (drawDebugRadius) circle.Draw(renderer, transform.position, {detectionRadius, detectionRadius}, Vector2f::zero(), circleColor); 41 | 42 | // Display rules 43 | if (drawDebugRules) 44 | for (auto& rule : rules) 45 | if (rule->isEnabled) rule->draw(*this, renderer); 46 | 47 | Particle::OnDraw(renderer); // super() 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | env: 12 | CTEST_OUTPUT_ON_FAILURE: 1 13 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 14 | CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules 15 | 16 | jobs: 17 | build: 18 | runs-on: ${{ matrix.os }} 19 | 20 | strategy: 21 | matrix: 22 | os: [ ubuntu-latest, macos-latest ] # , windows-latest] 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | with: 27 | submodules: recursive 28 | 29 | - uses: actions/cache@v2 30 | with: 31 | path: "**/cpm_modules" 32 | key: ${{ matrix.os }}-${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} 33 | 34 | - name: Install dependencies 35 | if: startsWith(matrix.os,'ubuntu') 36 | run: | 37 | sudo apt update 38 | sudo apt install -y build-essential cmake mesa-common-dev libgl1-mesa-dev libx11-dev mesa-common-dev mesa-utils libgl-dev python3-distutils libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev 39 | 40 | # - name: Upload coverage reports to Codecov 41 | # uses: codecov/codecov-action@v3 42 | 43 | - name: configure 44 | run: cmake -S. -Bbuild -DENABLE_TEST_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug 45 | 46 | - name: build 47 | run: cmake --build build --parallel --target CoreTests 48 | 49 | - name: test 50 | run: | 51 | cd build 52 | cd test 53 | ctest --build-config Debug 54 | 55 | - name: collect code coverage on ubuntu 56 | if: startsWith(matrix.os,'ubuntu') 57 | run: bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports" 58 | -------------------------------------------------------------------------------- /examples/flocking/gameobjects/World.h: -------------------------------------------------------------------------------- 1 | #ifndef WORLD_H 2 | #define WORLD_H 3 | 4 | #include "../behaviours/FlockingRule.h" 5 | #include "Boid.h" 6 | #include "scene/GameObject.h" 7 | 8 | class Particle; 9 | 10 | // todo: make world a game engine scene manager 11 | class World : public GameObject { 12 | private: 13 | /// MEMBERS 14 | /// Configuration 15 | // Boids 16 | int nbBoids = 300; 17 | 18 | bool hasConstantSpeed = false; 19 | float desiredSpeed = 120.0f; 20 | 21 | bool hasMaxAcceleration = false; 22 | float maxAcceleration = 10.0f; 23 | 24 | float detectionRadius = 35; 25 | 26 | // Display 27 | bool showRadius = false; 28 | bool showRules = false; 29 | bool showAcceleration = false; 30 | 31 | // rules 32 | std::vector> boidsRules; 33 | // todo: make this a vector 34 | std::vector defaultWeights; // array of default rules weight 35 | 36 | /// METHODS 37 | void initializeRules(); 38 | 39 | // Boids 40 | 41 | void applyFlockingRulesToAllBoids(); 42 | void setNumberOfBoids(int number); 43 | void randomizeBoidPositionAndVelocity(Boid* boid); 44 | void warpParticleIfOutOfBounds(Particle* particle); 45 | 46 | Boid* createBoid(); 47 | 48 | public: 49 | // cached list to manipulate objects 50 | std::vector boids; 51 | 52 | /// METHODS 53 | explicit World(Engine* pEngine); 54 | 55 | // Getters 56 | std::vector* getAllBoids(); 57 | 58 | int getNbBoids() const; 59 | 60 | /// Setters 61 | 62 | // ImGui 63 | void drawGeneralUI(); 64 | void drawRulesUI(); 65 | 66 | // Update 67 | void Update(float deltaTime) override; 68 | 69 | void showConfigurationWindow(float deltaTime); 70 | void drawPerformanceUI(float deltaTime); 71 | 72 | void OnGui(ImGuiContext* context) override; 73 | void Start() override; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /examples/scenario/generators/RandomGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "RandomGenerator.h" 2 | #include "../FastNoiseLite.h" 3 | 4 | #include 5 | // do not use this one to your assignment. this is my sample generator 6 | std::vector RandomScenarioGenerator::Generate(int sideSize, float displacement) { 7 | std::vector colors; 8 | // create your own function for noise generation 9 | FastNoiseLite base; 10 | base.SetFractalOctaves(3); 11 | base.SetNoiseType(FastNoiseLite::NoiseType_OpenSimplex2S); 12 | base.SetFractalType(FastNoiseLite::FractalType_FBm); 13 | FastNoiseLite cellular; 14 | cellular.SetNoiseType(FastNoiseLite::NoiseType_Cellular); 15 | cellular.SetFractalOctaves(3); 16 | for (int l = 0; l < sideSize; l++) { 17 | for (int c = 0; c < sideSize; c++) { 18 | // island generation 19 | float posY = (float)((l - sideSize / 2)) / ((float)sideSize / 2); 20 | float posX = (float)((c - sideSize / 2)) / ((float)sideSize / 2); 21 | 22 | float islandInfluence = (2 - (abs(posX) + abs(posY))) / 2; 23 | islandInfluence *= 255; 24 | 25 | float c1 = ((base.GetNoise((float)c, (float)l, displacement * 50) + 1) / 2) * 255; 26 | // float c2 = ((cellular.GetNoise((float)c,(float)l, displacement*50) +1)/2) *255; 27 | 28 | auto avg = (c1 + islandInfluence) / 2; 29 | 30 | if (avg < 50) 31 | colors.emplace_back(Color::DarkBlue); 32 | else if (avg < 100) 33 | colors.emplace_back(Color::Yellow); 34 | else if (avg < 150) 35 | colors.emplace_back(Color::Green); 36 | else if (avg < 200) 37 | colors.emplace_back(Color::Brown); 38 | else 39 | colors.emplace_back(Color::White); 40 | } 41 | } 42 | std::cout << colors.size() << std::endl; 43 | return colors; 44 | } 45 | std::string RandomScenarioGenerator::GetName() { return "EXAMPLE"; } 46 | -------------------------------------------------------------------------------- /core/engine/Engine.h: -------------------------------------------------------------------------------- 1 | #ifndef ENGINE_H 2 | #define ENGINE_H 3 | 4 | #include "EngineForwards.h" 5 | #include "imgui.h" 6 | #include "imgui_impl_sdl2.h" 7 | #include "imgui_impl_sdlrenderer2.h" 8 | #include "../Window.h" 9 | #include "../scene/SceneForwards.h" 10 | #include 11 | #include "SDL.h" 12 | #include "EngineSettings.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | class Engine { 19 | private: 20 | std::chrono::high_resolution_clock::time_point lastFrameTime; 21 | float deltaTime; 22 | double targetFPS = 60; 23 | int64_t accumulatedTime = 0; 24 | EngineSettings settings; 25 | inline static Engine* instance = nullptr; 26 | 27 | public: 28 | static Engine* GetInstance() { 29 | if (instance == nullptr) instance = new Engine(); 30 | return instance; 31 | } 32 | Window* window; 33 | 34 | // todo: move this to a scene manager and make this private 35 | std::unordered_set gameObjects; 36 | std::unordered_set gameObjectsToBeStarted; 37 | std::unordered_set scriptableObjects; 38 | Vector2f getInputArrow() const; 39 | 40 | private: 41 | bool done = false; 42 | 43 | ImVec4 clear_color = ImVec4(0, 0, 0, 1); 44 | 45 | // todo: move this to input class 46 | void processInput(); 47 | Vector2f arrowInput; 48 | 49 | // todo: better ordering 50 | std::vector toDestroy; 51 | 52 | public: 53 | explicit Engine(EngineSettings settings = EngineSettings()); 54 | 55 | ~Engine(); 56 | bool Start(std::string title); 57 | void Run(); 58 | void Tick(); 59 | void Exit(); 60 | 61 | // template std::unordered_set FindObjectsOfType(); 62 | 63 | void Destroy(GameObject* go); 64 | 65 | void AddScriptableObject(ScriptableObject* pObject) { scriptableObjects.insert(pObject); }; 66 | 67 | bool IsHeadless() const { return settings.headless; } 68 | }; 69 | #endif -------------------------------------------------------------------------------- /examples/flocking/behaviours/FlockingRule.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOCKINGRULE_H 2 | #define FLOCKINGRULE_H 3 | 4 | #include 5 | #include 6 | #include "math/Vector2.h" 7 | #include "math/Vector3.h" 8 | #include "math/ColorT.h" 9 | 10 | class Boid; 11 | class World; 12 | 13 | class FlockingRule { 14 | public: 15 | World* world; 16 | 17 | protected: 18 | // We'll cache the computed force to be able to display it later 19 | Vector2f force; 20 | 21 | // if displayed 22 | Color32 debugColor; 23 | 24 | explicit FlockingRule(World* pWorld, Color32 debugColor_, float weight_, bool isEnabled_ = true) 25 | : debugColor(debugColor_), force(Vector2f()), weight(weight_), isEnabled(isEnabled_), world(pWorld) {} 26 | 27 | virtual Vector2f computeForce(const std::vector& neighborhood, Boid* boid) = 0; 28 | 29 | // Multiplier for weight so we can tilt values closer to each other 30 | virtual float getBaseWeightMultiplier() { return 1.; }; 31 | 32 | // Name of the rule 33 | virtual const char* getRuleName() = 0; 34 | 35 | // Short explanation of the rule 36 | virtual const char* getRuleExplanation() = 0; 37 | 38 | // Function to override to draw extra tweakable settings on ImGui, depending on rule. 39 | virtual bool drawImguiRuleExtra() { return false; }; 40 | 41 | public: 42 | float weight; 43 | bool isEnabled; 44 | 45 | // Copy constructor 46 | FlockingRule(const FlockingRule& toCopy); 47 | 48 | virtual std::unique_ptr clone() = 0; 49 | 50 | // Compute the force, weight it, and save it in cache. 51 | Vector2f computeWeightedForce(const std::vector& neighborhood, Boid* boid); 52 | 53 | // Draw the core of the rule settings on ImGui. 54 | virtual bool drawImguiRule(); 55 | 56 | // todo: probably we need to call this and change boid to particle 57 | // Inherited via Drawable 58 | virtual void draw(const Boid& boid, SDL_Renderer* renderer) const; 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | option(ENABLE_TEST_COVERAGE "Enable test coverage" ON) 2 | option(TEST_INSTALLED_VERSION "Test the version found by find_package" OFF) 3 | 4 | # --- Import tools ---- 5 | 6 | include(../cmake/tools.cmake) 7 | 8 | # ---- Dependencies ---- 9 | 10 | include(../external/cpm.cmake) 11 | 12 | CPMAddPackage("gh:onqtam/doctest@2.4.12") 13 | CPMAddPackage("gh:TheLartians/Format.cmake@1.7.3") 14 | 15 | # if(TEST_INSTALLED_VERSION) find_package(Concurrency REQUIRED) else() CPMAddPackage(NAME 16 | # Concurrency SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) endif() 17 | 18 | # ---- Create binary ---- 19 | 20 | file(GLOB sourcestest CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 21 | add_executable(CoreTests ${sourcestest}) 22 | target_link_libraries(CoreTests doctest::doctest core) # cpr) 23 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../core/) 24 | set_target_properties(CoreTests PROPERTIES CXX_STANDARD 20) 25 | 26 | # enable compiler warnings if(NOT TEST_INSTALLED_VERSION) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" 27 | # OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") target_compile_options(core PUBLIC -Wall -Wpedantic 28 | # -Wextra) target_compile_options(core PUBLIC -Wall -Wpedantic -Wextra -Werror) elseif(MSVC) 29 | # target_compile_options(core PUBLIC /W4 /WX) target_compile_definitions(CoreTests PUBLIC 30 | # DOCTEST_CONFIG_USE_STD_HEADERS) endif() endif() 31 | 32 | # ---- Add CoreTests ---- 33 | 34 | enable_testing() 35 | 36 | # Note: doctest and similar testing frameworks can automatically configure CMake tests. For other 37 | # testing frameworks add the tests target instead: add_test(NAME ${PROJECT_NAME} COMMAND 38 | # ${PROJECT_NAME}) 39 | 40 | include(${doctest_SOURCE_DIR}/scripts/cmake/doctest.cmake) 41 | doctest_discover_tests(CoreTests) 42 | 43 | # ---- code coverage ---- 44 | 45 | if(ENABLE_TEST_COVERAGE) 46 | target_compile_options(core PUBLIC -O0 -g -fprofile-arcs -ftest-coverage) 47 | target_link_options(core PUBLIC -fprofile-arcs -ftest-coverage) 48 | endif() 49 | -------------------------------------------------------------------------------- /editor/Editor.cpp: -------------------------------------------------------------------------------- 1 | // #include "Editor.h" 2 | // #include "imgui.h" 3 | // #include "Engine.h" 4 | // 5 | // void Editor::OnGui(ImGuiContext *context) { 6 | // ImGui::SetCurrentContext(context); 7 | // if (ImGui::BeginMainMenuBar()) 8 | // { 9 | // if (ImGui::BeginMenu("File")) 10 | // { 11 | // ImGui::MenuItem("New Scene"); 12 | // ImGui::MenuItem("Open Scene"); 13 | // ImGui::MenuItem("Open Recent"); 14 | // ImGui::Separator(); 15 | // ImGui::MenuItem("Save"); 16 | // ImGui::MenuItem("Save As..."); 17 | // ImGui::MenuItem("Save As Scene Template..."); 18 | // ImGui::Separator(); 19 | // ImGui::MenuItem("New Project..."); 20 | // ImGui::MenuItem("Open Project..."); 21 | // ImGui::MenuItem("Save Project"); 22 | // ImGui::Separator(); 23 | // ImGui::MenuItem("Build Settings"); 24 | // ImGui::Separator(); 25 | // if(ImGui::MenuItem("Exit")) 26 | // engine->Exit(); 27 | // 28 | // ImGui::EndMenu(); 29 | // } 30 | // if(ImGui::BeginMenu("Edit")) { 31 | // ImGui::EndMenu(); 32 | // } 33 | // if(ImGui::BeginMenu("Assets")) { 34 | // ImGui::EndMenu(); 35 | // } 36 | // if(ImGui::BeginMenu("GameObject")) { 37 | // ImGui::EndMenu(); 38 | // } 39 | // if(ImGui::BeginMenu("Component")) { 40 | // ImGui::EndMenu(); 41 | // } 42 | // if(ImGui::BeginMenu("Window")) { 43 | // ImGui::EndMenu(); 44 | // } 45 | // if(ImGui::BeginMenu("Help")) { 46 | // ImGui::EndMenu(); 47 | // } 48 | // ImGui::Separator(); 49 | // ImGui::Text("%.3fms (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); 50 | // ImGui::EndMenuBar(); 51 | // } 52 | // } 53 | // 54 | // Editor::Editor(Engine *pEngine) : GameObject(pEngine) {} -------------------------------------------------------------------------------- /examples/flocking/behaviours/BoundedAreaRule.cpp: -------------------------------------------------------------------------------- 1 | #include "BoundedAreaRule.h" 2 | #include "../gameobjects/Boid.h" 3 | #include "../gameobjects/World.h" 4 | #include "engine/Engine.h" 5 | 6 | Vector2f BoundedAreaRule::computeForce(const std::vector& neighborhood, Boid* boid) { 7 | // Return a force proportional to the proximity of the boids with the bounds, and opposed to it 8 | Vector2f force = Vector2f::zero(); // zero 9 | 10 | // todo: add here your code code here do make the boid follow the bounded box rule 11 | // hint: use this->world->engine->window->size() and desiredDistance 12 | 13 | return force; 14 | } 15 | 16 | bool BoundedAreaRule::drawImguiRuleExtra() { 17 | ImGui::SetCurrentContext(world->engine->window->imGuiContext); 18 | auto size = this->world->engine->window->size(); 19 | auto widthWindows = size.x; 20 | auto heightWindows = size.y; 21 | bool valueHasChanged = false; 22 | 23 | // We cap the max separation as the third of the min of the width.height 24 | auto minHeightWidth = std::min(widthWindows, heightWindows); 25 | 26 | if (ImGui::SliderInt("Desired Distance From Borders", &desiredDistance, 0.0f, (int)(minHeightWidth / 3), "%i")) { 27 | valueHasChanged = true; 28 | } 29 | 30 | return valueHasChanged; 31 | } 32 | 33 | void BoundedAreaRule::draw(const Boid& boid, SDL_Renderer* renderer) const { 34 | FlockingRule::draw(boid, renderer); 35 | auto size = this->world->engine->window->size(); 36 | auto dist = (float)desiredDistance; 37 | 38 | // Draw a rectangle on the map 39 | Polygon::DrawLine(renderer, Vector2f(dist, dist), Vector2f(size.x - dist, dist), Color::Gray); // TOP 40 | Polygon::DrawLine(renderer, Vector2f(size.x - dist, dist), Vector2f(size.x - dist, size.y - dist), Color::Gray); // RIGHT 41 | Polygon::DrawLine(renderer, Vector2f(size.x - dist, size.y - dist), Vector2f(dist, size.y - dist), Color::Gray); // Bottom 42 | Polygon::DrawLine(renderer, Vector2f(dist, size.y - dist), Vector2f(dist, dist), Color::Gray); // LEFT 43 | } -------------------------------------------------------------------------------- /cmake/tools.cmake: -------------------------------------------------------------------------------- 1 | # todo: move this to external 2 | 3 | # this file contains a list of tools that can be activated and downloaded on-demand each tool is 4 | # enabled during configuration by passing an additional `-DUSE_=` argument to CMake 5 | 6 | # only activate tools for top level project 7 | if(NOT PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 8 | return() 9 | endif() 10 | 11 | include(${CMAKE_SOURCE_DIR}/external/cpm.cmake) 12 | 13 | # enables sanitizers support using the the `USE_SANITIZER` flag available values are: Address, 14 | # Memory, MemoryWithOrigins, Undefined, Thread, Leak, 'Address;Undefined' 15 | if(USE_SANITIZER OR USE_STATIC_ANALYZER) 16 | CPMAddPackage("gh:StableCoder/cmake-scripts#1f822d1fc87c8d7720c074cde8a278b44963c354") 17 | 18 | if(USE_SANITIZER) 19 | include(${cmake-scripts_SOURCE_DIR}/sanitizers.cmake) 20 | endif() 21 | 22 | if(USE_STATIC_ANALYZER) 23 | if("clang-tidy" IN_LIST USE_STATIC_ANALYZER) 24 | set(CLANG_TIDY 25 | ON 26 | CACHE INTERNAL "" 27 | ) 28 | else() 29 | set(CLANG_TIDY 30 | OFF 31 | CACHE INTERNAL "" 32 | ) 33 | endif() 34 | if("iwyu" IN_LIST USE_STATIC_ANALYZER) 35 | set(IWYU 36 | ON 37 | CACHE INTERNAL "" 38 | ) 39 | else() 40 | set(IWYU 41 | OFF 42 | CACHE INTERNAL "" 43 | ) 44 | endif() 45 | if("cppcheck" IN_LIST USE_STATIC_ANALYZER) 46 | set(CPPCHECK 47 | ON 48 | CACHE INTERNAL "" 49 | ) 50 | else() 51 | set(CPPCHECK 52 | OFF 53 | CACHE INTERNAL "" 54 | ) 55 | endif() 56 | 57 | include(${cmake-scripts_SOURCE_DIR}/tools.cmake) 58 | 59 | clang_tidy(${CLANG_TIDY_ARGS}) 60 | include_what_you_use(${IWYU_ARGS}) 61 | cppcheck(${CPPCHECK_ARGS}) 62 | endif() 63 | endif() 64 | 65 | # enables CCACHE support through the USE_CCACHE flag possible values are: YES, NO or equivalent 66 | if(USE_CCACHE) 67 | CPMAddPackage("gh:TheLartians/Ccache.cmake@1.2.3") 68 | endif() 69 | -------------------------------------------------------------------------------- /examples/flocking/behaviours/FlockingRule.cpp: -------------------------------------------------------------------------------- 1 | #include "FlockingRule.h" 2 | 3 | #include "imgui.h" 4 | #include "../utils/ImGuiExtra.h" 5 | #include "Polygon.h" 6 | #include "../gameobjects/Boid.h" 7 | #include "../gameobjects/World.h" 8 | #include "engine/Engine.h" 9 | 10 | FlockingRule::FlockingRule(const FlockingRule& toCopy) 11 | : weight(toCopy.weight), debugColor(toCopy.debugColor), force(toCopy.force), isEnabled(toCopy.isEnabled), world(toCopy.world) {} 12 | 13 | Vector2f FlockingRule::computeWeightedForce(const std::vector& neighborhood, Boid* boid) { 14 | // the computed force is cached in a var 15 | if (isEnabled) { 16 | force = getBaseWeightMultiplier() * weight * computeForce(neighborhood, boid); 17 | } else { 18 | // If the rule is not enabled, return vector zero. 19 | force = Vector2f::zero(); 20 | } 21 | 22 | return force; 23 | } 24 | 25 | bool FlockingRule::drawImguiRule() { 26 | ImGui::SetCurrentContext(world->engine->window->imGuiContext); 27 | bool valueHasChanged = false; 28 | 29 | ImGui::SetNextItemOpen(isEnabled, ImGuiCond_Once); // Opened by default if rule active 30 | if (ImGui::TreeNode(getRuleName())) { 31 | ImguiTooltip(getRuleExplanation()); 32 | 33 | if (ImGui::Checkbox("Enabled", &isEnabled)) { 34 | valueHasChanged = true; 35 | } 36 | 37 | if (isEnabled) { 38 | if (ImGui::DragFloat("Weight##", &weight, 0.025f)) { 39 | valueHasChanged = true; 40 | } 41 | 42 | ImGui::SameLine(); 43 | HelpMarker("Drag to change the weight's value or CTRL+Click to input a new value."); 44 | 45 | // Additional settings rule-dependant 46 | if (drawImguiRuleExtra()) { 47 | valueHasChanged = true; 48 | } 49 | } 50 | 51 | ImGui::TreePop(); 52 | } else 53 | ImguiTooltip(getRuleExplanation()); 54 | 55 | return valueHasChanged; 56 | } 57 | 58 | void FlockingRule::draw(const Boid& boid, SDL_Renderer* renderer) const { 59 | Polygon::DrawLine(renderer, boid.transform.position, boid.transform.position + force * 1.5f, debugColor); 60 | } 61 | -------------------------------------------------------------------------------- /examples/maze/World.h: -------------------------------------------------------------------------------- 1 | #ifndef MOBAGEN_WORLD_H 2 | #define MOBAGEN_WORLD_H 3 | 4 | #include "math/ColorT.h" 5 | #include "scene/GameObject.h" 6 | #include "MazeGeneratorBase.h" 7 | #include "Node.h" 8 | #include "math/Point2D.h" 9 | #include 10 | 11 | class World : GameObject { 12 | private: 13 | int sideSize; 14 | 15 | std::vector generators; 16 | int generatorId = 0; 17 | bool isSimulating = false; 18 | float timeBetweenAITicks = 0.0; 19 | float timeForNextTick = 0; 20 | int64_t moveDuration = 0; 21 | int64_t totalTime = 0; 22 | 23 | // ._ 24 | // | 25 | // even indexes are top elements; 26 | // odd indexes are left elements; 27 | std::vector data; 28 | // the boxes colors 29 | std::vector colors; 30 | // convert a point into the index of the left vertex of the node 31 | inline int Point2DtoIndex(const Point2D& point) { 32 | // todo: test. unstable interface 33 | auto sizeOver2 = sideSize / 2; 34 | return (point.y + sizeOver2) * (sideSize + 1) * 2 + (point.x + sizeOver2) * 2; 35 | } 36 | 37 | public: 38 | ~World(); 39 | explicit World(Engine* pEngine, int size); 40 | 41 | Node GetNode(const Point2D& point); 42 | bool GetNorth(const Point2D& point); 43 | bool GetEast(const Point2D& point); 44 | bool GetSouth(const Point2D& point); 45 | bool GetWest(const Point2D& point); 46 | 47 | void SetNode(const Point2D& point, const Node& node); 48 | void SetNorth(const Point2D& point, const bool& state); 49 | void SetEast(const Point2D& point, const bool& state); 50 | void SetSouth(const Point2D& point, const bool& state); 51 | void SetWest(const Point2D& point, const bool& state); 52 | 53 | void Start() override; 54 | void OnGui(ImGuiContext* context) override; 55 | void OnDraw(SDL_Renderer* renderer) override; 56 | void Update(float deltaTime) override; 57 | 58 | void Clear(); 59 | 60 | void SetNodeColor(const Point2D& node, const Color32& color); 61 | Color32 GetNodeColor(const Point2D& node); 62 | 63 | int GetSize() const; 64 | 65 | private: 66 | void step(); 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /examples/life/World.cpp: -------------------------------------------------------------------------------- 1 | #include "World.h" 2 | #include "Random.h" 3 | void World::Resize(int size) { 4 | currentBufferId = 0; 5 | sideSize = size; 6 | buffer[0].clear(); 7 | buffer[0].resize(size * size); 8 | buffer[1].clear(); 9 | buffer[1].resize(size * size); 10 | } 11 | void World::SwapBuffers() { 12 | currentBufferId = (currentBufferId + 1) % 2; 13 | for (int i = 0; i < buffer[currentBufferId].size(); i++) buffer[(currentBufferId + 1) % 2][i] = buffer[currentBufferId][i]; 14 | } 15 | // todo: improve those set / get accessors 16 | void World::SetNext(Point2D point, bool value) { 17 | if (point.x < 0) point.x += sideSize; 18 | if (point.x >= sideSize) point.x %= sideSize; 19 | if (point.y < 0) point.y += sideSize; 20 | if (point.y >= sideSize) point.y %= sideSize; 21 | auto index = point.y * sideSize + point.x; 22 | auto sideSquared = sideSize * sideSize; 23 | if (index >= sideSquared) index %= sideSquared; 24 | buffer[(currentBufferId + 1) % 2][index] = value; 25 | } 26 | // todo: improve those set / get accessors 27 | void World::SetCurrent(Point2D point, bool value) { 28 | if (point.x < 0) point.x += sideSize; 29 | if (point.x >= sideSize) point.x %= sideSize; 30 | if (point.y < 0) point.y += sideSize; 31 | if (point.y >= sideSize) point.y %= sideSize; 32 | auto index = point.y * sideSize + point.x; 33 | auto sideSquared = sideSize * sideSize; 34 | if (index >= sideSquared) index %= sideSquared; 35 | buffer[currentBufferId % 2][index] = value; 36 | } 37 | // todo: improve those set / get accessors 38 | bool World::Get(Point2D point) { 39 | if (point.x < 0) point.x += sideSize; 40 | if (point.x >= sideSize) point.x %= sideSize; 41 | if (point.y < 0) point.y += sideSize; 42 | if (point.y >= sideSize) point.y %= sideSize; 43 | auto index = point.y * sideSize + point.x; 44 | auto sideSquared = sideSize * sideSize; 45 | if (index >= sideSquared) index %= sideSquared; 46 | return buffer[currentBufferId % 2][index]; 47 | } 48 | void World::Randomize() { 49 | for (auto&& elem : buffer[0]) elem = (Random::Range(0, 1) != 0); 50 | 51 | for (int i = 0; i < buffer[0].size(); i++) buffer[1][i] = buffer[0][i]; 52 | } 53 | -------------------------------------------------------------------------------- /external/external.cmake: -------------------------------------------------------------------------------- 1 | if(COMMAND cmake_policy) 2 | cmake_policy(SET CMP0003 NEW) 3 | endif(COMMAND cmake_policy) 4 | 5 | if(EMSCRIPTEN) 6 | 7 | elseif(ANDROID) 8 | # set( SDL_STATIC ON CACHE BOOL "Build the static SDL library" ) set( SDL_SHARED OFF CACHE BOOL 9 | # "Build the shared SDL library" ) # set( SDL_FILESYSTEM FALSE ) set( PTHREADS OFF CACHE BOOL 10 | # "Pthread support" ) add_definitions(-DGL_GLEXT_PROTOTYPES) 11 | else() 12 | # INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/whereami/src/) IF (WIN32) add_library (whereami 13 | # STATIC ${CMAKE_CURRENT_SOURCE_DIR}/whereami/src/whereami.c 14 | # ${CMAKE_CURRENT_SOURCE_DIR}/whereami/src/whereami.h) ELSE () add_library (whereami SHARED 15 | # ${CMAKE_CURRENT_SOURCE_DIR}/whereami/src/whereami.c 16 | # ${CMAKE_CURRENT_SOURCE_DIR}/whereami/src/whereami.h) ENDIF () set( SDL_STATIC OFF CACHE BOOL 17 | # "Build the static SDL library" ) set( SDL_SHARED ON CACHE BOOL "Build the shared SDL library" ) 18 | 19 | # set( glew-cmake_BUILD_SHARED ON CACHE BOOL "Build the shared glew library" ) set( 20 | # glew-cmake_BUILD_STATIC OFF CACHE BOOL "Build the static glew library" ) set( 21 | # glew-cmake_BUILD_SINGLE_CONTEXT ON CACHE BOOL "Build the single context glew library" ) set( 22 | # glew-cmake_BUILD_MULTI_CONTEXT OFF CACHE BOOL "Build the multi context glew library" ) 23 | # 24 | # add_subdirectory( glew ) 25 | endif() 26 | 27 | # include(external/quickjs.cmake) if(NOT EMSCRIPTEN) IF(APPLE) set(CMAKE_THREAD_LIBS_INIT 28 | # "-lpthread") set(CMAKE_HAVE_THREADS_LIBRARY 1) set(CMAKE_USE_WIN32_THREADS_INIT 0) 29 | # set(CMAKE_USE_PTHREADS_INIT 1) set(THREADS_PREFER_PTHREAD_FLAG ON) ENDIF() find_package(Threads 30 | # REQUIRED) include(external/wasm.cmake) include(external/v8.cmake) endif() 31 | 32 | # include(external/quickjs.cmake) include(filament.cmake) include(threadpool.cmake) 33 | # include(external/zlib.cmake) 34 | include(external/sdl.cmake) 35 | # include(glm.cmake) include(glew.cmake) 36 | include(external/imgui.cmake) 37 | # if(NOT EMSCRIPTEN) include(external/mbedtls.cmake) include(external/curl.cmake) 38 | # include(external/cpr.cmake) endif() include(assimp.cmake) include(bullet.cmake) 39 | -------------------------------------------------------------------------------- /documentation/INSPIRATION.md: -------------------------------------------------------------------------------- 1 | - https://www.haroldserrano.com/blog/books-i-used-to-develop-a-game-engine 2 | - https://gafferongames.com/ 3 | - https://www.redblobgames.com/ 4 | - https://research.ncl.ac.uk/game/mastersdegree/gametechnologies/previousinformation/ 5 | - https://www.toptal.com/game/video-game-physics-part-i-an-introduction-to-rigid-body-dynamics 6 | - http://www.aortiz.me/2018/12/21/CG.html 7 | - https://github.com/Angelo1211/SoftwareRenderer/wiki/Rendering-References 8 | - https://fabiensanglard.net/duke3d/id%20as%20Super-Ego-%20The%20Creation%20of%20Duke%20Nukem%203D.pdf 9 | - https://fabiensanglard.net/ 10 | - https://www.gamedesigning.org/learn/make-a-game-engine/ 11 | - http://twvideo01.ubm-us.net/o1/vault/gdc2015/presentations/Gyrling_Christian_Parallelizing_The_Naughty.pdf 12 | - https://software.intel.com/content/www/us/en/develop/articles/designing-the-framework-of-a-parallel-game-engine.html 13 | - https://learnopengl.com/ 14 | - https://github.com/id-Software 15 | - https://www.gamasutra.com/blogs/MichaelKissner/20151027/257369/Writing_a_Game_Engine_from_Scratch__Part_1_Messaging.php 16 | - https://fabiensanglard.net/duke3d/index.php 17 | - https://github.com/Shervanator/Engine 18 | - https://github.com/urho3d/Urho3D 19 | - https://github.com/godotengine/godot 20 | - https://github.com/OGRECave/ogre 21 | - http://irrlicht.sourceforge.net/ 22 | - https://github.com/spring 23 | - https://github.com/cocos2d/cocos2d-x 24 | - https://github.com/MonoGame/MonoGame 25 | - https://github.com/libgdx/libgdx 26 | - https://github.com/CRYTEK/CRYENGINE 27 | - https://openmw.org/en/ 28 | - http://www.horde3d.org/ 29 | - https://www.unrealengine.com/en-US/eula 30 | - https://github.com/EpicGames/UnrealEngine 31 | 32 | - https://unity3d.com/ 33 | 34 | Uses the following 3rd party libraries: 35 | - SDL2 window library. 36 | - stb_image.h image library. 37 | - OpenGL 3 / OpenGL ES 2.0 / OpenGL ES 3.0 Graphics APIs. 38 | - Assimp asset importing library. 39 | - GLEW extension loading library. 40 | - Dear ImGui UI library. 41 | 42 | Docs: 43 | - https://medium.com/@kevinkreuzer/the-way-to-fully-automated-releases-in-open-source-projects-44c015f38fd6?_branch_match_id=467041473575681523 44 | -------------------------------------------------------------------------------- /examples/chess/pieces/Bishop.cpp: -------------------------------------------------------------------------------- 1 | #include "Bishop.h" 2 | unordered_set Bishop::AttackMoves(WorldState& world, const Point2D& origin) { 3 | auto piece = world.PieceAtPosition(origin); 4 | if (piece.Piece() != PieceType::Bishop) return {}; 5 | 6 | unordered_set moves; 7 | 8 | vector const directions = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; 9 | 10 | for (auto direction : directions) { 11 | Point2D currentPosition; 12 | PieceData otherPiece; 13 | for (currentPosition = origin + direction, otherPiece = world.PieceAtPosition(currentPosition); otherPiece.Piece() != PieceType::WRONG; 14 | currentPosition += direction, otherPiece = world.PieceAtPosition(currentPosition)) { 15 | // add if it is empty and continue 16 | if (otherPiece.Piece() == PieceType::NONE) moves.insert(currentPosition); 17 | // add if it is the opposite color and break 18 | else if (otherPiece.Color() != piece.Color()) { 19 | moves.insert(currentPosition); 20 | break; 21 | } else 22 | break; 23 | // if it is the same color 24 | } 25 | } 26 | return moves; 27 | } 28 | unordered_set Bishop::CoverMoves(WorldState& world, const Point2D& origin) { 29 | auto piece = world.PieceAtPosition(origin); 30 | if (piece.Piece() != PieceType::Bishop) return {}; 31 | 32 | unordered_set moves; 33 | 34 | vector const directions = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; 35 | 36 | for (auto direction : directions) { 37 | Point2D currentPosition; 38 | PieceData otherPiece; 39 | for (currentPosition = origin + direction, otherPiece = world.PieceAtPosition(currentPosition); otherPiece.Piece() != PieceType::WRONG; 40 | currentPosition += direction, otherPiece = world.PieceAtPosition(currentPosition)) { 41 | // add if it is empty and continue 42 | if (otherPiece.Piece() == PieceType::NONE) moves.insert(currentPosition); 43 | // add if it is the opposite color and break 44 | else if (otherPiece.Color() == piece.Color()) { 45 | moves.insert(currentPosition); 46 | break; 47 | } else 48 | break; 49 | // if it is the same color 50 | } 51 | } 52 | return moves; 53 | } 54 | -------------------------------------------------------------------------------- /examples/catchthecat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB CATCHTHECAT_INC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h 2 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 3 | ) 4 | 5 | file(GLOB CATCHTHECAT_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 7 | ) 8 | 9 | # If(NOT EMSCRIPTEN AND NOT ANDROID) add_definitions(-DGLEW_STATIC) # add_definitions(-DGLEW_BUILD) 10 | # set(GLEW_USE_STATIC_LIBS ON CACHE BOOL "bla") set(BUILD_SHARED_LIBS OFF CACHE BOOL "bla") set( 11 | # glew-cmake_BUILD_SHARED OFF CACHE BOOL "Build the shared glew library" ) set( 12 | # glew-cmake_BUILD_STATIC ON CACHE BOOL "Build the static glew library" ) set( 13 | # glew-cmake_BUILD_SINGLE_CONTEXT ON CACHE BOOL "Build the single context glew library" ) set( 14 | # glew-cmake_BUILD_MULTI_CONTEXT OFF CACHE BOOL "Build the multi context glew library" ) 15 | # 16 | # message(STATUS "######################### ADDING GLEW #######################################") 17 | # hunter_add_package(glew) find_package(glew CONFIG REQUIRED) 18 | # 19 | # target_link_libraries (engine PUBLIC ${ENGINE_LIBS} glew::glew) ELSE() target_link_libraries 20 | # (engine PUBLIC ${ENGINE_LIBS}) ENDIF() 21 | 22 | # TODO: Check if this approach bellow is better IF (ANDROID) add_library (engine STATIC 23 | # ${TARGET_SRC}) ELSE () add_library (engine SHARED ${TARGET_SRC}) ENDIF () 24 | # 25 | # target_link_libraries (engine ${ENGINE_LIBS}) set_target_properties(engine PROPERTIES 26 | # COTIRE_CXX_PREFIX_HEADER_INIT "stdafx.h") cotire(engine) 27 | 28 | # todo: check this install (TARGETS editor DESTINATION lib) 29 | install(FILES ${CATCHTHECAT_INC} DESTINATION include/catchthecat) 30 | 31 | # TODO: ADD THIS BACK WHEN NEEDED IF (NOT TARGET uninstall) # add make uninstall capability 32 | # configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in" 33 | # "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall 34 | # "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() 35 | 36 | add_executable(catchthecat ${CATCHTHECAT_SRC} ${CATCHTHECAT_INC}) 37 | target_link_libraries(catchthecat PUBLIC SDL2-static IMGUI core) 38 | target_include_directories(catchthecat PUBLIC ${SDL2_INCLUDE_DIR} ${CORE_INC_DIR}) 39 | -------------------------------------------------------------------------------- /examples/chess/pieces/Rook.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Rook.h" 3 | // todo: castling behavior 4 | unordered_set Rook::AttackMoves(WorldState& world, const Point2D& origin) { 5 | auto piece = world.PieceAtPosition(origin); 6 | if (piece.Piece() != PieceType::Rook) return {}; 7 | 8 | unordered_set moves; 9 | 10 | vector const directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; 11 | 12 | for (auto direction : directions) { 13 | Point2D currentPosition; 14 | PieceData otherPiece; 15 | for (currentPosition = origin + direction, otherPiece = world.PieceAtPosition(currentPosition); otherPiece.Piece() != PieceType::WRONG; 16 | currentPosition += direction, otherPiece = world.PieceAtPosition(currentPosition)) { 17 | // add if it is empty and continue 18 | if (otherPiece.Piece() == PieceType::NONE) moves.insert(currentPosition); 19 | // add if it is the opposite color and break 20 | else if (otherPiece.Color() != piece.Color()) { 21 | moves.insert(currentPosition); 22 | break; 23 | } else 24 | break; 25 | // if it is the same color 26 | } 27 | } 28 | return moves; 29 | } 30 | unordered_set Rook::CoverMoves(WorldState& world, const Point2D& origin) { 31 | auto piece = world.PieceAtPosition(origin); 32 | if (piece.Piece() != PieceType::Rook) return {}; 33 | 34 | unordered_set moves; 35 | 36 | vector const directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; 37 | 38 | for (auto direction : directions) { 39 | Point2D currentPosition; 40 | PieceData otherPiece; 41 | for (currentPosition = origin + direction, otherPiece = world.PieceAtPosition(currentPosition); otherPiece.Piece() != PieceType::WRONG; 42 | currentPosition += direction, otherPiece = world.PieceAtPosition(currentPosition)) { 43 | // add if it is empty and continue 44 | if (otherPiece.Piece() == PieceType::NONE) moves.insert(currentPosition); 45 | // add if it is the opposite color and break 46 | else if (otherPiece.Color() == piece.Color()) { 47 | moves.insert(currentPosition); 48 | break; 49 | } else 50 | break; 51 | // if it is the same color 52 | } 53 | } 54 | return moves; 55 | } 56 | -------------------------------------------------------------------------------- /examples/chess/pieces/Queen.cpp: -------------------------------------------------------------------------------- 1 | #include "Queen.h" 2 | unordered_set Queen::AttackMoves(WorldState& world, const Point2D& origin) { 3 | auto piece = world.PieceAtPosition(origin); 4 | if (piece.Piece() != PieceType::Queen) return {}; 5 | 6 | unordered_set moves; 7 | 8 | vector const directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; 9 | 10 | for (auto direction : directions) { 11 | Point2D currentPosition; 12 | PieceData otherPiece; 13 | for (currentPosition = origin + direction, otherPiece = world.PieceAtPosition(currentPosition); otherPiece.Piece() != PieceType::WRONG; 14 | currentPosition += direction, otherPiece = world.PieceAtPosition(currentPosition)) { 15 | // add if it is empty and continue 16 | if (otherPiece.Piece() == PieceType::NONE) moves.insert(currentPosition); 17 | // add if it is the opposite color and break 18 | else if (otherPiece.Color() != piece.Color()) { 19 | moves.insert(currentPosition); 20 | break; 21 | } else 22 | break; 23 | // if it is the same color 24 | } 25 | } 26 | return moves; 27 | } 28 | unordered_set Queen::CoverMoves(WorldState& world, const Point2D& origin) { 29 | auto piece = world.PieceAtPosition(origin); 30 | if (piece.Piece() != PieceType::Queen) return {}; 31 | 32 | unordered_set moves; 33 | 34 | vector const directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; 35 | 36 | for (auto direction : directions) { 37 | Point2D currentPosition; 38 | PieceData otherPiece; 39 | for (currentPosition = origin + direction, otherPiece = world.PieceAtPosition(currentPosition); otherPiece.Piece() != PieceType::WRONG; 40 | currentPosition += direction, otherPiece = world.PieceAtPosition(currentPosition)) { 41 | // add if it is empty and continue 42 | if (otherPiece.Piece() == PieceType::NONE) moves.insert(currentPosition); 43 | // add if it is the opposite color and break 44 | else if (otherPiece.Color() == piece.Color()) { 45 | moves.insert(currentPosition); 46 | break; 47 | } else 48 | break; 49 | // if it is the same color 50 | } 51 | } 52 | return moves; 53 | } 54 | -------------------------------------------------------------------------------- /core/Polygon.cpp: -------------------------------------------------------------------------------- 1 | #include "Polygon.h" 2 | #include "math/ColorT.h" 3 | 4 | std::vector Polygon::getDrawablePoints(const Transform& transform) { 5 | std::vector ret; 6 | for (auto p : points) { 7 | auto scaled = Vector2f(transform.scale.x * p.x, transform.scale.y * p.y); 8 | auto rotated = scaled.Rotate(transform.rotation.getAngleDegree()); 9 | auto displaced = rotated + transform.position; 10 | ret.push_back(displaced); 11 | } 12 | return ret; 13 | } 14 | 15 | void Polygon::Draw(SDL_Renderer* renderer, const Transform& transform, const Color32& color) { 16 | SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, SDL_ALPHA_OPAQUE); 17 | auto drawablePoints = getDrawablePoints(transform); 18 | for (int i = 0; i < drawablePoints.size(); i++) { 19 | int other = i + 1; 20 | if (other == drawablePoints.size()) other = 0; 21 | SDL_RenderDrawLine(renderer, (int)drawablePoints[i].x, (int)drawablePoints[i].y, (int)drawablePoints[other].x, (int)drawablePoints[other].y); 22 | } 23 | } 24 | 25 | void Polygon::DrawLine(SDL_Renderer* renderer, const Vector2f& v1, const Vector2f& v2, const Color32& color) { 26 | SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, SDL_ALPHA_OPAQUE); 27 | SDL_RenderDrawLine(renderer, (int)v1.x, (int)v1.y, (int)v2.x, (int)v2.y); 28 | } 29 | 30 | void Polygon::Draw(SDL_Renderer* renderer, const Vector2f& position, const Vector2f& scale, const Vector2f& rotation, const Color32& color) { 31 | Transform transform = {position, scale, rotation}; 32 | Draw(renderer, transform, color); 33 | } 34 | 35 | Circle::Circle(int sample) { 36 | for (int i = 0; i < sample; i++) { 37 | Vector2f point = Vector2f::up().Rotate(360.f * (float)i / (float)sample); 38 | points.push_back(point); 39 | } 40 | } 41 | 42 | Square::Square() { 43 | points.push_back(Vector2f::up().Rotate(45)); 44 | points.push_back(Vector2f::up().Rotate(135)); 45 | points.push_back(Vector2f::up().Rotate(225)); 46 | points.push_back(Vector2f::up().Rotate(315)); 47 | } 48 | 49 | Hexagon::Hexagon() { 50 | points.push_back(Vector2f::up().Rotate(0)); 51 | points.push_back(Vector2f::up().Rotate(60)); 52 | points.push_back(Vector2f::up().Rotate(120)); 53 | points.push_back(Vector2f::up().Rotate(180)); 54 | points.push_back(Vector2f::up().Rotate(240)); 55 | points.push_back(Vector2f::up().Rotate(300)); 56 | } 57 | -------------------------------------------------------------------------------- /examples/headless/main.cpp: -------------------------------------------------------------------------------- 1 | #define SDL_MAIN_HANDLED true 2 | #include "engine/Engine.h" 3 | #include "scene/GameObject.h" 4 | #include "SDL.h" 5 | #include 6 | 7 | // Simple test object that runs for a limited time in headless mode 8 | class HeadlessTestObject : public GameObject { 9 | private: 10 | float totalTime = 0.0f; 11 | float maxRunTime = 5.0f; // Run for 5 seconds 12 | int frameCount = 0; 13 | 14 | public: 15 | HeadlessTestObject(Engine* pEngine) : GameObject(pEngine) {} 16 | 17 | void Update(float deltaTime) override { 18 | totalTime += deltaTime; 19 | frameCount++; 20 | 21 | // Log progress every second 22 | if (frameCount % 60 == 0) { // Assuming 60 FPS 23 | SDL_Log("Headless simulation running: %.2f seconds, frame %d", totalTime, frameCount); 24 | } 25 | 26 | // Exit after maxRunTime seconds 27 | if (totalTime >= maxRunTime) { 28 | SDL_Log("Headless simulation completed after %.2f seconds (%d frames)", totalTime, frameCount); 29 | engine->Exit(); 30 | } 31 | } 32 | 33 | void OnDraw(SDL_Renderer* renderer) override { 34 | // This should never be called in headless mode 35 | SDL_Log("Warning: OnDraw called in headless mode!"); 36 | } 37 | 38 | void OnGui(ImGuiContext* context) override { 39 | // This should never be called in headless mode 40 | SDL_Log("Warning: OnGui called in headless mode!"); 41 | } 42 | }; 43 | 44 | // Main code 45 | int main(int, char**) { 46 | SDL_Log("Creating Headless Engine"); 47 | 48 | // Create engine settings with headless mode enabled 49 | EngineSettings settings; 50 | settings.headless = true; 51 | settings.debug = true; 52 | 53 | auto engine = new Engine(settings); 54 | SDL_Log("Headless Engine Created"); 55 | 56 | SDL_Log("Creating Test Object"); 57 | new HeadlessTestObject(engine); 58 | SDL_Log("Test Object Created"); 59 | 60 | SDL_Log("Starting Headless Engine"); 61 | if (engine->Start("Headless Test")) { 62 | SDL_Log("Headless Engine Started"); 63 | 64 | SDL_Log("Running Headless Engine"); 65 | engine->Run(); 66 | SDL_Log("Headless Engine Stopped"); 67 | } 68 | 69 | SDL_Log("Exiting Headless Engine"); 70 | engine->Exit(); 71 | delete engine; 72 | SDL_Log("Headless Engine Exited"); 73 | 74 | std::cout << "Headless simulation completed successfully!" << std::endl; 75 | return 0; 76 | } -------------------------------------------------------------------------------- /documentation/doxygen/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | 14 | 15 | 16 | $treeview 17 | $search 18 | $mathjax 19 | 20 | $extrastylesheet 21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
36 |
$projectname 37 |  $projectnumber 38 |
39 |
$projectbrief
40 |
45 |
$projectbrief
46 |
$searchbox
57 |
58 | 59 | 60 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16.3 FATAL_ERROR) 2 | 3 | # CPM downloader 4 | include(external/cpm.cmake) 5 | 6 | # project declaration 7 | project( 8 | MoBaGEn 9 | VERSION 0.0.1 10 | HOMEPAGE_URL "https://infinbrains.com" 11 | DESCRIPTION "Module Based Game Engine" 12 | LANGUAGES C CXX 13 | ) 14 | 15 | # Include guards 16 | if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) 17 | message( 18 | FATAL_ERROR 19 | "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there." 20 | ) 21 | endif() 22 | 23 | # compiler checks 24 | include(external/compilerchecks.cmake) 25 | 26 | # set output dirs 27 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/libs) 28 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/libs) 29 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 30 | 31 | # set linkage 32 | link_directories(${CMAKE_BINARY_DIR}/libs) 33 | # LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/libs/Debug) 34 | 35 | if(EMSCRIPTEN) 36 | message(STATUS "emscripten build") 37 | set(CMAKE_CXX_FLAGS 38 | "${CMAKE_CXX_FLAGS} -Oz -s WASM=2 -s USE_SDL=0 -s ASYNCIFY -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1" 39 | ) 40 | set(CMAKE_C_FLAGS 41 | "${CMAKE_C_FLAGS} -Oz -s WASM=2 -s USE_SDL=0 -s ASYNCIFY -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1" 42 | ) 43 | 44 | file(GLOB HTML "${CMAKE_CURRENT_SOURCE_DIR}/html/*") 45 | file(COPY ${HTML} DESTINATION ${CMAKE_BINARY_DIR}/bin/) 46 | 47 | set(ENABLE_TEST_COVERAGE OFF) 48 | endif() 49 | 50 | include(cmake/subdirlist.cmake) 51 | 52 | include(external/external.cmake) 53 | 54 | add_subdirectory(modules) 55 | add_subdirectory(core) 56 | 57 | option(ENABLE_TEST_COVERAGE "ENABLE_TEST_COVERAGE" ON) 58 | if(ENABLE_TEST_COVERAGE) 59 | add_subdirectory(test) 60 | endif() 61 | 62 | option(BUILD_EXAMPLES "BUILD_EXAMPLES" ON) 63 | if(BUILD_EXAMPLES) 64 | add_subdirectory(examples) 65 | endif() 66 | 67 | option(ENABLE_DOCUMENTATION "ENABLE_DOCUMENTATION" OFF) 68 | if(ENABLE_DOCUMENTATION) 69 | add_subdirectory(documentation) 70 | endif() 71 | 72 | option(ENABLE_EDITOR "ENABLE_EDITOR" ON) 73 | if(ENABLE_EDITOR) 74 | add_subdirectory(editor) 75 | endif() 76 | 77 | CPMAddPackage( 78 | NAME CPMLicenses.cmake 79 | GITHUB_REPOSITORY cpm-cmake/CPMLicenses.cmake 80 | VERSION 0.0.5 81 | ) 82 | write_license_disclaimer("third_party.txt" "${CPM_PACKAGES}") 83 | 84 | # todo: follow https://github.com/TheLartians/ModernCppStarter 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mobagen", 3 | "version": "0.0.1", 4 | "description": "Module Based Game Engine", 5 | "main": "bin-emscripten/bin/index.js", 6 | "directories": { 7 | "doc": "documentation", 8 | "example": "examples", 9 | "engine": "engine" 10 | }, 11 | "scripts": { 12 | "test": "test", 13 | "pregenerate:windows:clang": "rimraf build", 14 | "generate:windows:clang": "cmake -H. -Bbuild -G \"Visual Studio 16 2019\" -T ClangCL -DCMAKE_BUILD_TYPE=MinSizeRel", 15 | "build": "cmake --build build --config MinSizeRel", 16 | "run": "cmake --open build", 17 | "release": "npx -y semantic-release", 18 | "prestyle": "cmake -S. -BbuildStyle -DENABLE_TEST_COVERAGE=ON -DENABLE_DOCUMENTATION=OFF", 19 | "style": "cmake --build buildStyle --target fix-format", 20 | "prebuildall": "cmake -S. -Bbuild -DENABLE_TEST_COVERAGE=OFF -DENABLE_DOCUMENTATION=OFF", 21 | "buildall": "cmake --build build --parallel", 22 | "buildwebgl": "bash scripts/emscripten-build.sh" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/InfiniBrains/mobagen.git" 27 | }, 28 | "keywords": [ 29 | "GameEngine", 30 | "SDL", 31 | "CPP", 32 | "WASM", 33 | "EMSCRIPTEN" 34 | ], 35 | "author": "InfiniBrains", 36 | "license": "MIT", 37 | "bugs": { 38 | "url": "https://github.com/InfiniBrains/mobagen/issues" 39 | }, 40 | "homepage": "https://github.com/InfiniBrains/mobagen#readme", 41 | "dependencies": { 42 | "@semantic-release/changelog": "^6.0.2", 43 | "@semantic-release/commit-analyzer": "^9.0.2", 44 | "@semantic-release/git": "^10.0.1", 45 | "@semantic-release/github": "^8.0.7", 46 | "@semantic-release/npm": "^9.0.1", 47 | "@semantic-release/release-notes-generator": "^10.0.3", 48 | "rimraf": "^3.0.2" 49 | }, 50 | "release": { 51 | "branches": [ 52 | "master", 53 | "main" 54 | ], 55 | "repositoryUrl": "https://github.com/InfiniBrains/mobagen", 56 | "plugins": [ 57 | "@semantic-release/commit-analyzer", 58 | "@semantic-release/release-notes-generator", 59 | [ 60 | "@semantic-release/changelog", 61 | { 62 | "changelogFile": "CHANGELOG.md" 63 | } 64 | ], 65 | [ 66 | "@semantic-release/git", 67 | { 68 | "assets": [ 69 | "CHANGELOG.md" 70 | ] 71 | } 72 | ], 73 | "@semantic-release/github" 74 | ] 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /external/sdl.cmake: -------------------------------------------------------------------------------- 1 | set(SDL_SHARED 2 | OFF 3 | CACHE BOOL "SDL_SHARED" 4 | ) 5 | set(SDL_STATIC 6 | ON 7 | CACHE BOOL "SDL_STATIC" 8 | ) 9 | set(SDL_STATIC_PIC 10 | ON 11 | CACHE BOOL "SDL_STATIC_PIC" 12 | ) 13 | 14 | if(NOT DEFINED EMSCRIPTEN) 15 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong") # required for opus 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong") # required for opus 17 | endif() 18 | 19 | # SDL2 20 | string(TIMESTAMP BEFORE "%s") 21 | CPMAddPackage( 22 | NAME SDL2 23 | GITHUB_REPOSITORY libsdl-org/SDL 24 | GIT_TAG release-2.32.8 25 | OPTIONS "SDL2_DISABLE_INSTALL ON" 26 | "SDL2_SHARED OFF" 27 | "SDL_SHARED OFF" 28 | "SDL_STATIC ON" 29 | "SDL_STATIC_PIC ON" 30 | "SDL_WERROR OFF" 31 | "SDL_TEST OFF" 32 | ) 33 | find_package(SDL2 REQUIRED) 34 | if(SDL2_ADDED) 35 | file(GLOB SDL_HEADERS "${SDL_SOURCE_DIR}/include/*.h") 36 | 37 | # Create a target that copies headers at build time, when they change 38 | add_custom_target( 39 | sdl_copy_headers_in_build_dir 40 | COMMAND ${CMAKE_COMMAND} -E copy_directory "${SDL_SOURCE_DIR}/include" 41 | "${CMAKE_BINARY_DIR}/SDLHeaders/SDL2" 42 | DEPENDS ${SDL_HEADERS} 43 | ) 44 | 45 | # Make SDL depend from it 46 | add_dependencies(SDL2 sdl_copy_headers_in_build_dir) 47 | 48 | # And add the directory where headers have been copied as an interface include dir 49 | target_include_directories(SDL2 INTERFACE "${CMAKE_BINARY_DIR}/SDLHeaders") 50 | 51 | set(SDL2_INCLUDE_DIR ${SDL2_SOURCE_DIR}/include) 52 | endif() 53 | include_directories(${SDL2_INCLUDE_DIR}) 54 | string(TIMESTAMP AFTER "%s") 55 | math(EXPR DELTASDL "${AFTER} - ${BEFORE}") 56 | message(STATUS "SDL2 TIME: ${DELTASDL}s") 57 | 58 | # SDL_image 59 | string(TIMESTAMP BEFORE "%s") 60 | CPMAddPackage( 61 | NAME SDL_image 62 | GITHUB_REPOSITORY libsdl-org/SDL_image 63 | GIT_TAG release-2.8.8 64 | OPTIONS "BUILD_SHARED_LIBS OFF" 65 | "SDL2_SHARED OFF" 66 | "SDL_SHARED OFF" 67 | "SDL2IMAGE_INSTALL OFF" 68 | "SDL2IMAGE_SAMPLES OFF" 69 | "SDL2IMAGE_VENDORED OFF" 70 | "SDL2IMAGE_BUILD_SHARED_LIBS OFF" 71 | "SDL2IMAGE_DEPS_SHARED OFF" 72 | ) 73 | if(SDL_image_ADDED) 74 | include_directories(${SDL_image_SOURCE_DIR}/include) 75 | else() 76 | message(FATAL_ERROR "SDL IMAGE NOT FOUND") 77 | endif() 78 | 79 | string(TIMESTAMP AFTER "%s") 80 | math(EXPR DELTASDL_image "${AFTER} - ${BEFORE}") 81 | message(STATUS "SDL_image TIME: ${DELTASDL_image}s") 82 | -------------------------------------------------------------------------------- /core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(BUILD_SHARED_LIBS FALSE) 2 | 3 | file( 4 | GLOB_RECURSE CORE_INC CONFIGURE_DEPENDS 5 | RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 6 | *.h *.hpp 7 | ) 8 | 9 | file( 10 | GLOB_RECURSE CORE_SRC CONFIGURE_DEPENDS 11 | RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 12 | *.c *.cpp 13 | ) 14 | 15 | set(CORE_INC_DIR 16 | ${CMAKE_CURRENT_SOURCE_DIR} 17 | CACHE PATH "CORE INCLUDE SOURCE PATH" 18 | ) 19 | 20 | add_library(core STATIC ${CORE_SRC} ${CORE_INC}) 21 | 22 | if(EMSCRIPTEN) 23 | # target_link_libraries(core PUBLIC SDL2::SDL2 SDL2_image::SDL2_image-static IMGUI quickjspp) 24 | target_link_libraries(core PUBLIC SDL2::SDL2 SDL2_image::SDL2_image-static IMGUI) 25 | else() 26 | target_link_libraries( 27 | core PUBLIC SDL2::SDL2 SDL2_image::SDL2_image-static IMGUI 28 | # MbedTLS::mbedtls MbedTLS::mbedcrypto MbedTLS::mbedx509 cpr::cpr 29 | ) 30 | endif() 31 | 32 | # If(NOT EMSCRIPTEN AND NOT ANDROID) add_definitions(-DGLEW_STATIC) # add_definitions(-DGLEW_BUILD) 33 | # set(GLEW_USE_STATIC_LIBS ON CACHE BOOL "bla") set(BUILD_SHARED_LIBS OFF CACHE BOOL "bla") set( 34 | # glew-cmake_BUILD_SHARED OFF CACHE BOOL "Build the shared glew library" ) set( 35 | # glew-cmake_BUILD_STATIC ON CACHE BOOL "Build the static glew library" ) set( 36 | # glew-cmake_BUILD_SINGLE_CONTEXT ON CACHE BOOL "Build the single context glew library" ) set( 37 | # glew-cmake_BUILD_MULTI_CONTEXT OFF CACHE BOOL "Build the multi context glew library" ) 38 | # 39 | # message(STATUS "######################### ADDING GLEW #######################################") 40 | # hunter_add_package(glew) find_package(glew CONFIG REQUIRED) 41 | # 42 | # target_link_libraries (engine PUBLIC ${ENGINE_LIBS} glew::glew) ELSE() target_link_libraries 43 | # (engine PUBLIC ${ENGINE_LIBS}) ENDIF() 44 | 45 | # TODO: Check if this approach bellow is better IF (ANDROID) add_library (core STATIC ${CORE_SRC}) 46 | # ELSE () add_library (core SHARED ${CORE_SRC}) ENDIF () 47 | # 48 | # target_link_libraries (core ${ENGINE_LIBS}) set_target_properties(core PROPERTIES 49 | # COTIRE_CXX_PREFIX_HEADER_INIT "stdafx.h") cotire(core) 50 | 51 | install(TARGETS core DESTINATION lib) 52 | install(FILES ${CORE_INC} DESTINATION include/core) 53 | 54 | # TODO: ADD THIS BACK WHEN NEEDED IF (NOT TARGET uninstall) # add make uninstall capability 55 | # configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in" 56 | # "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall 57 | # "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() 58 | 59 | # include_directories(${SDL2_INCLUDE_DIR} core) 60 | 61 | option(ENABLE_CURL "ENABLE_WEB" ON) 62 | if(ENABLE_CURL) 63 | 64 | endif() 65 | -------------------------------------------------------------------------------- /examples/chess/pieces/King.cpp: -------------------------------------------------------------------------------- 1 | #include "King.h" 2 | #include "../Search.h" 3 | // todo: castling 4 | // todo: deal with the case that the king cannot move to an attacked square 5 | unordered_set King::AttackMoves(WorldState& world, const Point2D& origin) { 6 | auto piece = world.PieceAtPosition(origin); 7 | auto attackedSquares = Search::ListPlacesKingCannotGo(world, piece.Color()); 8 | 9 | if (piece.Piece() != PieceType::King) return {}; 10 | 11 | unordered_set moves; 12 | 13 | vector const directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; 14 | 15 | for (auto direction : directions) { 16 | auto currentPosition = origin + direction; 17 | auto otherPiece = world.PieceAtPosition(currentPosition); 18 | if (otherPiece.Piece() == PieceType::WRONG) continue; 19 | // add if it is empty and continue 20 | if ((otherPiece.Piece() == PieceType::NONE || otherPiece.Color() != piece.Color()) && !attackedSquares.contains(currentPosition)) 21 | moves.insert(currentPosition); 22 | } 23 | return moves; 24 | } 25 | 26 | auto King::FindKing(WorldState& state, PieceColor color) -> Point2D { 27 | for (auto line = 0; line < 8; line++) { 28 | for (auto column = 0; column < 8; column++) { 29 | Point2D location = {column, line}; 30 | auto p = state.PieceAtPosition(location); 31 | if (p.Color() != color) continue; 32 | if (p.Piece() == PieceType::King) return location; 33 | } 34 | } 35 | return {}; 36 | } 37 | unordered_set King::CoverMovesNaive(WorldState& world, const Point2D& origin) { 38 | auto piece = world.PieceAtPosition(origin); 39 | // auto attackedSquares = Search::ListPlacesKingCannotGo(world, piece.Color()); 40 | 41 | if (piece.Piece() != PieceType::King) return {}; 42 | 43 | unordered_set moves; 44 | 45 | vector const directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; 46 | 47 | for (auto direction : directions) { 48 | auto currentPosition = origin + direction; 49 | auto otherPiece = world.PieceAtPosition(currentPosition); 50 | if (otherPiece.Piece() == PieceType::WRONG) continue; 51 | // add if it is empty and continue 52 | if (otherPiece.Piece() == PieceType::NONE || otherPiece.Color() == piece.Color()) moves.insert(currentPosition); 53 | } 54 | return moves; 55 | } 56 | auto King::IsInCheck(WorldState& state, PieceColor color) -> int { 57 | auto kingLocation = FindKing(state, color); 58 | auto attackedSquares = Search::ListMoves(state, (PieceColor)(!(bool)color)); 59 | int count = 0; 60 | for (auto square : attackedSquares) { 61 | if (square.To() == kingLocation) count++; 62 | } 63 | return count; 64 | } 65 | -------------------------------------------------------------------------------- /editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | option(BUILD_EDITOR "BUILD_EDITOR" ON) 2 | 3 | if(BUILD_EDITOR) 4 | file(GLOB EDITOR_INC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h 5 | ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp 6 | ) 7 | 8 | file(GLOB EDITOR_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp 9 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c 10 | ) 11 | 12 | # If(NOT EMSCRIPTEN AND NOT ANDROID) add_definitions(-DGLEW_STATIC) # 13 | # add_definitions(-DGLEW_BUILD) set(GLEW_USE_STATIC_LIBS ON CACHE BOOL "bla") 14 | # set(BUILD_SHARED_LIBS OFF CACHE BOOL "bla") set( glew-cmake_BUILD_SHARED OFF CACHE BOOL "Build 15 | # the shared glew library" ) set( glew-cmake_BUILD_STATIC ON CACHE BOOL "Build the static glew 16 | # library" ) set( glew-cmake_BUILD_SINGLE_CONTEXT ON CACHE BOOL "Build the single context glew 17 | # library" ) set( glew-cmake_BUILD_MULTI_CONTEXT OFF CACHE BOOL "Build the multi context glew 18 | # library" ) 19 | # 20 | # message(STATUS "######################### ADDING GLEW #######################################") 21 | # hunter_add_package(glew) find_package(glew CONFIG REQUIRED) 22 | # 23 | # target_link_libraries (engine PUBLIC ${ENGINE_LIBS} glew::glew) ELSE() target_link_libraries 24 | # (engine PUBLIC ${ENGINE_LIBS}) ENDIF() 25 | 26 | # TODO: Check if this approach bellow is better IF (ANDROID) add_library (engine STATIC 27 | # ${TARGET_SRC}) ELSE () add_library (engine SHARED ${TARGET_SRC}) ENDIF () 28 | # 29 | # target_link_libraries (engine ${ENGINE_LIBS}) set_target_properties(engine PROPERTIES 30 | # COTIRE_CXX_PREFIX_HEADER_INIT "stdafx.h") cotire(engine) 31 | 32 | # todo: check this install (TARGETS editor DESTINATION lib) 33 | install(FILES ${EDITOR_INC} DESTINATION include/editor) 34 | 35 | # TODO: ADD THIS BACK WHEN NEEDED IF (NOT TARGET uninstall) # add make uninstall capability 36 | # configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in" 37 | # "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall 38 | # "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() 39 | 40 | # include(itk.cmake) 41 | add_executable(editor ${EDITOR_SRC} ${EDITOR_INC}) 42 | # target_include_directories(editor PUBLIC ${ITKGDCM_INCLUDE_DIRS}) 43 | target_link_libraries(editor PUBLIC SDL2-static IMGUI core) 44 | # target_link_libraries (editor PUBLIC SDL2-static IMGUI engine core itkgdcmDSED-5.3 45 | # itkgdcmCommon-5.3 itkzlib-5.3) if(EMSCRIPTEN) target_compile_options(editor PUBLIC "-Oz") 46 | # target_link_options(editor PUBLIC "-s WASM=2 -s USE_SDL=0 -s EXPORT_ALL=1") endif() 47 | 48 | target_include_directories(editor PUBLIC ${SDL2_INCLUDE_DIR} ${ENGINE_INC_DIR} ${CORE_INC_DIR}) 49 | 50 | # target_sources(editor PUBLIC ${TARGET_SRC} ) 51 | endif() 52 | --------------------------------------------------------------------------------