diff --git a/include/Engine/Entity/Camera.h b/include/Engine/Entity/Camera.h deleted file mode 100644 index 03e5ad2..0000000 --- a/include/Engine/Entity/Camera.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -namespace Engine { - class Camera; -} - -class Engine::Camera : public Renderable { -public: - void Render() override {}; -public: - explicit Camera(const Vector2& position) : Renderable(position, 0) {} -}; diff --git a/include/Engine/Entity/Entity.h b/include/Engine/Entity/Entity.h deleted file mode 100644 index b3f5259..0000000 --- a/include/Engine/Entity/Entity.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include -#include -#include - -namespace Engine { - class Entity; -} - -class Engine::Entity { -protected: - // nullptr means no parent. - Entity* parent = nullptr; - - // Epoch micro-seconds. - long creation_time = 0.0f; - std::vector children{}; - Vector2 position = {0, 0}; - // Assuming 0 radians is up. - float face_angle = 0.0f; - void UpdateChildren(); -public: - // Movements independent of the face_angle. - void MoveX(float speed); - void MoveY(float speed); - void Move(float angle_rad, float speed); - - // Movements dependent on face angle. - void MoveForward(float speed); - void MoveBackward(float speed); - void MoveLeft(float speed); - void MoveRight(float speed); - - void Rotate(float speed); - void SetRotation(float new_rotation); - - // Parent child structure. - [[nodiscard]] bool AppendChild(Entity* entity); - void DestroyChild(Entity* entity); - void RemoveChild(Entity* entity); -public: - [[nodiscard]] std::vector GetChildren() const; - [[nodiscard]] Entity* GetParent() const; - - // Microseconds. - [[nodiscard]] long GetCreationTime() const; - [[nodiscard]] long GetAge() const; - - [[nodiscard]] float GetRotation() const; - [[nodiscard]] Vector2 GetPosition() const; - -public: - virtual void Update() {} -public: - virtual ~Entity(); - explicit Entity(const Vector2& position, float rotation = 0.0f) : - creation_time(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()), - position(position), face_angle(rotation) {} -}; \ No newline at end of file diff --git a/include/Engine/Entity/Renderable.h b/include/Engine/Entity/Renderable.h deleted file mode 100644 index 2f366b2..0000000 --- a/include/Engine/Entity/Renderable.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include - -namespace Engine { - class Renderable; -} - -class Engine::Renderable : public Entity { -protected: - // Higher numbers are farther to the back. - unsigned int depth = 0; -public: - [[nodiscard]] unsigned int GetDepth() const { return depth; } - void SetDepth(unsigned int new_depth) { depth = new_depth; } -public: - // *must* be overridden. - virtual void Render() = 0; -public: - explicit Renderable(const Vector2& position, unsigned int depth = 0, float rotation = 0.0f) : Entity(position, rotation), depth(depth) {} -}; \ No newline at end of file diff --git a/include/Engine/GameWindow.h b/include/Engine/GameWindow.h index 92d208d..e573bb4 100644 --- a/include/Engine/GameWindow.h +++ b/include/Engine/GameWindow.h @@ -1,5 +1,6 @@ -#include #pragma once +#include +#include namespace Engine { class DemoGameWindow; @@ -11,7 +12,16 @@ public: public: void OnRefresh(float elapsed) override; public: - DemoGameWindow() : ReWindow::RWindow() {} - DemoGameWindow(const std::string& title, int width, int height) : ReWindow::RWindow(title, width, height) {} + DemoGameWindow(const std::string& title, int width, int height) : ReWindow::RWindow(title, width, height) + { + ReWindow::Logger::Error.EnableConsole(false); + ReWindow::Logger::Warning.EnableConsole(false); + ReWindow::Logger::Debug.EnableConsole(false); + SetRenderer(RenderingAPI::OPENGL); + Open(); + InitGL(); + SetResizable(false); + SetVsyncEnabled(false); + } }; \ No newline at end of file diff --git a/include/Engine/Globals.h b/include/Engine/Globals.h index f1d08aa..50bd2dc 100644 --- a/include/Engine/Globals.h +++ b/include/Engine/Globals.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include namespace Globals { diff --git a/include/Engine/types/InstancedTexture.h b/include/Engine/types/InstancedTexture.h new file mode 100644 index 0000000..a384baa --- /dev/null +++ b/include/Engine/types/InstancedTexture.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include + +namespace Engine { + class InstancedTexture; + class InstancedSprite; +} + +class Engine::InstancedTexture { +protected: + JGL::Texture* texture; + std::vector users{}; +public: + [[nodiscard]] size_t ReferenceCount() { return users.size(); } + [[nodiscard]] bool InUseBy(const InstancedSprite* rhs); + [[nodiscard]] JGL::Texture* GetTexture() const { return texture; } +public: + void AddUser(const InstancedSprite* user); + void RemoveUser(const InstancedSprite* user); +public: + InstancedTexture(JGL::Texture* texture, const InstancedSprite* creator) : texture(texture) { users.push_back(creator); } + ~InstancedTexture(); +}; \ No newline at end of file diff --git a/include/Engine/Entity/Animation.h b/include/Engine/types/entity/Animation.h similarity index 100% rename from include/Engine/Entity/Animation.h rename to include/Engine/types/entity/Animation.h diff --git a/include/Engine/types/entity/Camera.h b/include/Engine/types/entity/Camera.h new file mode 100644 index 0000000..2c62530 --- /dev/null +++ b/include/Engine/types/entity/Camera.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include +#include + +namespace Engine { + class Camera; +} + +class Engine::Camera : public Entity, public Movable, public Renderable { +public: + void Render() override {}; +public: + explicit Camera(const Vector2& position) : Renderable(0), Movable(position) {} +}; diff --git a/include/Engine/types/entity/Entity.h b/include/Engine/types/entity/Entity.h new file mode 100644 index 0000000..5b0d859 --- /dev/null +++ b/include/Engine/types/entity/Entity.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include + +namespace Engine { + class Entity; +} + +class Engine::Entity { +protected: + // nullptr means no parent. + Entity* parent = nullptr; + + // Epoch micro-seconds. + long creation_time = 0.0f; + std::vector children{}; + void UpdateChildren(); +public: + // Parent child structure. + [[nodiscard]] bool AppendChild(Entity* entity); + void DestroyChild(Entity* entity); + void RemoveChild(Entity* entity); +public: + [[nodiscard]] std::vector GetChildren() const; + [[nodiscard]] Entity* GetParent() const; + + // Microseconds. + [[nodiscard]] long GetCreationTime() const; + [[nodiscard]] long GetAge() const; +public: + virtual void Update() {} +public: + virtual ~Entity(); + explicit Entity() : creation_time(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()) {} +}; \ No newline at end of file diff --git a/include/Engine/Entity/Hud.h b/include/Engine/types/entity/Hud.h similarity index 57% rename from include/Engine/Entity/Hud.h rename to include/Engine/types/entity/Hud.h index 2982a06..87a62ba 100644 --- a/include/Engine/Entity/Hud.h +++ b/include/Engine/types/entity/Hud.h @@ -1,5 +1,5 @@ #pragma once -#include +#include namespace Engine { class Hud; @@ -7,5 +7,5 @@ namespace Engine { class Engine::Hud : public Engine::Renderable { public: - Hud() : Renderable({0, 0}, 0, 0) {}; + Hud() : Renderable(0) {}; }; diff --git a/include/Engine/types/entity/InstancedSprite.h b/include/Engine/types/entity/InstancedSprite.h new file mode 100644 index 0000000..e1435f3 --- /dev/null +++ b/include/Engine/types/entity/InstancedSprite.h @@ -0,0 +1,28 @@ +#pragma once +#include + +namespace Engine { + class InstancedSprite; +} + +class Engine::InstancedSprite : public Sprite { +private: + std::string texture_path; + std::string alpha_mask_path; +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; +public: + /** The Texture *must* be instanced. The alpha-mask *can* be instanced. + * You can use SetAlphaMask() to change to a unique one. + * To change back to the instanced one if there is one, You can SetAlphaMask(nullptr); + * If there is no instanced alpha mask and unique alpha mask is set + * to nullptr, Then there is no alpha mask. - Redacted. + */ + 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 = "") + : texture_path(instanced_texture_filesystem_path), alpha_mask_path(instanced_alpha_mask_filesystem_path), + Sprite(position, layer, face_angle, base_color, nullptr, unique_alpha_mask) {} +}; diff --git a/include/Engine/Entity/Sprite.h b/include/Engine/types/entity/Sprite.h similarity index 50% rename from include/Engine/Entity/Sprite.h rename to include/Engine/types/entity/Sprite.h index 2012970..987a6d6 100644 --- a/include/Engine/Entity/Sprite.h +++ b/include/Engine/types/entity/Sprite.h @@ -1,6 +1,9 @@ #pragma once -#include +#include +#include +#include +#include #include #include @@ -8,23 +11,24 @@ namespace Engine { class Sprite; } -class Engine::Sprite : public Renderable { -protected: +using JGL::Texture; +class Engine::Sprite : public Entity, public Renderable, public Movable { +private: Texture* texture = nullptr; - // Positive alpha mask. Texture* alpha_mask = nullptr; +protected: Vector2 scale = {1, 1}; // Local space, Where the face_angle rotation should be preformed about. Vector2 origin = {0, 0}; Color4 base_color = Colors::White; -public: - [[nodiscard]] Texture* GetTexture(); - // World space. - [[nodiscard]] virtual AABB2D GetBounds(); +protected: + [[nodiscard]] virtual Texture* GetTexture(); + [[nodiscard]] virtual Texture* GetAlphaMask(); + void SetAlphaMask(Texture* new_alpha_mask); public: void Render() override; public: ~Sprite() override; - explicit Sprite(const Vector2& pos, unsigned int depth = 0, const float face_angle = 0.0f, const Color4& base_color = Colors::White, Texture* texture = nullptr, - Texture* alpha_mask = nullptr) : Renderable(pos, depth,face_angle), texture(texture), alpha_mask(alpha_mask), base_color(base_color) {} + 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) {} }; \ No newline at end of file diff --git a/include/Engine/types/entity/mixins/BoxCollider.h b/include/Engine/types/entity/mixins/BoxCollider.h new file mode 100644 index 0000000..0460426 --- /dev/null +++ b/include/Engine/types/entity/mixins/BoxCollider.h @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace Engine { + class BoxCollider; +} + +class Engine::BoxCollider { +private: + bool enabled = false; +public: + [[nodiscard]] virtual AABB2D GetBounds() = 0; + [[nodiscard]] bool BoxCollides(BoxCollider* rhs); + [[nodiscard]] bool BoxCollides(const Vector2& rhs); +public: + void EnableBoxCollision() { enabled = true; } + void DisableBoxCollision() { enabled = false; } +public: + explicit BoxCollider(bool enabled = true) : enabled(enabled) {} +}; \ No newline at end of file diff --git a/include/Engine/types/entity/mixins/Movable.h b/include/Engine/types/entity/mixins/Movable.h new file mode 100644 index 0000000..f51d4f6 --- /dev/null +++ b/include/Engine/types/entity/mixins/Movable.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace Engine { + class Movable; +} + +// Movable Object. +class Engine::Movable { +protected: + // Assuming 0 radians is up. + float face_angle = 0.0f; + Vector2 position = {0, 0}; +public: + // Movements independent of the face_angle. + void MoveX(float speed); + void MoveY(float speed); + void Move(float angle_rad, float speed); + + // Movements dependent on face angle. + void MoveForward(float speed); + void MoveBackward(float speed); + void MoveLeft(float speed); + void MoveRight(float speed); + + void Rotate(float speed); + void SetRotation(float new_rotation); +public: + [[nodiscard]] float GetRotation() const; + [[nodiscard]] Vector2 GetPosition() const; +public: + explicit Movable(const Vector2& position, float rad_rotation = 0.0f) : position(position), face_angle(rad_rotation) {} +}; \ No newline at end of file diff --git a/include/Engine/types/entity/mixins/Renderable.h b/include/Engine/types/entity/mixins/Renderable.h new file mode 100644 index 0000000..59669f6 --- /dev/null +++ b/include/Engine/types/entity/mixins/Renderable.h @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace Engine { + class Renderable; +} + +class Engine::Renderable { +protected: + // Higher numbers are farther to the back. + unsigned int layer = 0; +public: + [[nodiscard]] unsigned int GetLayer() const { return layer; } + void SetLayer(unsigned int new_layer) { layer = new_layer; } +public: + // *must* be overridden. + virtual void Render() = 0; +public: + explicit Renderable(unsigned int layer) : layer(layer) {} +}; \ No newline at end of file diff --git a/include/Engine/Level/Fixed.h b/include/Engine/types/scene/Fixed.h similarity index 90% rename from include/Engine/Level/Fixed.h rename to include/Engine/types/scene/Fixed.h index 96789f7..7957af1 100644 --- a/include/Engine/Level/Fixed.h +++ b/include/Engine/types/scene/Fixed.h @@ -1,8 +1,8 @@ #pragma once -#include "J3ML/LinearAlgebra/Vector2i.hpp" -#include "J3ML/Geometry/AABB2D.hpp" -#include "JGL/types/Texture.h" +#include +#include +#include using J3ML::LinearAlgebra::Vector2i; using JGL::Texture; diff --git a/include/Engine/Level/Scene.h b/include/Engine/types/scene/Scene.h similarity index 74% rename from include/Engine/Level/Scene.h rename to include/Engine/types/scene/Scene.h index 599e5b9..58ca8d4 100644 --- a/include/Engine/Level/Scene.h +++ b/include/Engine/types/scene/Scene.h @@ -1,9 +1,9 @@ #pragma once #include -#include -#include -#include +#include +#include +#include #include namespace Engine { @@ -11,11 +11,18 @@ namespace Engine { class Scene; } +using namespace JGL; + class Engine::Scene { protected: std::string name; Hud* heads_up_display = nullptr; Camera* active_camera = nullptr; + + std::vector instanced_textures{}; + std::vector instanced_alpha_masks{}; + + std::vector layers{}; std::vector fixed_list{}; std::vector entity_list{}; protected: @@ -27,6 +34,8 @@ public: [[nodiscard]] size_t EntityCount() const; [[nodiscard]] std::string GetName() const; [[nodiscard]] Camera* GetActiveCamera() const; + [[nodiscard]] Texture* GetInstancedTexture(const InstancedSprite* user); + [[nodiscard]] Texture* GetInstancedAlphaMask(const InstancedSprite* user); public: void AppendEntity(Entity* entity); void AppendFixed(Fixed* fixed); diff --git a/include/Game/Entity/Box.h b/include/Game/Entity/Box.h deleted file mode 100644 index bfae2e1..0000000 --- a/include/Game/Entity/Box.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include - -namespace Game { - class Box; -} - -class Game::Box final : public Engine::Renderable { -public: - void Render() final; - void Update() final; -public: - explicit Box(const Vector2& position, unsigned int depth = 0, float rotation = 0.0f) : Renderable(position, depth, rotation) {} -}; \ No newline at end of file diff --git a/include/Game/entity/Box.h b/include/Game/entity/Box.h new file mode 100644 index 0000000..a947daf --- /dev/null +++ b/include/Game/entity/Box.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include + +namespace Game { + class Box; +} + +class Game::Box final : public Engine::Entity, public Engine::Renderable, public Engine::Movable { +public: + void Render() final; + void Update() final; +public: + explicit Box(const Vector2& position, unsigned int depth = 0, float rotation = 0.0f) : Renderable(depth), Movable(position, rotation) {} +}; \ No newline at end of file diff --git a/include/Game/Entity/DemoGameHud.h b/include/Game/entity/DemoGameHud.h similarity index 82% rename from include/Game/Entity/DemoGameHud.h rename to include/Game/entity/DemoGameHud.h index e0f9493..f61aff6 100644 --- a/include/Game/Entity/DemoGameHud.h +++ b/include/Game/entity/DemoGameHud.h @@ -1,4 +1,4 @@ -#include +#include namespace Game { class DemoGameHud; diff --git a/include/Game/Scene/ControllableBox.h b/include/Game/scene/ControllableBox.h similarity index 82% rename from include/Game/Scene/ControllableBox.h rename to include/Game/scene/ControllableBox.h index 052d7a6..a698938 100644 --- a/include/Game/Scene/ControllableBox.h +++ b/include/Game/scene/ControllableBox.h @@ -1,5 +1,5 @@ #pragma once -#include +#include class ControllableBox final : public Engine::Scene { public: diff --git a/include/Game/Scene/Loading.h b/include/Game/scene/Loading.h similarity index 69% rename from include/Game/Scene/Loading.h rename to include/Game/scene/Loading.h index 2cb753c..22c1ae1 100644 --- a/include/Game/Scene/Loading.h +++ b/include/Game/scene/Loading.h @@ -1,5 +1,6 @@ #pragma once -#include +#include +#include class LoadingScreen final : public Engine::Scene { protected: @@ -11,6 +12,6 @@ public: void Init() final; void Update() final; - void Render(RenderTarget* render_target = nullptr) final; + void Render(JGL::RenderTarget* render_target = nullptr) final; ~LoadingScreen() final; }; diff --git a/main.cpp b/main.cpp index d480b35..33028cc 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,6 @@ #include -#include -#include -#include +#include +#include using namespace JGL; @@ -14,16 +13,7 @@ void CreateScenes() { }; int main() { - ReWindow::Logger::Error.EnableConsole(false); - ReWindow::Logger::Warning.EnableConsole(false); - ReWindow::Logger::Debug.EnableConsole(false); - Globals::Window = new Engine::DemoGameWindow("Demo Game", 1024, 896); - Globals::Window->SetRenderer(RenderingAPI::OPENGL); - Globals::Window->Open(); - Globals::Window->InitGL(); - Globals::Window->SetResizable(false); - Globals::Window->SetVsyncEnabled(false); CreateScenes(); Globals::ChangeScene("LoadingScreen"); diff --git a/src/Engine/Animation.cpp b/src/Engine/Animation.cpp index 4bf8096..244de39 100644 --- a/src/Engine/Animation.cpp +++ b/src/Engine/Animation.cpp @@ -1,5 +1,5 @@ -#include "Engine/Entity/Animation.h" -#include "jlog/Logger.hpp" +#include +#include float Animation::GetMsBetweenFrames() const { return ms_between_frames; diff --git a/src/Engine/Entity/Entity.cpp b/src/Engine/Entity/Entity.cpp deleted file mode 100644 index f9bdd59..0000000 --- a/src/Engine/Entity/Entity.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include - -using namespace J3ML; -void Engine::Entity::MoveX(float speed) { - position.x = position.x + (speed * Globals::Window->GetDeltaTime()); -} - -void Engine::Entity::MoveY(float speed) { - position.y = position.y + (speed * Globals::DeltaTime()); -} - -void Engine::Entity::Move(float angle_rad, float speed) { - position.x = position.x + (speed * Globals::DeltaTime()) * Math::Cos(angle_rad); - position.y = position.y + (speed * Globals::DeltaTime()) * Math::Sin(angle_rad); -} - -void Engine::Entity::MoveForward(float speed) { - Move(face_angle, speed); -} - -void Engine::Entity::MoveBackward(float speed) { - speed = -speed; - position.x = position.x + (speed * Globals::DeltaTime()) * Math::Cos(face_angle); - position.y = position.y + (speed * Globals::DeltaTime()) * Math::Sin(face_angle); -} - -void Engine::Entity::MoveLeft(float speed) { - position.x = position.x + (speed * Globals::DeltaTime()) * -Math::Sin(face_angle); - position.y = position.y + (speed * Globals::DeltaTime()) * Math::Cos(face_angle); -} - -void Engine::Entity::MoveRight(float speed) { - position.x = position.x + (speed * Globals::DeltaTime()) * Math::Sin(face_angle); - position.y = position.y + (speed * Globals::DeltaTime()) * -Math::Cos(face_angle); -} - -void Engine::Entity::SetRotation(float new_face_angle) { - face_angle = new_face_angle; - - if (face_angle < 0) - face_angle = fmod(face_angle + Math::Pi * 2, Math::Pi * 2); - else if (face_angle >= 2 * M_PI) - face_angle = fmod(face_angle, Math::Pi * 2); -} - -void Engine::Entity::Rotate(float speed) { - SetRotation(face_angle + speed * Globals::DeltaTime()); -} - -float Engine::Entity::GetRotation() const { - return face_angle; -} - -Vector2 Engine::Entity::GetPosition() const { - return position; -} - -bool Engine::Entity::AppendChild(Entity* entity) { - bool success = false; - if (!Globals::CurrentScene->EntityListContains(entity)) { - entity->parent = this; - children.push_back(entity); - success = true; - } - return success; -} - -Engine::Entity::~Entity() { - for (auto* e : children) - delete e; -} - -void Engine::Entity::UpdateChildren() { - for (auto& e : children) { - e->Update(); - if (!e->children.empty()) - e->UpdateChildren(); - } -} - -void Engine::Entity::DestroyChild(Entity* entity) { - auto it = std::find(children.begin(), children.end(), entity); - if (it != children.end()) - delete *it, children.erase(it); -} - -void Engine::Entity::RemoveChild(Entity* entity) { - auto it = std::find(children.begin(), children.end(), entity); - if (it != children.end()) - children.erase(it); -} - -long Engine::Entity::GetCreationTime() const { - return creation_time; -} - -long Engine::Entity::GetAge() const { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - creation_time; -} - -Engine::Entity* Engine::Entity::GetParent() const { - return parent; -} - -std::vector Engine::Entity::GetChildren() const { - return children; -} diff --git a/src/Engine/Entity/Sprite.cpp b/src/Engine/Entity/Sprite.cpp deleted file mode 100644 index 236cf7f..0000000 --- a/src/Engine/Entity/Sprite.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include - -Engine::Sprite::~Sprite() { - delete texture; - delete alpha_mask; -} - -void Engine::Sprite::Render() { - if (texture && !alpha_mask) - J2D::DrawSprite(texture, position, face_angle, origin, scale, base_color); - if (texture && alpha_mask) - J2D::DrawSprite(texture, alpha_mask, position, face_angle, origin, scale, base_color); -} - -AABB2D Engine::Sprite::GetBounds() { - return { position, texture->GetDimensions() + position }; -} - -Texture* Engine::Sprite::GetTexture() { - return texture; -} diff --git a/src/Engine/GameWindow.cpp b/src/Engine/GameWindow.cpp index 9572d60..0b606e3 100644 --- a/src/Engine/GameWindow.cpp +++ b/src/Engine/GameWindow.cpp @@ -1,6 +1,5 @@ #include #include -#include #include diff --git a/src/Engine/types/InstancedTexture.cpp b/src/Engine/types/InstancedTexture.cpp new file mode 100644 index 0000000..e96bd77 --- /dev/null +++ b/src/Engine/types/InstancedTexture.cpp @@ -0,0 +1,28 @@ +#include +#include + +using namespace Engine; +void InstancedTexture::AddUser(const InstancedSprite* user) { + // Prevent double references. + if (!InUseBy(user)) + users.push_back(user); +} + +void InstancedTexture::RemoveUser(const InstancedSprite* user) { + auto it = std::find(users.begin(), users.end(), user); + if (it != users.end()) + users.erase(it); +} + +bool InstancedTexture::InUseBy(const InstancedSprite* rhs) { + for (const auto* u : users) + if (u == rhs) + return true; + return false; +} + +InstancedTexture::~InstancedTexture() { + delete texture; + for (const auto* is: users) + delete is; +} diff --git a/src/Engine/types/entity/Entity.cpp b/src/Engine/types/entity/Entity.cpp new file mode 100644 index 0000000..dd10c9e --- /dev/null +++ b/src/Engine/types/entity/Entity.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +bool Engine::Entity::AppendChild(Entity* entity) { + if (!Globals::CurrentScene->EntityListContains(entity)) { + entity->parent = this; + children.push_back(entity); + return true; + } + return false; +} + +Engine::Entity::~Entity() { + for (auto* e : children) + delete e; +} + +void Engine::Entity::UpdateChildren() { + for (auto& e : children) { + e->Update(); + if (!e->children.empty()) + e->UpdateChildren(); + } +} + +void Engine::Entity::DestroyChild(Entity* entity) { + auto it = std::find(children.begin(), children.end(), entity); + if (it != children.end()) + delete *it, children.erase(it); +} + +void Engine::Entity::RemoveChild(Entity* entity) { + auto it = std::find(children.begin(), children.end(), entity); + if (it != children.end()) + children.erase(it); +} + +long Engine::Entity::GetCreationTime() const { + return creation_time; +} + +long Engine::Entity::GetAge() const { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - creation_time; +} + +Engine::Entity* Engine::Entity::GetParent() const { + return parent; +} + +std::vector Engine::Entity::GetChildren() const { + return children; +} diff --git a/src/Engine/types/entity/InstancedSprite.cpp b/src/Engine/types/entity/InstancedSprite.cpp new file mode 100644 index 0000000..53e7faf --- /dev/null +++ b/src/Engine/types/entity/InstancedSprite.cpp @@ -0,0 +1,13 @@ +#include +#include + +using namespace Engine; +Texture* InstancedSprite::GetTexture() { + return Globals::CurrentScene->GetInstancedTexture(this); +} + +Texture* InstancedSprite::GetAlphaMask() { + if (Sprite::GetAlphaMask()) + return Sprite::GetAlphaMask(); + return Globals::CurrentScene->GetInstancedAlphaMask(this); +} \ No newline at end of file diff --git a/src/Engine/types/entity/Moby.cpp b/src/Engine/types/entity/Moby.cpp new file mode 100644 index 0000000..4da41a8 --- /dev/null +++ b/src/Engine/types/entity/Moby.cpp @@ -0,0 +1,57 @@ +#include "Engine/types/entity/mixins/Movable.h" +#include "Engine/Globals.h" + +using namespace J3ML; +void Engine::Movable::MoveX(float speed) { + position.x = position.x + (speed * Globals::Window->GetDeltaTime()); +} + +void Engine::Movable::MoveY(float speed) { + position.y = position.y + (speed * Globals::DeltaTime()); +} + +void Engine::Movable::Move(float angle_rad, float speed) { + position.x = position.x + (speed * Globals::DeltaTime()) * Math::Cos(angle_rad); + position.y = position.y + (speed * Globals::DeltaTime()) * Math::Sin(angle_rad); +} + +void Engine::Movable::MoveForward(float speed) { + Move(face_angle, speed); +} + +void Engine::Movable::MoveBackward(float speed) { + speed = -speed; + position.x = position.x + (speed * Globals::DeltaTime()) * Math::Cos(face_angle); + position.y = position.y + (speed * Globals::DeltaTime()) * Math::Sin(face_angle); +} + +void Engine::Movable::MoveLeft(float speed) { + position.x = position.x + (speed * Globals::DeltaTime()) * -Math::Sin(face_angle); + position.y = position.y + (speed * Globals::DeltaTime()) * Math::Cos(face_angle); +} + +void Engine::Movable::MoveRight(float speed) { + position.x = position.x + (speed * Globals::DeltaTime()) * Math::Sin(face_angle); + position.y = position.y + (speed * Globals::DeltaTime()) * -Math::Cos(face_angle); +} + +void Engine::Movable::SetRotation(float new_face_angle) { + face_angle = new_face_angle; + + if (face_angle < 0) + face_angle = fmod(face_angle + Math::Pi * 2, Math::Pi * 2); + else if (face_angle >= 2 * M_PI) + face_angle = fmod(face_angle, Math::Pi * 2); +} + +void Engine::Movable::Rotate(float speed) { + SetRotation(face_angle + speed * Globals::DeltaTime()); +} + +float Engine::Movable::GetRotation() const { + return face_angle; +} + +Vector2 Engine::Movable::GetPosition() const { + return position; +} \ No newline at end of file diff --git a/src/Engine/types/entity/Sprite.cpp b/src/Engine/types/entity/Sprite.cpp new file mode 100644 index 0000000..5829d86 --- /dev/null +++ b/src/Engine/types/entity/Sprite.cpp @@ -0,0 +1,29 @@ +#include +#include + +Engine::Sprite::~Sprite() { + delete texture; + delete alpha_mask; +} + +void Engine::Sprite::Render() { + auto* t = GetTexture(); + auto* a = GetAlphaMask(); + + if (t && !a) + return J2D::DrawSprite(t, position, face_angle, origin, scale, base_color); + if (t && a) + return J2D::DrawSprite(t, a, position, face_angle, origin, scale, base_color); +} + +Texture* Engine::Sprite::GetTexture() { + return texture; +} + +Texture* Engine::Sprite::GetAlphaMask() { + return alpha_mask; +} + +void Engine::Sprite::SetAlphaMask(Texture* new_alpha_mask) { + alpha_mask = new_alpha_mask; +} diff --git a/src/Engine/types/entity/mixins/BoxCollider.cpp b/src/Engine/types/entity/mixins/BoxCollider.cpp new file mode 100644 index 0000000..c83f6d1 --- /dev/null +++ b/src/Engine/types/entity/mixins/BoxCollider.cpp @@ -0,0 +1,14 @@ +#include "Engine/types/entity/mixins/BoxCollider.h" + +using namespace Engine; +bool BoxCollider::BoxCollides(BoxCollider* rhs) { + if (GetBounds().Intersects(rhs->GetBounds())) + return true; + if (GetBounds().Contains(rhs->GetBounds())) + return true; + return false; +} + +bool BoxCollider::BoxCollides(const Vector2& rhs) { + return GetBounds().Contains(rhs); +} diff --git a/src/Engine/Level/Fixed.cpp b/src/Engine/types/scene/Fixed.cpp similarity index 96% rename from src/Engine/Level/Fixed.cpp rename to src/Engine/types/scene/Fixed.cpp index de2fad2..3988d11 100644 --- a/src/Engine/Level/Fixed.cpp +++ b/src/Engine/types/scene/Fixed.cpp @@ -1,4 +1,4 @@ -#include +#include "Engine/types/scene/Fixed.h" bool Engine::Fixed::Collidable() const { return collidable; diff --git a/src/Engine/Level/Scene.cpp b/src/Engine/types/scene/Scene.cpp similarity index 60% rename from src/Engine/Level/Scene.cpp rename to src/Engine/types/scene/Scene.cpp index f8e2b33..7869b9b 100644 --- a/src/Engine/Level/Scene.cpp +++ b/src/Engine/types/scene/Scene.cpp @@ -1,32 +1,35 @@ -#include -#include +#include +#include +#include +#include #include -bool Engine::Scene::EntityListContains(const Entity* entity) const { +using namespace Engine; +bool Scene::EntityListContains(const Entity* entity) const { auto flat = GetFlatEntityList(entity_list); - + for (auto* e : flat) if (e == entity) return true; return false; } -bool Engine::Scene::FixedListContains(const Fixed* fixed) const { +bool Scene::FixedListContains(const Fixed* fixed) const { for (auto* f : fixed_list) if (f == fixed) return true; return false; } -size_t Engine::Scene::FixedCount() const { +size_t Scene::FixedCount() const { return fixed_list.size(); } -size_t Engine::Scene::EntityCount() const { +size_t Scene::EntityCount() const { return GetFlatEntityList(entity_list).size(); } -void Engine::Scene::Update() { +void Scene::Update() { if (active_camera) active_camera->Update(); @@ -35,7 +38,7 @@ void Engine::Scene::Update() { e->Update(); } -void Engine::Scene::Render(RenderTarget* render_target) { +void Scene::Render(RenderTarget* render_target) { // The Camera and the HUD are ignored here because they're special cases. std::vector display_list{}; for (auto* e : GetFlatEntityList(entity_list)) @@ -45,7 +48,7 @@ void Engine::Scene::Render(RenderTarget* render_target) { display_list.push_back(r); std::sort(display_list.begin(), display_list.end(), [](Renderable* a, Renderable* b) { - return a->GetDepth() > b->GetDepth(); + return a->GetLayer() > b->GetLayer(); }); J2D::Begin( render_target, true); @@ -66,7 +69,7 @@ void Engine::Scene::Render(RenderTarget* render_target) { J2D::End(); } -Engine::Scene::~Scene() { +Scene::~Scene() { for (auto* f : fixed_list) delete f; @@ -77,7 +80,7 @@ Engine::Scene::~Scene() { delete active_camera; } -void Engine::Scene::Unload() { +void Scene::Unload() { for (auto* f : fixed_list) delete f; @@ -87,50 +90,50 @@ void Engine::Scene::Unload() { delete heads_up_display; } -void Engine::Scene::AppendEntity(Entity* entity) { +void Scene::AppendEntity(Entity* entity) { if (!EntityListContains(entity)) entity_list.push_back(entity); } -void Engine::Scene::AppendFixed(Fixed* fixed) { +void Scene::AppendFixed(Fixed* fixed) { if (!FixedListContains(fixed)) fixed_list.push_back(fixed); } -void Engine::Scene::DestroyEntity(Entity *entity) { +void Scene::DestroyEntity(Entity *entity) { auto it = std::find(entity_list.begin(), entity_list.end(), entity); if (it != entity_list.end()) delete *it, entity_list.erase(it); } -void Engine::Scene::DestroyFixed(Fixed* fixed) { +void Scene::DestroyFixed(Fixed* fixed) { auto it = std::find(fixed_list.begin(), fixed_list.end(), fixed); if (it != fixed_list.end()) delete *it, fixed_list.erase(it); } -void Engine::Scene::RemoveEntity(Entity* entity) { +void Scene::RemoveEntity(Entity* entity) { auto it = std::find(entity_list.begin(), entity_list.end(), entity); if (it != entity_list.end()) entity_list.erase(it); } -void Engine::Scene::RemoveFixed(Fixed* fixed) { +void Scene::RemoveFixed(Fixed* fixed) { auto it = std::find(fixed_list.begin(), fixed_list.end(), fixed); if (it != fixed_list.end()) fixed_list.erase(it); } -std::string Engine::Scene::GetName() const { +std::string Scene::GetName() const { return name; } -Engine::Camera* Engine::Scene::GetActiveCamera() const { +Camera* Scene::GetActiveCamera() const { return active_camera; } -std::vector Engine::Scene::GetFlatEntityList(const std::vector& ent_list) const { +std::vector Scene::GetFlatEntityList(const std::vector& ent_list) const { std::vector result{}; for (auto* e : ent_list) { @@ -142,3 +145,28 @@ std::vector Engine::Scene::GetFlatEntityList(const std::vector< return result; } +Texture* Scene::GetInstancedTexture(const InstancedSprite* user) { + for (auto* itx : instanced_textures) + if (itx->InUseBy(user)) + return itx->GetTexture(); + + auto* t = new Texture(user->GetTextureFilesystemPath()); + auto* itx = new InstancedTexture(t, user); + instanced_textures.push_back(itx); + return t; +} + +Texture* Scene::GetInstancedAlphaMask(const InstancedSprite* user) { + for (auto* itx : instanced_alpha_masks) + if (itx->InUseBy(user)) + return itx->GetTexture(); + + if (!user->GetAlphaMaskFilesystemPath().empty()) { + auto *t = new Texture(user->GetTextureFilesystemPath()); + auto *itx = new InstancedTexture(t, user); + instanced_textures.push_back(itx); + return t; + } + return nullptr; +} + diff --git a/src/Game/Entities/Box.cpp b/src/Game/Entities/Box.cpp index 552f717..3d72cf7 100644 --- a/src/Game/Entities/Box.cpp +++ b/src/Game/Entities/Box.cpp @@ -1,4 +1,6 @@ -#include +#include +#include +#include void Game::Box::Render() { J2D::FillRect(Colors::Red, Vector2(position), {20, 20}); @@ -13,4 +15,4 @@ void Game::Box::Update() { MoveX(-500); if (Globals::Window->IsKeyDown(Keys::D)) MoveX(500); - } \ No newline at end of file +} \ No newline at end of file diff --git a/src/Game/Entities/DemoGameHud.cpp b/src/Game/Entities/DemoGameHud.cpp index b6b404d..e72c15e 100644 --- a/src/Game/Entities/DemoGameHud.cpp +++ b/src/Game/Entities/DemoGameHud.cpp @@ -1,5 +1,6 @@ -#include +#include #include +#include void Game::DemoGameHud::Render() { J2D::DrawString(Colors::Whites::Ivory, "Framerate: " + std::to_string((int) Globals::Window->GetRefreshRate()), 0, 0, 1, 16); diff --git a/src/Game/Scene/ControllableBox.cpp b/src/Game/Scene/ControllableBox.cpp index 24575f3..8447e78 100644 --- a/src/Game/Scene/ControllableBox.cpp +++ b/src/Game/Scene/ControllableBox.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include void ControllableBox::Init() { auto* hud = new Game::DemoGameHud(); diff --git a/src/Game/Scene/Loading.cpp b/src/Game/Scene/Loading.cpp index 2ea9fc6..5900bf2 100644 --- a/src/Game/Scene/Loading.cpp +++ b/src/Game/Scene/Loading.cpp @@ -1,5 +1,6 @@ -#include +#include #include +#include void LoadingScreen::Init() { RedactedSoftware = new JGL::Texture("assets/sprites/Re3D.png");