From d307bd5dbe1c4a91605b1f31a37f837d7b0569b3 Mon Sep 17 00:00:00 2001 From: ShadesAndGrays Date: Thu, 16 Jul 2026 21:44:34 +0100 Subject: [PATCH] refactor: seperate engine and game --- imgui.ini | 4 +- makefile | 61 ++--- src/animation.cpp | 0 src/asset.cpp | 187 --------------- src/engine/asset/asset.cpp | 189 +++++++++++++++ src/engine/asset/asset.hpp | 54 +++++ src/engine/asset/raylib-asset.hpp | 35 +++ src/engine/core/application.cpp | 86 +++++++ src/engine/core/application.hpp | 29 +++ .../core}/engine_variant.hpp | 218 +++++++++--------- .../core}/engine_variant_operation.hpp | 148 ++++++------ src/engine/core/service-locator.hpp | 68 ++++++ src/engine/ecs/components.hpp | 28 +++ src/engine/render/render-system.cpp | 50 ++++ src/engine/render/render-system.hpp | 8 + src/engine/scene/scene.cpp | 65 ++++++ src/engine/scene/scene.hpp | 82 +++++++ src/{include => engine/util}/math_util.hpp | 43 ++-- src/fruit.cpp | 50 ---- src/game/ecs/components.hpp | 7 + src/game/main.cpp | 34 +++ src/game/scenes/main-scene/body.cpp | 67 ++++++ src/game/scenes/main-scene/body.hpp | 26 +++ src/game/scenes/main-scene/fruit.cpp | 57 +++++ src/game/scenes/main-scene/fruit.hpp | 7 + src/game/scenes/main-scene/main-scene.cpp | 73 ++++++ src/game/scenes/main-scene/main-scene.hpp | 20 ++ src/game/scenes/main-scene/player.cpp | 57 +++++ src/game/scenes/main-scene/player.hpp | 6 + src/game/scenes/main-scene/score-system.hpp | 15 ++ .../scenes/menu-scene/menu.cpp} | 111 +++++---- src/game/scenes/menu-scene/menu.hpp | 13 ++ src/include/animation.hpp | 22 -- src/include/asset/asset.hpp | 54 ----- src/include/asset/raylib_asset.hpp | 31 --- src/include/components.hpp | 30 --- src/include/fruit.hpp | 9 - src/include/locator.hpp | 24 -- src/include/movement.hpp | 4 - src/include/player.hpp | 24 -- src/include/render.hpp | 5 - src/include/scene.hpp | 73 ------ src/main.cpp | 94 -------- src/movement.cpp | 16 -- src/player.cpp | 104 --------- src/render.cpp | 45 ---- src/scenes/game_play_scene.cpp | 64 ----- src/scenes/scene.cpp | 60 ----- src/test.cpp | 58 ----- 49 files changed, 1371 insertions(+), 1244 deletions(-) delete mode 100644 src/animation.cpp delete mode 100644 src/asset.cpp create mode 100644 src/engine/asset/asset.cpp create mode 100644 src/engine/asset/asset.hpp create mode 100644 src/engine/asset/raylib-asset.hpp create mode 100644 src/engine/core/application.cpp create mode 100644 src/engine/core/application.hpp rename src/{include => engine/core}/engine_variant.hpp (97%) rename src/{include => engine/core}/engine_variant_operation.hpp (97%) create mode 100644 src/engine/core/service-locator.hpp create mode 100644 src/engine/ecs/components.hpp create mode 100644 src/engine/render/render-system.cpp create mode 100644 src/engine/render/render-system.hpp create mode 100644 src/engine/scene/scene.cpp create mode 100644 src/engine/scene/scene.hpp rename src/{include => engine/util}/math_util.hpp (93%) delete mode 100644 src/fruit.cpp create mode 100644 src/game/ecs/components.hpp create mode 100644 src/game/main.cpp create mode 100644 src/game/scenes/main-scene/body.cpp create mode 100644 src/game/scenes/main-scene/body.hpp create mode 100644 src/game/scenes/main-scene/fruit.cpp create mode 100644 src/game/scenes/main-scene/fruit.hpp create mode 100644 src/game/scenes/main-scene/main-scene.cpp create mode 100644 src/game/scenes/main-scene/main-scene.hpp create mode 100644 src/game/scenes/main-scene/player.cpp create mode 100644 src/game/scenes/main-scene/player.hpp create mode 100644 src/game/scenes/main-scene/score-system.hpp rename src/{scenes/menu_scene.cpp => game/scenes/menu-scene/menu.cpp} (77%) create mode 100644 src/game/scenes/menu-scene/menu.hpp delete mode 100644 src/include/animation.hpp delete mode 100644 src/include/asset/asset.hpp delete mode 100644 src/include/asset/raylib_asset.hpp delete mode 100644 src/include/components.hpp delete mode 100644 src/include/fruit.hpp delete mode 100644 src/include/locator.hpp delete mode 100644 src/include/movement.hpp delete mode 100644 src/include/player.hpp delete mode 100644 src/include/render.hpp delete mode 100644 src/include/scene.hpp delete mode 100644 src/main.cpp delete mode 100644 src/movement.cpp delete mode 100644 src/player.cpp delete mode 100644 src/render.cpp delete mode 100644 src/scenes/game_play_scene.cpp delete mode 100644 src/scenes/scene.cpp delete mode 100644 src/test.cpp diff --git a/imgui.ini b/imgui.ini index 09c68b7..4a9cd23 100644 --- a/imgui.ini +++ b/imgui.ini @@ -1,5 +1,5 @@ [Window][Debug##Default] -Pos=952,-6 +Pos=952,0 Size=400,400 [Window][CenterWindow] @@ -8,7 +8,7 @@ Size=1280,800 Collapsed=1 [Window][VBoxContainer] -Pos=540,275 +Pos=540,235 Size=200,250 [Window][Box] diff --git a/makefile b/makefile index 57c2571..c18f022 100644 --- a/makefile +++ b/makefile @@ -31,22 +31,21 @@ DEBUGFLAGS = -std=c++20 -g -O0 INCLUDES = -I./external/raylib/include \ -I./external/entt/single_include \ - -I./src/include \ -I./external/imgui \ -I./external/rlImGui \ -I./external/box2d/include \ -I./external/nhlohmann_json_3.12.0/ \ -I./external/asset_packer/bin/include \ + -I./src \ WEB_INCLUDES = -I./external/raylib-web/include \ -I./external/entt/single_include \ - -I./src/include \ -I./external/imgui \ -I./external/rlImGui \ -I./external/box2d/include \ -I./external/nhlohmann_json_3.12.0/ \ -I./external/asset_packer/bin/include \ - # -I./external/emscripten/include \ + -I./src \ IMGUI_SRCS = ./external/imgui/imgui.cpp \ ./external/imgui/imgui_demo.cpp \ @@ -56,38 +55,35 @@ IMGUI_SRCS = ./external/imgui/imgui.cpp \ IMGUI_BACKEND = ./external/rlImGui/rlImGui.cpp +# SRC_FILES = ./src/engine/core/application.cpp \ +# ./src/engine/scene/scene.cpp \ +# ./src/game/main.cpp +SRC_FILES := $(shell find ./src -name "*.cpp") -SRC_FILES = ./src/asset.cpp \ - ./src/movement.cpp \ - ./src/player.cpp \ - ./src/fruit.cpp \ - ./src/render.cpp \ - ./src/scenes/scene.cpp \ - ./src/scenes/game_play_scene.cpp \ - ./src/scenes/menu_scene.cpp - -ENTRY_POINT = ./src/main.cpp TEST_ENTRY_POINT = ./src/test.cpp -IMGUI_OBJS = $(patsubst ./external/imgui/%.cpp,./bin/%.o,$(IMGUI_SRCS)) -IMGUI_BACKEND_OBJS = $(patsubst ./external/rlImGui/%.cpp,./bin/%.o,$(IMGUI_BACKEND)) -OBJS_FILES = $(patsubst ./src/%.cpp,./bin/%.o,$(SRC_FILES)) +IMGUI_OBJS = $(patsubst ./external/imgui/%.cpp,./bin/external/%.o,$(IMGUI_SRCS)) +IMGUI_BACKEND_OBJS = $(patsubst ./external/rlImGui/%.cpp,./bin/external/%.o,$(IMGUI_BACKEND)) -DEP_FILES = $(patsubst ./bin/%.o,./bin/%.d,$(OBJS_FILES)) +OBJS_FILES = $(patsubst ./src/%.cpp,./bin/obj/%.o,$(SRC_FILES)) + +DEP_FILES = $(patsubst ./bin/obj/%.o,./bin/obj/%.d,$(OBJS_FILES)) all: build-desktop run-desktop -./bin/%.o: ./external/imgui/%.cpp +./bin/external/%.o: ./external/imgui/%.cpp @mkdir -p bin + @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ -./bin/%.o: ./external/rlImGui/%.cpp +./bin/external/%.o: ./external/rlImGui/%.cpp @mkdir -p bin + @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ -./bin/%.o: ./src/%.cpp +./bin/obj/%.o: ./src/%.cpp @mkdir -p bin @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ @@ -114,7 +110,7 @@ build-core: $(OBJS_FILES) build-desktop: $(OBJS_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) @mkdir -p bin - $(CXX) $(CXXFLAGS) $(INCLUDES) $(ENTRY_POINT) $(OBJS_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) $(LDFLAGS) $(LIBS) -o ./bin/main.exe + $(CXX) $(CXXFLAGS) $(INCLUDES) $(OBJS_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) $(LDFLAGS) $(LIBS) -o ./bin/main.exe cp ./assets ./bin -rf build-test: $(OBJS_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) @@ -125,20 +121,31 @@ build-test: $(OBJS_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) build-debug: @mkdir -p debug - $(CXX) $(DEBUGFLAGS) $(INCLUDES) $(ENTRY_POINT) $(SRC_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) $(LDFLAGS) $(LIBS) -o ./debug/d.exe + $(CXX) $(DEBUGFLAGS) $(INCLUDES) $(SRC_FILES) $(IMGUI_OBJS) $(IMGUI_BACKEND_OBJS) $(LDFLAGS) $(LIBS) -o ./debug/d.exe cp ./data.dat ./debug -rf web: @mkdir -p web - $(WEB_CXX) $(CXXFLAGS) $(WEB_INCLUDES) $(ENTRY_POINT) $(SRC_FILES) $(IMGUI_SRCS) $(IMGUI_BACKEND) $(WEB_LDFLAGS) $(WEB_LIBS) -o ./web/index.html + $(WEB_CXX) $(CXXFLAGS) $(WEB_INCLUDES) $(SRC_FILES) $(IMGUI_SRCS) $(IMGUI_BACKEND) $(WEB_LDFLAGS) $(WEB_LIBS) -o ./web/index.html web-native: @mkdir -p web em++ $(CXXFLAGS) $(WEB_INCLUDES) $(ENTRY_POINT) $(SRC_FILES) $(IMGUI_SRCS) $(IMGUI_BACKEND) $(WEB_LDFLAGS) $(WEB_LIBS) -o ./web/index.html -clean-desktop: +clean-all: @rm -r -f ./bin - @rm -f compile_commands.json + +clean-engine: + @rm -r -f ./bin/obj/engine + @rm -r -f ./bin/main.exe + +clean-game: + @rm -r -f ./bin/obj/game + @rm -r -f ./bin/main.exe + +clean-desktop: + @rm -r -f ./bin/obj + @rm -r -f ./bin/main.exe clean-debug: @rm -r -f ./debug @@ -170,5 +177,5 @@ run-test: build-test pack-assets: ./external/asset_packer/bin/assetpacker.exe assets/ - - +list-src-files: + @echo $(shell find src -name "*.cpp") diff --git a/src/animation.cpp b/src/animation.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/asset.cpp b/src/asset.cpp deleted file mode 100644 index f2fba34..0000000 --- a/src/asset.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include - - -namespace fs = std::filesystem; - -// Helper to determine if the asset path implies streaming music -bool should_stream_as_music(const std::filesystem::path& asset_path) { - for (const auto& part : asset_path) { - if (part == "music" || part == "bgm") { - return true; - } - } - return false; -} - -AssetLoader::AssetLoader(std::string asset_data) : asset_reader(asset_data){ - if (!asset_reader.load_index()){ - std::cerr << "Failed to load assets!!!" << std::endl; - } -} - -AssetReader AssetLoader::get_reader(){ - return asset_reader; -} - -RaylibAssetLoader::RaylibAssetLoader(std::string asset_data) : AssetLoader(asset_data) { - -} - -RaylibAssetLoader::~RaylibAssetLoader(){ - unload_all_assets(); -} - - - -void RaylibAssetLoader::load_asset(std::string path){ - fs::path file_path(path); - Asset new_asset; - new_asset.name = file_path.filename().string() ; - - // std::cout << file_path.extension() << std::endl; - auto bytes = get_reader().extract_asset(path); - - if (file_path.extension() == ".png"){ - Image img = LoadImageFromMemory(".png", bytes.data(), bytes.size()); - auto texture = LoadTextureFromImage(img); - UnloadImage(img); - new_asset.data = ImageData { new Texture(texture)}; - - - }else if(file_path.extension() == ".ogg"){ - - if (should_stream_as_music(file_path)){ - auto music = LoadMusicStreamFromMemory(".ogg",bytes.data(),bytes.size()); - new_asset.data = MusicData{new Music(music)}; - }else{ - auto wave = LoadWaveFromMemory(".ogg", bytes.data(),bytes.size()); - auto sound = LoadSoundFromWave(wave); - UnloadWave(wave); - new_asset.data = SoundData{new Sound(sound)}; - } - - } - else if(file_path.extension() == ".mp3"){ - if (should_stream_as_music(file_path)){ - auto music = LoadMusicStreamFromMemory(".mp3",bytes.data(),bytes.size()); - new_asset.data = MusicData{new Music(music)}; - }else{ - auto wave = LoadWaveFromMemory(".mp3", bytes.data(),bytes.size()); - auto sound = LoadSoundFromWave(wave); - UnloadWave(wave); - new_asset.data = SoundData{new Sound(sound)}; - } - - } - else if(file_path.extension() == ".wav"){ - if (should_stream_as_music(file_path)){ - auto music = LoadMusicStreamFromMemory(".wav",bytes.data(),bytes.size()); - new_asset.data = MusicData{new Music(music)}; - }else{ - auto wave = LoadWaveFromMemory(".wav", bytes.data(),bytes.size()); - auto sound = LoadSoundFromWave(wave); - UnloadWave(wave); - new_asset.data = SoundData{new Sound(sound)}; - } - } - - else if(file_path.extension() == ".json"){ - auto json = std::string(bytes.begin(),bytes.end()); - new_asset.data = JsonData {json}; - } - - assets[path] = new_asset; -} - -void RaylibAssetLoader::unload_asset(std::string path){ - if (!assets.contains(path)) return; - Asset asset = assets[path]; - - std::visit([](auto&& arg) { - using T = std::decay_t; - - if constexpr (std::is_same_v) { - Texture* tex = static_cast(arg.texture); - UnloadTexture(*tex); - delete tex; - arg.texture = nullptr; - } - else if constexpr (std::is_same_v) { - Sound* sound = static_cast(arg.sound); - UnloadSound(*sound); - delete sound; - arg.sound = nullptr; - } - else if constexpr (std::is_same_v) { - Music* music = static_cast(arg.music); - UnloadMusicStream(*music); - delete music; - arg.music = nullptr; - } - // JsonData requires no manual step because std::string cleans itself up! - }, asset.data); - - assets.erase(path); - -} - - -void RaylibAssetLoader::unload_all_assets(){ - std::vector assets_to_unload; - std::ranges::copy(std::views::keys(assets),std::back_inserter(assets_to_unload)); - for (const auto &path : assets_to_unload){ - unload_asset(path); - } -} - -Asset RaylibAssetLoader::get_asset(std::string path){ - if (assets.contains(path)){ - return assets[path]; - }else{ - return {}; - } -} - - -Texture* RaylibAssetLoader::get_texture(std::string path){ - Asset asset = get_asset(path); - if (auto* ptr = std::get_if(&asset.data)) { - return (Texture*)ptr->texture; - } - return nullptr; -} - -Sound* RaylibAssetLoader::get_sound(std::string path){ - Asset asset = get_asset(path); - if (auto* ptr = std::get_if(&asset.data)) { - return (Sound*)ptr->sound; - } - return nullptr; -} -Music* RaylibAssetLoader::get_music(std::string path){ - Asset asset = get_asset(path); - if (auto* ptr = std::get_if(&asset.data)) { - return (Music*)ptr->music; - } - return nullptr; -} - -std::string RaylibAssetLoader::get_json(std::string path){ - Asset asset = get_asset(path); - if (auto* ptr = std::get_if(&asset.data)) { - return ptr->json; - } - return "{}"; -} diff --git a/src/engine/asset/asset.cpp b/src/engine/asset/asset.cpp new file mode 100644 index 0000000..987aa9b --- /dev/null +++ b/src/engine/asset/asset.cpp @@ -0,0 +1,189 @@ +#include "engine/asset/asset.hpp" +#include "engine/asset/raylib-asset.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace fs = std::filesystem; + +// Helper to determine if the asset path implies streaming music +bool should_stream_as_music(const std::filesystem::path& asset_path) { + for (const auto& part : asset_path) { + if (part == "music" || part == "bgm") { + return true; + } + } + return false; +} + +namespace varicle { + + AssetLoader::AssetLoader(std::string asset_data) : asset_reader(asset_data){ + if (!asset_reader.load_index()){ + std::cerr << "Failed to load assets!!!" << std::endl; + } + } + + AssetReader AssetLoader::get_reader(){ + return asset_reader; + } + + RaylibAssetLoader::RaylibAssetLoader(std::string asset_data) : AssetLoader(asset_data) { + + } + + RaylibAssetLoader::~RaylibAssetLoader(){ + unload_all_assets(); + } + + + + void RaylibAssetLoader::load_asset(std::string path){ + fs::path file_path(path); + Asset new_asset; + new_asset.name = file_path.filename().string() ; + + // std::cout << file_path.extension() << std::endl; + auto bytes = get_reader().extract_asset(path); + + if (file_path.extension() == ".png"){ + Image img = LoadImageFromMemory(".png", bytes.data(), bytes.size()); + auto texture = LoadTextureFromImage(img); + UnloadImage(img); + new_asset.data = ImageData { new Texture(texture)}; + + + }else if(file_path.extension() == ".ogg"){ + + if (should_stream_as_music(file_path)){ + auto music = LoadMusicStreamFromMemory(".ogg",bytes.data(),bytes.size()); + new_asset.data = MusicData{new Music(music)}; + }else{ + auto wave = LoadWaveFromMemory(".ogg", bytes.data(),bytes.size()); + auto sound = LoadSoundFromWave(wave); + UnloadWave(wave); + new_asset.data = SoundData{new Sound(sound)}; + } + + } + else if(file_path.extension() == ".mp3"){ + if (should_stream_as_music(file_path)){ + auto music = LoadMusicStreamFromMemory(".mp3",bytes.data(),bytes.size()); + new_asset.data = MusicData{new Music(music)}; + }else{ + auto wave = LoadWaveFromMemory(".mp3", bytes.data(),bytes.size()); + auto sound = LoadSoundFromWave(wave); + UnloadWave(wave); + new_asset.data = SoundData{new Sound(sound)}; + } + + } + else if(file_path.extension() == ".wav"){ + if (should_stream_as_music(file_path)){ + auto music = LoadMusicStreamFromMemory(".wav",bytes.data(),bytes.size()); + new_asset.data = MusicData{new Music(music)}; + }else{ + auto wave = LoadWaveFromMemory(".wav", bytes.data(),bytes.size()); + auto sound = LoadSoundFromWave(wave); + UnloadWave(wave); + new_asset.data = SoundData{new Sound(sound)}; + } + } + + else if(file_path.extension() == ".json"){ + auto json = std::string(bytes.begin(),bytes.end()); + new_asset.data = JsonData {json}; + } + + assets[path] = new_asset; + } + + void RaylibAssetLoader::unload_asset(std::string path){ + if (!assets.contains(path)) return; + Asset asset = assets[path]; + + std::visit([](auto&& arg) { + using T = std::decay_t; + + if constexpr (std::is_same_v) { + Texture* tex = static_cast(arg.texture); + UnloadTexture(*tex); + delete tex; + arg.texture = nullptr; + } + else if constexpr (std::is_same_v) { + Sound* sound = static_cast(arg.sound); + UnloadSound(*sound); + delete sound; + arg.sound = nullptr; + } + else if constexpr (std::is_same_v) { + Music* music = static_cast(arg.music); + UnloadMusicStream(*music); + delete music; + arg.music = nullptr; + } + // JsonData requires no manual step because std::string cleans itself up! + }, asset.data); + + assets.erase(path); + + } + + + void RaylibAssetLoader::unload_all_assets(){ + std::vector assets_to_unload; + std::ranges::copy(std::views::keys(assets),std::back_inserter(assets_to_unload)); + for (const auto &path : assets_to_unload){ + unload_asset(path); + } + } + + Asset RaylibAssetLoader::get_asset(std::string path){ + if (assets.contains(path)){ + return assets[path]; + }else{ + return {}; + } + } + + + Texture* RaylibAssetLoader::get_texture(std::string path){ + Asset asset = get_asset(path); + if (auto* ptr = std::get_if(&asset.data)) { + return (Texture*)ptr->texture; + } + return nullptr; + } + + Sound* RaylibAssetLoader::get_sound(std::string path){ + Asset asset = get_asset(path); + if (auto* ptr = std::get_if(&asset.data)) { + return (Sound*)ptr->sound; + } + return nullptr; + } + Music* RaylibAssetLoader::get_music(std::string path){ + Asset asset = get_asset(path); + if (auto* ptr = std::get_if(&asset.data)) { + return (Music*)ptr->music; + } + return nullptr; + } + + std::string RaylibAssetLoader::get_json(std::string path){ + Asset asset = get_asset(path); + if (auto* ptr = std::get_if(&asset.data)) { + return ptr->json; + } + return "{}"; + } +} diff --git a/src/engine/asset/asset.hpp b/src/engine/asset/asset.hpp new file mode 100644 index 0000000..4b91f0b --- /dev/null +++ b/src/engine/asset/asset.hpp @@ -0,0 +1,54 @@ +#pragma once +#include + +#include +#include +#include + + + +namespace varicle { + + struct ImageData { + void* texture; + }; + + struct SoundData { + void* sound; + }; + + struct MusicData { + void* music; + }; + + struct JsonData { + std::string json; + }; + + struct Asset { + std::string name; + std::variant data; + }; + + + class AssetLoader{ + + private: + AssetReader asset_reader; + + protected: + std::unordered_map assets; + virtual void load_all_assets(std::string data_path) = 0; + virtual void unload_all_assets() = 0; + + public: + AssetLoader(std::string asset_data); + ~AssetLoader() = default; + virtual void load_asset(std::string path) = 0; + virtual void unload_asset(std::string path) = 0; + virtual Asset get_asset(std::string path) = 0;; + AssetReader get_reader(); + + }; + +} diff --git a/src/engine/asset/raylib-asset.hpp b/src/engine/asset/raylib-asset.hpp new file mode 100644 index 0000000..c23b9a8 --- /dev/null +++ b/src/engine/asset/raylib-asset.hpp @@ -0,0 +1,35 @@ +#pragma once +// #include "asset_packer/asset.hpp" +#include "engine/asset/asset.hpp" +#include + +namespace varicle { + + + class RaylibAssetLoader : public AssetLoader{ + protected: + void load_all_assets(std::string asset_list) override {}; + void unload_all_assets() override; + + public: + RaylibAssetLoader(std::string asset_data = "data.dat"); + ~RaylibAssetLoader(); + + + void load_asset(std::string path) override; + void unload_asset(std::string path) override; + Asset get_asset(std::string path) override; + + Texture* get_texture(std::string path); + Sound* get_sound(std::string path); + Music* get_music(std::string path); + std::string get_json(std::string path); + + }; + + + // extern RaylibAssetLoader asset_loader; + + + +} diff --git a/src/engine/core/application.cpp b/src/engine/core/application.cpp new file mode 100644 index 0000000..3fe3ef7 --- /dev/null +++ b/src/engine/core/application.cpp @@ -0,0 +1,86 @@ +// src/engine/core/application.cpp + +#include "engine/core/application.hpp" +#include "engine/core/service-locator.hpp" +#include "engine/asset/raylib-asset.hpp" + +#include "engine/scene/scene.hpp" +#include "raylib.h" +#include "rlImGui.h" +#include + + +#ifdef __EMSCRIPTEN__ +#include +#endif + +namespace varicle { + + void game_loop(void){ + + auto& scene_manager = ServiceLocator::get(); + + float dt = GetFrameTime(); + + // Update + scene_manager.update(dt); + + // Draw + BeginDrawing(); + ClearBackground(RAYWHITE); // Or a configurable engine default color + + scene_manager.render(); + + rlImGuiBegin(); + scene_manager.ui(); + rlImGuiEnd(); + + EndDrawing(); + + scene_manager.process_scene_switch(); + } + + void Application::run() { + // 1. Initialize Raylib + SetTraceLogLevel(LOG_NONE); + SetConfigFlags(FLAG_VSYNC_HINT); + InitWindow(m_window_width, m_window_height, m_window_title); + SetTargetFPS(60); + rlImGuiSetup(true); // initialize gui + + ServiceLocator::provide(std::make_unique()); + ServiceLocator::provide(std::make_unique()); + + // 2. Call game-specific startup (where the game creates its first scene) + on_init(); + + auto& scene_manager = ServiceLocator::get(); + + +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(game_loop, 0, 1); +#else + while (!scene_manager.should_game_close()){ + game_loop(); + } +#endif + + // 4. Call game-specific cleanup + on_shutdown(); + + ServiceLocator::shutdown(); // Clean up services + + // 5. Close Raylib + rlImGuiShutdown(); + CloseWindow(); + } + + void Application::change_scene(std::string scene_id) { + ServiceLocator::get().switch_to_scene(scene_id); + } + + void Application::quit() { + ServiceLocator::get().quit(); + } + +} diff --git a/src/engine/core/application.hpp b/src/engine/core/application.hpp new file mode 100644 index 0000000..badd20b --- /dev/null +++ b/src/engine/core/application.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "engine/scene/scene.hpp" + +#include "raylib.h" + +namespace varicle { + + class Application{ + + // Window configuration variables that a derived game can tweak in its constructor + int m_window_width = 1280; + int m_window_height = 720; + const char* m_window_title = "My Raylib Engine Game"; + + public: + Application() = default; + virtual ~Application() = default; + + virtual void on_init() = 0; + virtual void on_shutdown() = 0; + + void run(); + void change_scene(std::string scene_id); + void quit(); + + + }; +} diff --git a/src/include/engine_variant.hpp b/src/engine/core/engine_variant.hpp similarity index 97% rename from src/include/engine_variant.hpp rename to src/engine/core/engine_variant.hpp index f4849d8..d80bf74 100644 --- a/src/include/engine_variant.hpp +++ b/src/engine/core/engine_variant.hpp @@ -1,109 +1,109 @@ -#pragma once -#include -#include -#include -#include - -struct Vec2 { - float x = 0.0f; - float y = 0.0f; - - bool operator==(const Vec2& o) const { return x == o.x && y == o.y; } - bool operator!=(const Vec2& o) const { return !(*this == o); } - Vec2 operator+(const Vec2& o) const { return { x + o.x, y + o.y }; } - Vec2 operator-(const Vec2& o) const { return { x - o.x, y - o.y }; } - Vec2 operator*(float scalar) const { return { x * scalar, y * scalar }; } -}; - -struct Vec3 { - float x = 0.0f; - float y = 0.0f; - float z = 0.0f; - - bool operator==(const Vec3& o) const { return x == o.x && y == o.y && z == o.z; } - bool operator!=(const Vec3& o) const { return !(*this == o); } - Vec3 operator+(const Vec3& o) const { return { x + o.x, y + o.y, z + o.z }; } - Vec3 operator-(const Vec3& o) const { return { x - o.x, y - o.y, z - o.z }; } - Vec3 operator*(float scalar) const { return { x * scalar, y * scalar, z * scalar }; } -}; - -struct Vec4 { - float x = 0.0f; - float y = 0.0f; - float z = 0.0f; - float w = 1.0f; - - bool operator==(const Vec4& o) const { return x == o.x && y == o.y && z == o.z && w == o.w; } - bool operator!=(const Vec4& o) const { return !(*this == o); } - Vec4 operator+(const Vec4& o) const { return { x + o.x, y + o.y, z + o.z, w + o.w }; } - Vec4 operator-(const Vec4& o) const { return { x - o.x, y - o.y, z - o.z, w - o.w }; } - Vec4 operator*(float scalar) const { return { x * scalar, y * scalar, z * scalar, w * scalar }; } -}; - - -// Standalone Interpolation Helpers -inline Vec2 Vec2Lerp(const Vec2& s, const Vec2& e, float a) { return { s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a }; } -inline Vec3 Vec3Lerp(const Vec3& s, const Vec3& e, float a) { return { s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, s.z + (e.z - s.z) * a }; } -inline Vec4 Vec4Lerp(const Vec4& s, const Vec4& e, float a) { return { s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, s.z + (e.z - s.z) * a, s.w + (e.w - s.w) * a }; } - - - - -enum class VariantType { Null, Float, Vector2, Vector3, Vector4, String }; - -class EngineVariant{ - - public: - using InternalVariant = std::variant; - - EngineVariant() : data(std::monostate{}), type(VariantType::Null){} - EngineVariant(float v) : data(v), type(VariantType::Float){} - EngineVariant(Vec2 v) : data(v), type(VariantType::Vector2){} - EngineVariant(Vec3 v) : data(v), type(VariantType::Vector3){} - EngineVariant(Vec4 v) : data(v), type(VariantType::Vector4){} - EngineVariant(std::string v) : data(v), type(VariantType::String){} - - VariantType GetType() const { return type; } - - template - T Get() const { - std::lock_guard lock(v_mutex); - return std::get(data); - } - - void Print() const { - - std::lock_guard lock(v_mutex); - std::cout << "[Variant " << TypeToString(type) << "]: "; - std::visit([](auto &&arg){ - using T = std::decay_t; - if constexpr (std::is_same_v) std::cout << "Null"; - else if constexpr (std::is_same_v) std::cout << arg; - else if constexpr (std::is_same_v) std::cout << "(" << arg.x << ", " << arg.y << ")"; - else if constexpr (std::is_same_v) std::cout << "(" << arg.x << ", " << arg.y << ", " << arg.z << ")"; - else if constexpr (std::is_same_v) std::cout << "(" << arg.x << ", " << arg.y << ", " << arg.z << ", " << arg.w << ")"; - else if constexpr (std::is_same_v) std::cout << "\"" << arg << "\""; - - },data); - - std::cout << "\n"; - } - - private: - InternalVariant data; - VariantType type; - mutable std::mutex v_mutex; - - static std::string TypeToString(VariantType t) { - switch(t) { - case VariantType::Float: return "Float"; - case VariantType::Vector2: return "Vector2"; - case VariantType::Vector3: return "Vector3"; - case VariantType::Vector4: return "Vector4"; - case VariantType::String: return "String"; - default: return "Null"; - } - } - - friend class VariantOpManager; -}; +#pragma once +#include +#include +#include +#include + +struct Vec2 { + float x = 0.0f; + float y = 0.0f; + + bool operator==(const Vec2& o) const { return x == o.x && y == o.y; } + bool operator!=(const Vec2& o) const { return !(*this == o); } + Vec2 operator+(const Vec2& o) const { return { x + o.x, y + o.y }; } + Vec2 operator-(const Vec2& o) const { return { x - o.x, y - o.y }; } + Vec2 operator*(float scalar) const { return { x * scalar, y * scalar }; } +}; + +struct Vec3 { + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + + bool operator==(const Vec3& o) const { return x == o.x && y == o.y && z == o.z; } + bool operator!=(const Vec3& o) const { return !(*this == o); } + Vec3 operator+(const Vec3& o) const { return { x + o.x, y + o.y, z + o.z }; } + Vec3 operator-(const Vec3& o) const { return { x - o.x, y - o.y, z - o.z }; } + Vec3 operator*(float scalar) const { return { x * scalar, y * scalar, z * scalar }; } +}; + +struct Vec4 { + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + float w = 1.0f; + + bool operator==(const Vec4& o) const { return x == o.x && y == o.y && z == o.z && w == o.w; } + bool operator!=(const Vec4& o) const { return !(*this == o); } + Vec4 operator+(const Vec4& o) const { return { x + o.x, y + o.y, z + o.z, w + o.w }; } + Vec4 operator-(const Vec4& o) const { return { x - o.x, y - o.y, z - o.z, w - o.w }; } + Vec4 operator*(float scalar) const { return { x * scalar, y * scalar, z * scalar, w * scalar }; } +}; + + +// Standalone Interpolation Helpers +inline Vec2 Vec2Lerp(const Vec2& s, const Vec2& e, float a) { return { s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a }; } +inline Vec3 Vec3Lerp(const Vec3& s, const Vec3& e, float a) { return { s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, s.z + (e.z - s.z) * a }; } +inline Vec4 Vec4Lerp(const Vec4& s, const Vec4& e, float a) { return { s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, s.z + (e.z - s.z) * a, s.w + (e.w - s.w) * a }; } + + + + +enum class VariantType { Null, Float, Vector2, Vector3, Vector4, String }; + +class EngineVariant{ + + public: + using InternalVariant = std::variant; + + EngineVariant() : data(std::monostate{}), type(VariantType::Null){} + EngineVariant(float v) : data(v), type(VariantType::Float){} + EngineVariant(Vec2 v) : data(v), type(VariantType::Vector2){} + EngineVariant(Vec3 v) : data(v), type(VariantType::Vector3){} + EngineVariant(Vec4 v) : data(v), type(VariantType::Vector4){} + EngineVariant(std::string v) : data(v), type(VariantType::String){} + + VariantType GetType() const { return type; } + + template + T Get() const { + std::lock_guard lock(v_mutex); + return std::get(data); + } + + void Print() const { + + std::lock_guard lock(v_mutex); + std::cout << "[Variant " << TypeToString(type) << "]: "; + std::visit([](auto &&arg){ + using T = std::decay_t; + if constexpr (std::is_same_v) std::cout << "Null"; + else if constexpr (std::is_same_v) std::cout << arg; + else if constexpr (std::is_same_v) std::cout << "(" << arg.x << ", " << arg.y << ")"; + else if constexpr (std::is_same_v) std::cout << "(" << arg.x << ", " << arg.y << ", " << arg.z << ")"; + else if constexpr (std::is_same_v) std::cout << "(" << arg.x << ", " << arg.y << ", " << arg.z << ", " << arg.w << ")"; + else if constexpr (std::is_same_v) std::cout << "\"" << arg << "\""; + + },data); + + std::cout << "\n"; + } + + private: + InternalVariant data; + VariantType type; + mutable std::mutex v_mutex; + + static std::string TypeToString(VariantType t) { + switch(t) { + case VariantType::Float: return "Float"; + case VariantType::Vector2: return "Vector2"; + case VariantType::Vector3: return "Vector3"; + case VariantType::Vector4: return "Vector4"; + case VariantType::String: return "String"; + default: return "Null"; + } + } + + friend class VariantOpManager; +}; diff --git a/src/include/engine_variant_operation.hpp b/src/engine/core/engine_variant_operation.hpp similarity index 97% rename from src/include/engine_variant_operation.hpp rename to src/engine/core/engine_variant_operation.hpp index db02cd9..9216ecb 100644 --- a/src/include/engine_variant_operation.hpp +++ b/src/engine/core/engine_variant_operation.hpp @@ -1,74 +1,74 @@ -#pragma once - -#include - -template struct overloaded : Ts... { using Ts::operator()...; }; -template overloaded(Ts...) -> overloaded; - -enum class OpType { - Assign, // Replace the old value entirely - Add, // Add to the current value - Multiply, // Add to the current value - Lerp // Smoothly blend toward a value -}; - -struct VariantOpRequest { - EngineVariant* target; // The variable we want to change - OpType operation; // How we want to change it - EngineVariant operand; // The value we are using to make the change - float alpha; // Used ONLY for Lerp (0.0 to 1.0) -}; - -class VariantOpManager{ - - public: - VariantOpManager(){} - void ExecuteOperation(const VariantOpRequest& req) { - - if (req.target == nullptr) return; - - switch (req.operation){ - - case OpType::Assign: - req.target->data = req.operand.data; - req.target->type = req.operand.type; - break; - case OpType::Add: - req.target->data = std::visit( - overloaded{ - [](float p, float n) -> EngineVariant::InternalVariant {return p + n;}, - [](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant {return p + n;}, - [](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant {return p + n;}, - [](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant {return p + n;}, - - // Fallback - [](auto p, auto n) -> EngineVariant::InternalVariant {return p;}, - },req.target->data,req.operand.data); - break; - - case OpType::Lerp: - req.target->data = std::visit(overloaded{ - [&](float p, float n) -> EngineVariant::InternalVariant { return p + (n - p) * req.alpha; }, - [&](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant { return Vec2Lerp(p, n, req.alpha); }, - [&](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant { return Vec3Lerp(p, n, req.alpha); }, - [&](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant { return Vec4Lerp(p, n, req.alpha); }, - [&](const std::string& p, const std::string& n) -> EngineVariant::InternalVariant { - return req.alpha >= 0.5f ? n : p; // Discrete switch for strings - }, - - // Fallback - [](auto p, auto n) -> EngineVariant::InternalVariant { return p; } - }, req.target->data, req.operand.data); - break; - - case OpType::Multiply: - req.target->data = std::visit(overloaded{ - [](float p, float n) -> EngineVariant::InternalVariant { return p * n; }, - [](Vec2 p, float n) -> EngineVariant::InternalVariant { return p * n; }, // Scale a vector! - [](auto p, auto n) -> EngineVariant::InternalVariant { return p; } - }, req.target->data, req.operand.data); - break; - } - - } -}; +#pragma once + +#include + +template struct overloaded : Ts... { using Ts::operator()...; }; +template overloaded(Ts...) -> overloaded; + +enum class OpType { + Assign, // Replace the old value entirely + Add, // Add to the current value + Multiply, // Add to the current value + Lerp // Smoothly blend toward a value +}; + +struct VariantOpRequest { + EngineVariant* target; // The variable we want to change + OpType operation; // How we want to change it + EngineVariant operand; // The value we are using to make the change + float alpha; // Used ONLY for Lerp (0.0 to 1.0) +}; + +class VariantOpManager{ + + public: + VariantOpManager(){} + void ExecuteOperation(const VariantOpRequest& req) { + + if (req.target == nullptr) return; + + switch (req.operation){ + + case OpType::Assign: + req.target->data = req.operand.data; + req.target->type = req.operand.type; + break; + case OpType::Add: + req.target->data = std::visit( + overloaded{ + [](float p, float n) -> EngineVariant::InternalVariant {return p + n;}, + [](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant {return p + n;}, + [](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant {return p + n;}, + [](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant {return p + n;}, + + // Fallback + [](auto p, auto n) -> EngineVariant::InternalVariant {return p;}, + },req.target->data,req.operand.data); + break; + + case OpType::Lerp: + req.target->data = std::visit(overloaded{ + [&](float p, float n) -> EngineVariant::InternalVariant { return p + (n - p) * req.alpha; }, + [&](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant { return Vec2Lerp(p, n, req.alpha); }, + [&](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant { return Vec3Lerp(p, n, req.alpha); }, + [&](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant { return Vec4Lerp(p, n, req.alpha); }, + [&](const std::string& p, const std::string& n) -> EngineVariant::InternalVariant { + return req.alpha >= 0.5f ? n : p; // Discrete switch for strings + }, + + // Fallback + [](auto p, auto n) -> EngineVariant::InternalVariant { return p; } + }, req.target->data, req.operand.data); + break; + + case OpType::Multiply: + req.target->data = std::visit(overloaded{ + [](float p, float n) -> EngineVariant::InternalVariant { return p * n; }, + [](Vec2 p, float n) -> EngineVariant::InternalVariant { return p * n; }, // Scale a vector! + [](auto p, auto n) -> EngineVariant::InternalVariant { return p; } + }, req.target->data, req.operand.data); + break; + } + + } +}; diff --git a/src/engine/core/service-locator.hpp b/src/engine/core/service-locator.hpp new file mode 100644 index 0000000..6ab3c83 --- /dev/null +++ b/src/engine/core/service-locator.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace varicle{ + + class ServiceLocator{ + private: + + // generic storage + struct ServiceContainerBase { + virtual ~ServiceContainerBase() = default; + }; + + template + struct ServiceContainer : public ServiceContainerBase { + std::unique_ptr instance; + ServiceContainer(std::unique_ptr inst) : instance(std::move(inst)) {} + }; + + + static inline std::unordered_map> s_services; + + // Track registration order to ensure safe LIFO destruction + static inline std::vector s_registration_order; + + public: + // Wrap and pass ownership of a unique_ptr to the locator + template + static void provide(std::unique_ptr service) { + s_services[typeid(T)] = std::make_unique>(std::move(service)); + } + + template + static T& get(){ + auto it = s_services.find(typeid(T)); + + assert( it != s_services.end() && "Requested service was never provided!"); + + // Cast the container back, take a peek inside the container and send the address of the reference + // auto container = static_cast >(it->second); + + auto* container = static_cast*>(it->second.get()); + return *(container->instance); + } + + // Explicitly destroy a specific service + template + static void remove() { + s_services.erase(typeid(T)); // Automatically calls the destructor of T! + auto it = std::find(s_registration_order.begin(), s_registration_order.end(), typeid(T)); + if (it != s_registration_order.end()) s_registration_order.erase(it); + } + + static inline void shutdown(){ + for (auto it = s_registration_order.rbegin(); it != s_registration_order.rend(); ++it) { + s_services.erase(*it); + } + s_registration_order.clear(); + s_services.clear(); + } + }; +}; diff --git a/src/engine/ecs/components.hpp b/src/engine/ecs/components.hpp new file mode 100644 index 0000000..45845b9 --- /dev/null +++ b/src/engine/ecs/components.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace varicle{ + + struct Position{ + float x; + float y; + }; + + struct Velocity{ + float dx; + float dy; + }; + + struct Sprite{ + Texture *texture; + float offset_x; + float offset_y; + float width; + float height; + bool flip_h; + bool flip_v; + float rotation; + }; + +} diff --git a/src/engine/render/render-system.cpp b/src/engine/render/render-system.cpp new file mode 100644 index 0000000..d9d1c15 --- /dev/null +++ b/src/engine/render/render-system.cpp @@ -0,0 +1,50 @@ +#include "engine/render/render-system.hpp" +#include "engine/ecs/components.hpp" + +#include +#include + +namespace varicle { + + void update_render_system(entt::registry ®istry){ + auto view = registry.view(); + + for (entt::entity entity : view){ + const Sprite &sprite = view.get(entity); + const Position &pos = view.get(entity); + + if (sprite.texture){ + DrawTexturePro( + *(sprite.texture), + Rectangle{ + 0, + 0, + (float)sprite.texture->width, + (float)sprite.texture->height, + }, + Rectangle { + sprite.offset_x + pos.x, + sprite.offset_y + pos.y, + sprite.width, + sprite.height + }, + Vector2 {sprite.width * 0.5f, sprite.height*0.5f}, + sprite.rotation, + WHITE); + + }else{ + DrawRectanglePro(Rectangle { + sprite.offset_x + pos.x, + sprite.offset_y + pos.y, + sprite.width, + sprite.height + }, + Vector2 {sprite.width * 0.5f, sprite.height*0.5f}, + sprite.rotation, + PURPLE + ); + } + } + + } +} diff --git a/src/engine/render/render-system.hpp b/src/engine/render/render-system.hpp new file mode 100644 index 0000000..3577a25 --- /dev/null +++ b/src/engine/render/render-system.hpp @@ -0,0 +1,8 @@ +#pragma once +#include +#include + +namespace varicle { + + void update_render_system(entt::registry ®istry); +} diff --git a/src/engine/scene/scene.cpp b/src/engine/scene/scene.cpp new file mode 100644 index 0000000..180ceb4 --- /dev/null +++ b/src/engine/scene/scene.cpp @@ -0,0 +1,65 @@ +#include "raylib.h" +#include "engine/scene/scene.hpp" + +namespace varicle { + + + SceneManager::SceneManager(){ + // current_scene = std::make_unique(); + } + + SceneManager::~SceneManager(){ + // delete current_scene; + } + + Scene& SceneManager::get_current_scene(){ + return *current_scene; + } + + void SceneManager::process_scene_switch(){ + + if (next_scene_id.empty()) return; + + auto it = scene_registry.find(next_scene_id); + if (it != scene_registry.end()){ + + current_scene.reset(); + current_scene = it->second(); + current_scene->init(); + } + + + next_scene_id.clear(); + } + + void SceneManager::update(float dt){ + if (!current_scene) return; + current_scene->update(dt); + } + + void SceneManager::render(){ + if (!current_scene) return; + current_scene->render(); + } + + void SceneManager::ui(){ + if (!current_scene) return; + current_scene->ui(); + } + + bool SceneManager::should_game_close(){ + return should_quit || WindowShouldClose(); + } + + void SceneManager::switch_to_scene(std::string scene_id){ + next_scene_id = scene_id; + } + + void SceneManager::register_scene(std::string scene_id, SceneFactory factory){ + scene_registry[std::string(scene_id)] = factory; + } + + void SceneManager::quit(){ + should_quit = true; + } +} diff --git a/src/engine/scene/scene.hpp b/src/engine/scene/scene.hpp new file mode 100644 index 0000000..a4aea9d --- /dev/null +++ b/src/engine/scene/scene.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include + +#include +#include + +namespace varicle { + + + // enum class SceneType{ + // MENU, + // GAMEPLAY + // }; + // + + + class Scene{ + + public: + Scene() = default; + virtual ~Scene() = default; + + virtual void init() = 0; + virtual void update(float dt) = 0; + virtual void render() = 0; + virtual void ui() = 0; + }; + + // class GamePlayScene : public Scene{ + // + // private: + // entt::registry registry; + // + // public: + // GamePlayScene(); + // ~GamePlayScene(); + // + // void update(float dt) override; + // void render() override; + // void ui() override; + // + // }; + // + // class MenuScene : public Scene{ + // + // public: + // MenuScene(); + // ~MenuScene() = default; + // + // void update(float dt) override; + // void render() override; + // void ui() override; + // + // }; + + class SceneManager{ + private: + using SceneFactory = std::function()>; + std::unordered_map scene_registry; + + std::unique_ptr current_scene = nullptr; + std::string next_scene_id; + bool pending_switch = false; + bool should_quit = false; + + public: + + SceneManager(); + ~SceneManager(); + + void update(float dt); + void render(); + void ui(); + void process_scene_switch(); + bool should_game_close(); + void switch_to_scene(std::string scene_id); + void register_scene(std::string scene_id, SceneFactory factory); + void quit(); + Scene& get_current_scene(); + }; +} diff --git a/src/include/math_util.hpp b/src/engine/util/math_util.hpp similarity index 93% rename from src/include/math_util.hpp rename to src/engine/util/math_util.hpp index 5848c78..23066ea 100644 --- a/src/include/math_util.hpp +++ b/src/engine/util/math_util.hpp @@ -1,21 +1,22 @@ -#pragma once - -#include - -namespace Math { - // Generate a random float between min and max - inline float RandomRange(float min, float max) { - static std::random_device rd; - static std::mt19937 gen(rd()); - std::uniform_real_distribution dist(min, max); - return dist(gen); - } - - // Generate a random int between min and max - inline int RandomRange(int min, int max) { - static std::random_device rd; - static std::mt19937 gen(rd()); - std::uniform_int_distribution dist(min, max); - return dist(gen); - } -} +#pragma once + +#include + + +namespace varicle { + // Generate a random float between min and max + inline float RandomRange(float min, float max) { + static std::random_device rd; + static std::mt19937 gen(rd()); + std::uniform_real_distribution dist(min, max); + return dist(gen); + } + + // Generate a random int between min and max + inline int RandomRange(int min, int max) { + static std::random_device rd; + static std::mt19937 gen(rd()); + std::uniform_int_distribution dist(min, max); + return dist(gen); + } +} diff --git a/src/fruit.cpp b/src/fruit.cpp deleted file mode 100644 index 577b16b..0000000 --- a/src/fruit.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// src\fruit.cpp -#include - -#include -#include -#include -#include - -#include -#include -// #include - -entt::entity fruit; - - -// File Base Helper Function -Position get_player_position(entt::registry& registry){ - auto player_view = registry.view(); - if (player_view.empty()) return {}; - - entt::entity player_entity = player_view.front(); - return registry.get(player_entity); -} -void change_position(Position& pos){ - pos.x = Math::RandomRange(30, GetScreenWidth()-30); - pos.y = Math::RandomRange(30, GetScreenHeight()-30); -}; - - - -void create_fruit(entt::registry& registry,Texture* texture){ - const auto entity = registry.create(); - registry.emplace(entity,100.0f,0.0f); - registry.emplace(entity); - registry.emplace(entity,texture,0.0f,0.0f,30.f,30.0f,false,false,0.0f); -} - -void update_fruit_system(entt::registry& registry,float dt){ - - auto view = registry.view(); - const Position player_pos = get_player_position(registry); - - for (entt::entity entity : view){ - Position& pos = view.get(entity); - if (abs(pos.x - player_pos.x) < 35 && abs(pos.y - player_pos.y) < 35 ){ - change_position(pos); - } - } -} - diff --git a/src/game/ecs/components.hpp b/src/game/ecs/components.hpp new file mode 100644 index 0000000..995b830 --- /dev/null +++ b/src/game/ecs/components.hpp @@ -0,0 +1,7 @@ +#pragma once + +struct Player{}; +struct PlayerBody{ unsigned int idx;}; + +struct Fruit{}; + diff --git a/src/game/main.cpp b/src/game/main.cpp new file mode 100644 index 0000000..a23bad1 --- /dev/null +++ b/src/game/main.cpp @@ -0,0 +1,34 @@ + +#include "engine/core/application.hpp" +#include "engine/core/service-locator.hpp" +#include "engine/scene/scene.hpp" + +#include "game/scenes/main-scene/main-scene.hpp" +#include "game/scenes/menu-scene/menu.hpp" + +#include + + + +class Game : public varicle::Application{ + + public: + void on_init() override { + auto& scene_manager = varicle::ServiceLocator::get(); + scene_manager.register_scene("main", []() { return std::make_unique(); }); + + scene_manager.register_scene("menu", []() { return std::make_unique(); }); + + change_scene("menu"); + } + + void on_shutdown() override { + } + +}; + +int main(){ + Game game; + game.run(); + return 0; +} diff --git a/src/game/scenes/main-scene/body.cpp b/src/game/scenes/main-scene/body.cpp new file mode 100644 index 0000000..75b9f6a --- /dev/null +++ b/src/game/scenes/main-scene/body.cpp @@ -0,0 +1,67 @@ + +#include "body.hpp" + +#include "engine/ecs/components.hpp" +#include "game/ecs/components.hpp" +#include "engine/asset/raylib-asset.hpp" +#include "engine/core/service-locator.hpp" + +#include +#include +#include + +namespace v = varicle; + +void create_body(entt::registry& registry,unsigned int idx){ + auto& asset_loader = v::ServiceLocator::get(); + auto body_texture = asset_loader.get_texture("assets/snake_body.png"); + const auto entity = registry.create(); + registry.emplace(entity,-10000.0f,-10000.0f); + registry.emplace(entity,idx); + registry.emplace(entity,body_texture,0.0f,0.0f,70.0f,70.0f,false,false,0.0f); +} + +void BodyManager::add_body(entt::registry& registry) +{ + create_body(registry,parts_position_stack.size()); + parts_position_stack.push_back( v::Position{}); +} + +void BodyManager::pop_body(){ + parts_position_stack.pop_back(); +} + +void BodyManager::update_body_positions(v::Position player_head_position){ + if (parts_position_stack.size() >= 2){ + for ( auto i = parts_position_stack.size()-1; i > 0 ;i--){ + parts_position_stack[i] = parts_position_stack[i-1]; + } + } + + if (parts_position_stack.size() >= 1){ + parts_position_stack[0] = player_head_position; + } +} + +v::Position BodyManager::get_body_position(unsigned int part_idx){ + return parts_position_stack[part_idx]; +} + + +void update_body_system(entt::registry& registry){ + + auto& body_manager = v::ServiceLocator::get(); + auto player_view = registry.view(); + auto player_entity = player_view.front(); + if (player_entity == entt::null) return; + + body_manager.update_body_positions(player_view.get(player_entity)); + + auto body_view = registry.view(); + + body_view.each([&body_manager](const auto entity, const PlayerBody& pb, v::Position& pos){ + auto new_pos = body_manager.get_body_position(pb.idx); + pos.x = new_pos.x; + pos.y = new_pos.y; + }); +} diff --git a/src/game/scenes/main-scene/body.hpp b/src/game/scenes/main-scene/body.hpp new file mode 100644 index 0000000..8299e26 --- /dev/null +++ b/src/game/scenes/main-scene/body.hpp @@ -0,0 +1,26 @@ +#pragma once + +// #include "game/ecs/components.hpp" +#include "engine/ecs/components.hpp" + +#include +#include +#include + +namespace v = varicle; +class BodyManager{ + private: + std::vector parts_position_stack = {}; + public: + Texture* body_texture; + BodyManager() = default; + ~BodyManager() = default; + + void add_body(entt::registry& registry); + void pop_body(); + void update_body_positions(v::Position player_head_position); + v::Position get_body_position(unsigned int part_idx); +}; + +void create_body(entt::registry& registry,unsigned int idx); +void update_body_system(entt::registry& registry); diff --git a/src/game/scenes/main-scene/fruit.cpp b/src/game/scenes/main-scene/fruit.cpp new file mode 100644 index 0000000..9235ae8 --- /dev/null +++ b/src/game/scenes/main-scene/fruit.cpp @@ -0,0 +1,57 @@ +#include "game/ecs/components.hpp" +#include "body.hpp" +#include "score-system.hpp" + +#include "engine/ecs/components.hpp" +#include "engine/util/math_util.hpp" +#include "engine/asset/raylib-asset.hpp" +#include "engine/core/service-locator.hpp" + +#include +#include + +namespace v = varicle ; + +void create_fruit(entt::registry& registry){ + auto& asset_loader = v::ServiceLocator::get(); + auto fruit_texture = asset_loader.get_texture("assets/fruit.png"); + + const auto entity = registry.create(); + registry.emplace(entity,640.0f,400.0f); + registry.emplace(entity,fruit_texture,0.0f,0.0f,30.f,30.0f,false,false,0.0f); + registry.emplace(entity); +} + +v::Position get_player_position(entt::registry& registry){ + auto player_view = registry.view(); + if (player_view.empty()) return {}; + + entt::entity player_entity = player_view.front(); + return registry.get(player_entity); +} + +void change_position(v::Position& pos){ + pos.x = varicle::RandomRange(30, GetScreenWidth()-30); + pos.y = varicle::RandomRange(30, GetScreenHeight()-30); +}; + + +void update_fruit_system(entt::registry& registry,float dt){ + + auto view = registry.view(); + const v::Position player_pos = get_player_position(registry); + + for (entt::entity entity : view){ + v::Position& pos = view.get(entity); + if (abs(pos.x - player_pos.x) < 35 && abs(pos.y - player_pos.y) < 35 ){ + + auto& score_system = v::ServiceLocator::get(); + auto& body_manager = v::ServiceLocator::get(); + body_manager.add_body(registry); + score_system.add_points(1); + + change_position(pos); + } + } +} + diff --git a/src/game/scenes/main-scene/fruit.hpp b/src/game/scenes/main-scene/fruit.hpp new file mode 100644 index 0000000..f8df195 --- /dev/null +++ b/src/game/scenes/main-scene/fruit.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + +void create_fruit(entt::registry& registry); +void update_fruit_system(entt::registry& registry,float dt); diff --git a/src/game/scenes/main-scene/main-scene.cpp b/src/game/scenes/main-scene/main-scene.cpp new file mode 100644 index 0000000..88cc6a1 --- /dev/null +++ b/src/game/scenes/main-scene/main-scene.cpp @@ -0,0 +1,73 @@ +#include "main-scene.hpp" +#include "fruit.hpp" +#include "player.hpp" +#include "body.hpp" + +#include "score-system.hpp" + +#include "engine/asset/raylib-asset.hpp" +#include "engine/core/service-locator.hpp" +#include "engine/render/render-system.hpp" +#include "engine/ecs/components.hpp" + +#include +#include + +#include +#include + +const float TICK_INTERVAL = 0.2f; + +namespace v = varicle; + + +void MainScene::init() { + v::ServiceLocator::provide(std::make_unique()); + v::ServiceLocator::provide(std::make_unique()); + + auto& asset_loader = v::ServiceLocator::get(); + asset_loader.load_asset("assets/snake_head.png"); + asset_loader.load_asset("assets/snake_body.png"); + asset_loader.load_asset("assets/fruit.png"); + + create_player(registry); + create_fruit(registry); +} + +void MainScene::update(float dt) { + update_player_system(registry,dt); + update_fruit_system(registry, dt); + + tick_timer += dt; + if (tick_timer >= TICK_INTERVAL) { + tick_timer -= TICK_INTERVAL; + update_body_system(registry); + update_movement_system(registry,dt); + } + +} + +void MainScene::render() { + v::update_render_system(registry); + + auto& score_system = v::ServiceLocator::get(); + DrawText(std::format("Score: {}",score_system.get_current_score()).c_str(),40,40,24,BLACK); +} + +void MainScene::ui() { + +} + +void update_movement_system(entt::registry& registry, float dt) { + using namespace varicle; + + // We get Position and Velocity, but EXCLUDE entities that have the Player tag + auto view = registry.view(); + + view.each([dt](Position &position, Velocity &velocity) { + // This will only run for pipes, enemies, or particles! + position.x += velocity.dx; + position.y += velocity.dy; + }); +} + diff --git a/src/game/scenes/main-scene/main-scene.hpp b/src/game/scenes/main-scene/main-scene.hpp new file mode 100644 index 0000000..26cb14f --- /dev/null +++ b/src/game/scenes/main-scene/main-scene.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "engine/scene/scene.hpp" + +#include + +class MainScene : public varicle::Scene { + private: + entt::registry registry; + float tick_timer = 0.0f; + + public: + void init() override; + void update(float dt) override; + void render() override; + void ui() override ; +}; + +void update_movement_system(entt::registry& registry, float dt); + diff --git a/src/game/scenes/main-scene/player.cpp b/src/game/scenes/main-scene/player.cpp new file mode 100644 index 0000000..6e50a3c --- /dev/null +++ b/src/game/scenes/main-scene/player.cpp @@ -0,0 +1,57 @@ + +#include "engine/ecs/components.hpp" +#include "engine/core/service-locator.hpp" +#include "engine/asset/raylib-asset.hpp" +#include "game/ecs/components.hpp" + +#include + +const float SPEED = 60.0f; + +void create_player(entt::registry ®istry){ + using namespace varicle; + + auto& asset_loader = ServiceLocator::get(); + auto player_texture = asset_loader.get_texture("assets/snake_head.png"); + + const auto entity = registry.create(); + registry.emplace(entity,100.0f,100.0f); + registry.emplace(entity,SPEED,0.0f); + registry.emplace(entity,player_texture,0.0f,0.0f,70.0f,70.0f,false,false,0.0f); + registry.emplace(entity); + +} + + + +void update_player_system(entt::registry& registry,float dt){ + using namespace varicle; + + auto view = registry.view(); + + // for (entt::entity entity : view){ + view.each([](const auto entity, const Position& pos, Velocity& vel, Sprite& sprite){ + + + if (IsKeyPressed(KEY_W) && vel.dy <= 0.0f){ + vel.dx = 0; + vel.dy = -SPEED; + } else if (IsKeyPressed(KEY_S) && vel.dy >= 0.0f){ + vel.dx = 0; + vel.dy = SPEED; + } else if (IsKeyPressed(KEY_A) && vel.dx <= 0.0f){ + vel.dx = -SPEED; + vel.dy = 0; + } else if (IsKeyPressed(KEY_D) && vel.dx >= 0.0f){ + vel.dx = SPEED; + vel.dy = 0; + } + + if (vel.dx != 0.0f || vel.dy != 0.0f) { + // atan2 returns radians. Convert to degrees if your renderer expects it! + float radians = std::atan2(vel.dy, vel.dx); + sprite.rotation = radians * (180.0f / 3.14159265f); + } + }); + +} diff --git a/src/game/scenes/main-scene/player.hpp b/src/game/scenes/main-scene/player.hpp new file mode 100644 index 0000000..caf4e28 --- /dev/null +++ b/src/game/scenes/main-scene/player.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include + +void create_player(entt::registry ®istry); +void update_player_system(entt::registry& registry,float dt); diff --git a/src/game/scenes/main-scene/score-system.hpp b/src/game/scenes/main-scene/score-system.hpp new file mode 100644 index 0000000..75b4d3b --- /dev/null +++ b/src/game/scenes/main-scene/score-system.hpp @@ -0,0 +1,15 @@ +#pragma once + +class ScoreSystem{ + private: + unsigned int current_score; + unsigned int high_score; + + public: + ScoreSystem() :current_score(0), high_score(0){} + int get_current_score(){return current_score;} + int get_high_score(){return high_score;} + void reset_score(){current_score = 0;} + void reset_high_score(){high_score = 0;} + void add_points(unsigned int points){ current_score +=points;} +}; diff --git a/src/scenes/menu_scene.cpp b/src/game/scenes/menu-scene/menu.cpp similarity index 77% rename from src/scenes/menu_scene.cpp rename to src/game/scenes/menu-scene/menu.cpp index ead46cc..541b7a8 100644 --- a/src/scenes/menu_scene.cpp +++ b/src/game/scenes/menu-scene/menu.cpp @@ -1,57 +1,54 @@ -#include "locator.hpp" -#include -#include -#include - -#include - -// #include - - -MenuScene::MenuScene() { -} - -void MenuScene::update(float dt) { -} - -void MenuScene::render() {} - -void MenuScene::ui() { - - // Get the current screen/viewport size - ImVec2 screen_size = ImGui::GetIO().DisplaySize; - - // size of button container - ImVec2 vbox_size = ImVec2(200.0f, 250.0f); - - // set next container to be center of the screen - ImVec2 screen_center = ImVec2(screen_size.x * 0.5f, screen_size.y * 0.5f); - ImGui::SetNextWindowPos(screen_center, ImGuiCond_Always,ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(vbox_size); - - // remove sub window decoration - ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground; - - ImGui::Begin("VBoxContainer", nullptr, flags); - - // set button width to be size fill container - ImVec2 button_size = ImVec2(ImGui::GetContentRegionAvail().x, 50.0f); - - // ImGui::SetCursorPos(centeredPos); - if (ImGui::Button("Play",button_size)){ - ServiceLocator::get_scene_manager().request_switch(SceneType::GAMEPLAY); - } - - ImGui::Dummy(ImVec2(0, 10)); // Gap - - if (ImGui::Button("Quit",button_size)){ - ServiceLocator::get_scene_manager().quit(); - } - - ImGui::End(); - - // ImGui::Begin("Debug"); - // ImGui::Button("Hello",button_size); - // ImGui::TextUnformatted(std::format("window size: {} {} ", screen_size.x,screen_size.y).c_str()); - // ImGui::End(); -} +#include "menu.hpp" + +#include "engine/core/service-locator.hpp" +#include "raylib.h" + +#include + +void MenuScene::init() {} + +void MenuScene::update(float dt) { +} + +void MenuScene::render() { +} + +void MenuScene::ui() { + + // Get the current screen/viewport size + ImVec2 screen_size = ImGui::GetIO().DisplaySize; + + // size of button container + ImVec2 vbox_size = ImVec2(200.0f, 250.0f); + + // set next container to be center of the screen + ImVec2 screen_center = ImVec2(screen_size.x * 0.5f, screen_size.y * 0.5f); + ImGui::SetNextWindowPos(screen_center, ImGuiCond_Always,ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(vbox_size); + + // remove sub window decoration + ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground; + + ImGui::Begin("VBoxContainer", nullptr, flags); + + // set button width to be size fill container + ImVec2 button_size = ImVec2(ImGui::GetContentRegionAvail().x, 50.0f); + + // ImGui::SetCursorPos(centeredPos); + if (ImGui::Button("Play",button_size)){ + v::ServiceLocator::get().switch_to_scene("main"); + } + + ImGui::Dummy(ImVec2(0, 10)); // Gap + + if (ImGui::Button("Quit",button_size)){ + v::ServiceLocator::get().quit(); + } + + ImGui::End(); + + // ImGui::Begin("Debug"); + // ImGui::Button("Hello",button_size); + // ImGui::TextUnformatted(std::format("window size: {} {} ", screen_size.x,screen_size.y).c_str()); + // ImGui::End(); +} diff --git a/src/game/scenes/menu-scene/menu.hpp b/src/game/scenes/menu-scene/menu.hpp new file mode 100644 index 0000000..0a6d01f --- /dev/null +++ b/src/game/scenes/menu-scene/menu.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "engine/scene/scene.hpp" + +namespace v = varicle; + +class MenuScene : public v::Scene{ + public: + void init() override; + void update(float dt) override; + void render() override; + void ui() override ; +}; diff --git a/src/include/animation.hpp b/src/include/animation.hpp deleted file mode 100644 index e66aa35..0000000 --- a/src/include/animation.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include - -class AnimationManager{ - private: - unsigned int glboal_id; - - public: - - -}; - -// Component attacked to an object for playing animation -struct AnimationComponent{ - unsigned int id; - std::string track_key; - float elapsed_time; - bool is_playing; - bool is_completed; - float speed_scale; - std::string group_name; -}; diff --git a/src/include/asset/asset.hpp b/src/include/asset/asset.hpp deleted file mode 100644 index 08ef308..0000000 --- a/src/include/asset/asset.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include - -#include -#include -#include - - - - - - -struct ImageData { - void* texture; -}; - -struct SoundData { - void* sound; -}; - -struct MusicData { - void* music; -}; - -struct JsonData { - std::string json; -}; - -struct Asset { - std::string name; - std::variant data; -}; - - -class AssetLoader{ - - private: - AssetReader asset_reader; - - protected: - std::unordered_map assets; - virtual void load_all_assets(std::string data_path) = 0; - virtual void unload_all_assets() = 0; - - public: - AssetLoader(std::string asset_data); - ~AssetLoader() = default; - virtual void load_asset(std::string path) = 0; - virtual void unload_asset(std::string path) = 0; - virtual Asset get_asset(std::string path) = 0;; - AssetReader get_reader(); - -}; - diff --git a/src/include/asset/raylib_asset.hpp b/src/include/asset/raylib_asset.hpp deleted file mode 100644 index f4b402b..0000000 --- a/src/include/asset/raylib_asset.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "asset_packer/asset.hpp" -#include -#include - -class RaylibAssetLoader : public AssetLoader{ - protected: - void load_all_assets(std::string asset_list) override {}; - void unload_all_assets() override; - - public: - RaylibAssetLoader(std::string asset_data = "data.dat"); - ~RaylibAssetLoader(); - - - void load_asset(std::string path) override; - void unload_asset(std::string path) override; - Asset get_asset(std::string path) override; - - Texture* get_texture(std::string path); - Sound* get_sound(std::string path); - Music* get_music(std::string path); - std::string get_json(std::string path); - -}; - - -// extern RaylibAssetLoader asset_loader; - - - diff --git a/src/include/components.hpp b/src/include/components.hpp deleted file mode 100644 index cc5e14c..0000000 --- a/src/include/components.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include - -struct Position{ - float x; - float y; -}; - -struct Velocity{ - float dx; - float dy; -}; - -struct Player{}; -struct PlayerBody{ - unsigned int part_idx; -}; - -struct Fruit{}; - -struct Sprite{ - Texture *texture; - float offset_x; - float offset_y; - float width; - float height; - bool flip_h; - bool flip_v; - float rotation; -}; diff --git a/src/include/fruit.hpp b/src/include/fruit.hpp deleted file mode 100644 index d0486c2..0000000 --- a/src/include/fruit.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include -#include - -void create_fruit(entt::registry& registry,Texture* texture); - -void update_fruit_system(entt::registry& registry,float dt); - diff --git a/src/include/locator.hpp b/src/include/locator.hpp deleted file mode 100644 index 76b5c0a..0000000 --- a/src/include/locator.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include - -// A simple Service Locator -class ServiceLocator { -private: - static inline SceneManager* s_scene_manager = nullptr; - static inline RaylibAssetLoader* s_asset_loader = nullptr; - - // static inline Configuration* s_config = nullptr; - - // static inline AssetManager* s_assets = nullptr; - -public: - static void provide(SceneManager* service) { s_scene_manager = service; } - static void provide(RaylibAssetLoader* service) { s_asset_loader = service; } - - static SceneManager& get_scene_manager() { return *s_scene_manager; } - static RaylibAssetLoader& get_asset_loader() { return *s_asset_loader; } - - // static SceneManager& get_config() { return *s_config; } - // static AssetManager& GetAssets() { return *s_assets; } -}; diff --git a/src/include/movement.hpp b/src/include/movement.hpp deleted file mode 100644 index 0b26b6d..0000000 --- a/src/include/movement.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -void update_movement_system(entt::registry& registry, float dt); diff --git a/src/include/player.hpp b/src/include/player.hpp deleted file mode 100644 index 807de39..0000000 --- a/src/include/player.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include - - -#include -#include - -void create_player(entt::registry& registry,Texture* texture); -void create_player_body(entt::registry& registry,Texture* texture,unsigned int idx); -void update_player_system(entt::registry& registry,float dt); - -class BodyManager{ - private: - std::vector parts_position_stack = {}; - public: - Texture* body_texture; - BodyManager(Texture* texture) : body_texture(texture){} - - void add_body(entt::registry& registry); - void pop_body(); - void update_body_positions(Position player_head_position); - Position get_body_position(unsigned int part_idx); -}; - diff --git a/src/include/render.hpp b/src/include/render.hpp deleted file mode 100644 index af27b16..0000000 --- a/src/include/render.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include - -void update_render_system(entt::registry ®istry); - diff --git a/src/include/scene.hpp b/src/include/scene.hpp deleted file mode 100644 index 6a59fc9..0000000 --- a/src/include/scene.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include - -#include -#include - -enum class SceneType{ - MENU, - GAMEPLAY -}; - - - -class Scene{ - - public: - Scene() = default; - virtual ~Scene() = default; - - virtual void update(float dt) = 0; - virtual void render() = 0; - virtual void ui() = 0; -}; - -class GamePlayScene : public Scene{ - - private: - entt::registry registry; - - public: - GamePlayScene(); - ~GamePlayScene(); - - void update(float dt) override; - void render() override; - void ui() override; - -}; - -class MenuScene : public Scene{ - - public: - MenuScene(); - ~MenuScene() = default; - - void update(float dt) override; - void render() override; - void ui() override; - -}; - -class SceneManager{ - private: - std::unique_ptr current_scene = nullptr; - SceneType next_scene_type; - bool pending_switch = false; - bool should_quit = false; - - public: - - SceneManager(); - ~SceneManager(); - - void update(float dt); - void render(); - void ui(); - void process_scene_switch(); - bool should_game_close(); - void request_switch(SceneType type); - void quit(); - Scene& get_current_scene(); -}; diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 7af0efd..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "locator.hpp" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __EMSCRIPTEN__ -#include -#endif - -void UpdateDrawFrame(void) { - // Update - - float dt = GetFrameTime(); - // cap dt just for now - if (dt > 0.1f) dt = 0.1f; - - // Draw - ServiceLocator::get_scene_manager().update(dt); - - BeginDrawing(); - ClearBackground(RAYWHITE); - - ServiceLocator::get_scene_manager().render(); - - rlImGuiBegin(); - ServiceLocator::get_scene_manager().ui(); - rlImGuiEnd(); - - EndDrawing(); - - ServiceLocator::get_scene_manager().process_scene_switch(); // !!! After scene_manager is done with the current loop -} - -int main(){ - - - int screen_width = 1280; - int screen_height = 800; - - RaylibAssetLoader asset_loader; - SceneManager scene_manager; - - ServiceLocator::provide(&asset_loader); - ServiceLocator::provide(&scene_manager); // Depends on asset loader! - - rlImGuiSetup(true); - - ImGuiStyle& style = ImGui::GetStyle(); - - // Rounded corners - style.WindowRounding = 6.0f; - style.ChildRounding = 4.0f; - style.FrameRounding = 4.0f; - style.PopupRounding = 4.0f; - style.ScrollbarRounding = 9.0f; - style.GrabRounding = 4.0f; - style.TabRounding = 4.0f; - - // Sizes and Spacing - style.WindowPadding = ImVec2(15.0f, 15.0f); - style.FramePadding = ImVec2(6.0f, 6.0f); - style.ItemSpacing = ImVec2(10.0f, 8.0f); - style.ScrollbarSize = 15.0f; - - SetTargetFPS(60); - // SetTraceLogLevel(TraceLogLevel::LOG_NONE); - - InitWindow(screen_width, screen_height, "Snake"); - SetWindowState(FLAG_WINDOW_RESIZABLE); - - -#ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - while (!ServiceLocator::get_scene_manager().should_game_close()){ - UpdateDrawFrame(); - } -#endif - - CloseWindow(); - rlImGuiShutdown(); - return 0; -} - diff --git a/src/movement.cpp b/src/movement.cpp deleted file mode 100644 index 94c086a..0000000 --- a/src/movement.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// src\movement.cpp -#include - -#include -#include - -void update_movement_system(entt::registry& registry, float dt) { - // We get Position and Velocity, but EXCLUDE entities that have the Player tag - auto view = registry.view(); - - view.each([dt](Position &position, Velocity &velocity) { - // This will only run for pipes, enemies, or particles! - position.x += velocity.dx * dt; - position.y += velocity.dy * dt; - }); -} diff --git a/src/player.cpp b/src/player.cpp deleted file mode 100644 index d74e36e..0000000 --- a/src/player.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// src\player.cpp -#include - -#include -#include - -#include - -entt::entity player; - -const float SPEED = 300.0f; - -class BodyManager; - - -void create_player(entt::registry& registry,Texture* texture){ - const auto entity = registry.create(); - registry.emplace(entity,100.0f,0.0f); - registry.emplace(entity,SPEED,0.0f); - registry.emplace(entity); - registry.emplace(entity,texture,0.0f,0.0f,70.0f,70.0f,false,false,0.0f); - - -} - -void update_player_system(entt::registry& registry,float dt){ - - auto view = registry.view(); - for (entt::entity entity : view){ - const Position& pos = view.get(entity); - Velocity& vel = view.get(entity); - Sprite& sprite = view.get(entity); - - if (IsKeyPressed(KEY_W)){ - if (vel.dy > 0) - continue; - vel.dx = 0; - vel.dy = -SPEED; - - } else if (IsKeyPressed(KEY_S)){ - if (vel.dy < 0) - continue; - vel.dx = 0; - vel.dy = SPEED; - } else if (IsKeyPressed(KEY_A)){ - if (vel.dx > 0) - continue; - vel.dx = -SPEED; - vel.dy = 0; - } else if (IsKeyPressed(KEY_D)){ - if (vel.dx < 0) - continue; - vel.dx = SPEED; - vel.dy = 0; - } - - if (vel.dx != 0.0f || vel.dy != 0.0f) { - // atan2 returns radians. Convert to degrees if your renderer expects it! - float radians = std::atan2(vel.dy, vel.dx); - sprite.rotation = radians * (180.0f / 3.14159265f); - } - } - - auto body_view = registry.view(); - for (entt::entity entity : body_view){ - const PlayerBody& body = body_view.get(entity); - Position& pos = body_view.get(entity); - - } - - - -} - -void create_player_body(entt::registry& registry,Texture* texture,unsigned int idx){ - const auto entity = registry.create(); - registry.emplace(entity,100.0f,0.0f); - registry.emplace(entity,SPEED,0.0f); - registry.emplace(entity,idx); - registry.emplace(entity,texture,0.0f,0.0f,70.0f,70.0f,false,false,0.0f); -} - -void BodyManager::add_body(entt::registry& registry) -{ - create_player_body(registry,body_texture,parts_position_stack.size()); - parts_position_stack.push_back( Position{}); -} - -void BodyManager::pop_body(){ - - parts_position_stack.pop_back(); -} - -void BodyManager::update_body_positions(Position player_head_position){ - for ( auto i = parts_position_stack.size()-1; i > 0 ;i--){ - parts_position_stack[i] = parts_position_stack[i-1]; - } - parts_position_stack[0] = player_head_position; -} - -Position BodyManager::get_body_position(unsigned int part_idx){ - return parts_position_stack[part_idx]; -} - diff --git a/src/render.cpp b/src/render.cpp deleted file mode 100644 index 5b60784..0000000 --- a/src/render.cpp +++ /dev/null @@ -1,45 +0,0 @@ - -#include -#include - -#include -#include - -void update_render_system(entt::registry ®istry){ - auto view = registry.view(); - - for (entt::entity entity : view){ - const Sprite &sprite = view.get(entity); - const Position &pos = view.get(entity); - - if (sprite.texture){ - DrawTexturePro( - *(sprite.texture), - Rectangle{ - 0, - 0, - (float)sprite.texture->width, - (float)sprite.texture->height, - }, - Rectangle { - sprite.offset_x + pos.x, - sprite.offset_y + pos.y, - sprite.width, - sprite.height - }, - Vector2 {sprite.width * 0.5f, sprite.height*0.5f}, - sprite.rotation, - WHITE); - - // DrawTexture( - // *(sprite.texture), - // pos.x + sprite.offset_x, - // pos.y + sprite.offset_y, - // WHITE - // ); - }else{ - DrawRectangle(pos.x,pos.y,100, 100,PURPLE); - } - } - -} diff --git a/src/scenes/game_play_scene.cpp b/src/scenes/game_play_scene.cpp deleted file mode 100644 index 2632428..0000000 --- a/src/scenes/game_play_scene.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "locator.hpp" -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -GamePlayScene::GamePlayScene() { - registry = entt::registry(); - - ServiceLocator::get_asset_loader().load_asset("assets/snake_head.png"); - ServiceLocator::get_asset_loader().load_asset("assets/fruit.png"); - create_player(registry,ServiceLocator::get_asset_loader().get_texture("assets/snake_head.png")); - create_fruit(registry,ServiceLocator::get_asset_loader().get_texture("assets/fruit.png")); - -} - -void GamePlayScene::update(float dt) { - update_movement_system(registry, dt); - update_player_system(registry, dt); - update_fruit_system(registry, dt); -} - - - -void GamePlayScene::render() { - update_render_system(registry); -} - -void GamePlayScene::ui() { - // Get the current screen/viewport size - ImVec2 screen_size = ImGui::GetIO().DisplaySize; - // set next container to be center of the screen - ImVec2 screen_center = ImVec2(screen_size.x * 0.9f, screen_size.y * 0.1f); - ImGui::SetNextWindowPos(screen_center, ImGuiCond_Always,ImVec2(0.5f, 0.5f)); - - ImGui::SetNextWindowSize({40.f,40.f}); - // remove sub window decoration - ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground; - - - ImGui::Begin("Exit", nullptr, flags); - - if (ImGui::Button("X",{40.f,40.f})){ - ServiceLocator::get_scene_manager().request_switch(SceneType::MENU); - } - - ImGui::End(); -} - -GamePlayScene::~GamePlayScene(){ - - ServiceLocator::get_scene_manager(); - ServiceLocator::get_asset_loader(); - - ServiceLocator::get_asset_loader().unload_asset("assets/snake_head.png"); - ServiceLocator::get_asset_loader().unload_asset("assets/fruit.png"); -} diff --git a/src/scenes/scene.cpp b/src/scenes/scene.cpp deleted file mode 100644 index 78d858c..0000000 --- a/src/scenes/scene.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "raylib.h" -#include - -SceneManager::SceneManager(){ - current_scene = std::make_unique(); -} - -SceneManager::~SceneManager(){ - // delete current_scene; -} - -Scene& SceneManager::get_current_scene(){ - return *current_scene; -} - -void SceneManager::process_scene_switch(){ - - if (!pending_switch) return; - - if (current_scene){ - current_scene.reset(); - } - - switch(next_scene_type){ - case SceneType::MENU: - current_scene = std::make_unique(); - break; - case SceneType::GAMEPLAY: - current_scene = std::make_unique(); - break; - } - pending_switch = false; -} - -void SceneManager::update(float dt){ - if (!current_scene) return; - current_scene->update(dt); -} - -void SceneManager::render(){ - if (!current_scene) return; - current_scene->render(); -} - -void SceneManager::ui(){ - if (!current_scene) return; - current_scene->ui(); -} - -bool SceneManager::should_game_close(){ - return should_quit || WindowShouldClose(); -} - -void SceneManager::request_switch(SceneType type){ - next_scene_type = type; - pending_switch = true; -} -void SceneManager::quit(){ - should_quit = true; -} diff --git a/src/test.cpp b/src/test.cpp deleted file mode 100644 index da0f077..0000000 --- a/src/test.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "engine_variant_operation.hpp" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -// #include - - -#include -#include -#include -#include -#include - - -EngineState g_Engine; -RaylibAssetLoader asset_loader; - -class Counter { - public: - int value; - -}; - -int main() { - // std::variant v1; - - // v1 = "hero"; - - // std::cout << v1.index(); - - Vec2 v1(1,2); - - EngineVariant position(v1); - - VariantOpRequest op{ - &position, - OpType::Multiply, - EngineVariant (2), - 0.0f - - }; - VariantOpManager().ExecuteOperation(op); - - position.Print(); - - // std::cout << var.Get(); - - return 0; -} -- 2.54.0