const const const const qualify!!!!

This commit is contained in:
2025-01-08 23:30:14 -05:00
parent 4ecddafcd5
commit d26237762e
10 changed files with 87 additions and 35 deletions

24
LICENSE Normal file
View File

@@ -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 <https://unlicense.org>

View File

@@ -19,6 +19,7 @@ private:
bool destroying = false; bool destroying = false;
bool last_rendered_to_window = false; bool last_rendered_to_window = false;
float render_target_frame_delta = 0; float render_target_frame_delta = 0;
unsigned long last_tick_time = 0;
protected: protected:
// 25ms. // 25ms.
u8 tick_rate = 40; u8 tick_rate = 40;
@@ -42,6 +43,8 @@ public:
[[nodiscard]] bool ShouldTick() const; [[nodiscard]] bool ShouldTick() const;
[[nodiscard]] float TickDeltaTime() const; [[nodiscard]] float TickDeltaTime() const;
[[nodiscard]] float FrameDeltaTime() 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: public:
void ShouldTick(bool state); void ShouldTick(bool state);
void SetActiveCamera(Camera* camera) { active_camera = camera; }; void SetActiveCamera(Camera* camera) { active_camera = camera; };

View File

@@ -12,8 +12,8 @@ private:
public: public:
[[nodiscard]] std::string GetTextureFilesystemPath() const { return texture_path; } [[nodiscard]] std::string GetTextureFilesystemPath() const { return texture_path; }
[[nodiscard]] std::string GetAlphaMaskFilesystemPath() const { return alpha_mask_path; } [[nodiscard]] std::string GetAlphaMaskFilesystemPath() const { return alpha_mask_path; }
[[nodiscard]] Texture* GetTexture() override; [[nodiscard]] Texture* GetTexture() const override;
[[nodiscard]] Texture* GetAlphaMask() override; [[nodiscard]] Texture* GetAlphaMask() const override;
public: public:
/** The Texture *must* be instanced. The alpha-mask *can* be instanced. /** The Texture *must* be instanced. The alpha-mask *can* be instanced.
* You can use SetAlphaMask() to change to a unique one. * You can use SetAlphaMask() to change to a unique one.
@@ -23,7 +23,7 @@ public:
*/ */
~InstancedSprite() override; ~InstancedSprite() override;
InstancedSprite(const Vector2& position, unsigned int layer, const std::string& instanced_texture_filesystem_path, 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 = "") 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, layer, face_angle, base_color, nullptr, unique_alpha_mask), texture_path(instanced_texture_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) {} alpha_mask_path(instanced_alpha_mask_filesystem_path) {}
}; };

View File

@@ -19,16 +19,23 @@ private:
protected: protected:
Vector2 scale = {1, 1}; Vector2 scale = {1, 1};
// Local space, Where the face_angle rotation should be preformed about. // 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}; Vector2 origin = {0, 0};
Color4 base_color = Colors::White; Color4 base_color = Colors::White;
protected: protected:
[[nodiscard]] virtual Texture* GetTexture(); [[nodiscard]] Vector2 GetRenderPosition() const;
[[nodiscard]] virtual Texture* GetAlphaMask(); [[nodiscard]] Vector2 GetLocalSpaceOrigin() const;
[[nodiscard]] virtual Texture* GetTexture() const;
[[nodiscard]] virtual Texture* GetAlphaMask() const;
protected:
void SetAlphaMask(Texture* new_alpha_mask); void SetAlphaMask(Texture* new_alpha_mask);
void SetOrigin(const Vector2& new_origin);
public: public:
void Render() override; void Render() override;
public: public:
~Sprite() override; ~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, 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) {} Texture* alpha_mask = nullptr) : Renderable(layer), Movable(pos, face_angle), texture(texture), alpha_mask(alpha_mask), base_color(base_color), origin(origin) {}
}; };

View File

@@ -10,5 +10,6 @@ class Game::Box final : public Engine::InstancedSprite {
public: public:
void Update() final; void Update() final;
public: 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") {}
}; };

View File

@@ -13,31 +13,33 @@ size_t Scene::EntityCount() const {
} }
void Scene::Update() { void Scene::Update() {
auto target_tick_time = std::chrono::microseconds(1000000 / tick_rate);
auto start = std::chrono::high_resolution_clock::now();
entity_list->UpdateChildren(); entity_list->UpdateChildren();
auto stop = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(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() { void Scene::UpdateLoop() {
while (!destroying) while (!destroying) {
if (should_tick) if (!should_tick) {
Update();
else {
auto target_tick_time = std::chrono::microseconds(1000000 / tick_rate); auto target_tick_time = std::chrono::microseconds(1000000 / tick_rate);
std::this_thread::sleep_for(std::chrono::microseconds(target_tick_time)); 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<std::chrono::microseconds>(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<std::chrono::microseconds>(stop.time_since_epoch()).count();
}
} }
void Scene::Render() { void Scene::Render() {
@@ -171,3 +173,7 @@ float Scene::FrameDeltaTime() const {
return render_target_frame_delta; return render_target_frame_delta;
} }
unsigned long Scene::LastTickTime() const {
return last_tick_time;
}

View File

@@ -2,14 +2,14 @@
#include <Engine/Globals.h> #include <Engine/Globals.h>
using namespace Engine; using namespace Engine;
Texture* InstancedSprite::GetTexture() { Texture* InstancedSprite::GetTexture() const {
auto* itx = GetScene()->GetInstancedTexture(this); auto* itx = GetScene()->GetInstancedTexture(this);
if (itx) if (itx)
return itx->GetTexture(); return itx->GetTexture();
return nullptr; return nullptr;
} }
Texture* InstancedSprite::GetAlphaMask() { Texture* InstancedSprite::GetAlphaMask() const {
auto* ita = GetScene()->GetInstancedAlphaMask(this); auto* ita = GetScene()->GetInstancedAlphaMask(this);
if (ita) if (ita)
return ita->GetTexture(); return ita->GetTexture();

View File

@@ -11,19 +11,31 @@ void Engine::Sprite::Render() {
auto* a = GetAlphaMask(); auto* a = GetAlphaMask();
if (t && !a) 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) 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; return texture;
} }
Texture* Engine::Sprite::GetAlphaMask() { Texture* Engine::Sprite::GetAlphaMask() const {
return alpha_mask; return alpha_mask;
} }
void Engine::Sprite::SetAlphaMask(Texture* new_alpha_mask) { void Engine::Sprite::SetAlphaMask(Texture* new_alpha_mask) {
alpha_mask = 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;
}

View File

@@ -2,7 +2,6 @@
#include <Engine/Globals.h> #include <Engine/Globals.h>
void Game::Box::Update() { void Game::Box::Update() {
if (Globals::Window->IsKeyDown(Keys::W)) if (Globals::Window->IsKeyDown(Keys::W))
MoveY(-500); MoveY(-500);
if (Globals::Window->IsKeyDown(Keys::S)) if (Globals::Window->IsKeyDown(Keys::S))

View File

@@ -4,7 +4,7 @@
void ControllableBox::Init() { void ControllableBox::Init() {
auto* hud = new Game::DemoGameHud(); 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}); auto *b = new Game::Box({0, 0});
entity_list->AppendChild(b); entity_list->AppendChild(b);
} }