From e2e748925336779ea49a9f2ef84eea86ffe124e8 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Thu, 21 Dec 2023 01:03:15 +0100 Subject: [PATCH] first draft of the engine --- .gitignore | 1 + .idea/.gitignore | 8 ++ .idea/misc.xml | 4 + .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 + CMakeLists.txt | 7 + Engine/CMakeLists.txt | 27 ++++ Engine/assets/apple.png | Bin 0 -> 50476 bytes Engine/include/component.h | 19 +++ Engine/include/components/sprite_component.h | 19 +++ Engine/include/entities/background_entity.h | 18 +++ Engine/include/entities/ui_fps_entity.h | 14 ++ Engine/include/entity.h | 139 +++++++++++++++++++ Engine/include/render_state.h | 16 +++ Engine/include/scene.h | 24 ++++ Engine/include/transform.h | 27 ++++ Engine/src/background_entity.cpp | 7 + Engine/src/main.cpp | 39 ++++++ Engine/src/render_state.cpp | 31 +++++ Engine/src/scene.cpp | 3 + Engine/src/sprite_component.cpp | 41 ++++++ Engine/src/ui_fps_entity.cpp | 10 ++ 22 files changed, 468 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 CMakeLists.txt create mode 100644 Engine/CMakeLists.txt create mode 100644 Engine/assets/apple.png create mode 100644 Engine/include/component.h create mode 100644 Engine/include/components/sprite_component.h create mode 100644 Engine/include/entities/background_entity.h create mode 100644 Engine/include/entities/ui_fps_entity.h create mode 100644 Engine/include/entity.h create mode 100644 Engine/include/render_state.h create mode 100644 Engine/include/scene.h create mode 100644 Engine/include/transform.h create mode 100644 Engine/src/background_entity.cpp create mode 100644 Engine/src/main.cpp create mode 100644 Engine/src/render_state.cpp create mode 100644 Engine/src/scene.cpp create mode 100644 Engine/src/sprite_component.cpp create mode 100644 Engine/src/ui_fps_entity.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72b18fd --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +cmake-build-*/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..79b3c94 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..34368da --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..5fca962 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c8d753c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.24) +project(Ant) +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_CXX_STANDARD 23) + +add_subdirectory(Engine) + diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt new file mode 100644 index 0000000..8be8fcc --- /dev/null +++ b/Engine/CMakeLists.txt @@ -0,0 +1,27 @@ +Include(FetchContent) + +FetchContent_Declare( + RayLib + GIT_REPOSITORY D:/AntiJeu/cmake-build-debug/_deps/raylib-src + GIT_TAG 4.5.0 + GIT_PROGRESS TRUE +) +FetchContent_MakeAvailable(RayLib) + +add_executable(Engine + src/main.cpp + include/entity.h + include/transform.h + include/component.h + include/scene.h + include/render_state.h + src/render_state.cpp + src/scene.cpp + include/entities/ui_fps_entity.h + src/ui_fps_entity.cpp + include/entities/background_entity.h + src/background_entity.cpp + include/components/sprite_component.h src/sprite_component.cpp) +target_include_directories(Engine PUBLIC include) +target_link_libraries(Engine PUBLIC raylib) +file(COPY assets/apple.png DESTINATION assets/apple.png) \ No newline at end of file diff --git a/Engine/assets/apple.png b/Engine/assets/apple.png new file mode 100644 index 0000000000000000000000000000000000000000..3e7877383dda81b596ba160ae0a1aefa8ddddc38 GIT binary patch literal 50476 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 + +namespace ant::core { + struct entity; + struct component { + virtual std::string name() = 0; + virtual void initialize() {} + virtual void render() {} + virtual void update(std::chrono::duration) {} + [[nodiscard]] auto owner() -> std::shared_ptr { + return m_owner.lock(); + } + private: + std::weak_ptr m_owner; + friend struct entity; + }; +} \ No newline at end of file diff --git a/Engine/include/components/sprite_component.h b/Engine/include/components/sprite_component.h new file mode 100644 index 0000000..e43aec6 --- /dev/null +++ b/Engine/include/components/sprite_component.h @@ -0,0 +1,19 @@ +#pragma once +#include "component.h" +#include +#include "raylib.h" +#include "transform.h" + +namespace ant::components::graphical { + struct sprite_component : public ant::core::component { + sprite_component() {} + sprite_component(const std::string& str, int layer = 0, ant::core::transform<> reposition = {{0,0},0}, ant::core::Vec2<> scale = {1,1}); + std::string name() override {return "sprite_component";} + void render() override; + private: + Texture2D current_texture; + ant::core::transform<> transform; + ant::core::Vec2<> m_scale; + int m_layer; + }; +} \ No newline at end of file diff --git a/Engine/include/entities/background_entity.h b/Engine/include/entities/background_entity.h new file mode 100644 index 0000000..ef5c2f5 --- /dev/null +++ b/Engine/include/entities/background_entity.h @@ -0,0 +1,18 @@ +#pragma once + +#include "entity.h" +#include "raylib.h" + +namespace ant::entities::utilities { + + struct background_entity : public ant::core::entity { + background_entity(const std::shared_ptr& parent, Color color) + : ant::core::entity(parent) + , m_color(color) + {} + void render() final; + private: + Color m_color; + }; + +} \ No newline at end of file diff --git a/Engine/include/entities/ui_fps_entity.h b/Engine/include/entities/ui_fps_entity.h new file mode 100644 index 0000000..064777b --- /dev/null +++ b/Engine/include/entities/ui_fps_entity.h @@ -0,0 +1,14 @@ +#pragma once + +#include "entity.h" + +namespace ant::entities::utilities { + + struct ui_fps_entity : public ant::core::entity { + ui_fps_entity(const std::shared_ptr& parent) + : ant::core::entity(parent) + {} + void render() final; + }; + +} \ No newline at end of file diff --git a/Engine/include/entity.h b/Engine/include/entity.h new file mode 100644 index 0000000..a6926f0 --- /dev/null +++ b/Engine/include/entity.h @@ -0,0 +1,139 @@ +#pragma once +#include +#include +#include +#include +#include +#include "transform.h" +#include "component.h" + +namespace ant::core { + struct entity { + [[nodiscard]] auto transform() const -> ant::core::transform { + return m_transform; + } + auto transform() -> ant::core::transform& { + return m_transform; + } + [[nodiscard]] auto world_transform() const -> ant::core::transform { + ant::core::transform ret{{0,0},0}; + if(auto parent = m_parent.lock(); parent) { + ret = parent->world_transform(); + } + auto transform_pivot = transform(); + if(ret.angle != 0.0f) { + transform_pivot.position.X *= std::cos(ret.angle*std::numbers::pi/180); + transform_pivot.position.Y *= std::sin(ret.angle*std::numbers::pi/180); + } + return ret + transform_pivot; + } + [[nodiscard]] auto parent() const -> std::shared_ptr { + return m_parent.lock(); + } + [[nodiscard]] auto is_visible() const -> bool { + if(auto parent = m_parent.lock(); parent){ + if(not parent->is_visible()) { + return false; + } + } + return m_is_visible; + } + [[nodiscard]] auto visibility_flag() const -> bool { + return m_is_visible; + } + [[nodiscard]] auto find_components(std::string name) const -> std::vector> { + decltype(m_components) ret; + auto source = m_components | std::views::filter([&](const auto& elem) {return name == elem->name();}); + std::ranges::copy(source, std::back_inserter(ret)); + return ret; + } + [[nodiscard]] auto components_list() const -> const std::vector>& { + return m_components; + } + [[nodiscard]] auto components_list() -> std::vector>& { + return m_components; + } + template ComponentType, typename... ARGS> + auto add_component(ARGS&&... constructor_args) -> std::shared_ptr { + auto component = std::make_shared(std::forward(constructor_args)...); + auto self = m_self.lock(); + component->m_owner = self; + m_components.push_back(component); + component->initialize(); + return self; + } + auto set_visible(bool visible) -> bool { + return std::exchange(m_is_visible, visible); + } + virtual void initialize() {} + virtual void render() { + if(not visibility_flag()) return; + for(auto& child : m_children | std::views::filter([](const std::shared_ptr& elem){return elem->visibility_flag();})) { + child->render(); + } + for(auto& component : m_components) { + component->render(); + } + } + virtual void update(std::chrono::duration delta_time) { + for(auto& child : m_children) { + child->update(delta_time); + } + for(auto& component : m_components) { + component->update(delta_time); + } + } + + entity(const std::shared_ptr& parent) + : m_is_visible(true) + , m_parent(parent) + , m_children() + , m_components() + , m_transform{.position = {0,0}, .angle = 0} + {} + + entity() + : m_is_visible(true) + , m_parent(std::shared_ptr(nullptr)) + , m_children() + , m_components() + , m_transform{.position = {0,0}, .angle = 0} + {} + private: + bool m_is_visible; + std::weak_ptr m_parent; + std::weak_ptr m_self; + std::vector> m_children; + std::vector> m_components; + ant::core::transform m_transform; + + template EntityType> + friend auto make_entity(const std::shared_ptr& parent, auto&&... ARGS) -> std::shared_ptr; + + template EntityType> + friend auto make_entity(auto&&... ARGS) -> std::shared_ptr; + }; + + template EntityType> + [[nodiscard]] auto make_entity(const std::shared_ptr& parent, auto&&... ARGS) -> std::shared_ptr { + auto object = std::make_shared(std::forward(ARGS)...); + const std::shared_ptr& entity_router = object; + entity_router->m_parent = parent; + entity_router->m_self = object; + if(parent) { + parent->m_children.push_back(object); + } + object->initialize(); + return object; + } + + template EntityType> + [[nodiscard]] auto make_entity(auto&&... ARGS) -> std::shared_ptr { + auto object = std::make_shared(std::shared_ptr(nullptr), std::forward(ARGS)...); + const std::shared_ptr& entity_router = object; + entity_router->m_parent = std::shared_ptr(nullptr); + entity_router->m_self = object; + object->initialize(); + return object; + } +} \ No newline at end of file diff --git a/Engine/include/render_state.h b/Engine/include/render_state.h new file mode 100644 index 0000000..ff19375 --- /dev/null +++ b/Engine/include/render_state.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace ant::render { + enum class layer_pos { + start, + any, + end + }; + void schedule_in_frame(int layer, std::function fn, layer_pos pos = layer_pos::any); + void schedule_in_frame(int layer, auto fn, layer_pos pos = layer_pos::any) { + schedule_in_frame(layer, std::function{std::move(fn)}, pos); + } + void render_all(); +} \ No newline at end of file diff --git a/Engine/include/scene.h b/Engine/include/scene.h new file mode 100644 index 0000000..71f60a8 --- /dev/null +++ b/Engine/include/scene.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include +#include "entity.h" + +namespace ant::core { + struct scene { + static std::shared_ptr current; + std::vector> root_nodes; + + void update(std::chrono::duration delta_time) { + for (auto &elem: root_nodes) { + elem->update(delta_time); + } + } + void render() { + for (auto &elem: root_nodes | std::views::filter([](const std::shared_ptr& elem){return elem->visibility_flag();})) { + elem->render(); + } + } + }; +} \ No newline at end of file diff --git a/Engine/include/transform.h b/Engine/include/transform.h new file mode 100644 index 0000000..ac8ec6f --- /dev/null +++ b/Engine/include/transform.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include + +namespace ant::core { + template + struct Vec2 { + T X; + T Y; + }; + + template + auto operator+(const Vec2& lhs, const Vec2& rhs) -> Vec2{ + return {.X = lhs.X + rhs.X, .Y = lhs.Y + rhs.Y}; + } + + template + struct transform { + Vec2 position; + float angle; + }; + + template + auto operator+(const transform& lhs, const transform& rhs) -> transform{ + return {.position = lhs.position + rhs.position, .angle = std::fmod(lhs.angle + rhs.angle, 180.0f)}; + } +} \ No newline at end of file diff --git a/Engine/src/background_entity.cpp b/Engine/src/background_entity.cpp new file mode 100644 index 0000000..b811390 --- /dev/null +++ b/Engine/src/background_entity.cpp @@ -0,0 +1,7 @@ +#include "entities/background_entity.h" +#include "render_state.h" +#include "raylib.h" + +void ant::entities::utilities::background_entity::render() { + ant::render::schedule_in_frame(-255, [color = m_color](){ ClearBackground(color);}); +} \ No newline at end of file diff --git a/Engine/src/main.cpp b/Engine/src/main.cpp new file mode 100644 index 0000000..ac43445 --- /dev/null +++ b/Engine/src/main.cpp @@ -0,0 +1,39 @@ +#include "raylib.h" +#include "scene.h" +#include "render_state.h" +#include "entities/ui_fps_entity.h" +#include "entities/background_entity.h" +#include "components/sprite_component.h" + +using namespace std::string_literals; + +int main() { + InitWindow(800, 600, "Example"); + ant::core::scene::current = std::make_shared(); + ant::core::scene::current->root_nodes.push_back(ant::core::make_entity()); + ant::core::scene::current->root_nodes.push_back(ant::core::make_entity()); + ant::core::scene::current->root_nodes.back() + ->add_component( + "Engine/assets/apple.png"s, + 0, + ant::core::transform<>{{560/2, 640/2}, 60}, + ant::core::Vec2<>{0.5,0.5} + ); + ant::core::scene::current->root_nodes.back()->transform().position = {250,250}; + ant::core::scene::current->root_nodes.back()->transform().angle = 120; + ant::core::scene::current->root_nodes.push_back(ant::core::make_entity(BLACK)); + auto ref = std::chrono::steady_clock::now(); + std::chrono::duration frame_time = ref - ref; + while(not WindowShouldClose()) { + ant::core::scene::current->update(frame_time); + ant::core::scene::current->render(); + BeginDrawing(); + ant::render::render_all(); + EndDrawing(); + auto new_time = std::chrono::steady_clock::now(); + frame_time = new_time - ref; + ref = new_time; + } + CloseWindow(); + return 0; +} \ No newline at end of file diff --git a/Engine/src/render_state.cpp b/Engine/src/render_state.cpp new file mode 100644 index 0000000..46dc3f6 --- /dev/null +++ b/Engine/src/render_state.cpp @@ -0,0 +1,31 @@ +#include +#include "render_state.h" + +struct render_thunk { + int prio; + ant::render::layer_pos pos = ant::render::layer_pos::any; + std::function op; +}; + +static bool operator<(const render_thunk& lhs, const render_thunk& rhs) { + if(lhs.prio < rhs.prio) { + if(lhs.pos > rhs.pos) { + return false; + } else { + return true; + } + } + return false; +} +static std::priority_queue renders; + +void ant::render::schedule_in_frame(int layer, std::function fn, ant::render::layer_pos pos) { + renders.push({layer, pos, std::move(fn)}); +} + +void ant::render::render_all() { + while(not renders.empty()) { + renders.top().op(); + renders.pop(); + } +} diff --git a/Engine/src/scene.cpp b/Engine/src/scene.cpp new file mode 100644 index 0000000..f6b191c --- /dev/null +++ b/Engine/src/scene.cpp @@ -0,0 +1,3 @@ +#include "scene.h" + +std::shared_ptr ant::core::scene::current; \ No newline at end of file diff --git a/Engine/src/sprite_component.cpp b/Engine/src/sprite_component.cpp new file mode 100644 index 0000000..74c6616 --- /dev/null +++ b/Engine/src/sprite_component.cpp @@ -0,0 +1,41 @@ +#include "components/sprite_component.h" +#include "entity.h" +#include "render_state.h" + +ant::components::graphical::sprite_component::sprite_component(const std::string& str, int layer, ant::core::transform<> reposition, ant::core::Vec2<> scale) +// TODO: Textures should be managed by an asset manager +: current_texture(LoadTexture(str.c_str())) +, transform(reposition) +, m_scale(scale) +, m_layer(layer) +{} + +void ant::components::graphical::sprite_component::render() { + Rectangle source = { + .x = 0, + .y = 0, + .width = static_cast(current_texture.width), + .height = static_cast(current_texture.height) + }; + auto draw_position = owner()->world_transform(); + draw_position = draw_position + transform; + Rectangle dest = { + .x = draw_position.position.X-transform.position.X, + .y = draw_position.position.Y-transform.position.Y, + .width = static_cast(current_texture.width) * m_scale.X, + .height = static_cast(current_texture.height) * m_scale.Y + }; + ant::render::schedule_in_frame(m_layer, [current_texture = this->current_texture, dest, transform = this->transform, source, draw_position, m_scale = this->m_scale](){ + DrawTexturePro( + current_texture, + source, + dest, + Vector2{ + transform.position.X * m_scale.X, + transform.position.Y * m_scale.Y + }, + draw_position.angle, + WHITE + ); + }); +} \ No newline at end of file diff --git a/Engine/src/ui_fps_entity.cpp b/Engine/src/ui_fps_entity.cpp new file mode 100644 index 0000000..bbae939 --- /dev/null +++ b/Engine/src/ui_fps_entity.cpp @@ -0,0 +1,10 @@ +#include "entities/ui_fps_entity.h" +#include "render_state.h" +#include "raylib.h" + +void ant::entities::utilities::ui_fps_entity::render() { + entity::render(); + ant::render::schedule_in_frame(255, [coords = this->transform().position](){ + DrawFPS(static_cast(coords.X),static_cast(coords.Y)); + }); +} \ No newline at end of file