From 71096200f6772feff87ec953bba91d2ef0aa35af Mon Sep 17 00:00:00 2001 From: VisualGMQ <2142587070@qq.com> Date: Mon, 7 Feb 2022 21:38:35 +0800 Subject: [PATCH] finished basic spaceship, it can move and shoot --- CMakeLists.txt | 9 +- assets/shoot.wav | Bin 0 -> 10188 bytes assets/tilesheet.png | Bin 0 -> 488 bytes include/game/action.hpp | 7 + include/game/component.hpp | 125 ++++++++++++++++++ include/game/constants.hpp | 9 ++ include/game/controller.hpp | 8 ++ .../game/controllers/spaceship_controller.hpp | 16 +++ include/game/entity.hpp | 8 ++ include/game/global.hpp | 18 +++ include/game/quick_list.hpp | 45 +++++++ include/game/stages/space.hpp | 19 +++ include/game/system.hpp | 41 ++++++ include/tinyengine/ecs/component.hpp | 4 +- include/tinyengine/ecs/context.hpp | 2 +- include/tinyengine/ecs/ecs.hpp | 1 + include/tinyengine/ecs/entity.hpp | 6 +- include/tinyengine/ecs/system.hpp | 48 +++++++ include/tinyengine/engine.hpp | 1 + include/tinyengine/event.hpp | 6 + include/tinyengine/pch.hpp | 4 +- include/tinyengine/tinyengine.hpp | 1 + .../{stbi_image.cpp => stbi_image.c} | 0 src/game/action.cpp | 14 ++ src/game/component.cpp | 9 ++ src/game/controllers/spaceship_controller.cpp | 37 ++++++ src/game/entity.cpp | 24 ++++ src/game/global.cpp | 22 +++ src/game/main.cpp | 4 +- src/game/stages/space.cpp | 32 +++++ src/game/system.cpp | 98 ++++++++++++++ src/tinyengine/audio.cpp | 2 +- src/tinyengine/camera.cpp | 2 +- src/tinyengine/ecs/component.cpp | 4 +- src/tinyengine/ecs/context.cpp | 4 +- src/tinyengine/ecs/system.cpp | 17 +++ src/tinyengine/engine.cpp | 2 +- src/tinyengine/event.cpp | 21 ++- src/tinyengine/glhelpfunc.cpp | 2 +- src/tinyengine/inner_bmpfont.cpp | 2 +- src/tinyengine/libmath.cpp | 2 +- src/tinyengine/renderer.cpp | 4 +- src/tinyengine/shader.cpp | 2 +- src/tinyengine/texture.cpp | 2 +- src/tinyengine/tilesheet.cpp | 2 +- tests/CMakeLists.txt | 9 +- tests/quicklist.cpp | 24 ++++ 47 files changed, 684 insertions(+), 35 deletions(-) create mode 100644 assets/shoot.wav create mode 100644 assets/tilesheet.png create mode 100644 include/game/action.hpp create mode 100644 include/game/component.hpp create mode 100644 include/game/constants.hpp create mode 100644 include/game/controller.hpp create mode 100644 include/game/controllers/spaceship_controller.hpp create mode 100644 include/game/entity.hpp create mode 100644 include/game/global.hpp create mode 100644 include/game/quick_list.hpp create mode 100644 include/game/stages/space.hpp create mode 100644 include/game/system.hpp create mode 100644 include/tinyengine/ecs/system.hpp rename libs/stb_image/{stbi_image.cpp => stbi_image.c} (100%) create mode 100644 src/game/action.cpp create mode 100644 src/game/component.cpp create mode 100644 src/game/controllers/spaceship_controller.cpp create mode 100644 src/game/entity.cpp create mode 100644 src/game/global.cpp create mode 100644 src/game/stages/space.cpp create mode 100644 src/game/system.cpp create mode 100644 src/tinyengine/ecs/system.cpp create mode 100644 tests/quicklist.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5401f34..57136d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,7 @@ add_subdirectory(libs/glfw) target_include_directories( ${ENGINE_NAME} - PRIVATE include/tinyengine - PUBLIC libs/glad/include libs/stb_image libs/miniaudio # /usr/local/Cellar/glm/0.9.9.8/include + PUBLIC include libs/glad/include libs/stb_image libs/miniaudio # /usr/local/Cellar/glm/0.9.9.8/include ) target_link_libraries( @@ -54,13 +53,9 @@ target_compile_options( ################ aux_source_directory(src/game GAME_SRC) aux_source_directory(src/game/stages GAME_SRC) +aux_source_directory(src/game/controllers GAME_SRC) add_executable(${PROJECT_NAME} ${GAME_SRC}) -target_include_directories( - ${PROJECT_NAME} - PRIVATE include -) - target_link_libraries( ${PROJECT_NAME} PRIVATE ${ENGINE_NAME} diff --git a/assets/shoot.wav b/assets/shoot.wav new file mode 100644 index 0000000000000000000000000000000000000000..cafe904abdb76dd25ea28bbbd14b54caa2e083c4 GIT binary patch literal 10188 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 q?f%FooXupqKIggvF!V_Tmp=10RoC}type = type; + this->owner = owner; + this->damage = damage; + this->shootSpeed = shootSpeed; + this->shootDuration = duration; + this->maxSpeed = maxSpeed; + } + + void Release() {} + bool IsCoolDowning() const { return coolDown >= 0; } + Entity* ShootBullet(const Point& dir); + + Type type; + int damage; + float shootSpeed; + float shootDuration; + float coolDown; + float maxSpeed; + Entity* owner; +}; + +class SpaceshipArmorCmpt: public Component { +public: + void Init(int defence, float duration) { + this->defence = defence; + this->recoverDuration = duration; + } + + int defence; + float recoverDuration; +}; + +class LifeCmpt: public Component { +public: + void Init(int hp) { this->hp = hp; } + void Release() {} + + int hp; +}; + +class RenderCmpt: public Component { +public: + enum Type { + TypeTexture = 1, + TypeTile, + }; + + void Init(Texture* image) { + texture = image; + type = TypeTexture; + } + void Init(const Tile& tile) { + this->tile = tile; + type = TypeTile; + } + void Release() {} + + Type type; + union { + Texture* texture; + Tile tile; + }; +}; + +class BulletCmpt: public Component { +public: + inline void Init(int damage, Entity* owner) { + this->owner = owner; + this->damage = damage; + } + inline void Release() override {} + + int damage; + Entity* owner; + bool alive; +}; diff --git a/include/game/constants.hpp b/include/game/constants.hpp new file mode 100644 index 0000000..8f0c186 --- /dev/null +++ b/include/game/constants.hpp @@ -0,0 +1,9 @@ +#pragma once + +constexpr float FreightMaxSpeed = 100; +constexpr float LazerDamage = 2; +constexpr float LazerShooterSpeed = 1000; +constexpr float LazerShooterMaxSpeed = 1000; +constexpr float LazerShooterCooldown = 0.3; +constexpr int GameWindowWidth = 1024; +constexpr int GameWindowHeight = 720; diff --git a/include/game/controller.hpp b/include/game/controller.hpp new file mode 100644 index 0000000..35a95ee --- /dev/null +++ b/include/game/controller.hpp @@ -0,0 +1,8 @@ +#pragma once + +class Controller { +public: + virtual ~Controller() = default; + + virtual void Update(float dt) = 0; +}; diff --git a/include/game/controllers/spaceship_controller.hpp b/include/game/controllers/spaceship_controller.hpp new file mode 100644 index 0000000..ccd366b --- /dev/null +++ b/include/game/controllers/spaceship_controller.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "game/controller.hpp" +#include "tinyengine/tinyengine.hpp" +#include "game/entity.hpp" +#include "game/component.hpp" +#include "game/action.hpp" + +class FreeRotationController: public Controller { +public: + FreeRotationController(Entity* entity); + void Update(float dt) override; + +private: + Entity* entity_; +}; diff --git a/include/game/entity.hpp b/include/game/entity.hpp new file mode 100644 index 0000000..36d17ab --- /dev/null +++ b/include/game/entity.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "tinyengine/tinyengine.hpp" +#include "game/component.hpp" +#include "game/global.hpp" + +Entity* CreateFreightShip(); +Entity* CreateBullet(int damage, Entity* owner, float maxSpeedß); diff --git a/include/game/global.hpp b/include/game/global.hpp new file mode 100644 index 0000000..7f07ce7 --- /dev/null +++ b/include/game/global.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "tinyengine/tinyengine.hpp" +#include "game/quick_list.hpp" + +extern Context ECSContext; +extern SystemManager SystemMgr; +extern std::unordered_map> TileSheets; +extern std::unordered_map> Sounds; +extern std::string TileSheetName; + +extern QuickList Bullets; + +using EntityList = std::vector; + +extern EntityList Entities; + +void LoadResources(); diff --git a/include/game/quick_list.hpp b/include/game/quick_list.hpp new file mode 100644 index 0000000..c55e304 --- /dev/null +++ b/include/game/quick_list.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "tinyengine/tinyengine.hpp" + +template +class QuickList final { +public: + void Add(const T& elem) { + datas_.push_back(elem); + } + + void RemoveAll(std::function func) { + int idx = 0; + while (idx < datas_.size()) { + if (func(datas_[idx]) && datas_.size() > idx) { + std::swap(datas_[idx], datas_[datas_.size() - 1]); + datas_.pop_back(); + } else { + idx ++; + } + } + } + void Clear() { datas_.clear(); } + + // for debug + void PrintAll(std::function func = nullptr) { + printf("QuickList: "); + for (auto& elem : datas_) { + if (func == nullptr) { + std::cout << elem << ", "; + } else { + func(elem); + } + } + printf("\n"); + } + + using const_iterator = typename std::vector::const_iterator; + + const_iterator begin() const { return datas_.begin(); } + const_iterator end() const { return datas_.end(); } + +private: + std::vector datas_; +}; diff --git a/include/game/stages/space.hpp b/include/game/stages/space.hpp new file mode 100644 index 0000000..3faefc6 --- /dev/null +++ b/include/game/stages/space.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "tinyengine/tinyengine.hpp" +#include "game/global.hpp" +#include "game/entity.hpp" +#include "game/system.hpp" +#include "game/controllers/spaceship_controller.hpp" + +class SpaceScence: public Scence { +public: + void OnInit() override; + void OnUpdate(float dt) override; + void OnRender() override; + void OnQuit() override; + +private: + Entity* spaceship_; + Unique controller_; +}; diff --git a/include/game/system.hpp b/include/game/system.hpp new file mode 100644 index 0000000..a250713 --- /dev/null +++ b/include/game/system.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "tinyengine/ecs/system.hpp" +#include "tinyengine/tinyengine.hpp" +#include "game/global.hpp" +#include "game/component.hpp" +#include "game/entity.hpp" + +class PhysicalSystem: public UpdateSystem { +public: + void Update(float dt) override; + +private: + void physicalStep(Entity* entity, float dt, MoveCmpt&, MotionCmpt&); +}; + +class ColliRectCorrectSystem: public UpdateSystem { +public: + void Update(float dt) override; + +private: + void correctColliRect(MoveCmpt&, CollisionCmpt&); +}; + +class CleanupSystem: public UpdateSystem { +public: + void Update(float dt) override; +}; + +class BulletCooldownSystem: public UpdateSystem { +public: + void Update(float dt) override; +}; + +class RenderEntitySystem: public RenderSystem { +public: + void Render() override; + +private: + void renderEntity(Entity* entity, const RenderCmpt&); +}; diff --git a/include/tinyengine/ecs/component.hpp b/include/tinyengine/ecs/component.hpp index 668a4f1..43b87f2 100644 --- a/include/tinyengine/ecs/component.hpp +++ b/include/tinyengine/ecs/component.hpp @@ -1,7 +1,7 @@ _Pragma("once") -#include "pch.hpp" -#include "pool.hpp" +#include "tinyengine/pch.hpp" +#include "tinyengine/pool.hpp" using ComponentId = unsigned int; diff --git a/include/tinyengine/ecs/context.hpp b/include/tinyengine/ecs/context.hpp index 1332c26..317f452 100644 --- a/include/tinyengine/ecs/context.hpp +++ b/include/tinyengine/ecs/context.hpp @@ -1,6 +1,6 @@ _Pragma("once") -#include "pool.hpp" +#include "tinyengine/pool.hpp" #include "component.hpp" class Entity; diff --git a/include/tinyengine/ecs/ecs.hpp b/include/tinyengine/ecs/ecs.hpp index 606c363..c1f8772 100644 --- a/include/tinyengine/ecs/ecs.hpp +++ b/include/tinyengine/ecs/ecs.hpp @@ -3,3 +3,4 @@ _Pragma("once") #include "entity.hpp" #include "component.hpp" #include "context.hpp" +#include "system.hpp" diff --git a/include/tinyengine/ecs/entity.hpp b/include/tinyengine/ecs/entity.hpp index efa66fa..0700803 100644 --- a/include/tinyengine/ecs/entity.hpp +++ b/include/tinyengine/ecs/entity.hpp @@ -1,7 +1,7 @@ -_Pragma("once") +#pragma once -#include "pch.hpp" -#include "pool.hpp" +#include "tinyengine/pch.hpp" +#include "tinyengine/pool.hpp" #include "component.hpp" #include "context.hpp" diff --git a/include/tinyengine/ecs/system.hpp b/include/tinyengine/ecs/system.hpp new file mode 100644 index 0000000..40eb5df --- /dev/null +++ b/include/tinyengine/ecs/system.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "entity.hpp" +#include "tinyengine/tinyengine.hpp" + +class System { +public: + virtual ~System() = default; + + bool IsWorking() const { return active_; } + void StartWork() { active_ = true; } + void StopWork() { active_ = false; } + +private: + bool active_ = true; +}; + +class UpdateSystem: public System { +public: + virtual ~UpdateSystem() = default; + + virtual void Update(float dt) = 0; +}; + +class RenderSystem: public System { +public: + virtual ~RenderSystem() = default; + + virtual void Render() = 0; +}; + + +class SystemManager final { +public: + void AddUpdateSystem(UpdateSystem* system) { updateSystems_.emplace_back(system); } + void AddRenderSystem(RenderSystem* system) { renderSystems_.emplace_back(system); } + + void Update(float dt); + void Render(); + + void Clear() { ClearUpdateSystems(); ClearRenderSystems(); } + void ClearUpdateSystems() { updateSystems_.clear(); } + void ClearRenderSystems() { renderSystems_.clear(); } + +private: + std::vector> updateSystems_; + std::vector> renderSystems_; +}; diff --git a/include/tinyengine/engine.hpp b/include/tinyengine/engine.hpp index 1e32472..88ddb1a 100644 --- a/include/tinyengine/engine.hpp +++ b/include/tinyengine/engine.hpp @@ -1,4 +1,5 @@ #pragma once + #include "pch.hpp" #include "libmath.hpp" #include "renderer.hpp" diff --git a/include/tinyengine/event.hpp b/include/tinyengine/event.hpp index f5da7ca..9781b8e 100644 --- a/include/tinyengine/event.hpp +++ b/include/tinyengine/event.hpp @@ -2,3 +2,9 @@ #include "renderer.hpp" void OnWindowResize(GLFWwindow* window, int width, int height); + +bool IsKeyPressing(int key); + +bool IsLeftPressing(); +bool IsRightPressing(); +Point GetMousePosition(); diff --git a/include/tinyengine/pch.hpp b/include/tinyengine/pch.hpp index b171621..29f5a2e 100644 --- a/include/tinyengine/pch.hpp +++ b/include/tinyengine/pch.hpp @@ -2,9 +2,10 @@ #include "glad/gl.h" #include "GLFW/glfw3.h" -#include "stb_image.h" + #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include "miniaudio.h" +#include "stb_image.h" #ifdef USE_GLM #include "glm/glm.hpp" diff --git a/include/tinyengine/tinyengine.hpp b/include/tinyengine/tinyengine.hpp index 7b64e94..02e5193 100644 --- a/include/tinyengine/tinyengine.hpp +++ b/include/tinyengine/tinyengine.hpp @@ -11,3 +11,4 @@ #include "inner_bmpfont.hpp" #include "audio.hpp" #include "tilesheet.hpp" +#include "ecs/ecs.hpp" diff --git a/libs/stb_image/stbi_image.cpp b/libs/stb_image/stbi_image.c similarity index 100% rename from libs/stb_image/stbi_image.cpp rename to libs/stb_image/stbi_image.c diff --git a/src/game/action.cpp b/src/game/action.cpp new file mode 100644 index 0000000..0cc8235 --- /dev/null +++ b/src/game/action.cpp @@ -0,0 +1,14 @@ +#include "game/action.hpp" + +void Shoot(SpaceshipWeaponCmpt& weapon, const Point& dir) { + if (weapon.IsCoolDowning()) return; + + Point playerCenterPos = weapon.owner->Get()->position; + + auto bullet = weapon.ShootBullet(Normalize(dir) * weapon.shootSpeed); + Bullets.Add(bullet); + + weapon.coolDown = weapon.shootDuration; + + Sounds["shoot"]->Play(); +} diff --git a/src/game/component.cpp b/src/game/component.cpp new file mode 100644 index 0000000..48d01f0 --- /dev/null +++ b/src/game/component.cpp @@ -0,0 +1,9 @@ +#include "game/component.hpp" +#include "game/entity.hpp" + +Entity* SpaceshipWeaponCmpt::ShootBullet(const Point& dir) { + Entity* bullet = CreateBullet(damage, owner, maxSpeed); + bullet->Use()->speed = Normalize(dir) * shootSpeed; + bullet->Use()->position = owner->Get()->position; + return bullet; +} diff --git a/src/game/controllers/spaceship_controller.cpp b/src/game/controllers/spaceship_controller.cpp new file mode 100644 index 0000000..770d99e --- /dev/null +++ b/src/game/controllers/spaceship_controller.cpp @@ -0,0 +1,37 @@ +#include "game/controllers/spaceship_controller.hpp" +#include "tinyengine/event.hpp" + +FreeRotationController::FreeRotationController(Entity* entity) + : entity_(entity) {} + +void FreeRotationController::Update(float dt) { + const float spd = 100; + auto motionCmpt = entity_->Use(); + if (IsKeyPressing(GLFW_KEY_A)) { + // motionCmpt->speed += Point{-spd, 0}; + motionCmpt->acceleration += Point{-spd, 0}; + // motionCmpt->speed.x = -spd; + } + if (IsKeyPressing(GLFW_KEY_D)) { + // motionCmpt->speed += Point{spd, 0}; + motionCmpt->acceleration += Point{spd, 0}; + // motionCmpt->speed.x = spd; + } + if (IsKeyPressing(GLFW_KEY_S)) { + // motionCmpt->speed += Point{0, spd}; + motionCmpt->acceleration += Point{0, spd}; + // motionCmpt->speed.y = spd; + } + if (IsKeyPressing(GLFW_KEY_W)) { + // motionCmpt->speed += Point{0, -spd}; + motionCmpt->acceleration += Point{0, -spd}; + // motionCmpt->speed.y = -spd; + } + + if (IsLeftPressing()) { + if (entity_->Has()) { + Shoot(*entity_->Use(), + GetMousePosition() - entity_->Get()->position); + } + } +} diff --git a/src/game/entity.cpp b/src/game/entity.cpp new file mode 100644 index 0000000..f9a363b --- /dev/null +++ b/src/game/entity.cpp @@ -0,0 +1,24 @@ +#include "game/entity.hpp" + +Entity* CreateFreightShip() { + Entity* entity = ECSContext.CreateEntity(); + entity->Add(Point{0, 0}); + entity->Add(Point{0, 0}, FreightMaxSpeed); + entity->Add(TileSheets[TileSheetName]->GetTile(0, 0)); + entity->Add(SpaceshipWeaponCmpt::Orientation, + entity, + LazerDamage, + LazerShooterSpeed, + LazerShooterMaxSpeed, + LazerShooterCooldown); + return entity; +} + +Entity* CreateBullet(int damage, Entity* owner, float maxSpeed) { + Entity* entity = ECSContext.CreateEntity(); + entity->Add(Point{0, 0}); + entity->Add(Point{0, 0}, maxSpeed); + entity->Add(TileSheets[TileSheetName]->GetTile(0, 1)); + entity->Add(damage, owner); + return entity; +} diff --git a/src/game/global.cpp b/src/game/global.cpp new file mode 100644 index 0000000..3a76481 --- /dev/null +++ b/src/game/global.cpp @@ -0,0 +1,22 @@ +#include "game/global.hpp" + +Context ECSContext; +SystemManager SystemMgr; +std::unordered_map> TileSheets; +std::unordered_map> Sounds; +std::string TileSheetName = "TileSheet"; +QuickList Bullets; +EntityList Entities; + +void loadImages() { + TileSheets[TileSheetName] = std::make_unique("assets/tilesheet.png", 8, 8); +} + +void loadSounds() { + Sounds["shoot"] = std::make_unique("assets/shoot.wav"); +} + +void LoadResources() { + loadImages(); + loadSounds(); +} diff --git a/src/game/main.cpp b/src/game/main.cpp index bc0a03b..b0ab3cb 100644 --- a/src/game/main.cpp +++ b/src/game/main.cpp @@ -1,3 +1,5 @@ #include "game/stages/gamelogo.hpp" +#include "game/stages/space.hpp" +#include "game/constants.hpp" -RUN_WINDOW("Space Sector", 1024, 720, GameLogoScence) +RUN_WINDOW("Space Sector", GameWindowWidth, GameWindowHeight, SpaceScence) diff --git a/src/game/stages/space.cpp b/src/game/stages/space.cpp new file mode 100644 index 0000000..1e996ba --- /dev/null +++ b/src/game/stages/space.cpp @@ -0,0 +1,32 @@ +#include "game/stages/space.hpp" + +void SpaceScence::OnInit() { + Renderer::SetClearColor(Color{0, 0, 0, 255}); + LoadResources(); + + spaceship_ = CreateFreightShip(); + Entities.push_back(spaceship_); + spaceship_->Use()->position = Point{400, 400}; + + controller_.reset(new FreeRotationController(spaceship_)); + + SystemMgr.Clear(); + SystemMgr.AddRenderSystem(new RenderEntitySystem); + SystemMgr.AddUpdateSystem(new BulletCooldownSystem); + SystemMgr.AddUpdateSystem(new PhysicalSystem); + SystemMgr.AddUpdateSystem(new ColliRectCorrectSystem); + SystemMgr.AddUpdateSystem(new CleanupSystem); +} + +void SpaceScence::OnUpdate(float dt) { + controller_->Update(dt); + SystemMgr.Update(dt); +} + +void SpaceScence::OnRender() { + SystemMgr.Render(); +} + +void SpaceScence::OnQuit() { + +} diff --git a/src/game/system.cpp b/src/game/system.cpp new file mode 100644 index 0000000..62f6b0c --- /dev/null +++ b/src/game/system.cpp @@ -0,0 +1,98 @@ +#include "game/system.hpp" + +void PhysicalSystem::Update(float dt) { + for (auto& entity: Entities) { + if (entity->Has() && entity->Has()) { + // update entities + physicalStep(entity, dt, + *entity->Use(), + *entity->Use()); + + // update bullets + for (auto& bullet : Bullets) { + if (bullet->Has() && bullet->Has()) { + physicalStep(bullet, dt, + *bullet->Use(), + *bullet->Use()); + } + } + + } + } +} + +void PhysicalSystem::physicalStep(Entity* entity, + float dt, + MoveCmpt& moveCmpt, + MotionCmpt& motionCmpt) { + moveCmpt.oldPosition = moveCmpt.position; + + motionCmpt.speed += motionCmpt.acceleration * dt; + if (Len(motionCmpt.speed) > motionCmpt.maxSpeed) { + motionCmpt.speed = Normalize(motionCmpt.speed) * motionCmpt.maxSpeed; + } + + moveCmpt.position += motionCmpt.speed * dt + 0.5 * motionCmpt.acceleration * dt * dt; + + motionCmpt.acceleration = Point{0, 0}; +} + +void ColliRectCorrectSystem::Update(float dt) { + for (auto& entity: Entities) { + if (entity->Has() && + entity->Has()) { + correctColliRect(*entity->Use(), + *entity->Use()); + } + } +} + +void ColliRectCorrectSystem::correctColliRect(MoveCmpt& move, CollisionCmpt& collision) { + collision.rect.x = move.position.x; + collision.rect.y = move.position.y; +} + +void CleanupSystem::Update(float dt) { + using EntityPtr = Entity*; + Bullets.RemoveAll([](const EntityPtr& entity){ + return !IsPointInRect(entity->Get()->position, + Rect{0, 0, GameWindowWidth, GameWindowHeight}); + }); +} + +void BulletCooldownSystem::Update(float dt) { + for (auto& entity : Entities) { + if (entity->Has()) { + auto weapon = entity->Use(); + if (weapon->coolDown >= 0) { + weapon->coolDown -= dt; + } + } + } +} + +void RenderEntitySystem::Render() { + for (auto& entity: Entities) { + if (entity->Has()) { + renderEntity(entity, *entity->Get()); + } + } + + for (auto& bullet: Bullets) { + renderEntity(bullet, *bullet->Get()); + } +} + +void RenderEntitySystem::renderEntity(Entity* entity, const RenderCmpt& renderCmpt) { + if (entity->Has()) { + auto& pos = entity->Get()->position; + if (renderCmpt.type == RenderCmpt::TypeTexture) { + Renderer::DrawTexture(renderCmpt.texture, + nullptr, + pos); + } else { + Renderer::DrawTile(renderCmpt.tile, + pos); + } + } +} diff --git a/src/tinyengine/audio.cpp b/src/tinyengine/audio.cpp index 5de48e6..4b71aef 100644 --- a/src/tinyengine/audio.cpp +++ b/src/tinyengine/audio.cpp @@ -1,4 +1,4 @@ -#include "audio.hpp" +#include "tinyengine/audio.hpp" ma_engine AudioEngine; diff --git a/src/tinyengine/camera.cpp b/src/tinyengine/camera.cpp index cf5af26..c484974 100644 --- a/src/tinyengine/camera.cpp +++ b/src/tinyengine/camera.cpp @@ -1,4 +1,4 @@ -#include "camera.hpp" +#include "tinyengine/camera.hpp" bool Camera::TryCalcView() { if (dirty_) { diff --git a/src/tinyengine/ecs/component.cpp b/src/tinyengine/ecs/component.cpp index 45e16b9..5c837b0 100644 --- a/src/tinyengine/ecs/component.cpp +++ b/src/tinyengine/ecs/component.cpp @@ -1,5 +1,5 @@ -#include "ecs/component.hpp" -#include "ecs/context.hpp" +#include "tinyengine/ecs/component.hpp" +#include "tinyengine/ecs/context.hpp" ComponentId ComponentIdx::count_ = 0; diff --git a/src/tinyengine/ecs/context.cpp b/src/tinyengine/ecs/context.cpp index a6e1f5f..46d0ff6 100644 --- a/src/tinyengine/ecs/context.cpp +++ b/src/tinyengine/ecs/context.cpp @@ -1,5 +1,5 @@ -#include "ecs/context.hpp" -#include "ecs/entity.hpp" +#include "tinyengine/ecs/context.hpp" +#include "tinyengine/ecs/entity.hpp" Pool::ElemContainer& Context::GetEntities() { return entities_.GetElems(); diff --git a/src/tinyengine/ecs/system.cpp b/src/tinyengine/ecs/system.cpp new file mode 100644 index 0000000..05ca7fb --- /dev/null +++ b/src/tinyengine/ecs/system.cpp @@ -0,0 +1,17 @@ +#include "tinyengine/ecs/system.hpp" + +void SystemManager::Update(float dt) { + for (auto& system: updateSystems_) { + if (system->IsWorking()) { + system->Update(dt); + } + } +} + +void SystemManager::Render() { + for (auto& system: renderSystems_) { + if (system->IsWorking()) { + system->Render(); + } + } +} diff --git a/src/tinyengine/engine.cpp b/src/tinyengine/engine.cpp index 04e6754..d0ed153 100644 --- a/src/tinyengine/engine.cpp +++ b/src/tinyengine/engine.cpp @@ -1,4 +1,4 @@ -#include "engine.hpp" +#include "tinyengine/engine.hpp" void error_callback(int error, const char* description) { fprintf(stderr, "Error: %s\n", description); diff --git a/src/tinyengine/event.cpp b/src/tinyengine/event.cpp index 67d7572..f560699 100644 --- a/src/tinyengine/event.cpp +++ b/src/tinyengine/event.cpp @@ -1,5 +1,24 @@ -#include "event.hpp" +#include "tinyengine/event.hpp" +#include "tinyengine/engine.hpp" void OnWindowResize(GLFWwindow* window, int width, int height) { Renderer::SetViewport(0, 0, width, height); } + +bool IsKeyPressing(int key) { + return glfwGetKey(engine.GetWindow(), key) == GLFW_PRESS; +} + +bool IsLeftPressing() { + return glfwGetMouseButton(engine.GetWindow(), GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; +} + +bool IsRightPressing() { + return glfwGetMouseButton(engine.GetWindow(), GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS; +} + +Point GetMousePosition() { + double x, y; + glfwGetCursorPos(engine.GetWindow(), &x, &y); + return Point{float(x), float(y)}; +} diff --git a/src/tinyengine/glhelpfunc.cpp b/src/tinyengine/glhelpfunc.cpp index 2e95254..a4f8fd6 100644 --- a/src/tinyengine/glhelpfunc.cpp +++ b/src/tinyengine/glhelpfunc.cpp @@ -1,4 +1,4 @@ -#include "glhelpfunc.hpp" +#include "tinyengine/glhelpfunc.hpp" #define CASE(e) case e: return #e; diff --git a/src/tinyengine/inner_bmpfont.cpp b/src/tinyengine/inner_bmpfont.cpp index 781f203..a5378e9 100644 --- a/src/tinyengine/inner_bmpfont.cpp +++ b/src/tinyengine/inner_bmpfont.cpp @@ -1,4 +1,4 @@ -#include "inner_bmpfont.hpp" +#include "tinyengine/inner_bmpfont.hpp" InnerBmpFont::InnerBmpFont() { saveChar('0', diff --git a/src/tinyengine/libmath.cpp b/src/tinyengine/libmath.cpp index 6c904ff..0522db2 100644 --- a/src/tinyengine/libmath.cpp +++ b/src/tinyengine/libmath.cpp @@ -1,4 +1,4 @@ -#include "libmath.hpp" +#include "tinyengine/libmath.hpp" Point operator+(const Point& p1, const Point& p2) { return Point{p1.x + p2.x, p1.y + p2.y}; diff --git a/src/tinyengine/renderer.cpp b/src/tinyengine/renderer.cpp index db85968..188e6f7 100644 --- a/src/tinyengine/renderer.cpp +++ b/src/tinyengine/renderer.cpp @@ -1,5 +1,5 @@ -#include "renderer.hpp" -#include "engine.hpp" +#include "tinyengine/renderer.hpp" +#include "tinyengine/engine.hpp" Color Renderer::color_ = {255, 255, 255, 255}; diff --git a/src/tinyengine/shader.cpp b/src/tinyengine/shader.cpp index ebe57e5..c73f988 100644 --- a/src/tinyengine/shader.cpp +++ b/src/tinyengine/shader.cpp @@ -1,4 +1,4 @@ -#include "shader.hpp" +#include "tinyengine/shader.hpp" GLuint createShader(const std::string& code, GLenum type) { GLuint shader; diff --git a/src/tinyengine/texture.cpp b/src/tinyengine/texture.cpp index f91affe..55b5acf 100644 --- a/src/tinyengine/texture.cpp +++ b/src/tinyengine/texture.cpp @@ -1,4 +1,4 @@ -#include "texture.hpp" +#include "tinyengine/texture.hpp" Texture::Texture(const std::string& filename) { int w, h, channels; diff --git a/src/tinyengine/tilesheet.cpp b/src/tinyengine/tilesheet.cpp index 4a558e4..5e9a888 100644 --- a/src/tinyengine/tilesheet.cpp +++ b/src/tinyengine/tilesheet.cpp @@ -1,4 +1,4 @@ -#include "tilesheet.hpp" +#include "tinyengine/tilesheet.hpp" TileSheet::TileSheet(const std::string& filename, int x, int y) { texture_.reset(new Texture(filename)); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d0434bd..504d3f1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,8 @@ macro(AddTest TEST_NAME TEST_FILE) target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include) endmacro() -AddTest(math math.cpp ${ENGINE_NAME}) -AddTest(renderer renderer.cpp ${ENGINE_NAME}) -AddTest(innerBmpFont innerBmpFont.cpp ${ENGINE_NAME}) -AddTest(audio audio.cpp ${ENGINE_NAME}) +AddTest(math math.cpp ${ENGINE_NAME}) +AddTest(renderer renderer.cpp ${ENGINE_NAME}) +AddTest(innerBmpFont innerBmpFont.cpp ${ENGINE_NAME}) +AddTest(audio audio.cpp ${ENGINE_NAME}) +AddTest(quicklist quicklist.cpp ${ENGINE_NAME}) diff --git a/tests/quicklist.cpp b/tests/quicklist.cpp new file mode 100644 index 0000000..765ee81 --- /dev/null +++ b/tests/quicklist.cpp @@ -0,0 +1,24 @@ +#include "game/quick_list.hpp" + +int main() { + QuickList list; + list.Add(1); + list.Add(3); + list.Add(2); + list.Add(5); + + list.PrintAll(); + + list.RemoveAll([](const int& elem){ + return elem < 3; + }); + + list.PrintAll(); + + list.RemoveAll([](const int& elem){ + return elem < 10; + }); + + list.PrintAll(); +} +