diff --git a/assets/tilesheet.png b/assets/tilesheet.png index 3dba339..e57a39e 100644 Binary files a/assets/tilesheet.png and b/assets/tilesheet.png differ diff --git a/include/game/component.hpp b/include/game/component.hpp index c5a3823..ae30970 100644 --- a/include/game/component.hpp +++ b/include/game/component.hpp @@ -5,11 +5,11 @@ class MoveCmpt: public Component { public: - void Init(const Point& p) { position = p; } + void Init(const Point& p) { position = p; oldPosition = position; } void Release() {} Point position; - Point oldPosition = {0, 0}; + Point oldPosition; }; class MotionCmpt: public Component { @@ -17,11 +17,12 @@ public: void Init(const Point& spd, float maxSpd) { speed = spd; maxSpeed = maxSpd; + acceleration = {0, 0}; } void Release() {} Point speed; - Point acceleration = {0, 0}; + Point acceleration; float maxSpeed; }; @@ -34,6 +35,22 @@ public: Rect rect; }; +class FightShipCmpt: public Component { +public: + void Init(float degree) { + this->degree = degree; + } + void Release() {} + + float degree; +}; + +class FreightShipCmpt: public Component { +public: + void Init() {} + void Release() {} +}; + class SpaceshipWeaponCmpt: public Component { public: enum Type { @@ -116,6 +133,7 @@ public: inline void Init(int damage, Entity* owner) { this->owner = owner; this->damage = damage; + alive = true; } inline void Release() override {} diff --git a/include/game/constants.hpp b/include/game/constants.hpp index 8f0c186..d66736c 100644 --- a/include/game/constants.hpp +++ b/include/game/constants.hpp @@ -1,8 +1,10 @@ #pragma once -constexpr float FreightMaxSpeed = 100; +constexpr float FreightShipMaxSpeed = 100; +constexpr float FightShipMaxSpeed = 300; +constexpr int FreightLife = 10; constexpr float LazerDamage = 2; -constexpr float LazerShooterSpeed = 1000; +constexpr float LazerShooterSpeed = 500; constexpr float LazerShooterMaxSpeed = 1000; constexpr float LazerShooterCooldown = 0.3; constexpr int GameWindowWidth = 1024; diff --git a/include/game/controllers/spaceship_controller.hpp b/include/game/controllers/fightship_controller.hpp similarity index 72% rename from include/game/controllers/spaceship_controller.hpp rename to include/game/controllers/fightship_controller.hpp index ccd366b..c860a47 100644 --- a/include/game/controllers/spaceship_controller.hpp +++ b/include/game/controllers/fightship_controller.hpp @@ -6,9 +6,9 @@ #include "game/component.hpp" #include "game/action.hpp" -class FreeRotationController: public Controller { +class FightShipController: public Controller { public: - FreeRotationController(Entity* entity); + FightShipController(Entity* entity); void Update(float dt) override; private: diff --git a/include/game/controllers/freightship_controller.hpp b/include/game/controllers/freightship_controller.hpp new file mode 100644 index 0000000..dd75ca6 --- /dev/null +++ b/include/game/controllers/freightship_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 FreightShipController: public Controller { +public: + FreightShipController(Entity* entity); + void Update(float dt) override; + +private: + Entity* entity_; +}; diff --git a/include/game/entity.hpp b/include/game/entity.hpp index 36d17ab..853fc00 100644 --- a/include/game/entity.hpp +++ b/include/game/entity.hpp @@ -5,4 +5,5 @@ #include "game/global.hpp" Entity* CreateFreightShip(); +Entity* CreateFightShip(); Entity* CreateBullet(int damage, Entity* owner, float maxSpeedß); diff --git a/include/game/global.hpp b/include/game/global.hpp index 7f07ce7..bb226e5 100644 --- a/include/game/global.hpp +++ b/include/game/global.hpp @@ -5,14 +5,11 @@ extern Context ECSContext; extern SystemManager SystemMgr; -extern std::unordered_map> TileSheets; +extern Unique GameTileSheet; extern std::unordered_map> Sounds; -extern std::string TileSheetName; extern QuickList Bullets; -using EntityList = std::vector; - -extern EntityList Entities; +extern QuickList Entities; void LoadResources(); diff --git a/include/game/quick_list.hpp b/include/game/quick_list.hpp index c55e304..9345626 100644 --- a/include/game/quick_list.hpp +++ b/include/game/quick_list.hpp @@ -9,11 +9,15 @@ public: datas_.push_back(elem); } - void RemoveAll(std::function func) { - int idx = 0; + void RemoveAll(std::function findFunc, + std::function destroyFunc = nullptr) { + std::size_t idx = 0; while (idx < datas_.size()) { - if (func(datas_[idx]) && datas_.size() > idx) { + if (datas_.size() > idx && findFunc(datas_[idx])) { std::swap(datas_[idx], datas_[datas_.size() - 1]); + if (destroyFunc) { + destroyFunc(datas_.back()); + } datas_.pop_back(); } else { idx ++; diff --git a/include/game/stages/space.hpp b/include/game/stages/space.hpp index 3faefc6..d837121 100644 --- a/include/game/stages/space.hpp +++ b/include/game/stages/space.hpp @@ -4,7 +4,8 @@ #include "game/global.hpp" #include "game/entity.hpp" #include "game/system.hpp" -#include "game/controllers/spaceship_controller.hpp" +#include "game/controllers/freightship_controller.hpp" +#include "game/controllers/fightship_controller.hpp" class SpaceScence: public Scence { public: @@ -15,5 +16,11 @@ public: private: Entity* spaceship_; - Unique controller_; + Unique freightController_; + Unique fightController_; + + void renderGUI(); + + Camera guiCamera_; + Camera gameCamera_; }; diff --git a/include/game/system.hpp b/include/game/system.hpp index a250713..195a9ae 100644 --- a/include/game/system.hpp +++ b/include/game/system.hpp @@ -22,6 +22,11 @@ private: void correctColliRect(MoveCmpt&, CollisionCmpt&); }; +class CollideSystem: public UpdateSystem { +public: + void Update(float dt) override; +}; + class CleanupSystem: public UpdateSystem { public: void Update(float dt) override; @@ -38,4 +43,5 @@ public: private: void renderEntity(Entity* entity, const RenderCmpt&); + void renderCollideBox(Entity* entity); }; diff --git a/include/tinyengine/libmath.hpp b/include/tinyengine/libmath.hpp index d307557..481c3ee 100644 --- a/include/tinyengine/libmath.hpp +++ b/include/tinyengine/libmath.hpp @@ -92,7 +92,7 @@ inline float Clamp(float min, float max, float value) { inline bool IsRectsIntersect(const Rect& r1, const Rect& r2) { return !(r1.x > r2.x + r2.w || r1.x + r1.w < r2.x || - r1.y > r2.x + r2.h || + r1.y > r2.y + r2.h || r1.y + r1.h < r2.y); } @@ -149,6 +149,14 @@ inline Point GetCenterAlign(const Rect& parent, const Size& child) { parent.y + (parent.h - child.h) / 2.0f}; } +inline Point Rotate(const Point& v, float degree) { + float radians = Radians(degree); + float sinTheta = std::sin(radians), + cosTheta = std::cos(radians); + return Point{v.x * cosTheta - v.y * sinTheta, + v.x * sinTheta + v.y * cosTheta}; +} + inline Mat44 CreateSRT(const Point& pos, const Point& scale, float degree) { float theta = Radians(degree); float sinTheta = std::sin(theta), diff --git a/src/game/action.cpp b/src/game/action.cpp index 0cc8235..eb00025 100644 --- a/src/game/action.cpp +++ b/src/game/action.cpp @@ -5,7 +5,7 @@ void Shoot(SpaceshipWeaponCmpt& weapon, const Point& dir) { Point playerCenterPos = weapon.owner->Get()->position; - auto bullet = weapon.ShootBullet(Normalize(dir) * weapon.shootSpeed); + auto bullet = weapon.ShootBullet(dir); Bullets.Add(bullet); weapon.coolDown = weapon.shootDuration; diff --git a/src/game/controllers/fightship_controller.cpp b/src/game/controllers/fightship_controller.cpp new file mode 100644 index 0000000..d69495e --- /dev/null +++ b/src/game/controllers/fightship_controller.cpp @@ -0,0 +1,33 @@ +#include "game/controllers/fightship_controller.hpp" +#include "tinyengine/event.hpp" + +FightShipController::FightShipController(Entity* entity) + : entity_(entity) {} + +void FightShipController::Update(float dt) { + const float spd = 100; + auto motionCmpt = entity_->Use(); + float& rotation = entity_->Use()->degree; + if (IsKeyPressing(GLFW_KEY_A)) { + rotation += 2; + } + if (IsKeyPressing(GLFW_KEY_D)) { + rotation -= 2; + } + if (IsKeyPressing(GLFW_KEY_S)) { + motionCmpt->acceleration = Rotate(Point{0, spd}, -rotation); + } + if (IsKeyPressing(GLFW_KEY_W)) { + motionCmpt->acceleration = Rotate(Point{0, -spd}, -rotation); + } + + motionCmpt->speed = Rotate(Point{0, -1} * Len(motionCmpt->speed), + -rotation); + + if (IsLeftPressing()) { + if (entity_->Has()) { + Shoot(*entity_->Use(), + GetMousePosition() - entity_->Get()->position); + } + } +} diff --git a/src/game/controllers/spaceship_controller.cpp b/src/game/controllers/freightship_controller.cpp similarity index 86% rename from src/game/controllers/spaceship_controller.cpp rename to src/game/controllers/freightship_controller.cpp index 770d99e..86df5eb 100644 --- a/src/game/controllers/spaceship_controller.cpp +++ b/src/game/controllers/freightship_controller.cpp @@ -1,10 +1,10 @@ -#include "game/controllers/spaceship_controller.hpp" +#include "game/controllers/freightship_controller.hpp" #include "tinyengine/event.hpp" -FreeRotationController::FreeRotationController(Entity* entity) +FreightShipController::FreightShipController(Entity* entity) : entity_(entity) {} -void FreeRotationController::Update(float dt) { +void FreightShipController::Update(float dt) { const float spd = 100; auto motionCmpt = entity_->Use(); if (IsKeyPressing(GLFW_KEY_A)) { diff --git a/src/game/entity.cpp b/src/game/entity.cpp index f9a363b..8c548a7 100644 --- a/src/game/entity.cpp +++ b/src/game/entity.cpp @@ -1,16 +1,37 @@ #include "game/entity.hpp" +#include "game/constants.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(Point{0, 0}, FreightShipMaxSpeed); + entity->Add(GameTileSheet->GetTile(0, 0)); entity->Add(SpaceshipWeaponCmpt::Orientation, entity, LazerDamage, LazerShooterSpeed, LazerShooterMaxSpeed, LazerShooterCooldown); + entity->Add(Size{16, 16}); + entity->Add(FreightLife); + entity->Add(); + return entity; +} + +Entity* CreateFightShip() { + Entity* entity = ECSContext.CreateEntity(); + entity->Add(Point{0, 0}); + entity->Add(Point{0, 0}, FightShipMaxSpeed); + entity->Add(GameTileSheet->GetTile(1, 0)); + entity->Add(SpaceshipWeaponCmpt::Orientation, + entity, + LazerDamage, + LazerShooterSpeed, + LazerShooterMaxSpeed, + LazerShooterCooldown); + entity->Add(Size{16, 16}); + entity->Add(FreightLife); + entity->Add(0); return entity; } @@ -18,7 +39,8 @@ 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(GameTileSheet->GetTile(0, 1)); entity->Add(damage, owner); + entity->Add(Size{8, 8}); return entity; } diff --git a/src/game/global.cpp b/src/game/global.cpp index 3a76481..9e1819f 100644 --- a/src/game/global.cpp +++ b/src/game/global.cpp @@ -2,14 +2,13 @@ Context ECSContext; SystemManager SystemMgr; -std::unordered_map> TileSheets; +Unique GameTileSheet; std::unordered_map> Sounds; -std::string TileSheetName = "TileSheet"; QuickList Bullets; -EntityList Entities; +QuickList Entities; void loadImages() { - TileSheets[TileSheetName] = std::make_unique("assets/tilesheet.png", 8, 8); + GameTileSheet.reset(new TileSheet("assets/tilesheet.png", 8, 8)); } void loadSounds() { diff --git a/src/game/stages/space.cpp b/src/game/stages/space.cpp index 1e996ba..226db14 100644 --- a/src/game/stages/space.cpp +++ b/src/game/stages/space.cpp @@ -4,27 +4,54 @@ void SpaceScence::OnInit() { Renderer::SetClearColor(Color{0, 0, 0, 255}); LoadResources(); - spaceship_ = CreateFreightShip(); - Entities.push_back(spaceship_); + spaceship_ = CreateFightShip(); + Entities.Add(spaceship_); spaceship_->Use()->position = Point{400, 400}; - controller_.reset(new FreeRotationController(spaceship_)); + Entity* enemy = CreateFreightShip(); + enemy->Use()->position = Point{100, 100}; + Entities.Add(enemy); + + enemy = CreateFreightShip(); + enemy->Use()->position = Point{200, 100}; + Entities.Add(enemy); + + enemy = CreateFreightShip(); + enemy->Use()->position = Point{100, 200}; + Entities.Add(enemy); + + // freightController_.reset(new FreightShipController(spaceship_)); + fightController_.reset(new FightShipController(spaceship_)); SystemMgr.Clear(); - SystemMgr.AddRenderSystem(new RenderEntitySystem); SystemMgr.AddUpdateSystem(new BulletCooldownSystem); SystemMgr.AddUpdateSystem(new PhysicalSystem); SystemMgr.AddUpdateSystem(new ColliRectCorrectSystem); + SystemMgr.AddUpdateSystem(new CollideSystem); SystemMgr.AddUpdateSystem(new CleanupSystem); + SystemMgr.AddRenderSystem(new RenderEntitySystem); } void SpaceScence::OnUpdate(float dt) { - controller_->Update(dt); + fightController_->Update(dt); SystemMgr.Update(dt); } void SpaceScence::OnRender() { + Renderer::SetCamera(gameCamera_); SystemMgr.Render(); + renderGUI(); +} + +void SpaceScence::renderGUI() { + Renderer::SetCamera(guiCamera_); + + auto life = spaceship_->Get()->hp; + float xOffset = 16 * life; + for (int i = 0; i < life; i++) { + Renderer::DrawTile(GameTileSheet->GetTile(1, 1), + Point{GameWindowWidth - xOffset + i * 16, 8}); + } } void SpaceScence::OnQuit() { diff --git a/src/game/system.cpp b/src/game/system.cpp index 62f6b0c..674b56d 100644 --- a/src/game/system.cpp +++ b/src/game/system.cpp @@ -1,22 +1,22 @@ #include "game/system.hpp" void PhysicalSystem::Update(float dt) { + // update entities for (auto& entity: Entities) { - if (entity->Has() && entity->Has()) { - // update entities + if (entity->Has()) { 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()); - } - } - + } + } + + // update bullets + for (auto& bullet : Bullets) { + if (bullet->Has()) { + physicalStep(bullet, dt, + *bullet->Use(), + *bullet->Use()); } } } @@ -39,25 +39,57 @@ void PhysicalSystem::physicalStep(Entity* entity, void ColliRectCorrectSystem::Update(float dt) { for (auto& entity: Entities) { - if (entity->Has() && - entity->Has()) { + if (entity->Has()) { correctColliRect(*entity->Use(), *entity->Use()); } } + for (auto& bullets: Bullets) { + if (bullets->Has()) { + correctColliRect(*bullets->Use(), + *bullets->Use()); + } + } } void ColliRectCorrectSystem::correctColliRect(MoveCmpt& move, CollisionCmpt& collision) { - collision.rect.x = move.position.x; - collision.rect.y = move.position.y; + collision.rect.x = move.position.x - collision.rect.w / 2; + collision.rect.y = move.position.y - collision.rect.h / 2; +} + +void CollideSystem::Update(float dt) { + for (auto& bullet : Bullets) { + for (auto& entity: Entities) { + if (entity->Has() && + bullet->Get()->owner != entity && + IsRectsIntersect(bullet->Get()->rect, + entity->Get()->rect)) { + if (entity->Has()) { + entity->Use()->hp -= bullet->Get()->damage; + } + bullet->Use()->alive = false; + } + } + } } void CleanupSystem::Update(float dt) { using EntityPtr = Entity*; Bullets.RemoveAll([](const EntityPtr& entity){ - return !IsPointInRect(entity->Get()->position, + return !entity->Get()->alive || !IsPointInRect(entity->Get()->position, Rect{0, 0, GameWindowWidth, GameWindowHeight}); }); + Entities.RemoveAll([](const EntityPtr& entity){ + if (entity->Has() && + entity->Get()->hp <= 0) { + return true; + } else { + return false; + } + }, + [&](const EntityPtr& entity){ + ECSContext.DestroyEntity(entity); + }); } void BulletCooldownSystem::Update(float dt) { @@ -75,24 +107,41 @@ void RenderEntitySystem::Render() { for (auto& entity: Entities) { if (entity->Has()) { renderEntity(entity, *entity->Get()); + renderCollideBox(entity); } } for (auto& bullet: Bullets) { renderEntity(bullet, *bullet->Get()); + renderCollideBox(bullet); + } +} + +void RenderEntitySystem::renderCollideBox(Entity* entity) { + if (entity && entity->Has()) { + Renderer::SetDrawColor(Color{0, 255, 0, 255}); + Renderer::DrawRect(entity->Get()->rect); } } void RenderEntitySystem::renderEntity(Entity* entity, const RenderCmpt& renderCmpt) { if (entity->Has()) { auto& pos = entity->Get()->position; + float degree = 0; + if (entity->Has()) { + degree = entity->Get()->degree; + } if (renderCmpt.type == RenderCmpt::TypeTexture) { Renderer::DrawTexture(renderCmpt.texture, nullptr, - pos); + pos, + Size{0, 0}, + degree); } else { Renderer::DrawTile(renderCmpt.tile, - pos); + pos, + Size{0, 0}, + degree); } } }