From 61fd49bb7d17e3c19d7da29b9a5a40cfb145c494 Mon Sep 17 00:00:00 2001 From: VisualGMQ <2142587070@qq.com> Date: Tue, 8 Feb 2022 21:02:52 +0800 Subject: [PATCH] add fight space ship and it's controller --- assets/tilesheet.png | Bin 488 -> 809 bytes include/game/component.hpp | 24 ++++- include/game/constants.hpp | 6 +- ...ontroller.hpp => fightship_controller.hpp} | 4 +- .../controllers/freightship_controller.hpp | 16 ++++ include/game/entity.hpp | 1 + include/game/global.hpp | 7 +- include/game/quick_list.hpp | 10 ++- include/game/stages/space.hpp | 11 ++- include/game/system.hpp | 6 ++ include/tinyengine/libmath.hpp | 10 ++- src/game/action.cpp | 2 +- src/game/controllers/fightship_controller.cpp | 33 +++++++ ...troller.cpp => freightship_controller.cpp} | 6 +- src/game/entity.cpp | 28 +++++- src/game/global.cpp | 7 +- src/game/stages/space.cpp | 37 ++++++-- src/game/system.cpp | 85 ++++++++++++++---- 18 files changed, 241 insertions(+), 52 deletions(-) rename include/game/controllers/{spaceship_controller.hpp => fightship_controller.hpp} (72%) create mode 100644 include/game/controllers/freightship_controller.hpp create mode 100644 src/game/controllers/fightship_controller.cpp rename src/game/controllers/{spaceship_controller.cpp => freightship_controller.cpp} (86%) diff --git a/assets/tilesheet.png b/assets/tilesheet.png index 3dba339f675fb75153052ac57515948b83a82dd7..e57a39efe7f0476a24c37811d91f9eafd1375cbf 100644 GIT binary patch delta 711 zcmV;&0yzEX1E~g(Fn$;^m?1bA>KL#?aFcc@84~;h1Tz$eOu8r}2$H3kb|@4a3rZ0U;&2Z24Y|Aby}Q&) z?xNq%(&T;LTta@&``(+oTB1?RrEOh%z1_8R?K;^)$#IMiFMn&HUyI3^bvG1qX*;zr zuN_>Jv^`1@tZ!6AMC8Tu>RCS@#>`UynJ3STgEJyh&#wj^)IIxE8>>L_I0~TAY}sqe zi~g@@w(N)b)xaRt>{pLj1(In-_5r`@{4h9y9K9 z{#Ip9TLk55Uw^hLbA#upg?Zyx7x%>;;l##;2a<%U{=esw7iYffzzv?kXkUX>Xc7N9@O4`o+X)pz?ejTX3-sc}u zZ+ETiwVW*?vb|FqjD7s5qSZk zdjv7_eEE%L%Xfq3z6$ua8#)RgUY;-C?`Du%_H}*t?mw_^+`2P(ez?CUZ(qN%g8C3I z&n8gq34e5hgYE<#?(dzc4?s*JTZX^hzUx>uE`NG&jna>JL=u8KTt$T()Q|WW1Nim5 z<_PWFg_3rxDcrCqf_Q1~1-QdEwPE^s3P1&Y&}(`IQw0AW?Fw+vYs$@3e$t->G0+wO z;r~A(`+opTC+!a0bgqy3mjJ&2;-_5!bU~ZK#~*YX+m*l|%>HDEG=#84K={cKc@RNG tK={crwlKK)1CyZvFq5zW7Z`v<_zjrt99e-BG}8b8002ovPDHLkV1kM{T!H`q delta 418 zcmV;T0bTy72IvEjFnGVA}(`hov|J(m}ri~DBak!Vq<_Ax& zjo3V^s}j(Q!@az{vlU%DdH<9IiKzs0n2n-Of8qS>L;@sadegree = 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); } } }