diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3c577b0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to \ No newline at end of file diff --git a/include/Engine/types/Scene.h b/include/Engine/types/Scene.h index b9d187f..a03efab 100644 --- a/include/Engine/types/Scene.h +++ b/include/Engine/types/Scene.h @@ -19,6 +19,7 @@ private: bool destroying = false; bool last_rendered_to_window = false; float render_target_frame_delta = 0; + unsigned long last_tick_time = 0; protected: // 25ms. u8 tick_rate = 40; @@ -42,6 +43,8 @@ public: [[nodiscard]] bool ShouldTick() const; [[nodiscard]] float TickDeltaTime() const; [[nodiscard]] float FrameDeltaTime() const; + /// @returns the number of microseconds since Jan 1st 1970 that the last tick was finished on. + [[nodiscard]] unsigned long LastTickTime() const; public: void ShouldTick(bool state); void SetActiveCamera(Camera* camera) { active_camera = camera; }; diff --git a/include/Engine/types/entity/InstancedSprite.h b/include/Engine/types/entity/InstancedSprite.h index 4fb7c1d..dc8629a 100644 --- a/include/Engine/types/entity/InstancedSprite.h +++ b/include/Engine/types/entity/InstancedSprite.h @@ -12,8 +12,8 @@ private: public: [[nodiscard]] std::string GetTextureFilesystemPath() const { return texture_path; } [[nodiscard]] std::string GetAlphaMaskFilesystemPath() const { return alpha_mask_path; } - [[nodiscard]] Texture* GetTexture() override; - [[nodiscard]] Texture* GetAlphaMask() override; + [[nodiscard]] Texture* GetTexture() const override; + [[nodiscard]] Texture* GetAlphaMask() const override; public: /** The Texture *must* be instanced. The alpha-mask *can* be instanced. * You can use SetAlphaMask() to change to a unique one. @@ -23,7 +23,7 @@ public: */ ~InstancedSprite() override; InstancedSprite(const Vector2& position, unsigned int layer, const std::string& instanced_texture_filesystem_path, - float face_angle = 0.0f, const Color4& base_color = Colors::White, Texture* unique_alpha_mask = nullptr, const std::string& instanced_alpha_mask_filesystem_path = "") - : Sprite(position, layer, face_angle, base_color, nullptr, unique_alpha_mask), texture_path(instanced_texture_filesystem_path), + const Vector2& origin = {0, 0}, float face_angle = 0.0f, const Color4& base_color = Colors::White, Texture* unique_alpha_mask = nullptr, const std::string& instanced_alpha_mask_filesystem_path = "") + : Sprite(position, origin, layer, face_angle, base_color, nullptr, unique_alpha_mask), texture_path(instanced_texture_filesystem_path), alpha_mask_path(instanced_alpha_mask_filesystem_path) {} }; diff --git a/include/Engine/types/entity/Sprite.h b/include/Engine/types/entity/Sprite.h index 987a6d6..357f0a2 100644 --- a/include/Engine/types/entity/Sprite.h +++ b/include/Engine/types/entity/Sprite.h @@ -19,16 +19,23 @@ private: protected: Vector2 scale = {1, 1}; // Local space, Where the face_angle rotation should be preformed about. + // In local space, Where on the texture the entities "position" is. + // Also, this is where rotations will be done about by default. + // TODO separate. Vector2 origin = {0, 0}; Color4 base_color = Colors::White; protected: - [[nodiscard]] virtual Texture* GetTexture(); - [[nodiscard]] virtual Texture* GetAlphaMask(); + [[nodiscard]] Vector2 GetRenderPosition() const; + [[nodiscard]] Vector2 GetLocalSpaceOrigin() const; + [[nodiscard]] virtual Texture* GetTexture() const; + [[nodiscard]] virtual Texture* GetAlphaMask() const; +protected: void SetAlphaMask(Texture* new_alpha_mask); + void SetOrigin(const Vector2& new_origin); public: void Render() override; public: ~Sprite() override; - explicit Sprite(const Vector2& pos, unsigned int layer = 0, const float face_angle = 0.0f, const Color4& base_color = Colors::White, Texture* texture = nullptr, - Texture* alpha_mask = nullptr) : Renderable(layer), Movable(pos, face_angle), texture(texture), alpha_mask(alpha_mask), base_color(base_color) {} + explicit Sprite(const Vector2& pos, const Vector2& origin = {0, 0}, unsigned int layer = 0, const float face_angle = 0.0f, const Color4& base_color = Colors::White, Texture* texture = nullptr, + Texture* alpha_mask = nullptr) : Renderable(layer), Movable(pos, face_angle), texture(texture), alpha_mask(alpha_mask), base_color(base_color), origin(origin) {} }; \ No newline at end of file diff --git a/include/Game/entity/Box.h b/include/Game/entity/Box.h index b22f7a6..872f69f 100644 --- a/include/Game/entity/Box.h +++ b/include/Game/entity/Box.h @@ -10,5 +10,6 @@ class Game::Box final : public Engine::InstancedSprite { public: void Update() final; public: - explicit Box(const Vector2& position, unsigned int layer = 1, float rad_rotation = 0.0f) : Engine::InstancedSprite(position, layer, "assets/sprites/Re3D.png", rad_rotation, Colors::White, nullptr, "assets/sprites/alpha_mask.png") {} + explicit Box(const Vector2& position, unsigned int layer = 1, float rad_rotation = 0.0f) : Engine::InstancedSprite(position, layer, "assets/sprites/Re3D.png", + {0.5, 0.5},rad_rotation, Colors::White, nullptr, "assets/sprites/alpha_mask.png") {} }; \ No newline at end of file diff --git a/src/Engine/types/Scene.cpp b/src/Engine/types/Scene.cpp index af70997..21b014d 100644 --- a/src/Engine/types/Scene.cpp +++ b/src/Engine/types/Scene.cpp @@ -13,31 +13,33 @@ size_t Scene::EntityCount() const { } void Scene::Update() { - auto target_tick_time = std::chrono::microseconds(1000000 / tick_rate); - - auto start = std::chrono::high_resolution_clock::now(); - entity_list->UpdateChildren(); - - auto stop = std::chrono::high_resolution_clock::now(); - auto elapsed = std::chrono::duration_cast(stop - start); - - if (elapsed < target_tick_time) - std::this_thread::sleep_for(std::chrono::microseconds(target_tick_time - elapsed)); - - // TODO Research how we can fix desync issues that would come about by a tick occasionally taking longer than we expected. - if (elapsed > target_tick_time) - Logger::Info("This tick took " + std::to_string((elapsed - target_tick_time).count()) + "μs longer than the target tick time."); } void Scene::UpdateLoop() { - while (!destroying) - if (should_tick) - Update(); - else { + while (!destroying) { + if (!should_tick) { auto target_tick_time = std::chrono::microseconds(1000000 / tick_rate); std::this_thread::sleep_for(std::chrono::microseconds(target_tick_time)); + continue; } + auto target_tick_time = std::chrono::microseconds(1000000 / tick_rate); + auto start = std::chrono::high_resolution_clock::now(); + + Update(); + + auto stop = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(stop - start); + + if (elapsed < target_tick_time) + std::this_thread::sleep_for(std::chrono::microseconds(target_tick_time - elapsed)); + + // TODO Research how we can fix desync issues that would come about by a tick occasionally taking longer than we expected. + if (elapsed > target_tick_time) + Logger::Info("This tick took " + std::to_string((elapsed - target_tick_time).count()) + "μs longer than the target tick time."); + + last_tick_time = std::chrono::duration_cast(stop.time_since_epoch()).count(); + } } void Scene::Render() { @@ -171,3 +173,7 @@ float Scene::FrameDeltaTime() const { return render_target_frame_delta; } +unsigned long Scene::LastTickTime() const { + return last_tick_time; +} + diff --git a/src/Engine/types/entity/InstancedSprite.cpp b/src/Engine/types/entity/InstancedSprite.cpp index f0f3bb9..58b3fbb 100644 --- a/src/Engine/types/entity/InstancedSprite.cpp +++ b/src/Engine/types/entity/InstancedSprite.cpp @@ -2,14 +2,14 @@ #include using namespace Engine; -Texture* InstancedSprite::GetTexture() { +Texture* InstancedSprite::GetTexture() const { auto* itx = GetScene()->GetInstancedTexture(this); if (itx) return itx->GetTexture(); return nullptr; } -Texture* InstancedSprite::GetAlphaMask() { +Texture* InstancedSprite::GetAlphaMask() const { auto* ita = GetScene()->GetInstancedAlphaMask(this); if (ita) return ita->GetTexture(); diff --git a/src/Engine/types/entity/Sprite.cpp b/src/Engine/types/entity/Sprite.cpp index 5829d86..b78e20d 100644 --- a/src/Engine/types/entity/Sprite.cpp +++ b/src/Engine/types/entity/Sprite.cpp @@ -11,19 +11,31 @@ void Engine::Sprite::Render() { auto* a = GetAlphaMask(); if (t && !a) - return J2D::DrawSprite(t, position, face_angle, origin, scale, base_color); + return J2D::DrawSprite(t, GetRenderPosition(), face_angle, origin, scale, base_color); if (t && a) - return J2D::DrawSprite(t, a, position, face_angle, origin, scale, base_color); + return J2D::DrawSprite(t, a, GetRenderPosition(), face_angle, origin, scale, base_color); } -Texture* Engine::Sprite::GetTexture() { +Texture* Engine::Sprite::GetTexture() const { return texture; } -Texture* Engine::Sprite::GetAlphaMask() { +Texture* Engine::Sprite::GetAlphaMask() const { return alpha_mask; } void Engine::Sprite::SetAlphaMask(Texture* new_alpha_mask) { alpha_mask = new_alpha_mask; } + +Vector2 Engine::Sprite::GetRenderPosition() const { + return position - (origin * GetTexture()->GetDimensions()); +} + +void Engine::Sprite::SetOrigin(const Vector2& new_origin) { + origin = new_origin; +} + +Vector2 Engine::Sprite::GetLocalSpaceOrigin() const { + return origin; +} diff --git a/src/Game/Entities/Box.cpp b/src/Game/Entities/Box.cpp index a62a580..0505462 100644 --- a/src/Game/Entities/Box.cpp +++ b/src/Game/Entities/Box.cpp @@ -2,7 +2,6 @@ #include void Game::Box::Update() { - if (Globals::Window->IsKeyDown(Keys::W)) MoveY(-500); if (Globals::Window->IsKeyDown(Keys::S)) diff --git a/src/Game/Scene/ControllableBox.cpp b/src/Game/Scene/ControllableBox.cpp index bcd4140..56dcf7f 100644 --- a/src/Game/Scene/ControllableBox.cpp +++ b/src/Game/Scene/ControllableBox.cpp @@ -4,7 +4,7 @@ void ControllableBox::Init() { auto* hud = new Game::DemoGameHud(); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 1; i++) { auto *b = new Game::Box({0, 0}); entity_list->AppendChild(b); }