├── premake-mingw.bat ├── premake-VisualStudio.bat ├── game ├── src │ ├── utilities │ │ ├── mesh_utils.cpp │ │ ├── ai_utils.cpp │ │ └── debug_draw_utility.cpp │ ├── components │ │ ├── map_opbject_component.cpp │ │ ├── trigger_component.cpp │ │ └── mobile_object_component.cpp │ ├── component.cpp │ ├── services │ │ ├── game_time.cpp │ │ ├── global_vars.cpp │ │ ├── table_manager.cpp │ │ ├── character_manager.cpp │ │ └── resource_manager.cpp │ ├── external │ │ └── LDtkLoader │ │ │ ├── include │ │ │ └── LDtkLoader │ │ │ │ ├── Version.hpp │ │ │ │ ├── containers │ │ │ │ └── TagsContainer.hpp │ │ │ │ ├── defs │ │ │ │ ├── LayerDef.hpp │ │ │ │ ├── EntityDef.hpp │ │ │ │ └── FieldDef.hpp │ │ │ │ ├── Tile.hpp │ │ │ │ ├── Tileset.hpp │ │ │ │ ├── Utils.hpp │ │ │ │ ├── Enum.hpp │ │ │ │ ├── Entity.hpp │ │ │ │ ├── World.hpp │ │ │ │ ├── Level.hpp │ │ │ │ ├── Field.hpp │ │ │ │ ├── Layer.hpp │ │ │ │ └── Project.hpp │ │ │ ├── src │ │ │ ├── Version.hpp.in │ │ │ ├── TagsContainer.cpp │ │ │ ├── LayerDef.cpp │ │ │ ├── EntityDef.cpp │ │ │ ├── DataTypes.cpp │ │ │ ├── Enum.cpp │ │ │ ├── Tileset.cpp │ │ │ ├── Entity.cpp │ │ │ ├── Tile.cpp │ │ │ └── Level.cpp │ │ │ └── LICENSE.md │ ├── system.cpp │ ├── systems │ │ ├── mobile_object_system.cpp │ │ ├── overlay_render_system.cpp │ │ ├── menu_render_system.cpp │ │ ├── player_management_system.cpp │ │ └── audio_system.cpp │ ├── scene.cpp │ └── game_object.cpp ├── include │ ├── utilities │ │ ├── mesh_utils.h │ │ ├── ai_utils.h │ │ ├── collision_utils.h │ │ ├── light_utils.h │ │ ├── string_utils.h │ │ ├── debug_draw_utility.h │ │ └── lighting_system.h │ ├── map │ │ ├── map_reader.h │ │ ├── raycaster.h │ │ ├── map_render.h │ │ └── map.h │ ├── systems │ │ ├── overlay_render_system.h │ │ ├── menu_render_system.h │ │ ├── mobile_object_system.h │ │ ├── scene_render_system.h │ │ ├── player_management_system.h │ │ ├── map_object_system.h │ │ ├── audio_system.h │ │ ├── console_render_system.h │ │ └── input_system.h │ ├── components │ │ ├── player_info_component.h │ │ ├── spawn_point_component.h │ │ ├── map_object_component.h │ │ ├── transform_component.h │ │ ├── mobile_object_component.h │ │ ├── mob_behavior_component.h │ │ ├── trigger_component.h │ │ └── door_controller_component.h │ ├── services │ │ ├── global_vars.h │ │ ├── texture_manager.h │ │ ├── game_time.h │ │ ├── resource_manager.h │ │ ├── table_manager.h │ │ ├── character_manager.h │ │ └── model_manager.h │ ├── object_lifetime_token.h │ ├── scene.h │ ├── game.h │ ├── system.h │ ├── component.h │ └── game_object.h └── premake5.lua ├── premake5 ├── premake5.exe ├── premake5.osx ├── resources ├── characters │ ├── manifest.table │ └── guard.table ├── test.png ├── textures │ ├── gun.png │ ├── gun.psd │ ├── guard.png │ ├── skybox.png │ ├── textures.png │ ├── crosshair.png │ ├── gray_textures.png │ ├── simple_shadow.png │ ├── skybox_night.png │ ├── models │ │ └── 1042954577.png │ ├── simple_shadow_wide.png │ └── defaultTiles.tsx ├── models │ ├── barrel.mesh │ ├── robot_z.anim │ ├── robot_z.mesh │ ├── barrels_rail.mesh │ ├── desk_chair.mesh │ ├── desk_chairArms.mesh │ ├── machine_barrel.mesh │ ├── machine_generator.mesh │ └── manifest.table ├── sounds │ ├── footstep07.ogg │ ├── doorClose_000.ogg │ ├── doorOpen_000.ogg │ ├── impactMetal_000.ogg │ ├── impactGeneric_light_000.ogg │ └── manifest.table ├── shaders │ ├── manifest.table │ ├── skybox.vs │ ├── skydome.fs │ ├── skybox.fs │ └── world.vs ├── bootstrap.table └── VFX │ └── light_sequence.table ├── assets ├── models │ ├── barrel.glb │ ├── desk_chair.glb │ ├── barrels_rail.glb │ ├── desk_chairArms.glb │ ├── desk_chairStool.glb │ ├── machine_barrel.glb │ └── machine_generator.glb └── characters │ ├── robot.glb │ ├── robot_z.glb │ └── LICENSE ├── documents ├── EngineOverview.vsdx ├── TODO.md └── tasks.md ├── .gitignore ├── .vscode ├── settings.json ├── tasks.json ├── c_cpp_properties.json └── launch.json ├── model_tool ├── include │ ├── model_info.h │ ├── transform_tools.h │ └── app.h ├── premake5.lua └── src │ ├── model_info.cpp │ └── main.cpp ├── extras ├── README.md └── staticLib │ ├── include │ └── lib.h │ ├── src │ └── lib.cpp │ └── premake5.lua ├── editor_common ├── include │ └── menu_container.h └── premake5.lua ├── model_lib ├── premake5.lua └── include │ └── model.h ├── rlImGui ├── premake5.lua └── include │ ├── extras │ └── FontAwsome_LICENSE.txt │ ├── rlImGuiColors.h │ └── imgui_impl_raylib.h └── README.md /premake-mingw.bat: -------------------------------------------------------------------------------- 1 | premake5.exe gmake || pause 2 | -------------------------------------------------------------------------------- /premake-VisualStudio.bat: -------------------------------------------------------------------------------- 1 | premake5.exe vs2026 || pause 2 | -------------------------------------------------------------------------------- /game/src/utilities/mesh_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utilities/mesh_utils.h" -------------------------------------------------------------------------------- /game/include/utilities/mesh_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "raylib.h" 4 | -------------------------------------------------------------------------------- /premake5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/premake5 -------------------------------------------------------------------------------- /premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/premake5.exe -------------------------------------------------------------------------------- /premake5.osx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/premake5.osx -------------------------------------------------------------------------------- /resources/characters/manifest.table: -------------------------------------------------------------------------------- 1 | guard;characters/guard.table 2 | walker;characters/walker.table -------------------------------------------------------------------------------- /resources/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/test.png -------------------------------------------------------------------------------- /assets/models/barrel.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/barrel.glb -------------------------------------------------------------------------------- /resources/textures/gun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/gun.png -------------------------------------------------------------------------------- /resources/textures/gun.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/gun.psd -------------------------------------------------------------------------------- /assets/characters/robot.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/characters/robot.glb -------------------------------------------------------------------------------- /assets/characters/robot_z.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/characters/robot_z.glb -------------------------------------------------------------------------------- /assets/models/desk_chair.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/desk_chair.glb -------------------------------------------------------------------------------- /documents/EngineOverview.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/documents/EngineOverview.vsdx -------------------------------------------------------------------------------- /resources/models/barrel.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/barrel.mesh -------------------------------------------------------------------------------- /resources/models/robot_z.anim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/robot_z.anim -------------------------------------------------------------------------------- /resources/models/robot_z.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/robot_z.mesh -------------------------------------------------------------------------------- /resources/textures/guard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/guard.png -------------------------------------------------------------------------------- /resources/textures/skybox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/skybox.png -------------------------------------------------------------------------------- /assets/models/barrels_rail.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/barrels_rail.glb -------------------------------------------------------------------------------- /game/include/map/map_reader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Scene; 4 | 5 | void ReadWorld(const char* fileName, Scene& world); -------------------------------------------------------------------------------- /resources/sounds/footstep07.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/sounds/footstep07.ogg -------------------------------------------------------------------------------- /resources/textures/textures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/textures.png -------------------------------------------------------------------------------- /assets/models/desk_chairArms.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/desk_chairArms.glb -------------------------------------------------------------------------------- /assets/models/desk_chairStool.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/desk_chairStool.glb -------------------------------------------------------------------------------- /assets/models/machine_barrel.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/machine_barrel.glb -------------------------------------------------------------------------------- /resources/models/barrels_rail.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/barrels_rail.mesh -------------------------------------------------------------------------------- /resources/models/desk_chair.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/desk_chair.mesh -------------------------------------------------------------------------------- /resources/sounds/doorClose_000.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/sounds/doorClose_000.ogg -------------------------------------------------------------------------------- /resources/sounds/doorOpen_000.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/sounds/doorOpen_000.ogg -------------------------------------------------------------------------------- /resources/textures/crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/crosshair.png -------------------------------------------------------------------------------- /assets/models/machine_generator.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/assets/models/machine_generator.glb -------------------------------------------------------------------------------- /resources/models/desk_chairArms.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/desk_chairArms.mesh -------------------------------------------------------------------------------- /resources/models/machine_barrel.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/machine_barrel.mesh -------------------------------------------------------------------------------- /resources/sounds/impactMetal_000.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/sounds/impactMetal_000.ogg -------------------------------------------------------------------------------- /resources/textures/gray_textures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/gray_textures.png -------------------------------------------------------------------------------- /resources/textures/simple_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/simple_shadow.png -------------------------------------------------------------------------------- /resources/textures/skybox_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/skybox_night.png -------------------------------------------------------------------------------- /resources/models/machine_generator.mesh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/models/machine_generator.mesh -------------------------------------------------------------------------------- /resources/textures/models/1042954577.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/models/1042954577.png -------------------------------------------------------------------------------- /resources/textures/simple_shadow_wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/textures/simple_shadow_wide.png -------------------------------------------------------------------------------- /resources/shaders/manifest.table: -------------------------------------------------------------------------------- 1 | skybox;shaders/skybox.fs:shaders/skybox.vs 2 | world;shaders/world.fs:shaders/world.vs 3 | skydome;shaders/skydome.fs -------------------------------------------------------------------------------- /resources/sounds/impactGeneric_light_000.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffM2501/ModernBoomerShooter/HEAD/resources/sounds/impactGeneric_light_000.ogg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | raylib-master 2 | _build 3 | _bin 4 | .vs 5 | /bin 6 | /build 7 | Makefile 8 | obj 9 | *.vcxproj 10 | *.filters 11 | *.user 12 | /*.sln 13 | -------------------------------------------------------------------------------- /resources/sounds/manifest.table: -------------------------------------------------------------------------------- 1 | door_open;sounds/doorOpen_000.ogg 2 | door_close;sounds/doorClose_000.ogg 3 | wall_hit;sounds/impactMetal_000.ogg 4 | spawn;sounds/footstep07.ogg -------------------------------------------------------------------------------- /resources/characters/guard.table: -------------------------------------------------------------------------------- 1 | type;model 2 | model;Robot 3 | idle;Robot_Idle 4 | walk;Robot_Walking 5 | run;Robot_Running 6 | turn;Robot_No 7 | rotation_offset;180 8 | shadow;textures/simple_shadow.png -------------------------------------------------------------------------------- /assets/characters/LICENSE: -------------------------------------------------------------------------------- 1 | robot.glb model by @Quaternius (https://www.patreon.com/quaternius) 2 | Licensed under CC0 1.0 Universal (CC0 1.0) - Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/) -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/*.o": true, 9 | "**/*.exe": true 10 | } 11 | } -------------------------------------------------------------------------------- /resources/models/manifest.table: -------------------------------------------------------------------------------- 1 | Barrel;models/barrel.mesh 2 | Barrel_pallete;models/barrels_rail.mesh 3 | Chair;models/desk_chairArms.mesh 4 | Robot;models/robot_z.mesh:models/robot_z.anim 5 | Walker;models/Leela.mesh:models/Leela.anim -------------------------------------------------------------------------------- /game/src/components/map_opbject_component.cpp: -------------------------------------------------------------------------------- 1 | #include "components/map_object_component.h" 2 | #include "systems/map_object_system.h" 3 | 4 | void MapObjectComponent::OnAddedToObject() 5 | { 6 | AddToSystem(); 7 | } 8 | -------------------------------------------------------------------------------- /model_tool/include/model_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "raylib.h" 3 | 4 | #include "app.h" 5 | 6 | class ModelInfoPanel : public Panel 7 | { 8 | public: 9 | ModelInfoPanel(); 10 | 11 | protected: 12 | void OnShowContents() override; 13 | }; -------------------------------------------------------------------------------- /game/include/systems/overlay_render_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "system.h" 3 | 4 | class OverlayRenderSystem : public System 5 | { 6 | public: 7 | DEFINE_SYSTEM(OverlayRenderSystem); 8 | 9 | protected: 10 | void OnUpdate() override; 11 | }; -------------------------------------------------------------------------------- /game/src/component.cpp: -------------------------------------------------------------------------------- 1 | #include "component.h" 2 | #include "game_object.h" 3 | #include "scene.h" 4 | 5 | void Component::AddToSystem(size_t systemGUID) 6 | { 7 | if (!Owner) 8 | return; 9 | 10 | Owner->AddToSystem(systemGUID); 11 | } 12 | -------------------------------------------------------------------------------- /game/src/services/game_time.cpp: -------------------------------------------------------------------------------- 1 | #include "services/game_time.h" 2 | 3 | namespace GameTime 4 | { 5 | float NominalFPS = 60.0f; 6 | 7 | void ComputeNominalFPS() 8 | { 9 | NominalFPS = float(GetMonitorRefreshRate(GetCurrentMonitor())); 10 | } 11 | } -------------------------------------------------------------------------------- /resources/textures/defaultTiles.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/bootstrap.table: -------------------------------------------------------------------------------- 1 | shader_manifest;shaders/manifest.table 2 | model_manifest;models/manifest.table 3 | audio_manifest;sounds/manifest.table 4 | boot_level;maps/example.ldtk 5 | default_skybox;textures/skybox.png 6 | light_sequences;VFX/light_sequence.table 7 | character_manifest;characters/manifest.table -------------------------------------------------------------------------------- /game/include/systems/menu_render_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "system.h" 3 | 4 | class MenuRenderSystem : public System 5 | { 6 | public: 7 | DEFINE_SYSTEM(MenuRenderSystem); 8 | 9 | protected: 10 | void OnUpdate() override; 11 | 12 | protected: 13 | bool InMenu = false; 14 | 15 | float LoadingSpinnerAngle = 0; 16 | }; -------------------------------------------------------------------------------- /game/include/components/player_info_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | 6 | #include "raylib.h" 7 | #include "map/map.h" 8 | 9 | class PlayerInfoComponent : public Component 10 | { 11 | public: 12 | DEFINE_COMPONENT(PlayerInfoComponent) 13 | 14 | uint32_t PlayerId = uint32_t(-1); 15 | 16 | }; -------------------------------------------------------------------------------- /game/include/utilities/ai_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "raylib.h" 4 | #include "raymath.h" 5 | 6 | namespace AIUtils 7 | { 8 | float GetRotationTo(const Vector3& position, const Vector3& facing, const Vector3& target); 9 | 10 | Vector3 MoveTo(const Vector3& position, Vector3& facing, const Vector3& target, float maxSpeed, float maxRotation); 11 | } -------------------------------------------------------------------------------- /game/include/services/global_vars.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace GlobalVars 4 | { 5 | extern bool UseGhostMovement; 6 | extern bool UseVisCulling; 7 | extern bool ShowCoordinates; 8 | extern bool ShowDebugDraw; 9 | extern bool UseVSync; 10 | extern int FPSCap; 11 | extern bool UseMouseDrag; 12 | 13 | extern float MasterVolume; 14 | 15 | extern bool Paused; 16 | } -------------------------------------------------------------------------------- /game/include/services/texture_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "raylib.h" 5 | 6 | namespace TextureManager 7 | { 8 | void Init(); 9 | void Cleanup(); 10 | 11 | Texture2D GetTexture(std::string_view name); 12 | Texture2D GetTextureCubemap(std::string_view name); 13 | void UnloadAll(); 14 | 15 | Shader GetShader(std::string_view name); 16 | 17 | size_t GetUsedVRAM(); 18 | }; -------------------------------------------------------------------------------- /game/include/services/game_time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "raylib.h" 3 | 4 | namespace GameTime 5 | { 6 | extern float NominalFPS; 7 | 8 | inline float GetDeltaTime() 9 | { 10 | #if defined(_DEBUG) 11 | return 1.0f / NominalFPS; 12 | #else 13 | return ::GetFrameTime(); 14 | #endif 15 | } 16 | 17 | inline float Scale(float value) 18 | { 19 | return value * GetDeltaTime(); 20 | } 21 | 22 | void ComputeNominalFPS(); 23 | } -------------------------------------------------------------------------------- /game/include/utilities/collision_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Rectangle; 4 | struct Vector2; 5 | struct Vector3; 6 | struct BoundingBox; 7 | 8 | namespace CollisionUtils 9 | { 10 | void PointNearestRect(const Rectangle& rect, const Vector2& point, Vector2* nearest, Vector2* normal); 11 | void PointNearestBoundsXY(const BoundingBox& rect, const Vector3& position, const Vector3& point, Vector3* nearest, Vector3* normal); 12 | 13 | void SetUnitAngleDeg(float& angle); 14 | } -------------------------------------------------------------------------------- /game/include/utilities/light_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace LightUtils 7 | { 8 | inline std::vector ParseLightSequence(const std::string_view text) 9 | { 10 | std::vector results; 11 | 12 | float range = int('m') - int('a'); 13 | for (const char c : text) 14 | { 15 | results.push_back((c - 'a') / range); 16 | } 17 | return results; 18 | } 19 | } -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Version.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar on 11/02/2023. 2 | 3 | #pragma once 4 | 5 | namespace ldtk { 6 | 7 | struct ApiVersion { 8 | static constexpr unsigned Major = 1; 9 | static constexpr unsigned Minor = 5; 10 | static constexpr unsigned Patch = 3; 11 | static constexpr unsigned Tweak = 1; 12 | }; 13 | 14 | constexpr const char* const API_VERSION_STRING = "1.5.3.1"; 15 | 16 | } // namespace ldtk 17 | -------------------------------------------------------------------------------- /game/include/components/spawn_point_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | #include "raylib.h" 6 | #include "raymath.h" 7 | 8 | #include "systems/player_management_system.h" 9 | 10 | enum class SpawnType 11 | { 12 | Player, 13 | }; 14 | 15 | class SpawnPointComponent : public Component 16 | { 17 | public: 18 | DEFINE_COMPONENT_WITH_SYSTEM(SpawnPointComponent, PlayerManagementSystem) 19 | 20 | SpawnType Type = SpawnType::Player; 21 | }; 22 | -------------------------------------------------------------------------------- /resources/VFX/light_sequence.table: -------------------------------------------------------------------------------- 1 | Flicker_1;mmnmmommommnonmmonqnmmo 2 | Flicker_2;nmonqnmomnmomomno 3 | Pulse;jklmnopqrstuvwxyzyxwvutsrqponmlkj 4 | Slow_pulse;abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba 5 | Slow_pulse_no_black;abcdefghijklmnopqrrqponmlkjihgfedcba 6 | Slow_strobe;aaaaaaaazzzzzzzz 7 | Fast_strobe;mamamamamama 8 | Candle_1;mmmmmaaaaammmmmaaaaaabcdefgabcdefg 9 | Candle_2;mmmaaaabcdefgmmmmaaaammmaamm 10 | Candle_3;mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa 11 | Flourecent_flicker;mmamammmmammamamaaamammma -------------------------------------------------------------------------------- /game/src/system.cpp: -------------------------------------------------------------------------------- 1 | #include "system.h" 2 | #include 3 | 4 | void System::Init() 5 | { 6 | OnInit(); 7 | } 8 | 9 | void System::Cleanup() 10 | { 11 | OnCleaup(); 12 | } 13 | 14 | void System::Setup() 15 | { 16 | OnSetup(); 17 | } 18 | 19 | void System::Update() 20 | { 21 | OnUpdate(); 22 | } 23 | 24 | void System::AddObject(GameObject* object) 25 | { 26 | Objects.insert(object); 27 | OnAddObject(object); 28 | } 29 | 30 | void System::RemoveObject(GameObject* object) 31 | { 32 | Objects.erase(object); 33 | } -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/Version.hpp.in: -------------------------------------------------------------------------------- 1 | // Created by Modar on 11/02/2023. 2 | 3 | #pragma once 4 | 5 | namespace ldtk { 6 | 7 | struct ApiVersion { 8 | static constexpr unsigned Major = @PROJECT_VERSION_MAJOR@; 9 | static constexpr unsigned Minor = @PROJECT_VERSION_MINOR@; 10 | static constexpr unsigned Patch = @PROJECT_VERSION_PATCH@; 11 | static constexpr unsigned Tweak = @PROJECT_VERSION_TWEAK@; 12 | }; 13 | 14 | constexpr const char* const API_VERSION_STRING = "@PROJECT_VERSION@"; 15 | 16 | } // namespace ldtk 17 | -------------------------------------------------------------------------------- /extras/README.md: -------------------------------------------------------------------------------- 1 | # Extras 2 | Optinal things to help with proejcts 3 | 4 | ## app_cpp 5 | A simple C++ example for raylib, if you want to start with C++, simply replace the contents of the game folder with the contents of app_cpp 6 | 7 | # example_library 8 | A simple example of a user library. Has a header and a source file and a premake script that will build a static library. copy and rename the folder into the root with the name of your library and give it the code it needs. 9 | Link your game to the library with the link_to("LIB_FOLDER_NAME") function in the premake5.lua script for the game. -------------------------------------------------------------------------------- /model_tool/include/transform_tools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "raylib.h" 3 | 4 | #include "app.h" 5 | 6 | namespace TransformTools 7 | { 8 | void CenterMesh(); 9 | void FloorMesh(); 10 | void RotateMesh(float angle, Vector3 axis); 11 | void BakeMaterialColors(); 12 | void CombineIdenticalMaterials(); 13 | void MergeMeshes(); 14 | 15 | void ScaleMeshes(Vector3 scale); 16 | } 17 | 18 | class TransformPanel : public Panel 19 | { 20 | public: 21 | TransformPanel(); 22 | 23 | protected: 24 | void OnShowContents() override; 25 | 26 | float ZSize = 0.75f; 27 | }; -------------------------------------------------------------------------------- /game/include/systems/mobile_object_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "system.h" 3 | #include "game_object.h" 4 | 5 | #include "components/mobile_object_component.h" 6 | 7 | class MobBehaviorComponent; 8 | 9 | class MobSystem : public System 10 | { 11 | public: 12 | DEFINE_SYSTEM(MobSystem); 13 | 14 | SystemComponentList Mobs; 15 | SystemComponentList MobBehaviors; 16 | 17 | protected: 18 | void OnUpdate() override; 19 | void OnAddObject(GameObject* object) override; 20 | void OnRemoveObject(GameObject* object) override; 21 | 22 | protected: 23 | }; -------------------------------------------------------------------------------- /game/include/components/map_object_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | #include "raylib.h" 6 | #include "raymath.h" 7 | 8 | #include 9 | #include 10 | 11 | class ModelInstance; 12 | 13 | class MapObjectComponent : public Component 14 | { 15 | public: 16 | DEFINE_COMPONENT(MapObjectComponent) 17 | 18 | MapObjectComponent(GameObject* owner, std::string_view modelName) : Component(owner), ModelName(modelName) {} 19 | 20 | void OnAddedToObject() override; 21 | 22 | std::string ModelName; 23 | std::shared_ptr Instance = nullptr; 24 | bool Solid = true; 25 | }; 26 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/containers/TagsContainer.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 22/02/2022. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 9 | 10 | namespace ldtk { 11 | 12 | class TagsContainer 13 | { 14 | public: 15 | auto hasTag(const std::string& tag) const -> bool; 16 | auto allTags() const -> const std::vector&; 17 | 18 | protected: 19 | explicit TagsContainer(const nlohmann::json& j); 20 | 21 | private: 22 | const std::vector m_tags; 23 | }; 24 | 25 | } // namespace ldtk 26 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/TagsContainer.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 22/02/2022. 2 | 3 | #include "LDtkLoader/containers/TagsContainer.hpp" 4 | 5 | #include "json.hpp" 6 | 7 | using namespace ldtk; 8 | 9 | TagsContainer::TagsContainer(const nlohmann::json& j) 10 | : m_tags(j.empty() ? std::vector{} : j.get>()) 11 | {} 12 | 13 | auto TagsContainer::hasTag(const std::string& tag) const -> bool 14 | { 15 | auto pos = std::find(m_tags.begin(), m_tags.end(), tag); 16 | return pos != m_tags.end(); 17 | } 18 | 19 | auto TagsContainer::allTags() const -> const std::vector& 20 | { 21 | return m_tags; 22 | } 23 | -------------------------------------------------------------------------------- /game/include/services/resource_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct ResoureInfo 7 | { 8 | size_t NameHash = 0; 9 | 10 | uint8_t* DataBuffer = nullptr; 11 | size_t DataSize = 0; 12 | 13 | ~ResoureInfo(); 14 | }; 15 | 16 | namespace ResourceManager 17 | { 18 | void Init(std::string_view rootFolder); 19 | void Cleanup(); 20 | 21 | std::shared_ptr OpenResource(std::string_view filePath, bool asText = false); 22 | 23 | void ReleaseResource(std::shared_ptr resource); 24 | void ReleaseResource(const char* resourceName); 25 | void ReleaseResourceByData(void* resourceData); 26 | }; -------------------------------------------------------------------------------- /game/src/systems/mobile_object_system.cpp: -------------------------------------------------------------------------------- 1 | #include "systems/mobile_object_system.h" 2 | 3 | #include "components/mob_behavior_component.h" 4 | #include "components/transform_component.h" 5 | #include "utilities/collision_utils.h" 6 | 7 | void MobSystem::OnUpdate() 8 | { 9 | // do AI updates 10 | 11 | for (auto& behavior : MobBehaviors.Components) 12 | { 13 | behavior->Process(); 14 | } 15 | } 16 | 17 | void MobSystem::OnAddObject(GameObject* object) 18 | { 19 | Mobs.Add(object); 20 | MobBehaviors.Add(object); 21 | } 22 | 23 | void MobSystem::OnRemoveObject(GameObject* object) 24 | { 25 | MobBehaviors.Remove(object); 26 | Mobs.Remove(object); 27 | } 28 | -------------------------------------------------------------------------------- /game/include/object_lifetime_token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class ObjectLifetimeToken 6 | { 7 | private: 8 | void* Owner = nullptr; 9 | 10 | public: 11 | ObjectLifetimeToken(void* owner) : Owner(owner) {} 12 | 13 | using Ptr = std::shared_ptr; 14 | static Ptr Create(void* owner) 15 | { 16 | return std::make_shared(owner); 17 | } 18 | 19 | bool IsValid() const { return Owner != nullptr; } 20 | 21 | void Invalidate() { Owner = nullptr; } 22 | 23 | void* GetOwner() { return Owner; } 24 | 25 | template 26 | T* GetOwner() { return static_cast(Owner); } 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /resources/shaders/skybox.vs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes 4 | in vec3 vertexPosition; 5 | 6 | // Input uniform values 7 | uniform mat4 matProjection; 8 | uniform mat4 matView; 9 | uniform mat4 matModel; 10 | 11 | // Output vertex attributes (to fragment shader) 12 | out vec3 fragPosition; 13 | 14 | void main() 15 | { 16 | // Calculate fragment position based on model transformations 17 | fragPosition = vec3(matModel * vec4(vertexPosition, 1.0f)); 18 | 19 | // Remove translation from the view matrix 20 | mat4 rotView = mat4(mat3(matView)); 21 | vec4 clipPos = matProjection*rotView*vec4(vertexPosition, 1.0); 22 | 23 | // Calculate final vertex position 24 | gl_Position = clipPos; 25 | } 26 | -------------------------------------------------------------------------------- /game/src/services/global_vars.cpp: -------------------------------------------------------------------------------- 1 | #include "services/global_vars.h" 2 | 3 | namespace GlobalVars 4 | { 5 | #if defined(_DEBUG) 6 | static constexpr bool DebugTrue = true; 7 | #else 8 | static constexpr bool DebugTrue = false; 9 | #endif 10 | 11 | #if defined(_DEBUG) 12 | static constexpr bool DebugFalse = false; 13 | #else 14 | static constexpr bool DebugFalse = true; 15 | #endif 16 | 17 | bool UseGhostMovement = false; 18 | bool UseVisCulling = true; 19 | bool ShowCoordinates = DebugTrue; 20 | bool ShowDebugDraw = false; 21 | 22 | bool UseVSync = DebugFalse; 23 | int FPSCap = 300; 24 | 25 | bool UseMouseDrag = DebugTrue; 26 | 27 | float MasterVolume = 0.5f; 28 | 29 | bool Paused = false; 30 | } -------------------------------------------------------------------------------- /game/include/services/table_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | static constexpr char BootstrapTable[] = "bootstrap.table"; 10 | 11 | class Table : public std::map 12 | { 13 | public: 14 | bool HasField(const std::string& key) const; 15 | std::string_view GetField(const std::string& key) const; 16 | const Table* GetFieldAsTable(const std::string& key) const; 17 | 18 | std::vector SplitField(const std::string& key, std::string_view deliminator) const; 19 | }; 20 | 21 | 22 | namespace TableManager 23 | { 24 | void Init(); 25 | void Cleanup(); 26 | 27 | const Table* GetTable(std::string_view name); 28 | void UnloadAll(); 29 | }; -------------------------------------------------------------------------------- /documents/TODO.md: -------------------------------------------------------------------------------- 1 | # Stuff left to do 2 | 3 | * !Objects 4 | * !Object Collisions 5 | * !Triggers 6 | * !Doors 7 | * !Behaviors 8 | * Scripting 9 | * Pathfiding JPS(https://github.com/fgenesis/tinypile/blob/master/jps.hh) 10 | * Terminals 11 | * HUD 12 | * Pickups 13 | * MiniMap 14 | * Chunks? 15 | * Height 16 | * Open Ceiling wall caps 17 | * Shooting 18 | * Sound effects 19 | * Tasks 20 | * Music 21 | * User Prefs/keymaps 22 | * Package System 23 | 24 | 25 | # Ideas 26 | 27 | ## Prefabs 28 | Use component data objects, with codegen functions to read/write binary data. Prefab overrides are just applied as sparse data as an addiitional read. Allow other objects to hold an override set for some other component, so that a spawner can apply overrides to each obecjt spawned. -------------------------------------------------------------------------------- /resources/shaders/skydome.fs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes (from vertex shader) 4 | in vec2 fragTexCoord; 5 | in vec4 fragColor; 6 | in vec3 fragPosition; 7 | 8 | // Input uniform values 9 | uniform sampler2D texture0; 10 | uniform vec4 colDiffuse; 11 | 12 | uniform float radius; 13 | uniform vec4 zenithColor; 14 | uniform vec4 horizonColor; 15 | uniform vec4 undergroundColor; 16 | 17 | // Output fragment color 18 | out vec4 finalColor; 19 | 20 | // NOTE: Add here your custom variables 21 | 22 | void main() 23 | { 24 | // Texel color fetching from texture sampler 25 | 26 | float factor = fragPosition.y/radius; 27 | if (factor >= 0) 28 | finalColor = mix(horizonColor,zenithColor, factor); 29 | else 30 | finalColor = mix(horizonColor,undergroundColor, -factor); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /game/include/utilities/string_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace StringUtils 8 | { 9 | static inline std::vector SplitString(std::string_view input, std::string_view delimiter) 10 | { 11 | size_t pos_start = 0, pos_end, delim_len = delimiter.length(); 12 | std::string token; 13 | std::vector results; 14 | 15 | while ((pos_end = input.find(delimiter, pos_start)) != std::string::npos) 16 | { 17 | token = input.substr(pos_start, pos_end - pos_start); 18 | pos_start = pos_end + delim_len; 19 | results.push_back(token); 20 | } 21 | 22 | results.push_back(std::string(input.substr(pos_start))); 23 | return results; 24 | } 25 | } -------------------------------------------------------------------------------- /game/include/components/transform_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | #include "raylib.h" 6 | #include "raymath.h" 7 | 8 | class TransformComponent : public Component 9 | { 10 | private: 11 | public: 12 | DEFINE_COMPONENT(TransformComponent) 13 | 14 | Vector3 Position = Vector3Zeros; 15 | 16 | Vector3 Forward = { 0 }; 17 | 18 | inline void Rotate(float angle) 19 | { 20 | Vector2 rot = Vector2Rotate(Vector2{ Forward.x, Forward.y }, angle * DEG2RAD); 21 | Forward.x = rot.x; 22 | Forward.y = rot.y; 23 | } 24 | 25 | inline void SetFacing(float angle) { Forward = Vector3{ cosf((angle +90) * DEG2RAD), sinf((angle +90) * DEG2RAD), 0 }; } 26 | inline float GetFacing() const { return atan2f(Forward.y, Forward.x) * RAD2DEG - 90; } 27 | 28 | }; -------------------------------------------------------------------------------- /game/include/scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "game_object.h" 9 | #include "system.h" 10 | #include "map/map.h" 11 | #include "map/raycaster.h" 12 | 13 | #include "game.h" 14 | 15 | class Scene 16 | { 17 | public: 18 | Scene(); 19 | 20 | void Init(); 21 | void Cleanup(); 22 | 23 | void Load(std::string_view map); 24 | void ReloadMap(); 25 | 26 | GameObject* AddObject(); 27 | 28 | Map& GetMap() { return WorldMap; } 29 | const Map& GetMap() const { return WorldMap; } 30 | 31 | Raycaster& GetRaycaster() { return WorldRaycaster; } 32 | 33 | protected: 34 | std::unique_ptr RootObject; 35 | 36 | Map WorldMap; 37 | Raycaster WorldRaycaster; 38 | 39 | std::string CurrentWorldMap; 40 | }; -------------------------------------------------------------------------------- /resources/shaders/skybox.fs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes (from vertex shader) 4 | in vec3 fragPosition; 5 | 6 | // Input uniform values 7 | uniform samplerCube environmentMap; 8 | uniform bool vflipped; 9 | uniform bool doGamma; 10 | 11 | // Output fragment color 12 | out vec4 finalColor; 13 | 14 | void main() 15 | { 16 | // Fetch color from texture map 17 | vec3 color = vec3(0.0); 18 | 19 | if (vflipped) color = texture(environmentMap, vec3(fragPosition.x, -fragPosition.y, fragPosition.z)).rgb; 20 | else color = texture(environmentMap, fragPosition).rgb; 21 | 22 | if (doGamma)// Apply gamma correction 23 | { 24 | color = color/(color + vec3(1.0)); 25 | color = pow(color, vec3(1.0/2.2)); 26 | } 27 | 28 | // Calculate final fragment color 29 | finalColor = vec4(color, 1.0); 30 | } 31 | -------------------------------------------------------------------------------- /game/include/services/character_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "raylib.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | enum class CharacterAnimationState 13 | { 14 | None, 15 | Idle, 16 | Walking, 17 | Running, 18 | Turning 19 | }; 20 | 21 | 22 | struct CharacterInfo 23 | { 24 | virtual ~CharacterInfo() = default; 25 | 26 | std::string Name; 27 | std::string ModelName; 28 | float RotationOffset = 0; 29 | bool IsYUp = false; 30 | std::unordered_map SequenceNames; 31 | std::string ShadowTexture; 32 | }; 33 | 34 | namespace CharacterManager 35 | { 36 | void Init(); 37 | void Cleanup(); 38 | 39 | std::shared_ptr GetCharacter(const std::string& name); 40 | void UnloadAll(); 41 | }; -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/LICENSE.md: -------------------------------------------------------------------------------- 1 | LDtkLoader - Copyright (C) 2020 Modar Nasser - 2 | 3 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 4 | 5 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 6 | 7 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 8 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 9 | 3. This notice may not be removed or altered from any source distribution. 10 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/defs/LayerDef.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 12/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 9 | 10 | #include "LDtkLoader/DataTypes.hpp" 11 | #include "LDtkLoader/Tileset.hpp" 12 | 13 | namespace ldtk { 14 | 15 | class Project; 16 | 17 | class LayerDef 18 | { 19 | friend class Layer; 20 | 21 | public: 22 | const LayerType type; 23 | const std::string name; 24 | const int uid; 25 | const int cell_size; 26 | const float opacity; 27 | const IntPoint offset; 28 | const FloatPoint tile_pivot; 29 | 30 | LayerDef(const nlohmann::json& j, Project* p); 31 | 32 | private: 33 | const Tileset* const m_tileset; 34 | std::map m_intgrid_values; 35 | }; 36 | 37 | } // namespace ldtk 38 | -------------------------------------------------------------------------------- /game/src/scene.cpp: -------------------------------------------------------------------------------- 1 | #include "scene.h" 2 | 3 | #include "system.h" 4 | #include "game_object.h" 5 | 6 | #include "map/map_reader.h" 7 | 8 | Scene::Scene() 9 | { 10 | RootObject = std::make_unique(); 11 | } 12 | 13 | void Scene::Init() 14 | { 15 | WorldRaycaster.SetMap(&WorldMap); 16 | } 17 | 18 | void Scene::Load(std::string_view map) 19 | { 20 | CurrentWorldMap = map; 21 | WorldMap.Clear(); 22 | 23 | if (!map.empty()) 24 | ReadWorld(map.data(), *this); 25 | 26 | WorldRaycaster.SetMap(&WorldMap); 27 | } 28 | 29 | void Scene::ReloadMap() 30 | { 31 | WorldMap.Clear(); 32 | if (!CurrentWorldMap.empty()) 33 | ReadWorld(CurrentWorldMap.data(), *this); 34 | 35 | WorldRaycaster.SetMap(&WorldMap); 36 | } 37 | 38 | void Scene::Cleanup() 39 | { 40 | RootObject = nullptr; 41 | } 42 | 43 | GameObject* Scene::AddObject() 44 | { 45 | auto* object = RootObject->AddChild(); 46 | 47 | return object; 48 | } -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/defs/EntityDef.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 16/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "LDtkLoader/defs/FieldDef.hpp" 10 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 11 | 12 | #include "LDtkLoader/DataTypes.hpp" 13 | #include "LDtkLoader/Tileset.hpp" 14 | #include "LDtkLoader/containers/TagsContainer.hpp" 15 | 16 | namespace ldtk { 17 | 18 | class Project; 19 | 20 | class EntityDef : public TagsContainer 21 | { 22 | public: 23 | const std::string name; 24 | const int uid; 25 | const IntPoint size; 26 | const Color color; 27 | const FloatPoint pivot; 28 | const Tileset* tileset; 29 | const IntRect texture_rect; 30 | std::vector fields; 31 | NineSliceBorders nine_slice_borders; 32 | 33 | EntityDef(const nlohmann::json& j, Project* p); 34 | }; 35 | 36 | } // namespace ldtk 37 | -------------------------------------------------------------------------------- /game/include/components/mobile_object_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | #include "raylib.h" 6 | #include "raymath.h" 7 | #include "services/character_manager.h" 8 | 9 | #include 10 | #include 11 | 12 | class ModelInstance; 13 | class AnimatedModelInstance; 14 | struct CharacterInfo; 15 | 16 | class MobComponent : public Component 17 | { 18 | public: 19 | DEFINE_COMPONENT(MobComponent) 20 | 21 | void OnAddedToObject() override; 22 | 23 | void Draw(); 24 | 25 | ModelInstance* GetModelInstance(); 26 | 27 | void SetSpeedFactor(float value); 28 | void SetAnimationState(CharacterAnimationState state); 29 | 30 | protected: 31 | void OnCreate() override; 32 | 33 | protected: 34 | std::shared_ptr Instance = nullptr; 35 | 36 | std::shared_ptr Character = nullptr; 37 | CharacterAnimationState AnimationState = CharacterAnimationState::None; 38 | 39 | Texture ShadowTexture = { 0 }; 40 | }; 41 | -------------------------------------------------------------------------------- /game/include/systems/scene_render_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system.h" 4 | #include "map/map_render.h" 5 | #include "utilities/lighting_system.h" 6 | #include "services/model_manager.h" 7 | #include "raylib.h" 8 | 9 | class PlayerManagementSystem; 10 | class MapObjectSystem; 11 | class MobSystem; 12 | 13 | class SceneRenderSystem : public System 14 | { 15 | public: 16 | DEFINE_SYSTM_NO_CONSTRUCTOR(SceneRenderSystem); 17 | 18 | SceneRenderSystem(); 19 | void MapObjectAdded(class MapObjectComponent* object); 20 | 21 | protected: 22 | void OnSetup() override; 23 | void OnUpdate() override; 24 | 25 | protected: 26 | MapRenderer Render; 27 | PlayerManagementSystem* PlayerManager = nullptr; 28 | MapObjectSystem* MapObjects = nullptr; 29 | MobSystem* Mobs = nullptr; 30 | 31 | Shader SkyboxShader = { 0 }; 32 | Texture2D SkyboxTexture = { 0 }; 33 | Mesh Skybox = { 0 }; 34 | Material SkyboxMaterial = { 0 }; 35 | 36 | LightScene ObjectLights; 37 | Shader MapShader = { 0 }; 38 | 39 | int AnimationShaderLocation = 0; 40 | }; -------------------------------------------------------------------------------- /game/include/components/mob_behavior_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "component.h" 3 | #include "systems/mobile_object_system.h" 4 | 5 | #include "utilities/debug_draw_utility.h" 6 | 7 | class MobBehaviorComponent : public Component 8 | { 9 | public: 10 | DEFINE_COMPONENT_WITH_SYSTEM_NO_CONSTRUCTOR(MobBehaviorComponent, MobSystem); 11 | 12 | MobBehaviorComponent(GameObject* owner); 13 | 14 | void Process(); 15 | 16 | bool FollowPath = false; 17 | bool LoopPath = true; 18 | 19 | float MoveSpeed = 2; 20 | float RotationSpeed = 180; 21 | 22 | std::vector Path; 23 | 24 | protected: 25 | enum class AIState 26 | { 27 | Unknown, 28 | Moving, 29 | Waiting, 30 | }; 31 | 32 | AIState State = AIState::Unknown; 33 | 34 | float WaitTime = 0; 35 | size_t CurrentPathIndex = 0; 36 | 37 | Vector3 DesiredPostion = { 0, 0, 0 }; 38 | float DesiredAngle = 0; 39 | 40 | DebugDrawUtility::DebugDraw Visualizer; 41 | 42 | protected: 43 | float GetAngleToPathPoint() const; 44 | float GetDistanceToPlathPoint() const; 45 | }; 46 | -------------------------------------------------------------------------------- /game/include/components/trigger_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | 6 | #include "raylib.h" 7 | #include "map/map.h" 8 | 9 | #include "systems/map_object_system.h" 10 | #include "utilities/debug_draw_utility.h" 11 | 12 | class TriggerComponent : public Component 13 | { 14 | public: 15 | DEFINE_COMPONENT_WITH_SYSTEM_NO_CONSTRUCTOR(TriggerComponent, MapObjectSystem) 16 | 17 | TriggerComponent(GameObject* owner); 18 | TriggerComponent(GameObject* owner, const Rectangle& bounds); 19 | 20 | Rectangle Bounds = { 0 }; 21 | int TriggerId = 0; 22 | 23 | static constexpr char TriggerEnter[] = "TriggerComponentEnter"; 24 | static constexpr char TriggerExit[] = "TriggerComponentExit"; 25 | 26 | void AddObject(ObjectLifetimeToken::Ptr token); 27 | void RemovObject(ObjectLifetimeToken::Ptr token); 28 | 29 | bool HasObject(GameObject* object); 30 | bool HasAnyObjects(); 31 | 32 | protected: 33 | void DrawDebug(); 34 | 35 | protected: 36 | std::vector ConainedObjects; 37 | 38 | DebugDrawUtility::DebugDraw Visualizer; 39 | }; -------------------------------------------------------------------------------- /game/include/systems/player_management_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system.h" 4 | #include "raylib.h" 5 | #include "raymath.h" 6 | 7 | class SpawnPointComponent; 8 | class MapObjectSystem; 9 | class TransformComponent; 10 | 11 | class PlayerManagementSystem : public System 12 | { 13 | public: 14 | DEFINE_SYSTEM(PlayerManagementSystem) 15 | 16 | Vector3 GetPlayerPos() const; 17 | Vector3 GetPlayerFacing() const; 18 | 19 | float GetPlayerPitch() const; 20 | 21 | static constexpr char PlayerHitWall[] = "PlayerHitWall"; 22 | static constexpr char PlayerHitObstacle[] = "PlayerHitObstacle"; 23 | 24 | protected: 25 | void OnSetup() override; 26 | void OnUpdate() override; 27 | void OnAddObject(GameObject* object) override; 28 | 29 | protected: 30 | class InputSystem* Input = nullptr; 31 | 32 | float PlayerPitch = 0; 33 | 34 | float PlayerFowardSpeed = 4; 35 | float PlayerSideStepSpeed = 2; 36 | 37 | SpawnPointComponent* Spawn = nullptr; 38 | 39 | MapObjectSystem* MapObjects = nullptr; 40 | 41 | GameObject* PlayerObject = nullptr; 42 | TransformComponent* PlayerTransform = nullptr; 43 | }; -------------------------------------------------------------------------------- /extras/staticLib/include/lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | Raylib example file. 3 | This is an example main file for a simple raylib project. 4 | Use this as a starting point or replace it with your code. 5 | 6 | -- Copyright (c) 2020-2024 Jeffery Myers 7 | -- 8 | --This software is provided "as-is", without any express or implied warranty. In no event 9 | --will the authors be held liable for any damages arising from the use of this software. 10 | 11 | --Permission is granted to anyone to use this software for any purpose, including commercial 12 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 13 | 14 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 15 | -- wrote the original software. If you use this software in a product, an acknowledgment 16 | -- in the product documentation would be appreciated but is not required. 17 | -- 18 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 19 | -- as being the original software. 20 | -- 21 | -- 3. This notice may not be removed or altered from any source distribution. 22 | 23 | */ 24 | #pragma once 25 | 26 | #include "raylib.h" 27 | 28 | Color GetTextColor(); 29 | -------------------------------------------------------------------------------- /game/include/systems/map_object_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system.h" 4 | #include "systems/audio_system.h" 5 | #include "components/map_object_component.h" 6 | #include "component.h" 7 | #include "raylib.h" 8 | 9 | #include 10 | 11 | class TriggerComponent; 12 | class DoorControllerComponent; 13 | class SceneRenderSystem; 14 | 15 | 16 | class MapObjectSystem : public System 17 | { 18 | public: 19 | DEFINE_SYSTEM(MapObjectSystem) 20 | 21 | SystemComponentList MapObjects; 22 | SystemComponentList Triggers; 23 | SystemComponentList Doors; 24 | 25 | bool MoveEntity(Vector3& position, Vector3& desiredMotion, float radius, GameObject* entity = nullptr); 26 | void CheckTriggers(GameObject* entity, float radius, bool hitSomething); 27 | 28 | protected: 29 | void OnSetup() override; 30 | void OnUpdate() override; 31 | void OnAddObject(GameObject* object) override; 32 | void OnRemoveObject(GameObject* object) override; 33 | 34 | SceneRenderSystem* SceneRenderer = nullptr; 35 | AudioSystem* Audio = nullptr; 36 | 37 | SoundInstance::Ptr OpenDoorSound; 38 | SoundInstance::Ptr CloseDoorSound; 39 | }; -------------------------------------------------------------------------------- /extras/staticLib/src/lib.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Raylib example file. 3 | This is an example main file for a simple raylib project. 4 | Use this as a starting point or replace it with your code. 5 | 6 | -- Copyright (c) 2020-2024 Jeffery Myers 7 | -- 8 | --This software is provided "as-is", without any express or implied warranty. In no event 9 | --will the authors be held liable for any damages arising from the use of this software. 10 | 11 | --Permission is granted to anyone to use this software for any purpose, including commercial 12 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 13 | 14 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 15 | -- wrote the original software. If you use this software in a product, an acknowledgment 16 | -- in the product documentation would be appreciated but is not required. 17 | -- 18 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 19 | -- as being the original software. 20 | -- 21 | -- 3. This notice may not be removed or altered from any source distribution. 22 | 23 | */ 24 | 25 | #include "lib.h" 26 | 27 | Color GetTextColor() 28 | { 29 | return RED; 30 | } 31 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Tile.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 22/02/2022. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 8 | 9 | #include "LDtkLoader/DataTypes.hpp" 10 | 11 | namespace ldtk { 12 | 13 | class Layer; 14 | 15 | class Tile 16 | { 17 | public: 18 | const Layer* const layer; 19 | 20 | const int coordId = 0; 21 | const int tileId = 0; 22 | 23 | const bool flipX = false; 24 | const bool flipY = false; 25 | 26 | const float alpha; 27 | 28 | auto getPosition() const -> IntPoint; 29 | auto getGridPosition() const -> IntPoint; 30 | auto getWorldPosition() const -> IntPoint; 31 | 32 | auto getTextureRect() const -> IntRect; 33 | 34 | auto getVertices() const -> std::array; 35 | 36 | static const Tile None; 37 | 38 | Tile(const Layer* l, IntPoint pos, int coord_id, int tile_id, int flips, float a); 39 | 40 | private: 41 | IntPoint m_position; 42 | }; 43 | 44 | auto operator==(const Tile& l, const Tile& r) -> bool; 45 | auto operator!=(const Tile& l, const Tile& r) -> bool; 46 | 47 | } // namespace ldtk 48 | -------------------------------------------------------------------------------- /editor_common/include/menu_container.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "command_system.h" 4 | 5 | using namespace Commands; 6 | 7 | namespace Menus 8 | { 9 | class MenuBar : public CommandContainer 10 | { 11 | public: 12 | void Show(); 13 | 14 | void ProcessShortcuts(); 15 | 16 | float Height = 0; 17 | 18 | protected: 19 | void ShowSubmenu(CommandContainer* container); 20 | void ShowGroup(CommandContainer* container, bool first); 21 | void ShowMenuItem(Command* command); 22 | 23 | void ProcessShortcuts(CommandItem* command); 24 | }; 25 | 26 | class MenuPlaceHolder : public CommandItem 27 | { 28 | private: 29 | std::string Name; 30 | public: 31 | MenuPlaceHolder(std::string_view name) : Name(name) {} 32 | CommandItemType GetItemType() const override { return CommandItemType::None; } 33 | std::string_view GetName() override { return Name; } 34 | bool IsActive() const { return false; } 35 | }; 36 | 37 | class SubMenu : public CommandContainer 38 | { 39 | public: 40 | SubMenu() = default; 41 | SubMenu(std::string_view name) : CommandContainer(name) {} 42 | 43 | CommandItemType GetItemType() const override { return CommandItemType::Container; } 44 | }; 45 | } -------------------------------------------------------------------------------- /game/include/utilities/debug_draw_utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "raylib.h" 7 | 8 | class Component; 9 | 10 | namespace DebugDrawUtility 11 | { 12 | class DebugDraw 13 | { 14 | public: 15 | DebugDraw(Component* owner); 16 | ~DebugDraw(); 17 | 18 | DebugDraw(const DebugDraw&) = delete; 19 | DebugDraw* operator = (const DebugDraw&) = delete; 20 | 21 | void SetDrawFunctions(std::function draw3d, std::function draw2d = nullptr); 22 | 23 | #if defined(_DEBUG) 24 | std::function Draw2D = nullptr; 25 | std::function Draw3D = nullptr; 26 | #endif 27 | }; 28 | 29 | void Draw2D(); 30 | void Draw3D(const Camera3D& camera); 31 | 32 | void Cleanup(); 33 | 34 | void DisableComponent(size_t componentHash); 35 | template 36 | inline void DisableComponent() { DisableComponent(T::TypeID()); } 37 | 38 | void EnableComponent(size_t componentHash); 39 | template 40 | inline void EnableComponent() { EnableComponent(T::TypeID()); } 41 | 42 | bool IsComponentEnabled(size_t componentHash); 43 | template 44 | inline bool IsComponentEnabled() { return IsComponentEnabled(T::TypeID()); } 45 | } -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/LayerDef.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 12/11/2020. 2 | 3 | #include "LDtkLoader/defs/LayerDef.hpp" 4 | 5 | #include 6 | 7 | #include "LDtkLoader/Project.hpp" 8 | 9 | #include "json.hpp" 10 | 11 | using namespace ldtk; 12 | 13 | LayerDef::LayerDef(const nlohmann::json& j, Project* p) 14 | : type(getLayerTypeFromString(j["type"].get())) 15 | , name(j["identifier"].get()) 16 | , uid(j["uid"].get()) 17 | , cell_size(j["gridSize"].get()) 18 | , opacity(j["displayOpacity"].get()) 19 | , offset(j["pxOffsetX"].get(), j["pxOffsetY"].get()) 20 | , tile_pivot(j["tilePivotX"].get(), j["tilePivotY"].get()) 21 | , m_tileset(j["tilesetDefUid"].is_null() ? nullptr : &p->getTileset(j["tilesetDefUid"].get())) 22 | { 23 | if (type == LayerType::IntGrid) { 24 | for (const auto& int_grid_val : j["intGridValues"]) { 25 | auto val = int_grid_val["value"].get(); 26 | auto identifier = int_grid_val["identifier"].is_null() 27 | ? "" 28 | : int_grid_val["identifier"].get(); 29 | auto color = Color(int_grid_val["color"].get()); 30 | m_intgrid_values.emplace(val, IntGridValue{val, identifier, color}); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /game/include/game.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "game_object.h" 5 | 6 | enum class SystemStage 7 | { 8 | PreUpdate, 9 | Update, 10 | PostUpdate, 11 | Async, 12 | PreRender, 13 | Render, 14 | PostRender, 15 | }; 16 | 17 | enum class GameState 18 | { 19 | Empty, 20 | Loading, 21 | Playing, 22 | Closing, 23 | }; 24 | 25 | class System; 26 | class Scene; 27 | 28 | namespace App 29 | { 30 | void RegisterSystem(SystemStage stage, std::unique_ptr system); 31 | 32 | template 33 | inline void RegisterSystem(SystemStage stage) 34 | { 35 | App::RegisterSystem(stage, std::move(std::make_unique())); 36 | } 37 | 38 | System* GetSystem(size_t systemId); 39 | 40 | template 41 | inline T* GetSystem() 42 | { 43 | return static_cast(GetSystem(T::GUID())); 44 | } 45 | 46 | void Init(); 47 | void Cleanup(); 48 | 49 | void Reset(); 50 | 51 | void NewFrame(); 52 | 53 | void AddEventHandler(size_t hash, GameObjectEventHandler handler, ObjectLifetimeToken::Ptr token); 54 | void AddEventHandler(std::string_view name, GameObjectEventHandler handler, ObjectLifetimeToken::Ptr token); 55 | void CallEvent(size_t hash, GameObject* sender, GameObject* target); 56 | 57 | void Quit(); 58 | 59 | GameState& GetState(); 60 | Scene& GetScene(); 61 | } -------------------------------------------------------------------------------- /model_tool/include/app.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "raylib.h" 8 | #include "model.h" 9 | 10 | enum class PanelDockingType 11 | { 12 | Floating = 0, 13 | LeftDock, 14 | RightDock, 15 | }; 16 | 17 | class Panel 18 | { 19 | public: 20 | std::string Name; 21 | std::string Icon; 22 | 23 | uint32_t ExtraWindowFlags = 0; 24 | 25 | Vector2 MinSize = { -1. - 1 }; 26 | 27 | PanelDockingType DockingType = PanelDockingType::Floating; 28 | 29 | bool Open = true; 30 | 31 | virtual ~Panel() = default; 32 | 33 | void Show(); 34 | 35 | protected: 36 | virtual void OnShowContents() = 0; 37 | }; 38 | 39 | namespace App 40 | { 41 | Models::AnimateableModel& GetModel(); 42 | 43 | void SetSeletedMesh(int mesh); 44 | int GetSelectedMesh(); 45 | 46 | void SetSeletedBone(int bone); 47 | int GetSelectedBone(); 48 | 49 | struct AnimationState 50 | { 51 | std::string Sequence; 52 | int Frame = -1; 53 | Models::AnimationSet Animations; 54 | }; 55 | AnimationState& GetAnimations(); 56 | 57 | void ModelUpdated(); 58 | 59 | void LoadModel(const char* filename); 60 | 61 | void SaveStandardResource(); 62 | 63 | void RequestQuit(); 64 | 65 | void AddPanel(std::unique_ptr panel); 66 | 67 | template 68 | void AddPanel() { AddPanel(std::make_unique()); } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /game/include/systems/audio_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "raylib.h" 12 | 13 | class Table; 14 | 15 | class SoundInstance 16 | { 17 | public: 18 | int Play(); 19 | bool IsPlaying(int instanceID); 20 | void Stop(int instanceID); 21 | void StopAll(); 22 | 23 | using Ptr = std::shared_ptr; 24 | 25 | SoundInstance(Sound sound); 26 | ~SoundInstance(); 27 | private: 28 | Sound SourceSound = { 0 }; 29 | std::vector Aliases; 30 | 31 | private: 32 | int FindFreeSoundInstance(); 33 | const Sound& GetSound(int instanceID) const; 34 | }; 35 | 36 | class AudioSystem : public System 37 | { 38 | public: 39 | DEFINE_SYSTEM(AudioSystem) 40 | 41 | SoundInstance::Ptr GetSound(const std::string& name); 42 | Music GetMusic(const std::string& name); 43 | 44 | bool IsReady() override { return AudioReady; } 45 | 46 | protected: 47 | void OnInit() override; 48 | void OnSetup() override; 49 | void OnUpdate() override; 50 | 51 | void OnCleaup() override; 52 | 53 | private: 54 | Sound* LoadSound(const std::string& name, const std::string_view& file); 55 | 56 | private: 57 | std::unordered_map LoadedSounds; 58 | const Table* AudioManifestTable = nullptr; 59 | std::thread AudioLoaderThread; 60 | 61 | bool AudioReady = false; 62 | }; -------------------------------------------------------------------------------- /model_lib/premake5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2020-2024 Jeffery Myers 2 | -- 3 | --This software is provided "as-is", without any express or implied warranty. In no event 4 | --will the authors be held liable for any damages arising from the use of this software. 5 | 6 | --Permission is granted to anyone to use this software for any purpose, including commercial 7 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 10 | -- wrote the original software. If you use this software in a product, an acknowledgment 11 | -- in the product documentation would be appreciated but is not required. 12 | -- 13 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | -- as being the original software. 15 | -- 16 | -- 3. This notice may not be removed or altered from any source distribution. 17 | 18 | baseName = path.getbasename(os.getcwd()); 19 | 20 | project (baseName) 21 | kind "StaticLib" 22 | location "./" 23 | targetdir "../bin/%{cfg.buildcfg}" 24 | 25 | vpaths 26 | { 27 | ["Header Files/*"] = { "include/**.h", "include/**.hpp", "**.h", "**.hpp"}, 28 | ["Source Files/*"] = { "src/**.cpp", "src/**.c", "**.cpp","**.c"}, 29 | } 30 | files {"**.hpp", "**.h", "**.cpp","**.c"} 31 | 32 | includedirs { "./" } 33 | includedirs { "./src" } 34 | includedirs { "./include" } 35 | 36 | include_raylib() -------------------------------------------------------------------------------- /rlImGui/premake5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2020-2024 Jeffery Myers 2 | -- 3 | --This software is provided "as-is", without any express or implied warranty. In no event 4 | --will the authors be held liable for any damages arising from the use of this software. 5 | 6 | --Permission is granted to anyone to use this software for any purpose, including commercial 7 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 10 | -- wrote the original software. If you use this software in a product, an acknowledgment 11 | -- in the product documentation would be appreciated but is not required. 12 | -- 13 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | -- as being the original software. 15 | -- 16 | -- 3. This notice may not be removed or altered from any source distribution. 17 | 18 | baseName = path.getbasename(os.getcwd()); 19 | 20 | project (baseName) 21 | kind "StaticLib" 22 | location "./" 23 | targetdir "../bin/%{cfg.buildcfg}" 24 | 25 | vpaths 26 | { 27 | ["Header Files/*"] = { "include/**.h", "include/**.hpp", "**.h", "**.hpp"}, 28 | ["Source Files/*"] = { "src/**.cpp", "src/**.c", "**.cpp","**.c"}, 29 | } 30 | files {"**.hpp", "**.h", "**.cpp","**.c"} 31 | 32 | includedirs { "./" } 33 | includedirs { "./src" } 34 | includedirs { "./include" } 35 | 36 | include_raylib() -------------------------------------------------------------------------------- /extras/staticLib/premake5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2020-2024 Jeffery Myers 2 | -- 3 | --This software is provided "as-is", without any express or implied warranty. In no event 4 | --will the authors be held liable for any damages arising from the use of this software. 5 | 6 | --Permission is granted to anyone to use this software for any purpose, including commercial 7 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 10 | -- wrote the original software. If you use this software in a product, an acknowledgment 11 | -- in the product documentation would be appreciated but is not required. 12 | -- 13 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | -- as being the original software. 15 | -- 16 | -- 3. This notice may not be removed or altered from any source distribution. 17 | 18 | baseName = path.getbasename(os.getcwd()); 19 | 20 | project (baseName) 21 | kind "StaticLib" 22 | location "./" 23 | targetdir "../bin/%{cfg.buildcfg}" 24 | 25 | vpaths 26 | { 27 | ["Header Files/*"] = { "include/**.h", "include/**.hpp", "**.h", "**.hpp"}, 28 | ["Source Files/*"] = { "src/**.cpp", "src/**.c", "**.cpp","**.c"}, 29 | } 30 | files {"**.hpp", "**.h", "**.cpp","**.c"} 31 | 32 | includedirs { "./" } 33 | includedirs { "./src" } 34 | includedirs { "./include" } 35 | 36 | include_raylib() -------------------------------------------------------------------------------- /editor_common/premake5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2020-2024 Jeffery Myers 2 | -- 3 | --This software is provided "as-is", without any express or implied warranty. In no event 4 | --will the authors be held liable for any damages arising from the use of this software. 5 | 6 | --Permission is granted to anyone to use this software for any purpose, including commercial 7 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 10 | -- wrote the original software. If you use this software in a product, an acknowledgment 11 | -- in the product documentation would be appreciated but is not required. 12 | -- 13 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | -- as being the original software. 15 | -- 16 | -- 3. This notice may not be removed or altered from any source distribution. 17 | 18 | baseName = path.getbasename(os.getcwd()); 19 | 20 | project (baseName) 21 | kind "StaticLib" 22 | location "./" 23 | targetdir "../bin/%{cfg.buildcfg}" 24 | 25 | vpaths 26 | { 27 | ["Header Files/*"] = { "include/**.h", "include/**.hpp", "**.h", "**.hpp"}, 28 | ["Source Files/*"] = { "src/**.cpp", "src/**.c", "**.cpp","**.c"}, 29 | } 30 | files {"**.hpp", "**.h", "**.cpp","**.c"} 31 | 32 | includedirs { "./" } 33 | includedirs { "./src" } 34 | includedirs { "./include" } 35 | 36 | include_raylib() 37 | link_to("rlImGui") -------------------------------------------------------------------------------- /game/src/systems/overlay_render_system.cpp: -------------------------------------------------------------------------------- 1 | #include "systems/overlay_render_system.h" 2 | #include "systems/player_management_system.h" 3 | #include "services/texture_manager.h" 4 | #include "services/global_vars.h" 5 | #include "scene.h" 6 | 7 | #include "raylib.h" 8 | 9 | void OverlayRenderSystem::OnUpdate() 10 | { 11 | if (App::GetState() != GameState::Playing) 12 | return; 13 | 14 | DrawText(TextFormat("Rays Cast %d", App::GetScene().GetRaycaster().GetCastCount()), 10, GetScreenHeight() - 50, 20, SKYBLUE); 15 | DrawText(TextFormat("Cells Drawn %d of %d total cells", GlobalVars::UseVisCulling ? App::GetScene().GetRaycaster().GetHitCelList().size() : App::GetScene().GetMap().Cells.size(), App::GetScene().GetMap().Cells.size()), 10, GetScreenHeight() - 70, 20, YELLOW); 16 | 17 | float vram = TextureManager::GetUsedVRAM() / 1024.0f; 18 | const char* vramSuffix = "kb"; 19 | if (vram > 1024) 20 | { 21 | vram /= 1024.0f; 22 | vramSuffix = "mb"; 23 | } 24 | if (vram > 1024) 25 | { 26 | vram /= 1024.0f; 27 | vramSuffix = "gb"; 28 | } 29 | 30 | DrawText(TextFormat("Used Texture Memory %0.2f%s", vram, vramSuffix), 10, GetScreenHeight()-30, 20, WHITE); 31 | DrawFPS(10, GetScreenHeight() - 90); 32 | 33 | if (GlobalVars::ShowCoordinates) 34 | { 35 | auto playerPos = App::GetSystem()->GetPlayerPos(); 36 | 37 | DrawText(TextFormat("Player X%0.2f Y%0.2f", playerPos.x, playerPos.y), GetScreenWidth()-250, GetScreenHeight() - 30, 20, WHITE); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/EntityDef.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 16/11/2020. 2 | 3 | #include "LDtkLoader/defs/EntityDef.hpp" 4 | 5 | #include "LDtkLoader/Project.hpp" 6 | 7 | #include "json.hpp" 8 | 9 | using namespace ldtk; 10 | 11 | EntityDef::EntityDef(const nlohmann::json& j, Project* p) 12 | : TagsContainer(j["tags"]) 13 | , name(j["identifier"].get()) 14 | , uid(j["uid"].get()) 15 | , size(j["width"].get(), j["height"].get()) 16 | , color(j["color"].get()) 17 | , pivot(j["pivotX"].get(), j["pivotY"].get()) 18 | , tileset(j["tileRect"].is_null() ? nullptr : &p->getTileset(j["tileRect"]["tilesetUid"].get())) 19 | , texture_rect( 20 | j["tileRect"].is_null() 21 | ? IntRect{} 22 | : IntRect{j["tileRect"]["x"], j["tileRect"]["y"], j["tileRect"]["w"], j["tileRect"]["h"]} 23 | ) 24 | , nine_slice_borders({-1, -1, -1, -1}) 25 | { 26 | if (j.contains("nineSliceBorders") && !j["nineSliceBorders"].empty()) { 27 | auto borders = j["nineSliceBorders"].get>(); 28 | nine_slice_borders.top = borders[0]; 29 | nine_slice_borders.right = borders[1]; 30 | nine_slice_borders.bottom = borders[2]; 31 | nine_slice_borders.left = borders[3]; 32 | } 33 | 34 | for (const auto& fd : j["fieldDefs"]) { 35 | auto field_type = fd["__type"].get(); 36 | auto field_name = fd["identifier"].get(); 37 | fields.emplace_back(FieldDef{getFieldTypeFromString(field_type), field_name}); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /rlImGui/include/extras/FontAwsome_LICENSE.txt: -------------------------------------------------------------------------------- 1 | Font Awesome Free License 2 | ------------------------- 3 | 4 | Font Awesome Free is free, open source, and GPL friendly. You can use it for 5 | commercial projects, open source projects, or really almost whatever you want. 6 | Full Font Awesome Free license: https://fontawesome.com/license/free. 7 | 8 | # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) 9 | In the Font Awesome Free download, the CC BY 4.0 license applies to all icons 10 | packaged as SVG and JS file types. 11 | 12 | # Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL) 13 | In the Font Awesome Free download, the SIL OFL license applies to all icons 14 | packaged as web and desktop font files. 15 | 16 | # Code: MIT License (https://opensource.org/licenses/MIT) 17 | In the Font Awesome Free download, the MIT license applies to all non-font and 18 | non-icon files. 19 | 20 | # Attribution 21 | Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font 22 | Awesome Free files already contain embedded comments with sufficient 23 | attribution, so you shouldn't need to do anything additional when using these 24 | files normally. 25 | 26 | We've kept attribution comments terse, so we ask that you do not actively work 27 | to remove them from files, especially code. They're a great way for folks to 28 | learn about Font Awesome. 29 | 30 | # Brand Icons 31 | All brand icons are trademarks of their respective owners. The use of these 32 | trademarks does not indicate endorsement of the trademark holder by Font 33 | Awesome, nor vice versa. **Please do not use brand logos for any purpose except 34 | to represent the company, product, or service to which they refer.** 35 | -------------------------------------------------------------------------------- /game/include/components/door_controller_component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "component.h" 4 | #include "game_object.h" 5 | 6 | #include "raylib.h" 7 | #include "map/map.h" 8 | 9 | 10 | #include "systems/map_object_system.h" 11 | 12 | class DoorControllerComponent : public Component 13 | { 14 | public: 15 | DEFINE_COMPONENT(DoorControllerComponent) 16 | 17 | DoorControllerComponent(GameObject* owner, size_t doorId) : Component(owner) { Doors.push_back(doorId); } 18 | 19 | std::vector Doors = { 0 }; 20 | 21 | bool MustOpenBeforClose = true; 22 | 23 | float OpenSpeed = 1; 24 | float CloseSpeed = 1; 25 | 26 | float MiniumOpenTime = 0; 27 | 28 | bool StayOpen = false; 29 | 30 | void OnAddedToObject() override; 31 | 32 | void Update(); 33 | 34 | static constexpr char DoorOpening[] = "DoorOpening"; 35 | static constexpr char DoorOpened[] = "DoorOpened"; 36 | static constexpr char DoorClosing[] = "DoorClosing"; 37 | static constexpr char DoorClosed[] = "DoorClosed"; 38 | 39 | static constexpr char DoorSecuritySuccess[] = "DoorSecuritySuccess"; 40 | static constexpr char DoorSecurityFailed[] = "DoorSecurityFailed"; 41 | 42 | protected: 43 | void OnTriggerEnter(GameObject* sender, GameObject* subject); 44 | void OnTriggerExit(GameObject* sender, GameObject* subject); 45 | 46 | void SetDoorParams(float param); 47 | void SetDoorBlocked(bool blocked); 48 | 49 | enum class State 50 | { 51 | Closed, 52 | Opening, 53 | Open, 54 | WaitingForClose, 55 | Closing 56 | }; 57 | 58 | State OpenState = State::Closed; 59 | 60 | bool NeedCloseASAP = false; 61 | 62 | float Param = 0; 63 | }; -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Tileset.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 11/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "LDtkLoader/containers/TagsContainer.hpp" 10 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 11 | #include "LDtkLoader/thirdparty/optional.hpp" 12 | 13 | #include "LDtkLoader/DataTypes.hpp" 14 | #include "LDtkLoader/Enum.hpp" 15 | #include "LDtkLoader/Utils.hpp" 16 | 17 | namespace ldtk { 18 | 19 | class Project; 20 | 21 | class Tileset : public TagsContainer 22 | { 23 | public: 24 | const std::string name; 25 | const int uid; 26 | const std::string path; 27 | const IntPoint texture_size; 28 | const int tile_size; 29 | const int spacing; 30 | const int padding; 31 | 32 | auto getTileTexturePos(int tile_id) const -> IntPoint; 33 | auto getTileCustomData(int tile_id) const -> const std::string&; 34 | auto getTileEnumTags(int tile_id) const -> const std::vector>&; 35 | 36 | auto hasEnumTags() const -> bool; 37 | auto getEnumTagsEnum() const -> const Enum&; 38 | auto getTilesByEnumTag(const EnumValue& enumvalue) const -> const std::vector&; 39 | 40 | Tileset(const nlohmann::json& j, Project* p); 41 | 42 | private: 43 | const Enum* const m_enumtags_enum; 44 | std::unordered_map m_custom_data_map; 45 | std::unordered_map>> m_enumtags_by_tile; 46 | std::unordered_map> m_tiles_by_enumtag; 47 | }; 48 | 49 | } // namespace ldtk 50 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Utils.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 12/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "LDtkLoader/DataTypes.hpp" 9 | 10 | #ifdef LDTK_NO_THROW 11 | #include 12 | #define ldtk_error(msg) \ 13 | do { \ 14 | ldtk::print_error(__FUNCTION__, msg); \ 15 | exit(EXIT_FAILURE); \ 16 | } while (0) 17 | #define ldtk_json_error(ex) \ 18 | do { \ 19 | ldtk::print_json_error(ex.what()); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0) 22 | #define JSON_THROW_USER ldtk_json_error // override nlohmann::json throw macro 23 | #else 24 | #define ldtk_error(msg) \ 25 | throw std::invalid_argument( \ 26 | "LDtkLoader exception (in " + std::string(__FUNCTION__) + ") : " + std::string(msg) \ 27 | ) 28 | #endif 29 | 30 | namespace ldtk { 31 | 32 | template 33 | using ref_wrapper = std::reference_wrapper; 34 | 35 | auto getLayerTypeFromString(const std::string& type_name) -> LayerType; 36 | auto getWorldLayoutFromString(const std::string& layout_name) -> WorldLayout; 37 | auto getDirFromString(const std::string& dir_name) -> Dir; 38 | auto getFieldTypeFromString(const std::string& fieldtype_name) -> FieldType; 39 | 40 | void print_error(const std::string& fn, const std::string& msg); 41 | void print_json_error(const std::string& msg); 42 | 43 | } // namespace ldtk 44 | -------------------------------------------------------------------------------- /model_tool/premake5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2020-2024 Jeffery Myers 2 | -- 3 | --This software is provided "as-is", without any express or implied warranty. In no event 4 | --will the authors be held liable for any damages arising from the use of this software. 5 | 6 | --Permission is granted to anyone to use this software for any purpose, including commercial 7 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 10 | -- wrote the original software. If you use this software in a product, an acknowledgment 11 | -- in the product documentation would be appreciated but is not required. 12 | -- 13 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | -- as being the original software. 15 | -- 16 | -- 3. This notice may not be removed or altered from any source distribution. 17 | 18 | baseName = path.getbasename(os.getcwd()); 19 | 20 | project (baseName) 21 | kind "ConsoleApp" 22 | location "./" 23 | targetdir "../bin/%{cfg.buildcfg}" 24 | 25 | filter "action:vs*" 26 | debugdir "$(SolutionDir)" 27 | 28 | filter "system:windows" 29 | links {"Comdlg32", "ole32"} 30 | 31 | filter{} 32 | 33 | vpaths 34 | { 35 | ["Header Files/*"] = { "include/**.h", "include/**.hpp", "src/**.h", "src/**.hpp", "**.h", "**.hpp"}, 36 | ["Source Files/*"] = {"src/**.c", "src/**.cpp","**.c", "**.cpp"}, 37 | } 38 | files {"**.c", "**.cpp", "**.h", "**.hpp"} 39 | 40 | includedirs { "./" } 41 | includedirs { "src" } 42 | includedirs { "include" } 43 | includedirs { "src/external/tmxlite/include" } 44 | 45 | link_raylib() 46 | link_to("model_lib") 47 | link_to("rlImGui") 48 | link_to("editor_common") -------------------------------------------------------------------------------- /game/premake5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2020-2024 Jeffery Myers 2 | -- 3 | --This software is provided "as-is", without any express or implied warranty. In no event 4 | --will the authors be held liable for any damages arising from the use of this software. 5 | 6 | --Permission is granted to anyone to use this software for any purpose, including commercial 7 | --applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | -- 1. The origin of this software must not be misrepresented; you must not claim that you 10 | -- wrote the original software. If you use this software in a product, an acknowledgment 11 | -- in the product documentation would be appreciated but is not required. 12 | -- 13 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | -- as being the original software. 15 | -- 16 | -- 3. This notice may not be removed or altered from any source distribution. 17 | 18 | baseName = path.getbasename(os.getcwd()); 19 | 20 | project (workspaceName) 21 | kind "ConsoleApp" 22 | location "./" 23 | targetdir "../bin/%{cfg.buildcfg}" 24 | 25 | filter "action:vs*" 26 | debugdir "$(SolutionDir)" 27 | 28 | filter {"action:vs*", "configurations:Release"} 29 | kind "WindowedApp" 30 | entrypoint "mainCRTStartup" 31 | 32 | filter{} 33 | 34 | vpaths 35 | { 36 | ["Header Files/*"] = { "include/**.h", "include/**.hpp", "src/**.h", "src/**.hpp", "**.h", "**.hpp"}, 37 | ["Source Files/*"] = {"src/**.c", "src/**.cpp","**.c", "**.cpp"}, 38 | } 39 | files {"**.c", "**.cpp", "**.h", "**.hpp"} 40 | 41 | includedirs { "./" } 42 | includedirs { "src" } 43 | includedirs { "include" } 44 | includedirs { "src/external/LDtkLoader/include" } 45 | 46 | link_raylib() 47 | link_to("model_lib") 48 | -- use_library("LDtkLoader", "Madour/LDtkLoader", "master") -------------------------------------------------------------------------------- /game/src/utilities/ai_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utilities/ai_utils.h" 2 | 3 | namespace AIUtils 4 | { 5 | float GetRotationTo(const Vector3& position, const Vector3& facing, const Vector3& target) 6 | { 7 | Vector3 vecToTarget = target - position; 8 | 9 | float disanceToTarget = Vector3Length(vecToTarget); 10 | 11 | Vector3 normalizedToTarget = vecToTarget / disanceToTarget; 12 | 13 | float targetDot = Vector3DotProduct(normalizedToTarget, facing); 14 | 15 | float dotAngle = acosf(targetDot) * RAD2DEG; 16 | 17 | if (Vector3DotProduct(vecToTarget, facing) >= 0) 18 | dotAngle *= -1; 19 | 20 | return dotAngle; 21 | } 22 | 23 | constexpr float MinAngleCos = 0.99984769515639123915701155881391f; 24 | 25 | Vector3 MoveTo(const Vector3& position, Vector3& facing, const Vector3& target, float maxMove, float maxRotation) 26 | { 27 | Vector3 vecToTarget = target - position; 28 | 29 | float disanceToTarget = Vector3Length(vecToTarget); 30 | 31 | Vector3 normalizedToTarget = vecToTarget / disanceToTarget; 32 | 33 | float targetDot = Vector3DotProduct(normalizedToTarget, facing); 34 | 35 | Vector3 facingNormal = Vector3{ facing.y, -facing.x, 0 }; 36 | 37 | if (targetDot >= cosf(maxRotation * DEG2RAD)/*MinAngleCos*/) 38 | { 39 | facing = normalizedToTarget; 40 | } 41 | else 42 | { 43 | float rotAngle = maxRotation; 44 | if (Vector3DotProduct(vecToTarget, facingNormal) >= 0) 45 | rotAngle *= -1; 46 | 47 | Vector2 rot = Vector2Rotate(Vector2{ facing.x, facing.y }, rotAngle * DEG2RAD); 48 | facing.x = rot.x; 49 | facing.y = rot.y; 50 | } 51 | 52 | if (disanceToTarget < maxMove) 53 | { 54 | return target - position; 55 | } 56 | else 57 | { 58 | return facing * maxMove; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /game/include/map/raycaster.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map.h" 4 | #include "raymath.h" 5 | 6 | // used to know what side of a grid was hit 7 | enum class HitNormals : uint8_t 8 | { 9 | North = 0, 10 | South, 11 | East, 12 | West 13 | }; 14 | 15 | // a ray that has been cast, with cached info 16 | struct RayResult 17 | { 18 | // the ray's direction 19 | Vector2 Directon = { 0 }; 20 | 21 | // the distance to the cell hit 22 | float Distance = 0; 23 | 24 | // the side of the grid that was hit 25 | HitNormals Normal; 26 | 27 | // what kind of grid cell was hit 28 | uint8_t HitGridType = 0; 29 | 30 | int HitCellIndex = -1; 31 | MapCoordinate TargetCell; 32 | }; 33 | 34 | class Raycaster 35 | { 36 | public: 37 | void SetOutputSize(int renderWidth, float renderFOV); 38 | 39 | void StartFrame(const Vector3& viewLocation, const Vector3& facingVector); 40 | 41 | inline const std::vector& GetResults() const { return RaySet; } 42 | inline const std::vector& GetHitCelList() const { return HitCellLocs; } 43 | 44 | bool IsCellVis(int x, int y) const; 45 | 46 | inline int GetCastCount() const { return CastCount; } 47 | 48 | void SetMap(const Map* map); 49 | 50 | protected: 51 | 52 | void CastRay(RayResult& ray, const Vector3& pos); 53 | 54 | bool CastRayPair(int minPixel, int maxPixel, const Vector3& viewLocation, const Vector3& facingVector); 55 | 56 | void UpdateRayset(const Vector3& viewLocation, const Vector3& facingVector); 57 | 58 | void SetCellVis(int x, int y); 59 | 60 | void AddCellVis(int x, int y); 61 | 62 | const Map* WorldMap = nullptr; 63 | int RenderWidth; 64 | float RenderFOVX; 65 | 66 | int CastCount = 0; 67 | 68 | std::vector RaySet; 69 | Vector2 CameraPlane; 70 | Vector2 NominalCameraPlane; 71 | 72 | std::vector CellStatus; 73 | std::vector HitCells; 74 | std::vector HitCellLocs; 75 | }; -------------------------------------------------------------------------------- /game/include/system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "object_lifetime_token.h" 6 | 7 | /* 8 | Systems are classes that are tied to the world that have an update method that is called by the game loop. 9 | Each system is updated in order as defined by how it's registered. 10 | */ 11 | 12 | class GameObject; 13 | class Scene; 14 | 15 | 16 | using SystemHash = std::hash; 17 | 18 | #define DEFINE_SYSTEM(T) \ 19 | T() : System(){} \ 20 | static size_t GUID() { static std::hash hasher; return hasher(#T);} \ 21 | size_t GetGUID() const override {return T::GUID();} 22 | 23 | #define DEFINE_SYSTM_NO_CONSTRUCTOR(T) \ 24 | static size_t GUID() { static std::hash hasher; return hasher(#T);} \ 25 | size_t GetGUID() const override {return T::GUID();} 26 | 27 | class System 28 | { 29 | public: 30 | System() { Token = ObjectLifetimeToken::Create(this); } 31 | virtual ~System() { Token->Invalidate(); } 32 | 33 | void Init(); // called when the system is created 34 | void Cleanup(); // called when the system is destroyed 35 | 36 | void Setup(); // all systems and states are loaded 37 | 38 | void Update(); // called when the system is updated 39 | 40 | virtual bool IsReady() { return true; } 41 | 42 | void AddObject(GameObject* object); // called when an object is added to the system, 43 | void RemoveObject(GameObject* object); // called when an object is removed 44 | 45 | virtual size_t GetGUID() const = 0; 46 | 47 | const std::set& GetSystemObjects() const { return Objects; } 48 | 49 | protected: 50 | virtual void OnInit() {} 51 | virtual void OnSetup() {} 52 | virtual void OnCleaup() {} 53 | virtual void OnUpdate() {} 54 | 55 | virtual void OnAddObject(GameObject* object) {} 56 | virtual void OnRemoveObject(GameObject* object) {} 57 | 58 | protected: 59 | std::set Objects; 60 | 61 | ObjectLifetimeToken::Ptr Token; 62 | }; 63 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "build debug", 8 | "type": "process", 9 | "command": "make", 10 | "windows": { 11 | "command": "mingw32-make.exe", 12 | "args": [ 13 | "SHELL=cmd" 14 | ] 15 | }, 16 | "group": { 17 | "kind": "build", 18 | "isDefault": true 19 | }, 20 | "problemMatcher": [ 21 | "$gcc" 22 | ], 23 | "dependsOn":["UpdateMake"] 24 | }, 25 | { 26 | "label": "build release", 27 | "type": "process", 28 | "command": "make", 29 | "windows": { 30 | "command": "mingw32-make.exe", 31 | "args": [ 32 | "SHELL=cmd", 33 | "config=release_x64" 34 | ] 35 | }, 36 | "linux": { 37 | "args": [ 38 | "config=release_x64" 39 | ] 40 | }, 41 | "osx": { 42 | "args": [ 43 | ] 44 | }, 45 | "group": "build", 46 | "problemMatcher": [ 47 | "$gcc" 48 | ], 49 | "dependsOn":["UpdateMake"] 50 | }, 51 | { 52 | "label": "UpdateMake", 53 | "type": "process", 54 | "command": "./premake5", 55 | "args": [ 56 | "gmake2" 57 | ], 58 | "windows": { 59 | "command": "./premake5.exe" 60 | }, 61 | "linux": { 62 | "command": "./premake5" 63 | }, 64 | "osx": { 65 | "command": "./premake5.osx" 66 | }, 67 | "group": "build" 68 | } 69 | ] 70 | } -------------------------------------------------------------------------------- /rlImGui/include/rlImGuiColors.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * rlImGui * basic ImGui integration 6 | * 7 | * LICENSE: ZLIB 8 | * 9 | * Copyright (c) 2024 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #pragma once 32 | 33 | #include "raylib.h" 34 | #include "imgui.h" 35 | 36 | namespace rlImGuiColors 37 | { 38 | inline ImVec4 Convert(::Color color) 39 | { 40 | return ImVec4(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f); 41 | } 42 | 43 | inline ::Color Convert(ImVec4 color) 44 | { 45 | return ::Color{ (unsigned char)(color.x * 255.0f), (unsigned char)(color.y * 255.0f), (unsigned char)(color.z * 255.0f), (unsigned char)(color.w * 255.0f) }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /game/include/systems/console_render_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "system.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace ConsoleCommands 11 | { 12 | static constexpr char Reload[] = "reload"; 13 | 14 | static constexpr char ToggleCulling[] = "toggle_culling"; 15 | static constexpr char ToggleGhost[] = "toggle_ghost"; 16 | static constexpr char ToggleDebug[] = "toggle_debug"; 17 | static constexpr char ToggleShowCoordinates[] = "show_coordinates"; 18 | static constexpr char ToggleVSync[] = "toggle_vsync"; 19 | 20 | static constexpr char SetConsoleFontSize[] = "set_console_font"; 21 | static constexpr char SetFPSCap[] = "set_fps_cap"; 22 | 23 | static constexpr char ListCommands[] = "list"; 24 | } 25 | 26 | using CommandHandler = std::function&)>; 27 | 28 | class ConsoleRenderSystem : public System 29 | { 30 | public: 31 | DEFINE_SYSTM_NO_CONSTRUCTOR(ConsoleRenderSystem); 32 | ConsoleRenderSystem(); 33 | ~ConsoleRenderSystem(); 34 | 35 | bool WantKeyInput() const { return ConsoleState != State::Stowed; } 36 | 37 | void ProcessCommand(std::string_view command); 38 | 39 | void RegisterCommand(std::string_view command, CommandHandler handler); 40 | 41 | protected: 42 | void OnUpdate() override; 43 | 44 | void OnSetup() override; 45 | 46 | void OutputVarState(std::string_view name, const bool& value); 47 | void OutputVarState(std::string_view name, const float& value); 48 | void OutputMessage(std::string_view name); 49 | protected: 50 | enum class State 51 | { 52 | Stowed, 53 | Deploying, 54 | Deployed, 55 | Stowing, 56 | }; 57 | 58 | State ConsoleState = State::Stowed; 59 | float Param = 0; 60 | 61 | std::deque ConsoleOutput; 62 | 63 | std::vector ConsoleLog; 64 | size_t CurrentHistoryLogItem = 0; 65 | 66 | std::string CurrentConsoleInput; 67 | std::map CommandHandlers; 68 | }; -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Win32", 5 | "includePath": [ 6 | "${workspaceFolder}/raylib-master/src/", 7 | "${workspaceFolder}/game/**" 8 | ], 9 | "defines": [ 10 | "_DEBUG", 11 | "UNICODE", 12 | "_UNICODE", 13 | "GRAPHICS_API_OPENGL_33", 14 | "PLATFORM_DESKTOP" 15 | ], 16 | "cStandard": "c99", 17 | "cppStandard": "c++14", 18 | "intelliSenseMode": "gcc-x64" 19 | }, 20 | { 21 | "name": "Mac", 22 | "includePath": [ 23 | "${workspaceFolder}/raylib-master/src/", 24 | "${workspaceFolder}/game/**" 25 | ], 26 | "defines": [ 27 | "_DEBUG", 28 | "UNICODE", 29 | "_UNICODE", 30 | "GRAPHICS_API_OPENGL_33", 31 | "PLATFORM_DESKTOP" 32 | ], 33 | "macFrameworkPath": [ 34 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" 35 | ], 36 | "compilerPath": "/usr/bin/clang", 37 | "cStandard": "c11", 38 | "cppStandard": "c++14", 39 | "intelliSenseMode": "clang-x64" 40 | }, 41 | { 42 | "name": "Linux", 43 | "includePath": [ 44 | "${workspaceFolder}/raylib-master/src/", 45 | "${workspaceFolder}/game/**" 46 | ], 47 | "defines": [ 48 | "_DEBUG", 49 | "UNICODE", 50 | "_UNICODE", 51 | "GRAPHICS_API_OPENGL_33", 52 | "PLATFORM_DESKTOP" 53 | ], 54 | "compilerPath": "/usr/bin/clang", 55 | "cStandard": "c11", 56 | "cppStandard": "c++14", 57 | "intelliSenseMode": "clang-x64" 58 | 59 | } 60 | ], 61 | "version": 4 62 | } 63 | -------------------------------------------------------------------------------- /resources/shaders/world.vs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | #define MAX_BONE_NUM 128 4 | 5 | // Input vertex attributes 6 | in vec3 vertexPosition; 7 | in vec2 vertexTexCoord; 8 | in vec3 vertexNormal; 9 | in vec4 vertexColor; 10 | in vec4 vertexBoneIds; 11 | in vec4 vertexBoneWeights; 12 | 13 | // Input uniform values 14 | uniform mat4 mvp; 15 | uniform mat4 matModel; 16 | uniform mat4 matNormal; 17 | 18 | uniform mat4 boneMatrices[MAX_BONE_NUM]; 19 | 20 | uniform int animate; 21 | 22 | // Output vertex attributes (to fragment shader) 23 | out vec3 fragPosition; 24 | out vec2 fragTexCoord; 25 | out vec4 fragColor; 26 | out vec3 fragNormal; 27 | 28 | // NOTE: Add here your custom variables 29 | 30 | void main() 31 | { 32 | // Send vertex attributes to fragment shader 33 | fragTexCoord = vertexTexCoord; 34 | fragColor = vertexColor; 35 | 36 | vec4 vertPos = vec4(vertexPosition,1); 37 | vec4 vertNormal = vec4(vertexNormal,0); 38 | 39 | if (animate != 0) 40 | { 41 | int boneIndex0 = int(vertexBoneIds.x); 42 | int boneIndex1 = int(vertexBoneIds.y); 43 | int boneIndex2 = int(vertexBoneIds.z); 44 | int boneIndex3 = int(vertexBoneIds.w); 45 | 46 | // postion 47 | vertPos = 48 | vertexBoneWeights.x*(boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0)) + 49 | vertexBoneWeights.y*(boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0)) + 50 | vertexBoneWeights.z*(boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0)) + 51 | vertexBoneWeights.w*(boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0)); 52 | 53 | // normals 54 | vec4 normal4 = vec4(vertexNormal, 0.0f); 55 | vertNormal = 56 | boneMatrices[boneIndex0] * normal4 * vertexBoneWeights.x + 57 | boneMatrices[boneIndex1] * normal4 * vertexBoneWeights.y + 58 | boneMatrices[boneIndex2] * normal4 * vertexBoneWeights.z + 59 | boneMatrices[boneIndex3] * normal4 * vertexBoneWeights.w; 60 | vertNormal.w = 0.0f; 61 | } 62 | 63 | // Calculate final vertex data position 64 | fragPosition = vec3(matModel * vertPos); 65 | fragNormal = normalize(vec3(matNormal * vertNormal)); 66 | gl_Position = mvp * vertPos; 67 | } -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Enum.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 13/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "LDtkLoader/containers/TagsContainer.hpp" 10 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 11 | 12 | #include "LDtkLoader/DataTypes.hpp" 13 | 14 | namespace ldtk { 15 | 16 | class Enum; 17 | 18 | class Tileset; 19 | 20 | struct EnumValue 21 | { 22 | const std::string name; 23 | const Color color; 24 | const Enum& type; 25 | 26 | auto hasIcon() const -> bool; 27 | auto getIconTileset() const -> const Tileset&; 28 | auto getIconTextureRect() const -> const IntRect&; 29 | 30 | private: 31 | friend Enum; 32 | friend auto operator==(const EnumValue& l, const EnumValue& r) -> bool; 33 | EnumValue( 34 | std::string name, 35 | int id, 36 | const IntRect& tile_rect, 37 | const Color& color, 38 | const Enum& enum_type 39 | ); 40 | const int id; 41 | const IntRect tile_rect; 42 | }; 43 | 44 | auto operator==(const EnumValue& l, const EnumValue& r) -> bool; 45 | auto operator!=(const EnumValue& l, const EnumValue& r) -> bool; 46 | 47 | class Enum : public TagsContainer 48 | { 49 | friend class Project; 50 | 51 | public: 52 | ~Enum() = default; 53 | Enum(const Enum&) = delete; 54 | Enum(Enum&&) noexcept = default; 55 | auto operator=(const Enum&) -> Enum& = delete; 56 | auto operator=(Enum&&) -> Enum& = default; 57 | 58 | const std::string name; 59 | const int uid; 60 | 61 | auto operator[](const std::string& val_name) const -> const EnumValue&; 62 | 63 | auto hasIcons() const -> bool; 64 | auto getIconsTileset() const -> const Tileset&; 65 | 66 | explicit Enum(const nlohmann::json& j); 67 | 68 | private: 69 | const int m_tileset_id; 70 | const Tileset* m_tileset = nullptr; 71 | std::unordered_map m_values; 72 | }; 73 | 74 | } // namespace ldtk 75 | 76 | auto operator<<(std::ostream& os, const ldtk::EnumValue& enum_value) -> std::ostream&; 77 | -------------------------------------------------------------------------------- /game/include/map/map_render.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/map.h" 4 | #include "raylib.h" 5 | 6 | class Raycaster; 7 | 8 | class MapRenderer 9 | { 10 | public: 11 | Camera3D Viepoint = { 0 }; 12 | Map& WorldMap; 13 | Raycaster& WorldRaycaster; 14 | 15 | MapRenderer(Map& map, Raycaster& caster); 16 | void Reset(); 17 | 18 | void Render(); 19 | 20 | void SetViewpoint(Vector3 position, float pitch, const Vector3& facing); 21 | 22 | void SetEyeHeight(float height); 23 | 24 | Shader& GetWorldShader() { return WorldShader; } 25 | 26 | private: 27 | 28 | struct AmbientOcclusionVertexValue 29 | { 30 | int AOValue = 0; 31 | int ConveredValue = 0; 32 | }; 33 | 34 | struct AmbientOcclusionCellValues 35 | { 36 | AmbientOcclusionVertexValue Values[4]; 37 | }; 38 | 39 | void RenderCell(int x, int y); 40 | void RenderDoor(int x, int y, Color floorColor, const AmbientOcclusionCellValues& aoInfo); 41 | void DrawDoorPanelXAlligned(Color floorColor, Rectangle& uv, const AmbientOcclusionCellValues& aoInfo); 42 | void DrawDoorPanelYAlligned(Color floorColor, Rectangle& uv, const AmbientOcclusionCellValues& aoInfo); 43 | 44 | void RenderFloor(int x, int y, Color floorColor, Color exteriorFloorColor, const Rectangle& tileUv, const AmbientOcclusionCellValues& aoInfo); 45 | void RenderCeiling(int x, int y, Color tint, const Rectangle& tileUv, const AmbientOcclusionCellValues& aoInfo); 46 | void RenderNorthWall(int x, int y, Color tint, const Rectangle& tileUv, const AmbientOcclusionCellValues& aoInfo); 47 | void RenderSouthWall(int x, int y, Color tint, const Rectangle& tileUv, const AmbientOcclusionCellValues& aoInfo); 48 | void RenderEastWall(int x, int y, Color tint, const Rectangle& tileUv, const AmbientOcclusionCellValues& aoInfo); 49 | void RenderWestWall(int x, int y, Color tint, const Rectangle& tileUv, const AmbientOcclusionCellValues& aoInfo); 50 | 51 | private: 52 | float EyeHeight = 0.5f; 53 | 54 | float MapScale = 1; 55 | 56 | //float WallColors[4] = { 1, 0.4f, 0.75f , 0.8f }; 57 | float WallColors[4] = { 1, 1, 1 , 1 }; 58 | float DefaultExteriorZoneLevel = 0.95f; 59 | float DefaultIntereorZoneLevel = 0.8f; 60 | 61 | Shader WorldShader; 62 | 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /documents/tasks.md: -------------------------------------------------------------------------------- 1 | # ToDo 2 | -------------------------------------------------------------- 3 | ## Add assert system 4 | Add assert macro that hits an assert system, on assert take a screenshot get some state. Have the main loop check for asserts and if there is an assert state draw the assert instead of the game. 5 | 6 | ## Add API to set door state 7 | Allow other systems to force a door open or closed 8 | 9 | ## Add door security 10 | Add a basic door security system that is extensiable via scripting. 11 | 12 | ## Add split doors 13 | Add option for split doors, vertical and horizontal. 14 | 15 | ## Add start state for doors. 16 | Let doors start open or closed. 17 | 18 | ## Add max/min state for doors. 19 | Let some doors not open all the way. 20 | 21 | ## Add stay open state for doors 22 | Add an option to allow doors to stay open when triggered. 23 | 24 | ## Only draw meshes in visable cells 25 | Map each mesh's bbox to the vis cell list. 26 | 27 | ## Sort cells far to near 28 | Bucket the vis list by the distance the line has walked so that it can be sorted far to near for transperancy. 29 | 30 | ## Transperant cells 31 | Add option to give a cell a transpeerant wall and floor. 32 | 33 | ## Support rotation/flip of walls and floors 34 | Allow faces to be rotated or flipped based on tmx flags? 35 | 36 | ## Add Height zones 37 | Add zones to maps that let you define the ceiling and floor height 38 | 39 | ## Add height to movement 40 | Basic gravity and fall to the floor 41 | 42 | 43 | # In Progress 44 | -------------------------------------------------------------- 45 | 46 | 47 | 48 | # Commplete 49 | -------------------------------------------------------------- 50 | ## Add global event listeners 51 | Add callbacks that can be triggered fron events from any object. Have object fire events to global system. 52 | 53 | ## Draw top and bottom of doors 54 | Doors need tops and bottoms now that they can be vertical. 55 | 56 | ## Fix world lighting to use lighting shader 57 | Use the lighting shadder for ambient, but still apply AO and lighting zones. 58 | 59 | ## Add MOB system 60 | Mob components and mob processing system, seperate from map object system 61 | 62 | ## Remove billboards 63 | Just stick with models for now. 64 | 65 | ## Add Model Animations 66 | Load Animations for character models 67 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Entity.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 22/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "LDtkLoader/containers/FieldsContainer.hpp" 11 | #include "LDtkLoader/defs/EntityDef.hpp" 12 | #include "LDtkLoader/defs/FieldDef.hpp" 13 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 14 | 15 | #include "LDtkLoader/DataTypes.hpp" 16 | #include "LDtkLoader/Enum.hpp" 17 | #include "LDtkLoader/Utils.hpp" 18 | 19 | namespace ldtk { 20 | 21 | class World; 22 | 23 | class Layer; 24 | 25 | class Entity : public FieldsContainer 26 | { 27 | public: 28 | ~Entity() = default; 29 | Entity(const Entity&) = delete; 30 | Entity(Entity&&) noexcept = default; 31 | auto operator=(const Entity&) -> Entity& = delete; 32 | auto operator=(Entity&&) -> Entity& = default; 33 | 34 | const Layer* const layer; 35 | const IID iid; 36 | 37 | auto getName() const -> const std::string&; 38 | auto getSize() const -> const IntPoint&; 39 | auto getColor() const -> const Color&; 40 | 41 | auto getPosition() const -> const IntPoint&; 42 | auto getGridPosition() const -> const IntPoint&; 43 | auto getWorldPosition() const -> IntPoint; 44 | 45 | auto getPivot() const -> const FloatPoint&; 46 | 47 | auto hasSprite() const -> bool; 48 | auto getTexturePath() const -> const std::string&; 49 | auto getTextureRect() const -> const IntRect&; 50 | 51 | auto hasNineSlice() const -> bool; 52 | auto getNineSliceBorders() const -> const NineSliceBorders&; 53 | 54 | auto hasTag(const std::string& tag) const -> bool; 55 | auto allTags() const -> const std::vector&; 56 | 57 | auto allFields() const -> const std::vector&; 58 | 59 | explicit Entity(const nlohmann::json& j, const World* w, const Layer* l); 60 | 61 | private: 62 | const EntityDef* const m_definition; 63 | 64 | const IntPoint m_size; 65 | const IntPoint m_position; 66 | const IntPoint m_grid_pos; 67 | const Color m_color; 68 | 69 | const Tileset* const m_tileset; 70 | const IntRect m_texture_rect; 71 | }; 72 | 73 | } // namespace ldtk 74 | -------------------------------------------------------------------------------- /game/src/services/table_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "services/table_manager.h" 2 | #include "services/resource_manager.h" 3 | #include 4 | 5 | #include "utilities/string_utils.h" 6 | 7 | bool Table::HasField(const std::string& key) const 8 | { 9 | return find(key) != end(); 10 | } 11 | 12 | constexpr char EmptyField[] = ""; 13 | 14 | std::string_view Table::GetField(const std::string& key) const 15 | { 16 | auto itr = find(key); 17 | if (itr == end()) 18 | return EmptyField; 19 | 20 | return itr->second; 21 | } 22 | 23 | const Table* Table::GetFieldAsTable(const std::string& key) const 24 | { 25 | return TableManager::GetTable(GetField(key)); 26 | } 27 | 28 | std::vector Table::SplitField(const std::string& key, std::string_view deliminator) const 29 | { 30 | auto itr = find(key); 31 | if (itr == end()) 32 | return std::vector(); 33 | 34 | return StringUtils::SplitString(itr->second, deliminator); 35 | } 36 | 37 | namespace TableManager 38 | { 39 | static std::hash StringHasher; 40 | std::unordered_map LoadedTables; 41 | 42 | void Init() 43 | { 44 | 45 | } 46 | 47 | void Cleanup() 48 | { 49 | UnloadAll(); 50 | } 51 | 52 | 53 | const Table* GetTable(std::string_view name) 54 | { 55 | size_t hash = StringHasher(name); 56 | 57 | auto itr = LoadedTables.find(hash); 58 | if (itr != LoadedTables.end()) 59 | return &itr->second; 60 | 61 | auto resource = ResourceManager::OpenResource(name, true); 62 | 63 | if (resource == nullptr) 64 | return nullptr; 65 | 66 | auto lines = StringUtils::SplitString(std::string_view((char*)resource->DataBuffer, resource->DataSize), "\n"); 67 | 68 | Table& table = LoadedTables.try_emplace(hash).first->second; 69 | 70 | for (auto& line : lines) 71 | { 72 | auto parts = StringUtils::SplitString(line, ";"); 73 | if (!parts.empty()) 74 | { 75 | table.insert_or_assign(parts[0], parts.size() > 1 ? parts[1] : std::string()); 76 | } 77 | } 78 | 79 | ResourceManager::ReleaseResource(resource); 80 | 81 | return &table; 82 | } 83 | 84 | void UnloadAll() 85 | { 86 | LoadedTables.clear(); 87 | } 88 | }; -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/World.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 11/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include "LDtkLoader/defs/EntityDef.hpp" 8 | #include "LDtkLoader/defs/LayerDef.hpp" 9 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 10 | 11 | #include "LDtkLoader/DataTypes.hpp" 12 | #include "LDtkLoader/Enum.hpp" 13 | #include "LDtkLoader/Level.hpp" 14 | #include "LDtkLoader/Tileset.hpp" 15 | 16 | namespace ldtk { 17 | 18 | class Project; 19 | 20 | class World 21 | { 22 | public: 23 | ~World() = default; 24 | World(const World&) = delete; 25 | World(World&&) noexcept = default; 26 | auto operator=(const World&) -> World& = delete; 27 | auto operator=(World&&) -> World& = default; 28 | 29 | const IID iid; 30 | 31 | auto getName() const -> const std::string&; 32 | 33 | auto getDefaultPivot() const -> const FloatPoint&; 34 | 35 | auto getDefaultCellSize() const -> int; 36 | 37 | auto getBgColor() const -> const Color&; 38 | 39 | auto getLayout() const -> const WorldLayout&; 40 | 41 | auto getLayerDef(int id) const -> const LayerDef&; 42 | auto getLayerDef(const std::string& name) const -> const LayerDef&; 43 | 44 | auto getEntityDef(int id) const -> const EntityDef&; 45 | auto getEntityDef(const std::string& name) const -> const EntityDef&; 46 | 47 | auto allTilesets() const -> const std::vector&; 48 | auto getTileset(int id) const -> const Tileset&; 49 | auto getTileset(const std::string& name) const -> const Tileset&; 50 | 51 | auto getEnum(int id) const -> const Enum&; 52 | auto getEnum(const std::string& name) const -> const Enum&; 53 | 54 | auto allLevels() const -> const std::vector&; 55 | auto getLevel(int id) const -> const Level&; 56 | auto getLevel(const std::string& name) const -> const Level&; 57 | auto getLevel(const IID& iid) const -> const Level&; 58 | 59 | World(const nlohmann::json& j, Project* p, const FileLoader& file_loader, bool external_levels); 60 | 61 | private: 62 | const Project* const m_project; 63 | std::string m_name; 64 | 65 | WorldLayout m_layout = WorldLayout::Free; 66 | std::vector m_levels; 67 | }; 68 | 69 | } // namespace ldtk 70 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Level.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 12/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "LDtkLoader/containers/FieldsContainer.hpp" 11 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 12 | #include "LDtkLoader/thirdparty/optional.hpp" 13 | 14 | #include "LDtkLoader/DataTypes.hpp" 15 | #include "LDtkLoader/Layer.hpp" 16 | 17 | namespace ldtk { 18 | 19 | class World; 20 | 21 | class Level : public FieldsContainer 22 | { 23 | friend World; 24 | 25 | public: 26 | struct BgImage 27 | { 28 | FilePath path; 29 | IntPoint pos; 30 | FloatPoint scale; 31 | IntRect crop; 32 | }; 33 | 34 | ~Level() = default; 35 | Level(const Level&) = delete; 36 | Level(Level&&) noexcept = default; 37 | auto operator=(const Level&) -> Level& = delete; 38 | auto operator=(Level&&) -> Level& = delete; 39 | 40 | const World* const world; 41 | 42 | const std::string name; 43 | const IID iid; 44 | const int uid; 45 | const IntPoint size; 46 | const IntPoint position; 47 | const Color bg_color; 48 | const int depth; 49 | 50 | auto allLayers() const -> const std::vector&; 51 | auto getLayer(const std::string& layer_name) const -> const Layer&; 52 | auto getLayer(const IID& iid) const -> const Layer&; 53 | 54 | auto hasBgImage() const -> bool; 55 | auto getBgImage() const -> const BgImage&; 56 | 57 | auto allNeighbours() const -> const std::vector>&; 58 | auto getNeighbours(const Dir& direction) const -> const std::vector>&; 59 | auto getNeighbourDirection(const Level& level) const -> Dir; 60 | 61 | explicit Level(const nlohmann::json& j, World* w); 62 | 63 | private: 64 | std::vector m_layers; 65 | std::experimental::optional m_bg_image; 66 | 67 | std::unordered_set m_neighbours_iid; 68 | std::map> m_neighbours_iid_by_dir; 69 | 70 | std::vector> m_neighbours; 71 | std::map>> m_neighbours_by_dir; 72 | }; 73 | 74 | } // namespace ldtk 75 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Debug", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/bin/Debug/${workspaceFolderBasename}.exe", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${workspaceFolder}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": false 23 | } 24 | ], 25 | "windows": { 26 | "miDebuggerPath": "gdb.exe" 27 | }, 28 | "osx": { 29 | "MIMode": "lldb" 30 | }, 31 | "linux": { 32 | "program": "${workspaceFolder}/bin/Debug/${workspaceFolderBasename}", 33 | "miDebuggerPath": "/usr/bin/gdb" 34 | }, 35 | "preLaunchTask": "build debug" 36 | }, 37 | { 38 | "name": "Run", 39 | "type": "cppdbg", 40 | "request": "launch", 41 | "args": [], 42 | "stopAtEntry": false, 43 | "cwd": "${workspaceFolder}", 44 | "environment": [], 45 | "externalConsole": false, 46 | "program": "${workspaceFolder}/bin/Release/${workspaceFolderBasename}.exe", 47 | "MIMode": "gdb", 48 | "windows": { 49 | "program": "${workspaceFolder}/bin/Release/${workspaceFolderBasename}.exe", 50 | "miDebuggerPath": "gdb.exe" 51 | }, 52 | "osx": { 53 | "program": "${workspaceFolder}/bin/Release/${workspaceFolderBasename}", 54 | "MIMode": "lldb" 55 | }, 56 | "linux": { 57 | "program": "${workspaceFolder}/bin/Release/${workspaceFolderBasename}", 58 | "miDebuggerPath": "/usr/bin/gdb" 59 | }, 60 | "preLaunchTask": "build release" 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /game/include/services/model_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "model.h" 4 | #include "raylib.h" 5 | #include "raymath.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class ModelInstance; 13 | 14 | 15 | class ModelRecord 16 | { 17 | public: 18 | virtual ~ModelRecord() = default; 19 | 20 | Models::AnimateableModel ModelGeometry; 21 | 22 | BoundingBox GetBounds(); 23 | 24 | Matrix OrientationTransform = MatrixIdentity(); 25 | 26 | protected: 27 | size_t ReferenceCount = 0; 28 | BoundingBox Bounds = { 0 }; 29 | bool BoundsValid = false; 30 | protected: 31 | friend ModelInstance; 32 | std::shared_ptr GetModelInstance(); 33 | 34 | void ReleaseInstance(); 35 | 36 | void CheckBounds(); 37 | }; 38 | 39 | class AnimatedModelRecord : public ModelRecord 40 | { 41 | public: 42 | Models::AnimationSet Animations; 43 | }; 44 | 45 | class ModelInstance 46 | { 47 | public: 48 | virtual ~ModelInstance(); 49 | public: 50 | ModelRecord* Geometry; 51 | virtual void Draw(class TransformComponent& transform); 52 | ModelInstance(ModelRecord* geomeetry); 53 | 54 | void SetShader(Shader shader); 55 | 56 | protected: 57 | std::vector MaterialOverrides; 58 | }; 59 | 60 | class AnimatedModelInstance : public ModelInstance 61 | { 62 | public: 63 | AnimatedModelRecord* AnimatedModel = nullptr; 64 | 65 | AnimatedModelInstance(AnimatedModelRecord* model); 66 | 67 | void Advance(float dt); 68 | void Draw(class TransformComponent& transform) override; 69 | 70 | void SetSequence(const std::string& name, int startFrame = 0); 71 | 72 | void SetAnimationFPS(int fps) { AnimationFPS = fps; } 73 | 74 | void SetAnimationFPSMultiplyer(float value) { AnimationFPSMultiply = value; } 75 | 76 | protected: 77 | int AnimationFPS = 90; 78 | 79 | int CurrentFrame = 0; 80 | float CurrentParam = 0; 81 | 82 | Models::AnimatableSequence* CurrentAnimaton = nullptr; 83 | 84 | Models::AnimateablePose CurrentPose; 85 | 86 | float AnimationAccumulator = 0; 87 | float AnimationFPSMultiply = 1; 88 | }; 89 | 90 | namespace ModelManager 91 | { 92 | void Init(); 93 | void Cleanup(); 94 | 95 | std::shared_ptr GetModel(std::string_view name); 96 | std::shared_ptr GetAnimatedModel(std::string_view name); 97 | void UnloadAll(); 98 | }; -------------------------------------------------------------------------------- /game/src/game_object.cpp: -------------------------------------------------------------------------------- 1 | #include "game_object.h" 2 | #include "scene.h" 3 | #include "system.h" 4 | 5 | #include "game.h" 6 | 7 | static std::hash StringHasher; 8 | 9 | GameObject::~GameObject() 10 | { 11 | Token->Invalidate(); 12 | 13 | for (auto guid : LinkedSystems) 14 | { 15 | auto* system = App::GetSystem(guid); 16 | if (system) 17 | system->RemoveObject(this); 18 | } 19 | } 20 | 21 | GameObject* GameObject::AddChild() 22 | { 23 | GameObject* object = Children.emplace_back(std::make_unique()).get(); 24 | object->ParentPtr = this; 25 | return object; 26 | } 27 | 28 | GameObject::GameObject() 29 | { 30 | Token = ObjectLifetimeToken::Create(this); 31 | } 32 | 33 | GameObject* GameObject::GetParent() const 34 | { 35 | return ParentPtr; 36 | } 37 | 38 | void GameObject::AddToSystem(size_t systemGUID) 39 | { 40 | auto* system = App::GetSystem(systemGUID); 41 | if (!system) 42 | return; 43 | 44 | LinkedSystems.insert(systemGUID); 45 | 46 | system->AddObject(this); 47 | } 48 | 49 | void GameObject::AddEventHandler(size_t hash, GameObjectEventHandler handler, ObjectLifetimeToken::Ptr token) 50 | { 51 | auto itr = EventHandlers.find(hash); 52 | if (itr == EventHandlers.end()) 53 | { 54 | itr = EventHandlers.insert_or_assign(hash, std::vector()).first; 55 | } 56 | 57 | itr->second.emplace_back(GameObjectEventRecord{ handler, token }); 58 | } 59 | 60 | void GameObject::AddEventHandler(std::string_view name, GameObjectEventHandler handler, ObjectLifetimeToken::Ptr token) 61 | { 62 | AddEventHandler(StringHasher(name), handler, token); 63 | } 64 | 65 | void GameObject::CallEvent(size_t hash, GameObject* target) 66 | { 67 | App::CallEvent(hash, this, target); 68 | 69 | auto itr = EventHandlers.find(hash); 70 | if (itr == EventHandlers.end()) 71 | return; 72 | 73 | for (std::vector::iterator eventItr = itr->second.begin(); eventItr != itr->second.end();) 74 | { 75 | if (eventItr->LifetimeToken->IsValid()) 76 | { 77 | eventItr->Handler(hash, this, target); 78 | ++eventItr; 79 | } 80 | else 81 | { 82 | eventItr = itr->second.erase(eventItr); 83 | } 84 | } 85 | } 86 | 87 | void GameObject::CallEvent(std::string_view name, GameObject* target) 88 | { 89 | CallEvent(StringHasher(name), target); 90 | } 91 | -------------------------------------------------------------------------------- /game/src/systems/menu_render_system.cpp: -------------------------------------------------------------------------------- 1 | #include "systems/menu_render_system.h" 2 | #include "services/global_vars.h" 3 | 4 | #include "scene.h" 5 | #include "raylib.h" 6 | #include "rlgl.h" 7 | 8 | void MenuRenderSystem::OnUpdate() 9 | { 10 | switch (App::GetState()) 11 | { 12 | default: 13 | case GameState::Empty: 14 | ClearBackground(DARKBLUE); 15 | DrawText("Empty", 600, 400, 40, WHITE); 16 | break; 17 | 18 | case GameState::Loading: 19 | { 20 | ClearBackground(BLACK); 21 | LoadingSpinnerAngle += 180 * GetFrameTime(); 22 | 23 | float loadingSize = 40; 24 | Font font = GetFontDefault(); 25 | 26 | Vector2 size = MeasureTextEx(font, "Loading", loadingSize, loadingSize / 10); 27 | 28 | Vector2 pos = { GetScreenWidth() * 0.5f - size.x * 0.5f, GetScreenHeight() * 0.5f - size.y * 0.5f }; 29 | DrawTextEx(font, "Loading", pos, loadingSize, loadingSize/10, WHITE); 30 | 31 | DrawTextEx(font, "Please Wait", pos + (Vector2UnitY * loadingSize), loadingSize/2, loadingSize / 20, WHITE); 32 | 33 | float throberSize = 60; 34 | 35 | rlPushMatrix(); 36 | 37 | rlTranslatef(pos.x - throberSize, pos.y + loadingSize * 0.5f, 0); 38 | 39 | 40 | rlPushMatrix(); 41 | rlRotatef(LoadingSpinnerAngle, 0, 0, 1); 42 | DrawRectangleRec(Rectangle{ -throberSize * 0.5f, -throberSize * 0.5f, throberSize, throberSize }, WHITE); 43 | rlPopMatrix(); 44 | 45 | rlPushMatrix(); 46 | rlRotatef(-LoadingSpinnerAngle - 45, 0, 0, 1); 47 | DrawRectangleRec(Rectangle{ -throberSize * 0.25f, -throberSize * 0.25f, throberSize * 0.5f, throberSize * 0.5f }, DARKGRAY); 48 | rlPopMatrix(); 49 | 50 | rlPopMatrix(); 51 | } 52 | break; 53 | 54 | case GameState::Playing: 55 | 56 | if (InMenu) 57 | { 58 | DrawText("Paused, Y to exit, escape to resume", 300, 400, 40, WHITE); 59 | if (IsKeyPressed(KEY_Y)) 60 | { 61 | App::Quit(); 62 | } 63 | } 64 | 65 | if (IsKeyPressed(KEY_ESCAPE)) 66 | { 67 | InMenu = !InMenu; 68 | GlobalVars::Paused = InMenu; 69 | } 70 | 71 | break; 72 | 73 | case GameState::Closing: 74 | DrawText("Closing", 600, 400, 40, WHITE); 75 | break; 76 | } 77 | 78 | bool wantCuror = InMenu || GlobalVars::UseMouseDrag; 79 | 80 | if (wantCuror && IsCursorHidden()) 81 | EnableCursor(); 82 | 83 | if (!wantCuror && !IsCursorHidden()) 84 | DisableCursor(); 85 | } 86 | -------------------------------------------------------------------------------- /model_tool/src/model_info.cpp: -------------------------------------------------------------------------------- 1 | #include "model_info.h" 2 | 3 | #include "extras/IconsFontAwesome6.h" 4 | 5 | #include "imgui.h" 6 | 7 | namespace App 8 | { 9 | extern bool ShowBones; 10 | } 11 | 12 | ModelInfoPanel::ModelInfoPanel() 13 | { 14 | Name = "Model Info"; 15 | Icon = ICON_FA_CUBE; 16 | 17 | MinSize = { 250, 300 }; 18 | 19 | DockingType = PanelDockingType::RightDock; 20 | } 21 | 22 | void ModelInfoPanel::OnShowContents() 23 | { 24 | auto& model = App::GetModel(); 25 | if (model.Groups.empty()) 26 | { 27 | ImGui::TextUnformatted("No Model Loaded"); 28 | return; 29 | } 30 | 31 | if (ImGui::BeginChild("Meshes", ImVec2(0, 200))) 32 | { 33 | ImGui::Text("Meshes"); 34 | if (ImGui::BeginChild("MeshList", ImVec2(0, 175), ImGuiChildFlags_Borders)) 35 | { 36 | int i = 0; 37 | for (auto& group : model.Groups) 38 | { 39 | for (auto& mesh : group.Meshes) 40 | { 41 | bool selected = App::GetSelectedMesh() == i; 42 | if (ImGui::Selectable(TextFormat("Mesh %2d", i), &selected, ImGuiSelectableFlags_None)) 43 | { 44 | if (selected) 45 | App::SetSeletedMesh(i); 46 | } 47 | 48 | i++; 49 | } 50 | } 51 | ImGui::EndChild(); 52 | } 53 | 54 | ImGui::EndChild(); 55 | } 56 | 57 | auto& anims = App::GetAnimations(); 58 | 59 | if (!anims.Animations.Sequences.empty() && ImGui::BeginChild("Animations", ImVec2(0, 250))) 60 | { 61 | ImGui::Text("Animations %d", int(anims.Animations.Sequences.size())); 62 | 63 | if (ImGui::BeginChild("AnimList", ImVec2(0, 200), ImGuiChildFlags_Borders)) 64 | { 65 | int count = 0; 66 | for (auto & [name, sequence] : anims.Animations.Sequences) 67 | { 68 | bool selected = name == anims.Sequence; 69 | if (ImGui::Selectable(TextFormat("%s", name.c_str()), &selected, ImGuiSelectableFlags_None)) 70 | { 71 | if (name != anims.Sequence) 72 | { 73 | anims.Sequence = name; 74 | anims.Frame = 0; 75 | } 76 | } 77 | count++; 78 | } 79 | ImGui::EndChild(); 80 | } 81 | 82 | if (!anims.Sequence.empty()) 83 | { 84 | ImGui::SliderInt("Frame", &anims.Frame, 0, int(anims.Animations.Sequences[anims.Sequence].Frames.size()) - 1); 85 | } 86 | ImGui::EndChild(); 87 | } 88 | } -------------------------------------------------------------------------------- /game/src/components/trigger_component.cpp: -------------------------------------------------------------------------------- 1 | #include "components/trigger_component.h" 2 | 3 | #include 4 | 5 | TriggerComponent::TriggerComponent(GameObject* owner) 6 | : Component(owner), Visualizer(this) 7 | { 8 | } 9 | 10 | TriggerComponent::TriggerComponent(GameObject* owner, const Rectangle& bounds) 11 | : Component(owner), Bounds(bounds), Visualizer(this) 12 | { 13 | Visualizer.SetDrawFunctions([this](const Camera&) {DrawDebug(); }); 14 | } 15 | 16 | static constexpr float DebugFloorHeight = 0.01f; 17 | 18 | void TriggerComponent::DrawDebug() 19 | { 20 | DrawLine3D(Vector3{ Bounds.x, Bounds.y, DebugFloorHeight }, 21 | Vector3{ Bounds.x + Bounds.width, Bounds.y, DebugFloorHeight }, 22 | RED); 23 | 24 | DrawLine3D(Vector3{ Bounds.x + Bounds.width, Bounds.y, DebugFloorHeight }, 25 | Vector3{ Bounds.x + Bounds.width, Bounds.y + Bounds.height, DebugFloorHeight }, 26 | RED); 27 | 28 | DrawLine3D(Vector3{ Bounds.x + Bounds.width, Bounds.y + Bounds.height, DebugFloorHeight }, 29 | Vector3{ Bounds.x, Bounds.y + Bounds.height, DebugFloorHeight }, 30 | RED); 31 | 32 | DrawLine3D(Vector3{ Bounds.x, Bounds.y + Bounds.height, DebugFloorHeight }, 33 | Vector3{ Bounds.x, Bounds.y, DebugFloorHeight }, 34 | RED); 35 | } 36 | 37 | void TriggerComponent::AddObject(ObjectLifetimeToken::Ptr token) 38 | { 39 | if (token->IsValid()) 40 | ConainedObjects.push_back(token); 41 | } 42 | 43 | void TriggerComponent::RemovObject(ObjectLifetimeToken::Ptr token) 44 | { 45 | if (!token->IsValid()) 46 | return; 47 | 48 | auto itr = std::find(ConainedObjects.begin(), ConainedObjects.end(), token); 49 | if (itr != ConainedObjects.end()) 50 | ConainedObjects.erase(itr); 51 | } 52 | 53 | bool TriggerComponent::HasObject(GameObject* object) 54 | { 55 | for (auto itr = ConainedObjects.begin(); itr != ConainedObjects.end();) 56 | { 57 | ObjectLifetimeToken* tokenPtr = itr->get(); 58 | 59 | if (!tokenPtr->IsValid()) 60 | { 61 | ConainedObjects.erase(itr); 62 | } 63 | else 64 | { 65 | if (tokenPtr->GetOwner() == object) 66 | return true; 67 | 68 | itr++; 69 | } 70 | } 71 | return false; 72 | } 73 | 74 | bool TriggerComponent::HasAnyObjects() 75 | { 76 | for (auto itr = ConainedObjects.begin(); itr != ConainedObjects.end();) 77 | { 78 | ObjectLifetimeToken* tokenPtr = itr->get(); 79 | 80 | if (!tokenPtr->IsValid()) 81 | { 82 | ConainedObjects.erase(itr); 83 | } 84 | else 85 | { 86 | return true; 87 | } 88 | } 89 | return false; 90 | } 91 | -------------------------------------------------------------------------------- /game/include/component.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class GameObject; 7 | 8 | class Component 9 | { 10 | public: 11 | Component(GameObject* owner) : Owner(owner) {} 12 | virtual ~Component() = default; 13 | 14 | virtual size_t GetTypeID() const = 0; 15 | 16 | virtual std::string_view GetName() const = 0; 17 | 18 | template 19 | inline bool Is() 20 | { 21 | return GetTypeID() == T::TypeID(); 22 | } 23 | 24 | template 25 | inline T* As() 26 | { 27 | if (GetTypeID() != T::TypeID()) 28 | return nullptr; 29 | 30 | return reinterpret_cast(this); 31 | } 32 | 33 | void AddToSystem(size_t systemGUID); 34 | 35 | template 36 | inline void AddToSystem() 37 | { 38 | AddToSystem(T::GUID()); 39 | } 40 | 41 | virtual void OnAddedToObject() {} 42 | 43 | inline GameObject* GetOwner() { return Owner; } 44 | inline const GameObject* GetOwner() const { return Owner; } 45 | 46 | protected: 47 | GameObject* Owner = nullptr; 48 | 49 | protected: 50 | virtual void OnCreate() {}; 51 | }; 52 | 53 | #define DEFINE_COMPONENT(T) \ 54 | T(GameObject* owner) : Component(owner){OnCreate();} \ 55 | static size_t TypeID() { static std::hash hasher; return hasher(#T);} \ 56 | size_t GetTypeID() const override {return T::TypeID();} \ 57 | std::string_view GetName() const override {return #T;} \ 58 | static std::unique_ptr Create(GameObject* owner){ return std::make_unique(owner);} 59 | 60 | #define DEFINE_COMPONENT_WITH_SYSTEM(T, S) \ 61 | T(GameObject* owner) : Component(owner){} \ 62 | static size_t TypeID() { static std::hash hasher; return hasher(#T);} \ 63 | size_t GetTypeID() const override {return T::TypeID();} \ 64 | std::string_view GetName() const override {return #T;} \ 65 | static std::unique_ptr Create(GameObject* owner) { return std::make_unique(owner); } \ 66 | void OnAddedToObject() override { AddToSystem(); } 67 | 68 | #define DEFINE_COMPONENT_NO_CONSTRUCTOR(T) \ 69 | static size_t TypeID() { static std::hash hasher; return hasher(#T);} \ 70 | size_t GetTypeID() const override {return T::TypeID();} \ 71 | std::string_view GetName() const override {return #T;} \ 72 | static std::unique_ptr Create(GameObject* owner){ return std::make_unique(owner);} 73 | 74 | #define DEFINE_COMPONENT_WITH_SYSTEM_NO_CONSTRUCTOR(T, S) \ 75 | static size_t TypeID() { static std::hash hasher; return hasher(#T);} \ 76 | size_t GetTypeID() const override {return T::TypeID();} \ 77 | std::string_view GetName() const override {return #T;} \ 78 | static std::unique_ptr Create(GameObject* owner) { return std::make_unique(owner); } \ 79 | void OnAddedToObject() override { AddToSystem(); } 80 | -------------------------------------------------------------------------------- /rlImGui/include/imgui_impl_raylib.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * rlImGui * basic ImGui integration 6 | * 7 | * LICENSE: ZLIB 8 | * 9 | * Copyright (c) 2024 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | // dear imgui: Platform Backend for Raylib 32 | // (Info: Raylib is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc. using OpenGL) 33 | // This is is the low level ImGui backend for raylib, a higher level API that matches the raylib API can be found in rlImGui.h 34 | 35 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 36 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 37 | // Learn about Dear ImGui: 38 | // - FAQ https://dearimgui.com/faq 39 | // - Getting Started https://dearimgui.com/getting-started 40 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 41 | // - Introduction, links and more at the top of imgui.cpp 42 | 43 | #pragma once 44 | #include "imgui.h" // IMGUI_IMPL_API 45 | #ifndef IMGUI_DISABLE 46 | 47 | IMGUI_IMPL_API bool ImGui_ImplRaylib_Init(void); 48 | IMGUI_IMPL_API void ImGui_ImplRaylib_BuildFontAtlas(void); 49 | IMGUI_IMPL_API void ImGui_ImplRaylib_Shutdown(void); 50 | IMGUI_IMPL_API void ImGui_ImplRaylib_NewFrame(void); 51 | IMGUI_IMPL_API void ImGui_ImplRaylib_RenderDrawData(ImDrawData* draw_data); 52 | IMGUI_IMPL_API bool ImGui_ImplRaylib_ProcessEvents(void); 53 | 54 | #endif // #ifndef IMGUI_DISABLE 55 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/defs/FieldDef.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 20/03/2022. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 10 | 11 | #include "LDtkLoader/DataTypes.hpp" 12 | #include "LDtkLoader/Enum.hpp" 13 | 14 | namespace ldtk { 15 | 16 | class FieldDef 17 | { 18 | friend class EntityDef; 19 | 20 | public: 21 | FieldType type; 22 | std::string name; 23 | }; 24 | 25 | template 26 | struct Field; 27 | 28 | template 29 | struct ArrayField; 30 | 31 | namespace detail { 32 | 33 | // clang-format off 34 | template struct field_type_from_enum_; 35 | template<> struct field_type_from_enum_ { using type = Field; }; 36 | template<> struct field_type_from_enum_ { using type = Field; }; 37 | template<> struct field_type_from_enum_ { using type = Field; }; 38 | template<> struct field_type_from_enum_ { using type = Field; }; 39 | template<> struct field_type_from_enum_ { using type = Field; }; 40 | template<> struct field_type_from_enum_ { using type = Field; }; 41 | template<> struct field_type_from_enum_ { using type = Field; }; 42 | template<> struct field_type_from_enum_ { using type = Field; }; 43 | template<> struct field_type_from_enum_ { using type = Field; }; 44 | 45 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 46 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 47 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 48 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 49 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 50 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 51 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 52 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 53 | template<> struct field_type_from_enum_ { using type = ArrayField; }; 54 | // clang-format on 55 | 56 | } // namespace detail 57 | 58 | template 59 | using getFieldType = typename detail::field_type_from_enum_::type; 60 | 61 | } // namespace ldtk 62 | -------------------------------------------------------------------------------- /game/include/map/map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "raylib.h" 8 | 9 | struct MapCoordinate 10 | { 11 | uint16_t X = 0; 12 | uint16_t Y = 0; 13 | 14 | inline uint32_t GetHash() const { return ((X << 16) | ((Y) & 0xffff)); } 15 | static uint32_t GetHash(uint16_t x, uint16_t y) { return ((x << 16) | ((y) & 0xffff)); } 16 | }; 17 | 18 | enum class MapCellState : uint8_t 19 | { 20 | Empty = 0, 21 | Wall = 1, 22 | Door = 2, 23 | Invalid = 0xFF 24 | }; 25 | 26 | namespace MapCellFlags 27 | { 28 | static constexpr uint8_t None = (1u << 0); 29 | static constexpr uint8_t HorizontalVertical = (1u << 1); 30 | static constexpr uint8_t XAllignment = (1u << 2); 31 | static constexpr uint8_t Impassible = (1u << 3); 32 | static constexpr uint8_t Split = (1u << 4); 33 | static constexpr uint8_t Reversed = (1u << 5); 34 | } 35 | 36 | static constexpr uint8_t MapCellInvalidTile = 0xff; 37 | static constexpr uint8_t MapCellInvalidLightZone = 0xff; 38 | 39 | struct MapCell //pad to 64 bits 40 | { 41 | MapCellState State = MapCellState::Empty; 42 | uint8_t Flags = 0; 43 | uint8_t LightZone = MapCellInvalidLightZone; 44 | uint8_t ParamState = 0; 45 | 46 | uint8_t Tiles[4] = { MapCellInvalidTile, MapCellInvalidTile, MapCellInvalidTile, MapCellInvalidTile }; 47 | }; 48 | 49 | struct LightingInfo 50 | { 51 | std::string SkyboxTextureName; 52 | 53 | float ExteriorAmbientLevel = 1; 54 | float InteriorAmbientLevel = 0.75f; 55 | float AmbientAngle = 45; 56 | }; 57 | 58 | struct LightZoneInfo 59 | { 60 | float MaxLevel = 1; 61 | float MinLevel = 0.25f; 62 | float SequenceLenght = 1; 63 | std::vector SequenceValues; 64 | 65 | size_t CurrentSequenceIndex = 0; 66 | float CurrentSequenceParam = 0; 67 | float SequenceFrameTime = 0.1f; 68 | 69 | float CurrenSequenceValue = 1; 70 | void Advance(); 71 | 72 | void Reset(); 73 | }; 74 | 75 | struct Map 76 | { 77 | std::vector Cells; 78 | MapCoordinate Size; 79 | Texture Tilemap = { 0 }; 80 | std::vector TileSourceRects; 81 | 82 | LightingInfo LightInfo; 83 | 84 | std::vector LightZones; 85 | 86 | MapCell GetCell(int x, int y) const; 87 | MapCell& GetCellRef(int x, int y); 88 | const MapCell& GetCellRef(int x, int y) const; 89 | bool IsCellSolid(int x, int y) const; 90 | bool IsCellPassable(int x, int y) const; 91 | bool IsCellCapped(int x, int y) const; 92 | void Clear(); 93 | 94 | inline size_t GetCellIndex(int x, int y) const { return y * Size.X + x; } 95 | 96 | bool MoveEntity(Vector3& position, Vector3& desiredMotion, float radius); 97 | 98 | std::vector DoorCells; 99 | 100 | private: 101 | void PointNearesGridPoint(int x, int y, const Vector3 point, Vector3* nearest, Vector3* normal); 102 | }; -------------------------------------------------------------------------------- /game/src/utilities/debug_draw_utility.cpp: -------------------------------------------------------------------------------- 1 | #include "utilities/debug_draw_utility.h" 2 | 3 | #include "component.h" 4 | 5 | #include "services/global_vars.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace DebugDrawUtility 11 | { 12 | #if defined(_DEBUG) 13 | struct DebugDrawItem 14 | { 15 | size_t ComponentType = 0; 16 | DebugDraw* DebugItem; 17 | }; 18 | 19 | static std::vector DebugItems; 20 | 21 | static std::unordered_map DebugItemStates; 22 | #endif 23 | 24 | DebugDraw::DebugDraw(Component* owner) 25 | { 26 | #if defined(_DEBUG) 27 | 28 | DebugItems.emplace_back(DebugDrawItem{ owner->GetTypeID(), this }); 29 | 30 | if (!DebugItemStates.contains(owner->GetTypeID())) 31 | DebugItemStates.insert_or_assign(owner->GetTypeID(), true); 32 | #endif 33 | } 34 | 35 | DebugDraw::~DebugDraw() 36 | { 37 | #if defined(_DEBUG) 38 | 39 | for (auto itr = DebugItems.begin(); itr != DebugItems.end(); itr++) 40 | { 41 | if (itr->DebugItem == this) 42 | { 43 | DebugItems.erase(itr); 44 | break; 45 | } 46 | } 47 | #endif 48 | } 49 | 50 | void DebugDraw::SetDrawFunctions(std::function draw3d, std::function draw2d) 51 | { 52 | #if defined(_DEBUG) 53 | Draw3D = draw3d; 54 | Draw2D = draw2d; 55 | #endif 56 | } 57 | 58 | 59 | void Draw2D() 60 | { 61 | if (!GlobalVars::ShowDebugDraw) 62 | return; 63 | 64 | #if defined(_DEBUG) 65 | for (auto& item : DebugItems) 66 | { 67 | if (IsComponentEnabled(item.ComponentType) && item.DebugItem->Draw2D) 68 | item.DebugItem->Draw2D(); 69 | } 70 | #endif 71 | } 72 | void Draw3D(const Camera3D& camera) 73 | { 74 | if (!GlobalVars::ShowDebugDraw) 75 | return; 76 | 77 | #if defined(_DEBUG) 78 | for (auto& item : DebugItems) 79 | { 80 | if (IsComponentEnabled(item.ComponentType) && item.DebugItem->Draw3D) 81 | item.DebugItem->Draw3D(camera); 82 | } 83 | #endif 84 | } 85 | 86 | void Cleanup() 87 | { 88 | #if defined(_DEBUG) 89 | DebugItems.clear(); 90 | #endif 91 | } 92 | 93 | void DisableComponent(size_t componentHash) 94 | { 95 | #if defined(_DEBUG) 96 | DebugItemStates.insert_or_assign(componentHash, false); 97 | #endif 98 | } 99 | 100 | void EnableComponent(size_t componentHash) 101 | { 102 | #if defined(_DEBUG) 103 | DebugItemStates.insert_or_assign(componentHash, true); 104 | #endif 105 | } 106 | 107 | bool IsComponentEnabled(size_t componentHash) 108 | { 109 | #if defined(_DEBUG) 110 | auto itr = DebugItemStates.find(componentHash); 111 | return itr == DebugItemStates.end() || itr->second; 112 | #endif 113 | return false; 114 | } 115 | 116 | } -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/DataTypes.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 11/11/2020. 2 | 3 | #include "LDtkLoader/DataTypes.hpp" 4 | 5 | #include 6 | 7 | using namespace ldtk; 8 | 9 | Color::Color(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha) 10 | : r(red & 0xffu) 11 | , g(green & 0xffu) 12 | , b(blue & 0xffu) 13 | , a(alpha & 0xffu) 14 | {} 15 | 16 | Color::Color(int hex) : Color((hex >> 16) & 0xff, (hex >> 8) & 0xff, hex & 0xff) 17 | {} 18 | 19 | Color::Color(const std::string& hex) 20 | : Color( 21 | std::stoul(hex.substr(1, 2), nullptr, 16), 22 | std::stoul(hex.substr(3, 2), nullptr, 16), 23 | std::stoul(hex.substr(5, 2), nullptr, 16) 24 | ) 25 | {} 26 | 27 | auto ldtk::operator==(const Color& lhs, const Color& rhs) -> bool 28 | { 29 | return (lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b && lhs.a == rhs.a); 30 | } 31 | 32 | const IntGridValue IntGridValue::None{-1, "", Color()}; 33 | 34 | ldtk::FilePath::FilePath(const std::string& str) 35 | { 36 | this->assign(str); 37 | } 38 | 39 | auto ldtk::FilePath::directory() const -> std::string 40 | { 41 | auto i = find_last_of("/\\"); 42 | if (i == npos) { 43 | return ""; 44 | } 45 | return substr(0, i + 1); 46 | } 47 | 48 | auto ldtk::FilePath::filename() const -> std::string 49 | { 50 | auto i = find_last_of("/\\"); 51 | if (i == npos) { 52 | return *this; 53 | } 54 | return substr(i + 1); 55 | } 56 | 57 | auto ldtk::FilePath::extension() const -> std::string 58 | { 59 | auto f = filename(); 60 | auto i = f.find_last_of('.'); 61 | if (i == npos) { 62 | return ""; 63 | } 64 | return f.substr(i + 1); 65 | } 66 | 67 | IID::IID(std::string iid) : m_iid(std::move(iid)) 68 | {} 69 | 70 | auto IID::str() const -> const std::string& 71 | { 72 | return m_iid; 73 | } 74 | 75 | auto ldtk::operator==(const IID& lhs, const IID& rhs) -> bool 76 | { 77 | return lhs.str() == rhs.str(); 78 | } 79 | 80 | auto ldtk::operator!=(const IID& lhs, const IID& rhs) -> bool 81 | { 82 | return !(lhs == rhs); 83 | } 84 | 85 | EntityRef::EntityRef(IID ent, IID layer, IID level, IID world) 86 | : entity_iid(std::move(ent)) 87 | , layer_iid(std::move(layer)) 88 | , level_iid(std::move(level)) 89 | , world_iid(std::move(world)) 90 | {} 91 | 92 | auto EntityRef::operator->() const -> const Entity* 93 | { 94 | return ref; 95 | } 96 | 97 | TileRef::TileRef(int id, int x, int y, int w, int h) 98 | : tile_set_id(id) 99 | , bounds(x, y, w, h) 100 | {} 101 | 102 | auto operator<<(std::ostream& os, const ldtk::Color& color) -> std::ostream& 103 | { 104 | os << "rgb(" << (int)color.r << ", " << (int)color.g << ", " << (int)color.b << ")"; 105 | return os; 106 | } 107 | 108 | 109 | auto operator<<(std::ostream& os, const ldtk::FilePath& path) -> std::ostream& 110 | { 111 | os << path.c_str(); 112 | return os; 113 | } 114 | 115 | auto operator<<(std::ostream& os, const ldtk::IID& iid) -> std::ostream& 116 | { 117 | os << iid.str(); 118 | return os; 119 | } 120 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/Enum.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 13/11/2020. 2 | 3 | #include "LDtkLoader/Enum.hpp" 4 | 5 | #include "LDtkLoader/Tileset.hpp" 6 | #include "LDtkLoader/Utils.hpp" 7 | 8 | #include "json.hpp" 9 | 10 | using namespace ldtk; 11 | 12 | EnumValue::EnumValue( 13 | std::string val_name, 14 | int val_id, 15 | const IntRect& val_tile_rect, 16 | const Color& val_color, 17 | const Enum& val_enum_type 18 | ) 19 | : name(std::move(val_name)) 20 | , color(val_color) 21 | , type(val_enum_type) 22 | , id(val_id) 23 | , tile_rect(val_tile_rect) 24 | {} 25 | 26 | auto EnumValue::hasIcon() const -> bool 27 | { 28 | return type.hasIcons() && tile_rect != IntRect(-1, -1, -1, -1); 29 | } 30 | 31 | auto EnumValue::getIconTileset() const -> const Tileset& 32 | { 33 | return type.getIconsTileset(); 34 | } 35 | 36 | auto EnumValue::getIconTextureRect() const -> const IntRect& 37 | { 38 | return tile_rect; 39 | } 40 | 41 | auto ldtk::operator==(const EnumValue& l, const EnumValue& r) -> bool 42 | { 43 | return (l.id == r.id) && (l.type.uid == r.type.uid); 44 | } 45 | auto ldtk::operator!=(const EnumValue& l, const EnumValue& r) -> bool 46 | { 47 | return !(ldtk::operator==(l, r)); 48 | } 49 | 50 | Enum::Enum(const nlohmann::json& j) 51 | : TagsContainer(j.contains("tags") ? j["tags"] : nlohmann::json{}) 52 | , name(j["identifier"].get()) 53 | , uid(j["uid"].get()) 54 | , m_tileset_id(j["iconTilesetUid"].is_null() ? -1 : j["iconTilesetUid"].get()) 55 | { 56 | int id = 0; 57 | for (const auto& value : j["values"]) { 58 | const auto& val_name = value["id"].get(); 59 | const auto& j_tile_rect = value["tileRect"]; 60 | const auto tile_rect = j_tile_rect.is_null() ? IntRect{-1, -1, -1, -1} 61 | : IntRect{ 62 | j_tile_rect["x"].get(), 63 | j_tile_rect["y"].get(), 64 | j_tile_rect["w"].get(), 65 | j_tile_rect["h"].get() 66 | }; 67 | const auto color = Color(value["color"].get()); 68 | m_values.insert({val_name, {val_name, id++, tile_rect, color, *this}}); 69 | } 70 | } 71 | 72 | auto Enum::operator[](const std::string& val_name) const -> const EnumValue& 73 | { 74 | if (m_values.count(val_name) > 0) { 75 | return m_values.at(val_name); 76 | } 77 | ldtk_error("Enum \"" + name + "\" does not have value \"" + val_name + "\"."); 78 | } 79 | 80 | auto Enum::hasIcons() const -> bool 81 | { 82 | return m_tileset != nullptr; 83 | } 84 | 85 | auto Enum::getIconsTileset() const -> const Tileset& 86 | { 87 | if (m_tileset != nullptr) { 88 | return *m_tileset; 89 | } 90 | ldtk_error("Enum \"" + name + "\" values don't have icons."); 91 | } 92 | 93 | auto operator<<(std::ostream& os, const ldtk::EnumValue& enum_value) -> std::ostream& 94 | { 95 | os << enum_value.type.name << "." << enum_value.name; 96 | return os; 97 | } 98 | -------------------------------------------------------------------------------- /game/src/services/character_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "services/character_manager.h" 2 | #include "services/table_manager.h" 3 | #include "services/texture_manager.h" 4 | #include "utilities/collision_utils.h" 5 | #include "utilities/string_utils.h" 6 | #include "scene.h" 7 | 8 | static constexpr char CharacterManifest[] = "character_manifest"; 9 | 10 | const Table* CharacterManifestTable = nullptr; 11 | 12 | namespace CharacterManager 13 | { 14 | static std::unordered_map> CharacterCache; 15 | 16 | 17 | std::shared_ptr LoadCharacter(const std::string& key) 18 | { 19 | if (!CharacterManifestTable) 20 | return nullptr; 21 | 22 | auto* characterTable = CharacterManifestTable->GetFieldAsTable(key); 23 | if (!characterTable) 24 | return nullptr; 25 | 26 | auto character = std::make_shared(); 27 | character->Name = key; 28 | 29 | character->ModelName = characterTable->GetField("model"); 30 | 31 | if (characterTable->HasField("rotation_offset")) 32 | character->RotationOffset = float(atof(characterTable->GetField("rotation_offset").data())); 33 | 34 | if (characterTable->HasField("idle")) 35 | character->SequenceNames.insert_or_assign(CharacterAnimationState::Idle, std::string(characterTable->GetField("idle"))); 36 | 37 | if (characterTable->HasField("walk")) 38 | character->SequenceNames.insert_or_assign(CharacterAnimationState::Walking, std::string(characterTable->GetField("walk"))); 39 | 40 | if (characterTable->HasField("run")) 41 | character->SequenceNames.insert_or_assign(CharacterAnimationState::Running, std::string(characterTable->GetField("run"))); 42 | 43 | if (characterTable->HasField("turn")) 44 | character->SequenceNames.insert_or_assign(CharacterAnimationState::Turning, std::string(characterTable->GetField("turn"))); 45 | 46 | if (characterTable->HasField("y_up")) 47 | character->IsYUp = characterTable->GetField("y_up") != "0"; 48 | 49 | if (characterTable->HasField("shadow")) 50 | character->ShadowTexture = characterTable->GetField("shadow"); 51 | 52 | CharacterCache.insert_or_assign(key, character); 53 | 54 | return character; 55 | } 56 | 57 | static bool Preload = true; 58 | 59 | void Init() 60 | { 61 | CharacterManifestTable = TableManager::GetTable(BootstrapTable)->GetFieldAsTable(CharacterManifest); 62 | 63 | if (!CharacterManifestTable) 64 | return; 65 | 66 | if (Preload) 67 | { 68 | for (const auto& [key, file] : *CharacterManifestTable) 69 | { 70 | LoadCharacter(key); 71 | } 72 | } 73 | } 74 | 75 | void Cleanup() 76 | { 77 | 78 | } 79 | 80 | std::shared_ptr GetCharacter(const std::string& name) 81 | { 82 | auto itr = CharacterCache.find(name); 83 | if (itr != CharacterCache.end()) 84 | return itr->second; 85 | 86 | return LoadCharacter(name); 87 | } 88 | 89 | void UnloadAll() 90 | { 91 | } 92 | }; -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/Tileset.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 11/11/2020. 2 | 3 | #include "LDtkLoader/Tileset.hpp" 4 | 5 | #include "LDtkLoader/Project.hpp" 6 | 7 | #include "json.hpp" 8 | 9 | using namespace ldtk; 10 | 11 | Tileset::Tileset(const nlohmann::json& j, Project* p) 12 | : TagsContainer(j.contains("tags") ? j["tags"] : nlohmann::json{}) 13 | , name(j["identifier"].get()) 14 | , uid(j["uid"].get()) 15 | , path(j["relPath"].is_null() ? "" : j["relPath"].get()) 16 | , texture_size({j["pxWid"].get(), j["pxHei"].get()}) 17 | , tile_size(j["tileGridSize"].get()) 18 | , spacing(j["spacing"].get()) 19 | , padding(j["padding"].get()) 20 | , m_enumtags_enum(j["tagsSourceEnumUid"].is_null() ? nullptr : &p->getEnum(j["tagsSourceEnumUid"].get())) 21 | { 22 | // parse tiles custom data 23 | m_custom_data_map.reserve(j["customData"].size() + 1); 24 | m_custom_data_map.emplace(-1, ""); 25 | for (const auto& data : j["customData"]) { 26 | m_custom_data_map.emplace(data["tileId"].get(), data["data"].get()); 27 | } 28 | 29 | // parse tiles enum tags 30 | m_enumtags_by_tile.reserve(j["enumTags"].size() + 1); 31 | m_enumtags_by_tile.insert({-1, {}}); 32 | if (m_enumtags_enum != nullptr) { 33 | for (const auto& tag : j["enumTags"]) { 34 | auto enumval_name = tag["enumValueId"].get(); 35 | const auto& tiles = tag["tileIds"]; 36 | 37 | m_tiles_by_enumtag[enumval_name].reserve(tiles.size()); 38 | for (const auto& tile_id : tiles) { 39 | m_tiles_by_enumtag[enumval_name].push_back(tile_id.get()); 40 | m_enumtags_by_tile[tile_id].emplace_back(getEnumTagsEnum()[enumval_name]); 41 | } 42 | } 43 | } 44 | } 45 | 46 | auto Tileset::getTileTexturePos(int tile_id) const -> IntPoint 47 | { 48 | auto grid_width = texture_size.x / tile_size; 49 | return { 50 | padding + (tile_id % grid_width) * (tile_size + spacing), 51 | padding + (tile_id / grid_width) * (tile_size + spacing) 52 | }; 53 | } 54 | 55 | auto Tileset::getTileCustomData(int tile_id) const -> const std::string& 56 | { 57 | if (m_custom_data_map.find(tile_id) != m_custom_data_map.end()) { 58 | return m_custom_data_map.at(tile_id); 59 | } 60 | return m_custom_data_map.at(-1); 61 | } 62 | 63 | auto Tileset::getTileEnumTags(int tile_id) const -> const std::vector>& 64 | { 65 | if (m_enumtags_by_tile.find(tile_id) != m_enumtags_by_tile.end()) { 66 | return m_enumtags_by_tile.at(tile_id); 67 | } 68 | return m_enumtags_by_tile.at(-1); 69 | } 70 | 71 | auto Tileset::hasEnumTags() const -> bool 72 | { 73 | return m_enumtags_enum != nullptr; 74 | } 75 | 76 | auto Tileset::getEnumTagsEnum() const -> const Enum& 77 | { 78 | return *m_enumtags_enum; 79 | } 80 | 81 | auto Tileset::getTilesByEnumTag(const EnumValue& enumvalue) const -> const std::vector& 82 | { 83 | if (enumvalue.type.uid != m_enumtags_enum->uid) { 84 | ldtk_error("Enum value \"" + enumvalue.name + "\" is not a value of Enum \"" + m_enumtags_enum->name 85 | + "\"."); 86 | } 87 | 88 | return m_tiles_by_enumtag.at(enumvalue.name); 89 | } 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modern Boomer Shooter 2 | Inspired by this video by ModernVintageGamer 3 | https://www.youtube.com/watch?v=SV8uBtUHAkQ 4 | 5 | This is an OpenGL Wolfenstein3d like system using raylib. 6 | 7 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/62fb4c547c4b4208a32282a98cbb89b4)](https://app.codacy.com/gh/JeffM2501/ModernBoomerShooter/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) 8 | 9 | # Features 10 | * Reads levels from LDtk (https://ldtk.io/) 11 | * Data Driven design 12 | * Resource and Texture Management 13 | * Fake lighting and Ambient Occlusion 14 | 15 | # Building 16 | This project uses game-premake for raylib (https://github.com/raylib-extras/game-premake) and is configured using premake. 17 | 18 | ## Building for Windows (Visual Studio) 19 | Run the premake-VisualStudio.bat to generate the .sln, then open it. 20 | 21 | ## Building for Windows (MinGW-W64) 22 | Run the premake-mingw.bat to generate the makefile, then run make in the folder. If you get shell errors then run make SHELL=cmd 23 | 24 | ## Building for Linux 25 | Run run ./premake5 gmake, then run make in the folder 26 | 27 | ## Building for MacOS 28 | Run run ./premake5.osx gmake, then run make in the folder 29 | 30 | ## Building with VSCode 31 | Open the folder in vscode and build 32 | 33 | 34 | # Code Design 35 | 36 | ## App 37 | Holds the main app, very lightweight. 38 | 39 | ## World 40 | Holds the map, game objects, and systems 41 | 42 | ## Map 43 | Cube based level, read from Tiled TMX files 44 | 45 | ## Systems 46 | Things that need to be updated in some specific order. Tracked by a hash ID so they can be found by other things. 47 | * Input/Action System 48 | * Player Management System 49 | * Rendering System 50 | 51 | ## Services 52 | Global thigns that manage stuff, but don't need an update. 53 | * Texture Manager 54 | * Resource Manager 55 | * Table Manager 56 | * Game Time 57 | 58 | ## Game Objects 59 | Entities in the game, have components, can register with systems for simple ECS-like operations 60 | 61 | ## Components 62 | Data attached to components, can register with systems, for simple ECS-like operations 63 | 64 | ## Resources 65 | Any file read by the game at runtime, managed by resource manager 66 | 67 | ## Tables 68 | Simple key/value pairs for storing generic resource data. All data is initally read from the bootstrap table and it's dependencies. 69 | 70 | 71 | # License 72 | Copyright (c) 2020-2024 Jeffery Myers 73 | 74 | This software is provided "as-is", without any express or implied warranty. In no event 75 | will the authors be held liable for any damages arising from the use of this software. 76 | 77 | Permission is granted to anyone to use this software for any purpose, including commercial 78 | applications, and to alter it and redistribute it freely, subject to the following restrictions: 79 | 80 | 1. The origin of this software must not be misrepresented; you must not claim that you 81 | wrote the original software. If you use this software in a product, an acknowledgment 82 | in the product documentation would be appreciated but is not required. 83 | 84 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented 85 | as being the original software. 86 | 87 | 3. This notice may not be removed or altered from any source distribution. 88 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Field.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 23/03/2022. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "LDtkLoader/thirdparty/optional.hpp" 9 | 10 | namespace ldtk { 11 | 12 | template 13 | using optional = std::experimental::optional; 14 | 15 | constexpr auto null = std::experimental::nullopt; 16 | 17 | struct IField 18 | { 19 | IField() = default; 20 | virtual ~IField() = default; 21 | IField(const IField&) = default; 22 | IField(IField&&) noexcept = default; 23 | auto operator=(const IField&) -> IField& = default; 24 | auto operator=(IField&&) -> IField& = default; 25 | }; 26 | 27 | template 28 | struct Field; 29 | 30 | template 31 | struct ArrayField; 32 | 33 | template 34 | #if defined LDTK_FIELD_PUBLIC_OPTIONAL 35 | struct Field : IField, public optional 36 | #else 37 | struct Field : IField, private optional 38 | #endif 39 | { 40 | private: 41 | static const ArrayField m_dummy; 42 | 43 | public: 44 | using value_type = T; 45 | 46 | using optional::optional; 47 | using optional::value; 48 | using optional::value_or; 49 | 50 | constexpr auto is_null() const -> bool { return !optional::has_value(); } 51 | 52 | operator const ArrayField&() const 53 | { 54 | throw std::runtime_error("Cannot convert ldtk::Field to ldtk::ArrayField"); 55 | return m_dummy; 56 | } 57 | }; 58 | 59 | template 60 | const ArrayField Field::m_dummy; 61 | 62 | template 63 | auto operator==(const Field& lhs, const T& rhs) -> bool 64 | { 65 | if (lhs.is_null()) { 66 | return false; 67 | } 68 | return (lhs.value() == rhs); 69 | } 70 | 71 | template 72 | auto operator==(const T& lhs, const Field& rhs) -> bool 73 | { 74 | if (rhs.is_null()) { 75 | return false; 76 | } 77 | return (rhs.value() == lhs); 78 | } 79 | 80 | template 81 | auto operator!=(const Field& lhs, const T& rhs) -> bool 82 | { 83 | return !(lhs == rhs); 84 | } 85 | 86 | template 87 | auto operator!=(const T& lhs, const Field& rhs) -> bool 88 | { 89 | return !(lhs == rhs); 90 | } 91 | 92 | template 93 | struct ArrayField : IField, std::vector> 94 | { 95 | using value_type = T; 96 | 97 | ArrayField() = default; 98 | explicit ArrayField(const std::vector>& vals) : std::vector>(vals) {} 99 | 100 | operator const Field&() const 101 | { 102 | throw std::runtime_error("Cannot convert ldtk::ArrayField to ldtk::Field"); 103 | return this->at(0); 104 | } 105 | }; 106 | 107 | } // namespace ldtk 108 | 109 | template 110 | auto operator<<(std::ostream& os, ldtk::Field field) -> std::ostream& 111 | { 112 | if (field.is_null()) 113 | os << "null"; 114 | else 115 | os << field.value(); 116 | return os; 117 | } 118 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/Entity.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 22/11/2020. 2 | 3 | #include "LDtkLoader/Entity.hpp" 4 | 5 | #include "LDtkLoader/Layer.hpp" 6 | #include "LDtkLoader/World.hpp" 7 | 8 | #include "json.hpp" 9 | 10 | using namespace ldtk; 11 | 12 | Entity::Entity(const nlohmann::json& j, const World* w, const Layer* l) 13 | : FieldsContainer(j["fieldInstances"], w) 14 | , layer(l) 15 | , iid(j.contains("iid") ? j["iid"].get() : "") 16 | , m_definition(&w->getEntityDef(j["defUid"].get())) 17 | , m_size(j["width"].get(), j["height"].get()) 18 | , m_position(j["px"][0].get(), j["px"][1].get()) 19 | , m_grid_pos(j["__grid"][0].get(), j["__grid"][1].get()) 20 | , m_color(j.contains("__smartColor") ? Color(j["__smartColor"].get()) : m_definition->color) 21 | , m_tileset(j["__tile"].is_null() ? nullptr : &w->getTileset(j["__tile"]["tilesetUid"].get())) 22 | , m_texture_rect( 23 | j["__tile"].is_null() ? IntRect{} 24 | : IntRect{j["__tile"]["x"], j["__tile"]["y"], j["__tile"]["w"], j["__tile"]["h"]} 25 | ) 26 | {} 27 | 28 | auto Entity::getName() const -> const std::string& 29 | { 30 | return m_definition->name; 31 | } 32 | 33 | auto Entity::getSize() const -> const IntPoint& 34 | { 35 | return m_size; 36 | } 37 | 38 | auto Entity::getColor() const -> const Color& 39 | { 40 | return m_color; 41 | } 42 | 43 | auto Entity::getPosition() const -> const IntPoint& 44 | { 45 | return m_position; 46 | } 47 | 48 | auto Entity::getGridPosition() const -> const IntPoint& 49 | { 50 | return m_grid_pos; 51 | } 52 | 53 | auto Entity::getWorldPosition() const -> IntPoint 54 | { 55 | const auto& layer_offset = layer->getOffset(); 56 | const auto& level_position = layer->level->position; 57 | return { 58 | m_position.x + layer_offset.x + level_position.x, 59 | m_position.y + layer_offset.y + level_position.y 60 | }; 61 | } 62 | 63 | auto Entity::getPivot() const -> const FloatPoint& 64 | { 65 | return m_definition->pivot; 66 | } 67 | 68 | auto Entity::hasSprite() const -> bool 69 | { 70 | return m_tileset != nullptr; 71 | } 72 | 73 | auto Entity::getTexturePath() const -> const std::string& 74 | { 75 | static const std::string empty; 76 | if (m_tileset == nullptr) { 77 | return empty; 78 | } 79 | 80 | return m_tileset->path; 81 | } 82 | 83 | auto Entity::getTextureRect() const -> const IntRect& 84 | { 85 | return m_texture_rect; 86 | } 87 | 88 | auto Entity::hasNineSlice() const -> bool 89 | { 90 | // clang-format off 91 | return m_definition->nine_slice_borders.top != -1 92 | && m_definition->nine_slice_borders.right != -1 93 | && m_definition->nine_slice_borders.bottom != -1 94 | && m_definition->nine_slice_borders.left != -1; 95 | // clang-format on 96 | } 97 | 98 | auto Entity::getNineSliceBorders() const -> const NineSliceBorders& 99 | { 100 | return m_definition->nine_slice_borders; 101 | } 102 | 103 | auto Entity::hasTag(const std::string& tag) const -> bool 104 | { 105 | return m_definition->hasTag(tag); 106 | } 107 | 108 | auto Entity::allTags() const -> const std::vector& 109 | { 110 | return m_definition->allTags(); 111 | } 112 | 113 | auto Entity::allFields() const -> const std::vector& 114 | { 115 | return m_definition->fields; 116 | } 117 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Layer.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 12/11/2020. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include "LDtkLoader/defs/LayerDef.hpp" 8 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 9 | 10 | #include "LDtkLoader/DataTypes.hpp" 11 | #include "LDtkLoader/Entity.hpp" 12 | #include "LDtkLoader/Tile.hpp" 13 | #include "LDtkLoader/Tileset.hpp" 14 | 15 | namespace ldtk { 16 | 17 | class World; 18 | 19 | class Level; 20 | 21 | class Layer 22 | { 23 | public: 24 | ~Layer() = default; 25 | Layer(const Layer&) = delete; 26 | Layer(Layer&&) noexcept = default; 27 | auto operator=(const Layer&) -> Layer& = delete; 28 | auto operator=(Layer&&) -> Layer& = default; 29 | 30 | const Level* const level; 31 | const IID iid; 32 | 33 | auto getType() const -> const LayerType&; 34 | auto getName() const -> const std::string&; 35 | 36 | auto isVisible() const -> bool; 37 | 38 | auto getCellSize() const -> int; 39 | auto getGridSize() const -> const IntPoint&; 40 | 41 | auto getOffset() const -> const IntPoint&; 42 | 43 | auto getOpacity() const -> float; 44 | 45 | auto hasTileset() const -> bool; 46 | auto getTileset() const -> const Tileset&; 47 | 48 | auto allTiles() const -> const std::vector&; 49 | auto getTile(int grid_x, int grid_y) const -> const Tile&; 50 | auto getTilesByEnumTag(const EnumValue& enumvalue) const -> const std::vector>&; 51 | 52 | auto getIntGridVal(int grid_x, int grid_y) const -> const IntGridValue&; 53 | auto getIntGridValPositions(int intgridval_value) const -> const std::vector&; 54 | auto getIntGridValPositions(const std::string& intgridval_name) const -> const std::vector&; 55 | 56 | auto hasEntity(const std::string& entity_name) const -> bool; 57 | auto allEntities() const -> const std::vector&; 58 | auto getEntitiesByName(const std::string& name) const -> const std::vector>&; 59 | auto getEntitiesByTag(const std::string& tag) const -> const std::vector>&; 60 | auto getEntity(const IID& entity_iid) const -> const Entity&; 61 | 62 | auto getCoordIdAt(int grid_x, int grid_y) const -> int; 63 | auto getGridPositionFromCoordId(int coord_id) const -> IntPoint; 64 | 65 | Layer(const nlohmann::json& j, const World* w, const Level* l); 66 | 67 | private: 68 | const LayerDef* const m_definition; 69 | const Tileset* const m_override_tileset; 70 | 71 | bool m_visible; 72 | IntPoint m_total_offset; 73 | float m_opacity; 74 | const IntPoint m_grid_size; 75 | 76 | std::vector m_tiles; 77 | std::map> m_tiles_map; 78 | std::map>> m_tiles_by_enumtag; 79 | 80 | std::map> m_intgrid; 81 | mutable std::map> m_intgridpos_by_value; 82 | mutable std::map> m_intgridpos_by_name; 83 | 84 | std::vector m_entities; 85 | mutable std::unordered_map>> m_entities_by_name; 86 | mutable std::unordered_map>> m_entities_by_tag; 87 | }; 88 | 89 | } // namespace ldtk 90 | -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/Tile.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 22/02/2022. 2 | 3 | #include "LDtkLoader/Tile.hpp" 4 | 5 | #include "LDtkLoader/Layer.hpp" 6 | #include "LDtkLoader/Level.hpp" 7 | 8 | using namespace ldtk; 9 | 10 | const Tile Tile::None{nullptr, {-1, -1}, -1, -1, 0, 0}; 11 | 12 | Tile::Tile(const Layer* l, IntPoint pos, int coord_id, int tile_id, int flips, float a) 13 | : layer(l) 14 | , coordId(coord_id) 15 | , tileId(tile_id) 16 | , flipX((flips & 1) != 0) 17 | , flipY(((flips >> 1) & 1) != 0) 18 | , alpha(a) 19 | , m_position(pos) 20 | {} 21 | 22 | auto Tile::getPosition() const -> IntPoint 23 | { 24 | auto offset = layer->getOffset(); 25 | return {m_position.x + offset.x, m_position.y + offset.y}; 26 | } 27 | 28 | auto Tile::getGridPosition() const -> IntPoint 29 | { 30 | return layer->getGridPositionFromCoordId(coordId); 31 | } 32 | 33 | auto Tile::getWorldPosition() const -> IntPoint 34 | { 35 | auto pos = getPosition(); 36 | return {pos.x + layer->level->position.x, pos.y + layer->level->position.y}; 37 | } 38 | 39 | auto Tile::getTextureRect() const -> IntRect 40 | { 41 | const auto& tile_size = layer->getTileset().tile_size; 42 | auto tex_pos = layer->getTileset().getTileTexturePos(tileId); 43 | return {tex_pos.x, tex_pos.y, tile_size, tile_size}; 44 | } 45 | 46 | auto Tile::getVertices() const -> std::array 47 | { 48 | const auto tex_rect = getTextureRect(); 49 | const auto pos = getPosition(); 50 | const auto& cell_size = tex_rect.width; 51 | 52 | const auto left = static_cast(pos.x); 53 | const auto top = static_cast(pos.y); 54 | const auto right = static_cast(pos.x + cell_size); 55 | const auto bottom = static_cast(pos.y + cell_size); 56 | 57 | // clang-format off 58 | // set vertices coordinates 59 | std::array verts{}; 60 | verts[0].pos.x = left; verts[1].pos.x = right; 61 | verts[0].pos.y = top; verts[1].pos.y = top; 62 | 63 | verts[3].pos.x = left; verts[2].pos.x = right; 64 | verts[3].pos.y = bottom; verts[2].pos.y = bottom; 65 | 66 | // compute vertices texture coordinates 67 | std::array tex_coo{}; 68 | tex_coo[0].x = 0; tex_coo[1].x = cell_size; 69 | tex_coo[0].y = 0; tex_coo[1].y = 0; 70 | 71 | tex_coo[3].x = 0; tex_coo[2].x = cell_size; 72 | tex_coo[3].y = cell_size; tex_coo[2].y = cell_size; 73 | 74 | std::array modif{}; 75 | if (flipX) { 76 | modif[0].x = cell_size; modif[1].x = -cell_size; 77 | modif[3].x = cell_size; modif[2].x = -cell_size; 78 | } 79 | if (flipY) { 80 | modif[0].y = cell_size; modif[1].y = cell_size; 81 | modif[3].y = -cell_size; modif[2].y = -cell_size; 82 | } 83 | 84 | // set vertices texture coordinates 85 | for (size_t i = 0; i < verts.size(); ++i) { 86 | verts[i].tex.x = tex_rect.x + tex_coo.at(i).x + modif.at(i).x; 87 | verts[i].tex.y = tex_rect.y + tex_coo.at(i).y + modif.at(i).y; 88 | } 89 | // clang-format on 90 | 91 | return verts; 92 | } 93 | 94 | 95 | auto ldtk::operator==(const Tile& l, const Tile& r) -> bool 96 | { 97 | return (l.coordId == r.coordId) && (l.tileId == r.tileId); 98 | } 99 | 100 | auto ldtk::operator!=(const Tile& l, const Tile& r) -> bool 101 | { 102 | return !(ldtk::operator==(l, r)); 103 | } 104 | -------------------------------------------------------------------------------- /game/src/systems/player_management_system.cpp: -------------------------------------------------------------------------------- 1 | #include "systems/player_management_system.h" 2 | 3 | #include "components/player_info_component.h" 4 | #include "components/spawn_point_component.h" 5 | #include "components/transform_component.h" 6 | #include "services/game_time.h" 7 | #include "services/global_vars.h" 8 | #include "systems/audio_system.h" 9 | #include "systems/input_system.h" 10 | #include "systems/map_object_system.h" 11 | 12 | #include "scene.h" 13 | 14 | void PlayerManagementSystem::OnSetup() 15 | { 16 | Input = App::GetSystem(); 17 | MapObjects = App::GetSystem(); 18 | 19 | if (PlayerObject == nullptr) 20 | { 21 | PlayerObject = App::GetScene().AddObject(); 22 | PlayerTransform = PlayerObject->AddComponent(); 23 | } 24 | 25 | PlayerObject->MustGetComponent().PlayerId = 0; 26 | 27 | PlayerPitch = 0; 28 | 29 | if (Spawn) 30 | { 31 | TransformComponent& transform = Spawn->GetOwner()->MustGetComponent(); 32 | PlayerTransform->Position = transform.Position; 33 | PlayerTransform->Forward = transform.Forward; 34 | } 35 | 36 | App::GetSystem()->GetSound("spawn")->Play(); 37 | } 38 | 39 | Vector3 PlayerManagementSystem::GetPlayerPos() const 40 | { 41 | if (PlayerTransform) 42 | return PlayerTransform->Position; 43 | 44 | return Vector3Zeros; 45 | } 46 | 47 | Vector3 PlayerManagementSystem::GetPlayerFacing() const 48 | { 49 | if (PlayerTransform) 50 | return PlayerTransform->Forward; 51 | 52 | return Vector3UnitY; 53 | } 54 | 55 | float PlayerManagementSystem::GetPlayerPitch() const 56 | { 57 | return PlayerPitch; 58 | } 59 | 60 | void PlayerManagementSystem::OnAddObject(GameObject* object) 61 | { 62 | if (object->HasComponent()) 63 | Spawn = object->GetComponent(); 64 | } 65 | 66 | void PlayerManagementSystem::OnUpdate() 67 | { 68 | if (!Input || !PlayerObject) 69 | return; 70 | 71 | if (!GlobalVars::UseMouseDrag || IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) 72 | { 73 | PlayerTransform->Rotate(Input->GetActionValue(Actions::Yaw)); 74 | PlayerPitch += Input->GetActionValue(Actions::Pitch); 75 | 76 | // clamp 77 | if (PlayerPitch > 89) 78 | PlayerPitch = 89; 79 | if (PlayerPitch < -89) 80 | PlayerPitch = -89; 81 | } 82 | 83 | float speed = (PlayerFowardSpeed * GameTime::Scale(Input->GetActionValue(Actions::Forward))); 84 | if (speed < 0) 85 | speed *= 0.5f; 86 | 87 | Vector3 forward = PlayerTransform->Forward * speed; 88 | Vector3 sideways = Vector3RotateByAxisAngle(PlayerTransform->Forward, Vector3UnitZ, -90 * DEG2RAD); 89 | 90 | sideways *= (PlayerSideStepSpeed * GameTime::Scale(Input->GetActionValue(Actions::Sideways))); 91 | 92 | Vector3 motion = forward + sideways; 93 | 94 | static constexpr float playerRadius = 0.25f; 95 | 96 | bool hitWall = false; 97 | bool hitObstacle = false; 98 | if (!GlobalVars::UseGhostMovement) 99 | { 100 | hitWall = App::GetScene().GetMap().MoveEntity(PlayerTransform->Position, motion, playerRadius); 101 | hitObstacle = MapObjects->MoveEntity(PlayerTransform->Position, motion, playerRadius); 102 | 103 | if (hitWall || hitObstacle) 104 | { 105 | // trigger event ? 106 | } 107 | } 108 | 109 | PlayerTransform->Position += motion; 110 | 111 | MapObjects->CheckTriggers(PlayerObject, playerRadius, hitWall || hitObstacle); 112 | } -------------------------------------------------------------------------------- /game/include/utilities/lighting_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "raylib.h" 9 | 10 | static constexpr char ViewPosName[] = "viewPos"; 11 | static constexpr char EnabledName[] = "enabled"; 12 | static constexpr char TypeName[] = "type"; 13 | static constexpr char PositionName[] = "position"; 14 | static constexpr char DirectionName[] = "direction"; 15 | static constexpr char ColorName[] = "color"; 16 | static constexpr char AttenuationName[] = "attenuation"; 17 | static constexpr char FallofName[] = "falloff"; 18 | static constexpr char ConeName[] = "cone"; 19 | static constexpr char AmbientName[] = "ambient"; 20 | 21 | enum class LightTypes 22 | { 23 | Directional = 0, 24 | Point = 1, 25 | Spot = 2 26 | }; 27 | 28 | struct ShaderInfo 29 | { 30 | Shader LightShader; 31 | 32 | struct ShaderUniformLocs 33 | { 34 | int EnabledLoc = -1; 35 | int TypeLoc = -1; 36 | int PositionLoc = -1; 37 | int ColorLoc = -1; 38 | int IntensityLoc = -1; 39 | int AttenuationLoc = -1; 40 | int FalloffLoc = -1; 41 | int ConeLoc = -1; 42 | int DirectionLoc = -1; 43 | }; 44 | std::vector UniformLocations; 45 | 46 | int AmbientLoc = -1; 47 | }; 48 | 49 | class Light 50 | { 51 | public: 52 | virtual ~Light() = default; 53 | 54 | bool IsDirty() const { return Dirty; } 55 | 56 | LightTypes GetType() const { return LightType; } 57 | 58 | void SetPosition(const Vector3& pos); 59 | void SetIntensity(const Color& color); 60 | void SetAttenuation(float attenuation); 61 | void SetFalloff(float falloff); 62 | 63 | virtual void UpdateShaderVars(const ShaderInfo& shader, int lightId) const; 64 | 65 | bool Enabled = true; 66 | 67 | protected: 68 | LightTypes LightType = LightTypes::Directional; 69 | 70 | float Position[3] = { 0,0,0 }; 71 | float Intensity[4] = { 1,1,1,1 }; 72 | 73 | float Attenuation = 5; 74 | float Falloff = 10; 75 | 76 | void SetDirty() { Dirty = true; } 77 | 78 | private: 79 | bool Dirty = false; 80 | std::string FieldNameCache; 81 | }; 82 | 83 | class PointLight : public Light 84 | { 85 | public: 86 | PointLight() { LightType = LightTypes::Point; } 87 | }; 88 | 89 | class DirectionalLight : public Light 90 | { 91 | public: 92 | DirectionalLight(); 93 | 94 | void SetDirection(const Vector3& dir); 95 | 96 | void UpdateShaderVars(const ShaderInfo& shader, int lightId) const override; 97 | 98 | protected: 99 | float Direction[3] = { 1,1,-1 }; 100 | }; 101 | 102 | class SpotLight : public DirectionalLight 103 | { 104 | public: 105 | SpotLight(); 106 | 107 | void SetConeAngle(const float& cone); 108 | void UpdateShaderVars(const ShaderInfo& shader, int lightId) const override; 109 | 110 | protected: 111 | float Cone = 45; 112 | }; 113 | 114 | class LightScene 115 | { 116 | public: 117 | static constexpr int MaxShaderLights = 4; // Max dynamic lights supported by shader 118 | 119 | void SetShader(Shader shader); 120 | Shader GetShader(); 121 | 122 | void SetAmbientColor(Color color); 123 | void SetAmbientColor(float luminance); 124 | 125 | Light* AddLight(LightTypes lightType); 126 | void RemoveLight(Light* light); 127 | 128 | void ClearLights(); 129 | 130 | void ApplyLights(const Camera3D& viewportCamear); 131 | 132 | private: 133 | ShaderInfo LightShader; 134 | 135 | float Ambient[4] = { 0.05f ,0.05f, 0.05f, 1.0f }; 136 | std::list> LightList; 137 | }; -------------------------------------------------------------------------------- /game/src/components/mobile_object_component.cpp: -------------------------------------------------------------------------------- 1 | #include "components/mobile_object_component.h" 2 | #include "components/transform_component.h" 3 | #include "systems/mobile_object_system.h" 4 | #include "services/model_manager.h" 5 | #include "services/character_manager.h" 6 | #include "services/texture_manager.h" 7 | 8 | #include "raylib.h" 9 | #include "rlgl.h" 10 | 11 | ModelInstance* MobComponent::GetModelInstance() 12 | { 13 | return Instance.get(); 14 | } 15 | 16 | void MobComponent::SetSpeedFactor(float value) 17 | { 18 | if (Instance) 19 | Instance->SetAnimationFPSMultiplyer(value); 20 | } 21 | 22 | void MobComponent::OnAddedToObject() 23 | { 24 | AddToSystem(); 25 | } 26 | 27 | void MobComponent::Draw() 28 | { 29 | auto* transform = GetOwner()->GetComponent(); 30 | if (!transform) 31 | return; 32 | 33 | if (Instance) 34 | { 35 | Instance->Advance(GetFrameTime()); 36 | Instance->Draw(*transform); 37 | } 38 | else 39 | { 40 | rlPushMatrix(); 41 | rlTranslatef(transform->Position.x, transform->Position.y, transform->Position.z + 0.375f); 42 | rlRotatef(transform->GetFacing(), 0, 0, 1); 43 | DrawCube(Vector3Zeros, 0.25f, 0.25f, 0.75f, RED); 44 | DrawCube(Vector3UnitY * 0.125f + Vector3UnitZ * 0.3f, 0.25f, 0.005f, 0.125f, YELLOW); 45 | DrawCube(Vector3UnitZ * 0.125f, 0.5f, 0.125f, 0.125f, MAROON); 46 | DrawCube(Vector3UnitX * 0.3f + Vector3UnitY * 0.125f, 0.125f, 0.4f, 0.125f, PURPLE); 47 | rlPopMatrix(); 48 | } 49 | 50 | rlPushMatrix(); 51 | rlTranslatef(transform->Position.x, transform->Position.y, transform->Position.z + 0.01f); 52 | rlRotatef(transform->GetFacing(), 0, 0, 1); 53 | if (IsTextureValid(ShadowTexture)) 54 | { 55 | rlBegin(RL_QUADS); 56 | 57 | float shadowSize = 0.45f; 58 | float shadowAlpha = 0.25f; 59 | 60 | rlSetTexture(ShadowTexture.id); 61 | 62 | rlNormal3f(0, 0, 1); 63 | rlColor4f(1, 1, 1, shadowAlpha); 64 | 65 | rlTexCoord2f(0, 0); 66 | rlVertex3f(-shadowSize, -shadowSize, 0); 67 | 68 | rlTexCoord2f(1, 0); 69 | rlVertex3f(shadowSize, -shadowSize, 0); 70 | 71 | rlTexCoord2f(1, 1); 72 | rlVertex3f(shadowSize, shadowSize, 0); 73 | 74 | rlTexCoord2f(0, 1); 75 | rlVertex3f(-shadowSize, shadowSize, 0); 76 | 77 | rlEnd(); 78 | rlSetTexture(-1); 79 | } 80 | rlPopMatrix(); 81 | } 82 | 83 | void MobComponent::OnCreate() 84 | { 85 | Character = CharacterManager::GetCharacter("walker"); 86 | 87 | if (!Character) 88 | return; 89 | 90 | Instance = ModelManager::GetAnimatedModel(Character->ModelName); 91 | 92 | Instance->Geometry->OrientationTransform = MatrixIdentity(); 93 | 94 | Instance->Geometry->OrientationTransform = MatrixRotate(Vector3UnitZ, Character->RotationOffset * DEG2RAD); 95 | if (Character->IsYUp) 96 | Instance->Geometry->OrientationTransform = MatrixMultiply(Instance->Geometry->OrientationTransform, MatrixRotate(Vector3UnitX, -90 * DEG2RAD)); 97 | 98 | SetAnimationState(CharacterAnimationState::Idle); 99 | if (!Character->ShadowTexture.empty()) 100 | ShadowTexture = TextureManager::GetTexture(Character->ShadowTexture); 101 | } 102 | 103 | void MobComponent::SetAnimationState(CharacterAnimationState state) 104 | { 105 | if (Character == nullptr || AnimationState == state || !Character->SequenceNames.contains(state)) 106 | return; 107 | 108 | AnimationState = state; 109 | Instance->SetSequence(Character->SequenceNames[state]); 110 | } 111 | -------------------------------------------------------------------------------- /game/include/systems/input_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system.h" 4 | #include "raylib.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Actions 12 | { 13 | static constexpr uint8_t Forward = 0; 14 | static constexpr uint8_t Sideways = 1; 15 | static constexpr uint8_t Fire = 2; 16 | static constexpr uint8_t Yaw = 3; 17 | static constexpr uint8_t Pitch = 4; 18 | 19 | 20 | // commands 21 | static constexpr uint8_t Reload = 128; 22 | } 23 | 24 | enum class ActionType 25 | { 26 | Button, 27 | Axis, 28 | Command, 29 | }; 30 | 31 | struct ActionDef 32 | { 33 | ActionType Type = ActionType::Axis; 34 | 35 | virtual void Update(bool allowKeyboard = true) = 0; 36 | 37 | virtual float GetValue() const = 0; 38 | virtual bool IsActive() const = 0; 39 | }; 40 | 41 | struct AxisActionDef : public ActionDef 42 | { 43 | std::vector PositiveKeys; 44 | std::vector NegativeKeys; 45 | 46 | int GamePadAxis = -1; 47 | float AxisScale = 1; 48 | 49 | int MouseAxis = -1; 50 | float MouseAxisScale = 1; 51 | 52 | AxisActionDef() { Type = ActionType::Axis; } 53 | AxisActionDef(KeyboardKey positive, KeyboardKey negative, int mouseAxis = -1, float mouseAxisScale = 1, int gamepadAxis = -1, float gamepadAxisScale = 1); 54 | 55 | void Update(bool allowKeyboard = true) override; 56 | 57 | float GetValue() const override; 58 | bool IsActive() const override; 59 | 60 | private: 61 | float AxisValue = 0; 62 | }; 63 | 64 | struct ButtonActionDef : public ActionDef 65 | { 66 | std::vector ButtonKeys; 67 | GamepadButton PadButton = GAMEPAD_BUTTON_UNKNOWN; 68 | int MouseButton = -1; 69 | 70 | ButtonActionDef() { Type = ActionType::Button; } 71 | ButtonActionDef(KeyboardKey key, int mouseButton = -1, GamepadButton button = GAMEPAD_BUTTON_UNKNOWN); 72 | 73 | void Update(bool allowKeyboard = true) override; 74 | 75 | float GetValue() const override; 76 | bool IsActive() const override; 77 | 78 | private: 79 | bool ButtonValue = false; 80 | }; 81 | 82 | struct CommandActionDef : public ActionDef 83 | { 84 | public: 85 | std::vector ActionKeys; 86 | std::string Command; 87 | class ConsoleRenderSystem* ConsoleSystem = nullptr; 88 | 89 | CommandActionDef() { Type = ActionType::Command; } 90 | CommandActionDef(KeyboardKey key, std::string_view command = nullptr, ConsoleRenderSystem * console = nullptr); 91 | 92 | void Update(bool allowKeyboard = true) override; 93 | 94 | float GetValue() const override { return 0; } 95 | bool IsActive() const override { return false; } 96 | }; 97 | 98 | class InputSystem : public System 99 | { 100 | public: 101 | DEFINE_SYSTEM(InputSystem) 102 | 103 | ButtonActionDef* AddButtonAction(uint8_t id, KeyboardKey key = KEY_NULL, int mouseButton = -1, GamepadButton button = GAMEPAD_BUTTON_UNKNOWN); 104 | AxisActionDef* AddAxisAction(uint8_t id, KeyboardKey positive = KEY_NULL, KeyboardKey negative = KEY_NULL, int mouseAxis = -1, float mouseAxisScale = 1, int gamepadAxis = -1, float gamepadAxisScale = 1); 105 | CommandActionDef* AddCommandAction(uint8_t id, KeyboardKey key, std::string_view command); 106 | 107 | ActionDef* GetAction(uint8_t id); 108 | 109 | float GetActionValue(uint8_t id) const; 110 | bool IsActionActive(uint8_t id) const; 111 | 112 | protected: 113 | void OnInit() override; 114 | void OnSetup() override; 115 | void OnUpdate() override; 116 | 117 | protected: 118 | std::unordered_map> Actions; 119 | 120 | class ConsoleRenderSystem* ConsoleSystem = nullptr; 121 | }; -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/include/LDtkLoader/Project.hpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 25/02/2022. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "LDtkLoader/defs/EntityDef.hpp" 10 | #include "LDtkLoader/defs/LayerDef.hpp" 11 | #include "LDtkLoader/thirdparty/json_fwd.hpp" 12 | 13 | #include "LDtkLoader/DataTypes.hpp" 14 | #include "LDtkLoader/Enum.hpp" 15 | #include "LDtkLoader/Level.hpp" 16 | #include "LDtkLoader/Tileset.hpp" 17 | #include "LDtkLoader/World.hpp" 18 | 19 | namespace ldtk { 20 | 21 | class Project 22 | { 23 | public: 24 | Project() = default; 25 | ~Project() = default; 26 | Project(const Project&) = delete; 27 | Project(Project&&) noexcept = default; 28 | auto operator=(const Project&) -> Project& = delete; 29 | auto operator=(Project&&) -> Project& = delete; 30 | 31 | IID iid; 32 | 33 | void loadFromFile(const std::string& filepath); 34 | void loadFromFile(const std::string& filepath, const FileLoader& file_loader); 35 | 36 | void loadFromMemory(const std::vector& bytes); 37 | void loadFromMemory(const unsigned char* data, size_t size); 38 | 39 | auto getFilePath() const -> const FilePath&; 40 | 41 | auto getDefaultPivot() const -> const FloatPoint&; 42 | 43 | auto getDefaultCellSize() const -> int; 44 | 45 | auto getBgColor() const -> const Color&; 46 | 47 | auto getLayerDef(int id) const -> const LayerDef&; 48 | auto getLayerDef(const std::string& name) const -> const LayerDef&; 49 | 50 | auto getEntityDef(int id) const -> const EntityDef&; 51 | auto getEntityDef(const std::string& name) const -> const EntityDef&; 52 | 53 | auto allTilesets() const -> const std::vector&; 54 | auto getTileset(int id) const -> const Tileset&; 55 | auto getTileset(const std::string& name) const -> const Tileset&; 56 | 57 | auto getEnum(int id) const -> const Enum&; 58 | auto getEnum(const std::string& name) const -> const Enum&; 59 | 60 | auto allWorlds() const -> const std::vector&; 61 | auto getWorld() const -> const World&; 62 | auto getWorld(const std::string& name) const -> const World&; 63 | auto getWorld(const IID& iid) const -> const World&; 64 | 65 | auto allTocEntities() const -> const std::vector&; 66 | auto getTocEntitiesByName(const std::string& name) const -> const std::vector&; 67 | 68 | private: 69 | void load(const nlohmann::json& j, const FileLoader& file_loader, bool from_memory); 70 | 71 | FilePath m_file_path; 72 | FloatPoint m_default_pivot; 73 | int m_default_cell_size = 0; 74 | Color m_background_color; 75 | std::string m_json_version; 76 | 77 | std::vector m_layers_defs; 78 | std::unordered_map> m_layers_defs_by_uid; 79 | std::unordered_map> m_layers_defs_by_name; 80 | 81 | std::vector m_entities_defs; 82 | std::unordered_map> m_entities_defs_by_uid; 83 | std::unordered_map> m_entities_defs_by_name; 84 | 85 | std::vector m_tilesets; 86 | std::unordered_map> m_tilesets_by_uid; 87 | std::unordered_map> m_tilesets_by_name; 88 | 89 | std::vector m_enums; 90 | std::unordered_map> m_enums_by_uid; 91 | std::unordered_map> m_enums_by_name; 92 | 93 | std::vector m_worlds; 94 | 95 | std::vector m_toc; 96 | mutable std::map> m_toc_map; 97 | }; 98 | 99 | } // namespace ldtk 100 | -------------------------------------------------------------------------------- /model_tool/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "raylib.h" 2 | #include "raymath.h" 3 | #include "rlgl.h" 4 | 5 | #include "app.h" 6 | #include "transform_tools.h" 7 | #include "model.h" 8 | 9 | #include "imgui.h" 10 | 11 | #include 12 | 13 | void ProcessModel(const char* name); 14 | 15 | namespace App 16 | { 17 | bool Run = false; 18 | 19 | Models::AnimateableModel TheModel; 20 | 21 | AnimationState TheAnimations; 22 | 23 | const char* ModelName = nullptr; 24 | 25 | void InitGui(); 26 | void ShowGui(); 27 | void CleanupGui(); 28 | void InitRender(); 29 | void CleanupRender(); 30 | void UpdateRender(); 31 | void DrawRender(); 32 | 33 | Models::AnimateableModel& GetModel() 34 | { 35 | return TheModel; 36 | } 37 | 38 | void RequestQuit() 39 | { 40 | Run = false; 41 | } 42 | 43 | void Init() 44 | { 45 | Run = true; 46 | SetConfigFlags(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE); 47 | InitWindow(1280, 800, "Model Tool"); 48 | SetTargetFPS(300); 49 | 50 | InitGui(); 51 | InitRender(); 52 | } 53 | 54 | void NewFrame() 55 | { 56 | UpdateRender(); 57 | 58 | if (!ImGui::GetIO().WantCaptureKeyboard) 59 | { 60 | } 61 | 62 | BeginDrawing(); 63 | ClearBackground(DARKGRAY); 64 | 65 | DrawRender(); 66 | 67 | ShowGui(); 68 | 69 | EndDrawing(); 70 | } 71 | 72 | void Cleanup() 73 | { 74 | CleanupRender(); 75 | CleanupGui(); 76 | 77 | CloseWindow(); 78 | } 79 | 80 | bool Quit() 81 | { 82 | return !Run || WindowShouldClose(); 83 | } 84 | 85 | void LoadModel(const char* filename) 86 | { 87 | App::ModelName = GetFileNameWithoutExt(filename); 88 | 89 | Model tempModel = ::LoadModel(filename); 90 | 91 | Models::LoadFromModel(App::TheModel, tempModel); 92 | 93 | SetSeletedMesh(-1); 94 | SetSeletedBone(-1); 95 | 96 | TheAnimations.Frame = 0; 97 | TheAnimations.Sequence.clear(); 98 | 99 | if (TheModel.RootBone != nullptr) 100 | { 101 | int count = 0; 102 | ModelAnimation* anims = ::LoadModelAnimations(filename, &count); 103 | Models::LoadFromAnimation(App::TheAnimations.Animations, App::TheModel, anims, count); 104 | MemFree(anims); 105 | } 106 | 107 | TheModel.AutoUnload = false; 108 | 109 | ModelUpdated(); 110 | } 111 | 112 | void SaveStandardResource() 113 | { 114 | App::TheModel.Write(App::ModelName); 115 | if (!App::TheAnimations.Animations.Sequences.empty()) 116 | App::TheAnimations.Animations.Write(App::ModelName); 117 | } 118 | 119 | AnimationState& GetAnimations() 120 | { 121 | return TheAnimations; 122 | } 123 | } 124 | 125 | void ProcessModel(const char* name) 126 | { 127 | App::LoadModel(name); 128 | 129 | if (!App::TheModel.Groups.empty()) 130 | { 131 | TransformTools::CenterMesh(); 132 | TransformTools::RotateMesh(90, Vector3UnitX); 133 | TransformTools::FloorMesh(); 134 | App::SaveStandardResource(); 135 | } 136 | } 137 | 138 | int main(int argc, char* argv[]) 139 | { 140 | App::Init(); 141 | 142 | std::string command; 143 | if (argc > 1) 144 | command = argv[1]; 145 | 146 | if (command == "-generate") 147 | { 148 | auto files = LoadDirectoryFilesEx("assets/models", ".glb", false); 149 | for (size_t i = 0; i < files.count; i++) 150 | { 151 | ProcessModel(files.paths[i]); 152 | } 153 | } 154 | else if (!command.empty()) 155 | { 156 | ProcessModel(command.c_str()); 157 | } 158 | 159 | while (!App::Quit()) 160 | { 161 | App::NewFrame(); 162 | } 163 | App::Cleanup(); 164 | 165 | return 0; 166 | } -------------------------------------------------------------------------------- /game/src/systems/audio_system.cpp: -------------------------------------------------------------------------------- 1 | #include "systems/audio_system.h" 2 | 3 | #include "services/table_manager.h" 4 | #include "services/resource_manager.h" 5 | #include "services/global_vars.h" 6 | 7 | #include 8 | #include 9 | 10 | void AudioSystem::OnInit() 11 | { 12 | if (!IsAudioDeviceReady()) 13 | { 14 | AudioReady = false; 15 | AudioLoaderThread = std::thread([]() 16 | { 17 | InitAudioDevice(); 18 | SetMasterVolume(GlobalVars::MasterVolume); 19 | }); 20 | } 21 | 22 | 23 | } 24 | 25 | void AudioSystem::OnSetup() 26 | { 27 | } 28 | 29 | void AudioSystem::OnUpdate() 30 | { 31 | if (!AudioReady) 32 | { 33 | if (!AudioManifestTable) 34 | AudioManifestTable = TableManager::GetTable(BootstrapTable)->GetFieldAsTable("audio_manifest"); 35 | 36 | if (AudioLoaderThread.joinable()) 37 | { 38 | AudioLoaderThread.join(); 39 | AudioReady = true; 40 | } 41 | } 42 | 43 | if (!AudioReady) 44 | return; 45 | 46 | // TODO handle music updates 47 | } 48 | 49 | void AudioSystem::OnCleaup() 50 | { 51 | if (!AudioReady) 52 | { 53 | AudioLoaderThread.join(); 54 | AudioReady = true; 55 | } 56 | } 57 | 58 | SoundInstance::Ptr AudioSystem::GetSound(const std::string& name) 59 | { 60 | auto itr = LoadedSounds.find(name); 61 | if (itr != LoadedSounds.end()) 62 | return itr->second; 63 | 64 | if (!AudioManifestTable || !AudioManifestTable->contains(name)) 65 | return nullptr; 66 | 67 | std::string_view file = AudioManifestTable->GetField(name); 68 | auto resource = ResourceManager::OpenResource(file); 69 | if (!resource) 70 | return nullptr; 71 | 72 | Wave wave = LoadWaveFromMemory(GetFileExtension(file.data()), resource->DataBuffer, int(resource->DataSize)); 73 | ResourceManager::ReleaseResource(resource); 74 | 75 | Sound sound = LoadSoundFromWave(wave); 76 | UnloadWave(wave); 77 | 78 | if (!IsSoundValid(sound)) 79 | return nullptr; 80 | 81 | SoundInstance::Ptr instance = std::make_shared(sound); 82 | LoadedSounds.insert_or_assign(name, instance); 83 | return instance; 84 | } 85 | 86 | int SoundInstance::Play() 87 | { 88 | int instnace = FindFreeSoundInstance(); 89 | 90 | PlaySound(GetSound(instnace)); 91 | 92 | return instnace; 93 | } 94 | 95 | bool SoundInstance::IsPlaying(int instanceID) 96 | { 97 | return IsSoundPlaying(GetSound(instanceID)); 98 | } 99 | 100 | void SoundInstance::Stop(int instanceID) 101 | { 102 | Sound sound = GetSound(instanceID); 103 | if (IsSoundPlaying(sound)) 104 | StopSound(sound); 105 | } 106 | 107 | void SoundInstance::StopAll() 108 | { 109 | for (auto& alias : Aliases) 110 | { 111 | if (IsSoundPlaying(alias)) 112 | StopSound(alias); 113 | } 114 | 115 | if (IsSoundPlaying(SourceSound)) 116 | StopSound(SourceSound); 117 | } 118 | 119 | const Sound& SoundInstance::GetSound(int instanceID) const 120 | { 121 | if (instanceID == 0) 122 | return SourceSound; 123 | 124 | return Aliases[instanceID - 1]; 125 | } 126 | 127 | int SoundInstance::FindFreeSoundInstance() 128 | { 129 | if (!IsSoundPlaying(SourceSound)) 130 | return 0; 131 | 132 | int index = 1; 133 | for (auto& alias : Aliases) 134 | { 135 | if (!IsSoundPlaying(alias)) 136 | return index; 137 | 138 | index++; 139 | } 140 | Aliases.push_back(LoadSoundAlias(SourceSound)); 141 | return int(Aliases.size()); 142 | } 143 | 144 | SoundInstance::SoundInstance(Sound sound) : SourceSound(sound) 145 | { 146 | } 147 | 148 | SoundInstance::~SoundInstance() 149 | { 150 | for (auto& alias : Aliases) 151 | { 152 | if (IsSoundPlaying(alias)) 153 | StopSound(alias); 154 | 155 | UnloadSoundAlias(alias); 156 | } 157 | 158 | if (IsSoundPlaying(SourceSound)) 159 | StopSound(SourceSound); 160 | UnloadSound(SourceSound); 161 | } 162 | -------------------------------------------------------------------------------- /game/src/services/resource_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "services/resource_manager.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "raylib.h" 8 | 9 | ResoureInfo::~ResoureInfo() 10 | { 11 | UnloadFileData(DataBuffer); 12 | } 13 | 14 | namespace ResourceManager 15 | { 16 | static std::hash StringHasher; 17 | 18 | using ResourceMap = std::unordered_map>; 19 | ResourceMap OpenResources; 20 | 21 | bool SearchAndSetResourceDir(const char* folderName) 22 | { 23 | // check the working dir 24 | if (DirectoryExists(folderName)) 25 | { 26 | ChangeDirectory(TextFormat("%s/%s", GetWorkingDirectory(), folderName)); 27 | return true; 28 | } 29 | 30 | const char* appDir = GetApplicationDirectory(); 31 | 32 | // check the applicationDir 33 | const char* dir = TextFormat("%s%s", appDir, folderName); 34 | if (DirectoryExists(dir)) 35 | { 36 | ChangeDirectory(dir); 37 | return true; 38 | } 39 | 40 | // check one up from the app dir 41 | dir = TextFormat("%s../%s", appDir, folderName); 42 | if (DirectoryExists(dir)) 43 | { 44 | ChangeDirectory(dir); 45 | return true; 46 | } 47 | 48 | // check two up from the app dir 49 | dir = TextFormat("%s../../%s", appDir, folderName); 50 | if (DirectoryExists(dir)) 51 | { 52 | ChangeDirectory(dir); 53 | return true; 54 | } 55 | 56 | // check three up from the app dir 57 | dir = TextFormat("%s../../../%s", appDir, folderName); 58 | if (DirectoryExists(dir)) 59 | { 60 | ChangeDirectory(dir); 61 | return true; 62 | } 63 | 64 | return false; 65 | } 66 | 67 | void Init(std::string_view rootFolder) 68 | { 69 | SearchAndSetResourceDir(rootFolder.data()); 70 | 71 | // TODO, handle reading from packages here, like reading an archive 72 | } 73 | 74 | void Cleanup() 75 | { 76 | OpenResources.clear(); 77 | } 78 | 79 | std::shared_ptr OpenResource(std::string_view filePath, bool asText) 80 | { 81 | if (filePath.empty()) 82 | return nullptr; 83 | 84 | size_t pathHash = StringHasher(filePath); 85 | 86 | auto itr = OpenResources.find(pathHash); 87 | if (itr != OpenResources.end()) 88 | return itr->second; 89 | 90 | int size = 0; 91 | uint8_t* buffer = nullptr; 92 | 93 | if (asText) 94 | { 95 | buffer = (uint8_t*)LoadFileText(filePath.data()); 96 | if (buffer) 97 | size = (int)strlen((char*)buffer); 98 | } 99 | else 100 | { 101 | buffer = LoadFileData(filePath.data(), &size); 102 | } 103 | 104 | if (!buffer) 105 | return nullptr; 106 | 107 | std::shared_ptr file = std::make_shared(); 108 | 109 | file->NameHash = pathHash; 110 | file->DataBuffer = buffer; 111 | file->DataSize = size; 112 | 113 | OpenResources.insert_or_assign(pathHash, file); 114 | return file; 115 | } 116 | 117 | void ReleaseResource(std::shared_ptr resource) 118 | { 119 | if (!resource) 120 | return; 121 | 122 | auto itr = OpenResources.find(resource->NameHash); 123 | if (itr != OpenResources.end()) 124 | OpenResources.erase(itr); 125 | } 126 | 127 | void ReleaseResource(const char* resourceName) 128 | { 129 | auto itr = OpenResources.find(StringHasher(resourceName)); 130 | if (itr != OpenResources.end()) 131 | OpenResources.erase(itr); 132 | } 133 | 134 | void ReleaseResourceByData(void* resourceData) 135 | { 136 | for (ResourceMap::iterator itr = OpenResources.begin(); itr != OpenResources.end(); ++itr) 137 | { 138 | if (itr->second->DataBuffer == resourceData) 139 | { 140 | OpenResources.erase(itr); 141 | return; 142 | } 143 | } 144 | } 145 | }; -------------------------------------------------------------------------------- /game/src/external/LDtkLoader/src/Level.cpp: -------------------------------------------------------------------------------- 1 | // Created by Modar Nasser on 12/11/2020. 2 | 3 | #include "LDtkLoader/Level.hpp" 4 | 5 | #include 6 | #include 7 | 8 | #include "LDtkLoader/World.hpp" 9 | 10 | #include "json.hpp" 11 | 12 | using namespace ldtk; 13 | 14 | Level::Level(const nlohmann::json& j, World* w) 15 | : FieldsContainer(j["fieldInstances"], w) 16 | , world(w) 17 | , name(j["identifier"].get()) 18 | , iid(j.contains("iid") ? j["iid"].get() : "") 19 | , uid(j["uid"].get()) 20 | , size(j["pxWid"].get(), j["pxHei"].get()) 21 | , position(j["worldX"].get(), j["worldY"].get()) 22 | , bg_color(j["__bgColor"].get()) 23 | , depth(j.contains("worldDepth") ? j["worldDepth"].get() : 0) 24 | { 25 | m_layers.reserve(j["layerInstances"].size()); 26 | for (const auto& level : j["layerInstances"]) { 27 | m_layers.emplace_back(level, w, this); 28 | } 29 | 30 | m_neighbours_iid_by_dir.emplace(Dir::None, 0); 31 | m_neighbours_iid_by_dir.emplace(Dir::North, 0); 32 | m_neighbours_iid_by_dir.emplace(Dir::NorthEast, 0); 33 | m_neighbours_iid_by_dir.emplace(Dir::East, 0); 34 | m_neighbours_iid_by_dir.emplace(Dir::SouthEast, 0); 35 | m_neighbours_iid_by_dir.emplace(Dir::South, 0); 36 | m_neighbours_iid_by_dir.emplace(Dir::SouthWest, 0); 37 | m_neighbours_iid_by_dir.emplace(Dir::West, 0); 38 | m_neighbours_iid_by_dir.emplace(Dir::NorthWest, 0); 39 | m_neighbours_iid_by_dir.emplace(Dir::Over, 0); 40 | m_neighbours_iid_by_dir.emplace(Dir::Under, 0); 41 | m_neighbours_iid_by_dir.emplace(Dir::Overlap, 0); 42 | for (const auto& neighbour : j["__neighbours"]) { 43 | const auto& dir = neighbour["dir"].get(); 44 | const auto& level_iid = IID(neighbour["levelIid"].get()); 45 | m_neighbours_iid.emplace(level_iid); 46 | m_neighbours_iid_by_dir[getDirFromString(dir)].emplace(level_iid); 47 | } 48 | 49 | if (j["bgRelPath"].is_null()) { 50 | m_bg_image = null; 51 | } 52 | else { 53 | m_bg_image = BgImage(); 54 | m_bg_image->path = FilePath(j["bgRelPath"].get()); 55 | m_bg_image->pos = {j["__bgPos"]["topLeftPx"][0].get(), j["__bgPos"]["topLeftPx"][1].get()}; 56 | m_bg_image->scale = {j["__bgPos"]["scale"][0].get(), j["__bgPos"]["scale"][1].get()}; 57 | m_bg_image->crop = { 58 | j["__bgPos"]["cropRect"][0].get(), 59 | j["__bgPos"]["cropRect"][1].get(), 60 | j["__bgPos"]["cropRect"][2].get(), 61 | j["__bgPos"]["cropRect"][3].get() 62 | }; 63 | } 64 | } 65 | 66 | auto Level::allLayers() const -> const std::vector& 67 | { 68 | return m_layers; 69 | } 70 | 71 | auto Level::getLayer(const std::string& layer_name) const -> const Layer& 72 | { 73 | for (const auto& layer : m_layers) { 74 | if (layer.getName() == layer_name) { 75 | return layer; 76 | } 77 | } 78 | ldtk_error("Layer name \"" + layer_name + "\" not found in Level \"" + name + "\"."); 79 | } 80 | 81 | auto Level::getLayer(const IID& layer_iid) const -> const Layer& 82 | { 83 | for (const auto& layer : m_layers) { 84 | if (layer.iid == layer_iid) { 85 | return layer; 86 | } 87 | } 88 | ldtk_error("Layer with IID \"" + layer_iid.str() + "\" not found in Level \"" + name + "\"."); 89 | } 90 | 91 | auto Level::hasBgImage() const -> bool 92 | { 93 | return m_bg_image.has_value(); 94 | } 95 | 96 | auto Level::getBgImage() const -> const BgImage& 97 | { 98 | return m_bg_image.value(); 99 | } 100 | 101 | auto Level::allNeighbours() const -> const std::vector>& 102 | { 103 | return m_neighbours; 104 | } 105 | 106 | auto Level::getNeighbours(const Dir& direction) const -> const std::vector>& 107 | { 108 | return m_neighbours_by_dir.at(direction); 109 | } 110 | 111 | auto Level::getNeighbourDirection(const Level& level) const -> Dir 112 | { 113 | for (const auto& item : m_neighbours_iid_by_dir) { 114 | const auto& neighbour_direction = item.first; 115 | for (const auto& neighbour_iid : item.second) { 116 | if (neighbour_iid == level.iid) { 117 | return neighbour_direction; 118 | } 119 | } 120 | } 121 | return Dir::None; 122 | } 123 | -------------------------------------------------------------------------------- /model_lib/include/model.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "raylib.h" 4 | #include "raymath.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void WriteModel(Model& model, std::string_view file); 14 | void ReadModel(Model& model, uint8_t* buffer, size_t size, bool supportCPUAnimation = false); 15 | 16 | void WriteModelAnimations(ModelAnimation* animations, size_t count, std::string_view file); 17 | ModelAnimation* ReadModelAnimations(const Model& model, size_t& count, uint8_t* buffer, size_t size); 18 | 19 | using ResolveModelTextureCallback = std::function; 20 | void SetModelTextureResolver(ResolveModelTextureCallback callback); 21 | 22 | namespace Models 23 | { 24 | // a mesh and it's material index 25 | struct AnimateableMesh 26 | { 27 | Mesh Geometry; 28 | }; 29 | 30 | // A bone with it's binding transform, and pointers to it's children 31 | struct AnimatableBoneInfo 32 | { 33 | std::string Name; 34 | size_t ParentBoneId = size_t(-1); 35 | Transform DefaultGlobalTransform; 36 | 37 | std::vector Children; 38 | }; 39 | 40 | // A cache of the transforms to apply to a bone for a specific display pose 41 | struct AnimateablePose 42 | { 43 | std::vector BoneTransforms; 44 | }; 45 | 46 | // A keyframe in an animation 47 | struct AnimateableKeyFrame 48 | { 49 | std::vector GlobalTransforms; 50 | }; 51 | 52 | // a sequence of animation keyframes 53 | struct AnimatableSequence 54 | { 55 | std::vector Frames; 56 | float FPS = 30; 57 | }; 58 | 59 | 60 | struct AnimatableMeshGroup 61 | { 62 | Material GroupMaterial; 63 | std::vector Meshes; 64 | }; 65 | 66 | // a model that can be animated 67 | struct AnimateableModel 68 | { 69 | AnimateableModel() = default; 70 | // unloads on destruction 71 | virtual ~AnimateableModel(); 72 | 73 | // noncopyable to prevent early unload 74 | AnimateableModel(const AnimateableModel&) = delete; 75 | AnimateableModel& operator = (const AnimateableModel&) = delete; 76 | 77 | std::vector Groups; 78 | 79 | std::vector Bones; 80 | 81 | // the root bone of the skeleton tree 82 | AnimatableBoneInfo* RootBone = nullptr; 83 | 84 | Matrix RootTransform = MatrixIdentity(); 85 | 86 | void Read(uint8_t* buffer, size_t size); 87 | void Write( std::string_view file); 88 | 89 | void Upload(); 90 | 91 | BoundingBox GetBounds(); 92 | 93 | bool AutoUnload = true; 94 | }; 95 | 96 | // a set of named animation sequences that can all be applied to the same skeleton 97 | struct AnimationSet 98 | { 99 | std::unordered_map Sequences; 100 | 101 | void Read(uint8_t* buffer, size_t size); 102 | void Write(std::string_view file); 103 | }; 104 | 105 | // loads an animated model from a raylib model, all the meshes and materials are transfered to the animateable model, and removed from the raylib model 106 | // do not call UnloadModel on the model 107 | void LoadFromModel(AnimateableModel& animModel, const Model& model); 108 | 109 | // loads an animation set from a raylib animation array, all the sequences are transfered to the animation set and each animation is unloaded 110 | // you are responsible for deleting the array memory, but not the animations it points to 111 | void LoadFromAnimation(AnimationSet & animSet, const AnimateableModel& model, ModelAnimation* animationsPointer, size_t count); 112 | 113 | // creates a pose in the default (bind pose) position that can be animated. 114 | AnimateablePose GetDefaultPose(const AnimateableModel& model); 115 | 116 | // updates a pose to match a keyframe 117 | void UpdatePoseToFrame(const AnimateableModel& model, AnimateablePose& pose, const AnimateableKeyFrame& frame); 118 | 119 | // updates a pose to be an interpolation value between two keyframes 120 | void InterpolatePose(const AnimateableModel& model, AnimateablePose& pose, const AnimateableKeyFrame& frame1, const AnimateableKeyFrame& frame2, float param); 121 | 122 | // draws a model, with transform, at a pose, with a set of optional material overrides 123 | void DrawAnimatableModel(const AnimateableModel& model, Matrix transform, AnimateablePose* pose = nullptr, const std::vector* materialOverrides = nullptr); 124 | } -------------------------------------------------------------------------------- /game/include/game_object.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "component.h" 13 | #include "object_lifetime_token.h" 14 | 15 | class Scene; 16 | class GameObject; 17 | 18 | using GameObjectEventHandler = std::function; 19 | 20 | struct GameObjectEventRecord 21 | { 22 | GameObjectEventHandler Handler; 23 | ObjectLifetimeToken::Ptr LifetimeToken; 24 | }; 25 | 26 | class GameObject 27 | { 28 | public: 29 | std::vector> Children; 30 | std::unordered_map> Components; 31 | 32 | public: 33 | GameObject(); 34 | ~GameObject(); 35 | 36 | GameObject* AddChild(); 37 | 38 | template 39 | inline T* AddComponent(Args&&... args) 40 | { 41 | auto itr = Components.find(T::TypeID()); 42 | if (itr != Components.end()) 43 | return static_cast(itr->second.get()); 44 | 45 | auto comp = std::make_unique(this, std::forward(args)...); 46 | T* ptr = static_cast(comp.get()); 47 | 48 | Components.try_emplace(T::TypeID(), std::move(comp)); 49 | 50 | ptr->OnAddedToObject(); 51 | return ptr; 52 | } 53 | 54 | template 55 | inline bool HasComponent() 56 | { 57 | return Components.find(T::TypeID()) != Components.end(); 58 | } 59 | 60 | template 61 | inline T* GetComponent() 62 | { 63 | auto itr = Components.find(T::TypeID()); 64 | if (itr == Components.end()) 65 | return nullptr; 66 | 67 | auto& comp = itr->second; 68 | return static_cast(comp.get()); 69 | } 70 | 71 | template 72 | inline const T* GetComponent() const 73 | { 74 | auto itr = Components.find(T::TypeID()); 75 | if (itr == Components.end()) 76 | return nullptr; 77 | 78 | auto& comp = itr->second; 79 | return static_cast(comp.get()); 80 | } 81 | 82 | template 83 | inline T& MustGetComponent() 84 | { 85 | auto itr = Components.find(T::TypeID()); 86 | if (itr == Components.end()) 87 | return *AddComponent(); 88 | 89 | auto& comp = itr->second; 90 | return *static_cast(comp.get()); 91 | } 92 | 93 | void AddToSystem(size_t systemGUID); 94 | 95 | ObjectLifetimeToken::Ptr GetToken() { return Token; } 96 | 97 | void AddEventHandler(size_t hash, GameObjectEventHandler handler, ObjectLifetimeToken::Ptr token); 98 | void AddEventHandler(std::string_view name, GameObjectEventHandler handler, ObjectLifetimeToken::Ptr token); 99 | 100 | void CallEvent(size_t hash, GameObject* target = nullptr); 101 | void CallEvent(std::string_view name, GameObject* target = nullptr); 102 | 103 | void AddFlag(size_t flag) { Flags.insert(flag); } 104 | void AddFlag(void* flag) { AddFlag(reinterpret_cast(flag)); } 105 | 106 | void ClearFlag(size_t flag) { Flags.erase(flag); } 107 | void ClearFlag(void* flag) { ClearFlag(reinterpret_cast(flag)); } 108 | 109 | bool HasFlag(size_t flag) const { return Flags.contains(flag); } 110 | bool HasFlag(void* flag) const { return HasFlag(reinterpret_cast(flag)); } 111 | 112 | protected: 113 | GameObject* ParentPtr = nullptr; 114 | std::set LinkedSystems; 115 | 116 | ObjectLifetimeToken::Ptr Token; 117 | 118 | std::unordered_map> EventHandlers; 119 | 120 | std::set Flags; 121 | 122 | protected: 123 | GameObject* GetParent() const; 124 | }; 125 | 126 | // utility class to cache a list of components in systems from the game objects they have 127 | // will check if the object has the component and if so, cache it's pointer for ECS-like iteration 128 | template 129 | class SystemComponentList 130 | { 131 | public: 132 | std::set Components; 133 | 134 | inline T* Add(GameObject* object) 135 | { 136 | T* comp = object->GetComponent(); 137 | if (comp) 138 | Components.insert(comp); 139 | 140 | return comp; 141 | } 142 | 143 | inline T* MustAdd(GameObject* object) 144 | { 145 | T& comp = object->MustGetComponent(); 146 | Components.push_back(&comp); 147 | 148 | return ∁ 149 | } 150 | 151 | inline void Remove(GameObject* object) 152 | { 153 | T* comp = object->GetComponent(); 154 | 155 | if (comp) 156 | { 157 | auto itr = std::find(Components.begin(), Components.end(), comp); 158 | if (itr != Components.end()) 159 | Components.erase(itr); 160 | } 161 | } 162 | }; --------------------------------------------------------------------------------