add fight space ship and it's controller

This commit is contained in:
VisualGMQ 2022-02-08 21:02:52 +08:00
parent 71096200f6
commit 61fd49bb7d
18 changed files with 241 additions and 52 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 809 B

View File

@ -5,11 +5,11 @@
class MoveCmpt: public Component { class MoveCmpt: public Component {
public: public:
void Init(const Point& p) { position = p; } void Init(const Point& p) { position = p; oldPosition = position; }
void Release() {} void Release() {}
Point position; Point position;
Point oldPosition = {0, 0}; Point oldPosition;
}; };
class MotionCmpt: public Component { class MotionCmpt: public Component {
@ -17,11 +17,12 @@ public:
void Init(const Point& spd, float maxSpd) { void Init(const Point& spd, float maxSpd) {
speed = spd; speed = spd;
maxSpeed = maxSpd; maxSpeed = maxSpd;
acceleration = {0, 0};
} }
void Release() {} void Release() {}
Point speed; Point speed;
Point acceleration = {0, 0}; Point acceleration;
float maxSpeed; float maxSpeed;
}; };
@ -34,6 +35,22 @@ public:
Rect rect; 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 { class SpaceshipWeaponCmpt: public Component {
public: public:
enum Type { enum Type {
@ -116,6 +133,7 @@ public:
inline void Init(int damage, Entity* owner) { inline void Init(int damage, Entity* owner) {
this->owner = owner; this->owner = owner;
this->damage = damage; this->damage = damage;
alive = true;
} }
inline void Release() override {} inline void Release() override {}

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
constexpr float FreightMaxSpeed = 100; constexpr float FreightShipMaxSpeed = 100;
constexpr float FightShipMaxSpeed = 300;
constexpr int FreightLife = 10;
constexpr float LazerDamage = 2; constexpr float LazerDamage = 2;
constexpr float LazerShooterSpeed = 1000; constexpr float LazerShooterSpeed = 500;
constexpr float LazerShooterMaxSpeed = 1000; constexpr float LazerShooterMaxSpeed = 1000;
constexpr float LazerShooterCooldown = 0.3; constexpr float LazerShooterCooldown = 0.3;
constexpr int GameWindowWidth = 1024; constexpr int GameWindowWidth = 1024;

View File

@ -6,9 +6,9 @@
#include "game/component.hpp" #include "game/component.hpp"
#include "game/action.hpp" #include "game/action.hpp"
class FreeRotationController: public Controller { class FightShipController: public Controller {
public: public:
FreeRotationController(Entity* entity); FightShipController(Entity* entity);
void Update(float dt) override; void Update(float dt) override;
private: private:

View File

@ -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_;
};

View File

@ -5,4 +5,5 @@
#include "game/global.hpp" #include "game/global.hpp"
Entity* CreateFreightShip(); Entity* CreateFreightShip();
Entity* CreateFightShip();
Entity* CreateBullet(int damage, Entity* owner, float maxSpeedß); Entity* CreateBullet(int damage, Entity* owner, float maxSpeedß);

View File

@ -5,14 +5,11 @@
extern Context ECSContext; extern Context ECSContext;
extern SystemManager SystemMgr; extern SystemManager SystemMgr;
extern std::unordered_map<std::string, Unique<TileSheet>> TileSheets; extern Unique<TileSheet> GameTileSheet;
extern std::unordered_map<std::string, Unique<Sound>> Sounds; extern std::unordered_map<std::string, Unique<Sound>> Sounds;
extern std::string TileSheetName;
extern QuickList<Entity*> Bullets; extern QuickList<Entity*> Bullets;
using EntityList = std::vector<Entity*>; extern QuickList<Entity*> Entities;
extern EntityList Entities;
void LoadResources(); void LoadResources();

View File

@ -9,11 +9,15 @@ public:
datas_.push_back(elem); datas_.push_back(elem);
} }
void RemoveAll(std::function<bool(const T&)> func) { void RemoveAll(std::function<bool(const T&)> findFunc,
int idx = 0; std::function<void(const T&)> destroyFunc = nullptr) {
std::size_t idx = 0;
while (idx < datas_.size()) { 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]); std::swap(datas_[idx], datas_[datas_.size() - 1]);
if (destroyFunc) {
destroyFunc(datas_.back());
}
datas_.pop_back(); datas_.pop_back();
} else { } else {
idx ++; idx ++;

View File

@ -4,7 +4,8 @@
#include "game/global.hpp" #include "game/global.hpp"
#include "game/entity.hpp" #include "game/entity.hpp"
#include "game/system.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 { class SpaceScence: public Scence {
public: public:
@ -15,5 +16,11 @@ public:
private: private:
Entity* spaceship_; Entity* spaceship_;
Unique<FreeRotationController> controller_; Unique<FreightShipController> freightController_;
Unique<FightShipController> fightController_;
void renderGUI();
Camera guiCamera_;
Camera gameCamera_;
}; };

View File

@ -22,6 +22,11 @@ private:
void correctColliRect(MoveCmpt&, CollisionCmpt&); void correctColliRect(MoveCmpt&, CollisionCmpt&);
}; };
class CollideSystem: public UpdateSystem {
public:
void Update(float dt) override;
};
class CleanupSystem: public UpdateSystem { class CleanupSystem: public UpdateSystem {
public: public:
void Update(float dt) override; void Update(float dt) override;
@ -38,4 +43,5 @@ public:
private: private:
void renderEntity(Entity* entity, const RenderCmpt&); void renderEntity(Entity* entity, const RenderCmpt&);
void renderCollideBox(Entity* entity);
}; };

View File

@ -92,7 +92,7 @@ inline float Clamp(float min, float max, float value) {
inline bool IsRectsIntersect(const Rect& r1, const Rect& r2) { inline bool IsRectsIntersect(const Rect& r1, const Rect& r2) {
return !(r1.x > r2.x + r2.w || return !(r1.x > r2.x + r2.w ||
r1.x + r1.w < r2.x || r1.x + r1.w < r2.x ||
r1.y > r2.x + r2.h || r1.y > r2.y + r2.h ||
r1.y + r1.h < r2.y); 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}; 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) { inline Mat44 CreateSRT(const Point& pos, const Point& scale, float degree) {
float theta = Radians(degree); float theta = Radians(degree);
float sinTheta = std::sin(theta), float sinTheta = std::sin(theta),

View File

@ -5,7 +5,7 @@ void Shoot(SpaceshipWeaponCmpt& weapon, const Point& dir) {
Point playerCenterPos = weapon.owner->Get<MoveCmpt>()->position; Point playerCenterPos = weapon.owner->Get<MoveCmpt>()->position;
auto bullet = weapon.ShootBullet(Normalize(dir) * weapon.shootSpeed); auto bullet = weapon.ShootBullet(dir);
Bullets.Add(bullet); Bullets.Add(bullet);
weapon.coolDown = weapon.shootDuration; weapon.coolDown = weapon.shootDuration;

View File

@ -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<MotionCmpt>();
float& rotation = entity_->Use<FightShipCmpt>()->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<SpaceshipWeaponCmpt>()) {
Shoot(*entity_->Use<SpaceshipWeaponCmpt>(),
GetMousePosition() - entity_->Get<MoveCmpt>()->position);
}
}
}

View File

@ -1,10 +1,10 @@
#include "game/controllers/spaceship_controller.hpp" #include "game/controllers/freightship_controller.hpp"
#include "tinyengine/event.hpp" #include "tinyengine/event.hpp"
FreeRotationController::FreeRotationController(Entity* entity) FreightShipController::FreightShipController(Entity* entity)
: entity_(entity) {} : entity_(entity) {}
void FreeRotationController::Update(float dt) { void FreightShipController::Update(float dt) {
const float spd = 100; const float spd = 100;
auto motionCmpt = entity_->Use<MotionCmpt>(); auto motionCmpt = entity_->Use<MotionCmpt>();
if (IsKeyPressing(GLFW_KEY_A)) { if (IsKeyPressing(GLFW_KEY_A)) {

View File

@ -1,16 +1,37 @@
#include "game/entity.hpp" #include "game/entity.hpp"
#include "game/constants.hpp"
Entity* CreateFreightShip() { Entity* CreateFreightShip() {
Entity* entity = ECSContext.CreateEntity(); Entity* entity = ECSContext.CreateEntity();
entity->Add<MoveCmpt>(Point{0, 0}); entity->Add<MoveCmpt>(Point{0, 0});
entity->Add<MotionCmpt>(Point{0, 0}, FreightMaxSpeed); entity->Add<MotionCmpt>(Point{0, 0}, FreightShipMaxSpeed);
entity->Add<RenderCmpt>(TileSheets[TileSheetName]->GetTile(0, 0)); entity->Add<RenderCmpt>(GameTileSheet->GetTile(0, 0));
entity->Add<SpaceshipWeaponCmpt>(SpaceshipWeaponCmpt::Orientation, entity->Add<SpaceshipWeaponCmpt>(SpaceshipWeaponCmpt::Orientation,
entity, entity,
LazerDamage, LazerDamage,
LazerShooterSpeed, LazerShooterSpeed,
LazerShooterMaxSpeed, LazerShooterMaxSpeed,
LazerShooterCooldown); LazerShooterCooldown);
entity->Add<CollisionCmpt>(Size{16, 16});
entity->Add<LifeCmpt>(FreightLife);
entity->Add<FreightShipCmpt>();
return entity;
}
Entity* CreateFightShip() {
Entity* entity = ECSContext.CreateEntity();
entity->Add<MoveCmpt>(Point{0, 0});
entity->Add<MotionCmpt>(Point{0, 0}, FightShipMaxSpeed);
entity->Add<RenderCmpt>(GameTileSheet->GetTile(1, 0));
entity->Add<SpaceshipWeaponCmpt>(SpaceshipWeaponCmpt::Orientation,
entity,
LazerDamage,
LazerShooterSpeed,
LazerShooterMaxSpeed,
LazerShooterCooldown);
entity->Add<CollisionCmpt>(Size{16, 16});
entity->Add<LifeCmpt>(FreightLife);
entity->Add<FightShipCmpt>(0);
return entity; return entity;
} }
@ -18,7 +39,8 @@ Entity* CreateBullet(int damage, Entity* owner, float maxSpeed) {
Entity* entity = ECSContext.CreateEntity(); Entity* entity = ECSContext.CreateEntity();
entity->Add<MoveCmpt>(Point{0, 0}); entity->Add<MoveCmpt>(Point{0, 0});
entity->Add<MotionCmpt>(Point{0, 0}, maxSpeed); entity->Add<MotionCmpt>(Point{0, 0}, maxSpeed);
entity->Add<RenderCmpt>(TileSheets[TileSheetName]->GetTile(0, 1)); entity->Add<RenderCmpt>(GameTileSheet->GetTile(0, 1));
entity->Add<BulletCmpt>(damage, owner); entity->Add<BulletCmpt>(damage, owner);
entity->Add<CollisionCmpt>(Size{8, 8});
return entity; return entity;
} }

View File

@ -2,14 +2,13 @@
Context ECSContext; Context ECSContext;
SystemManager SystemMgr; SystemManager SystemMgr;
std::unordered_map<std::string, Unique<TileSheet>> TileSheets; Unique<TileSheet> GameTileSheet;
std::unordered_map<std::string, Unique<Sound>> Sounds; std::unordered_map<std::string, Unique<Sound>> Sounds;
std::string TileSheetName = "TileSheet";
QuickList<Entity*> Bullets; QuickList<Entity*> Bullets;
EntityList Entities; QuickList<Entity*> Entities;
void loadImages() { void loadImages() {
TileSheets[TileSheetName] = std::make_unique<TileSheet>("assets/tilesheet.png", 8, 8); GameTileSheet.reset(new TileSheet("assets/tilesheet.png", 8, 8));
} }
void loadSounds() { void loadSounds() {

View File

@ -4,27 +4,54 @@ void SpaceScence::OnInit() {
Renderer::SetClearColor(Color{0, 0, 0, 255}); Renderer::SetClearColor(Color{0, 0, 0, 255});
LoadResources(); LoadResources();
spaceship_ = CreateFreightShip(); spaceship_ = CreateFightShip();
Entities.push_back(spaceship_); Entities.Add(spaceship_);
spaceship_->Use<MoveCmpt>()->position = Point{400, 400}; spaceship_->Use<MoveCmpt>()->position = Point{400, 400};
controller_.reset(new FreeRotationController(spaceship_)); Entity* enemy = CreateFreightShip();
enemy->Use<MoveCmpt>()->position = Point{100, 100};
Entities.Add(enemy);
enemy = CreateFreightShip();
enemy->Use<MoveCmpt>()->position = Point{200, 100};
Entities.Add(enemy);
enemy = CreateFreightShip();
enemy->Use<MoveCmpt>()->position = Point{100, 200};
Entities.Add(enemy);
// freightController_.reset(new FreightShipController(spaceship_));
fightController_.reset(new FightShipController(spaceship_));
SystemMgr.Clear(); SystemMgr.Clear();
SystemMgr.AddRenderSystem(new RenderEntitySystem);
SystemMgr.AddUpdateSystem(new BulletCooldownSystem); SystemMgr.AddUpdateSystem(new BulletCooldownSystem);
SystemMgr.AddUpdateSystem(new PhysicalSystem); SystemMgr.AddUpdateSystem(new PhysicalSystem);
SystemMgr.AddUpdateSystem(new ColliRectCorrectSystem); SystemMgr.AddUpdateSystem(new ColliRectCorrectSystem);
SystemMgr.AddUpdateSystem(new CollideSystem);
SystemMgr.AddUpdateSystem(new CleanupSystem); SystemMgr.AddUpdateSystem(new CleanupSystem);
SystemMgr.AddRenderSystem(new RenderEntitySystem);
} }
void SpaceScence::OnUpdate(float dt) { void SpaceScence::OnUpdate(float dt) {
controller_->Update(dt); fightController_->Update(dt);
SystemMgr.Update(dt); SystemMgr.Update(dt);
} }
void SpaceScence::OnRender() { void SpaceScence::OnRender() {
Renderer::SetCamera(gameCamera_);
SystemMgr.Render(); SystemMgr.Render();
renderGUI();
}
void SpaceScence::renderGUI() {
Renderer::SetCamera(guiCamera_);
auto life = spaceship_->Get<LifeCmpt>()->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() { void SpaceScence::OnQuit() {

View File

@ -1,22 +1,22 @@
#include "game/system.hpp" #include "game/system.hpp"
void PhysicalSystem::Update(float dt) { void PhysicalSystem::Update(float dt) {
// update entities
for (auto& entity: Entities) { for (auto& entity: Entities) {
if (entity->Has<MoveCmpt>() && entity->Has<MotionCmpt>()) { if (entity->Has<MoveCmpt, MotionCmpt>()) {
// update entities
physicalStep(entity, dt, physicalStep(entity, dt,
*entity->Use<MoveCmpt>(), *entity->Use<MoveCmpt>(),
*entity->Use<MotionCmpt>()); *entity->Use<MotionCmpt>());
// update bullets }
for (auto& bullet : Bullets) { }
if (bullet->Has<MoveCmpt>() && bullet->Has<MotionCmpt>()) {
physicalStep(bullet, dt, // update bullets
*bullet->Use<MoveCmpt>(), for (auto& bullet : Bullets) {
*bullet->Use<MotionCmpt>()); if (bullet->Has<MoveCmpt, MotionCmpt>()) {
} physicalStep(bullet, dt,
} *bullet->Use<MoveCmpt>(),
*bullet->Use<MotionCmpt>());
} }
} }
} }
@ -39,25 +39,57 @@ void PhysicalSystem::physicalStep(Entity* entity,
void ColliRectCorrectSystem::Update(float dt) { void ColliRectCorrectSystem::Update(float dt) {
for (auto& entity: Entities) { for (auto& entity: Entities) {
if (entity->Has<CollisionCmpt>() && if (entity->Has<CollisionCmpt, MoveCmpt>()) {
entity->Has<MoveCmpt>()) {
correctColliRect(*entity->Use<MoveCmpt>(), correctColliRect(*entity->Use<MoveCmpt>(),
*entity->Use<CollisionCmpt>()); *entity->Use<CollisionCmpt>());
} }
} }
for (auto& bullets: Bullets) {
if (bullets->Has<CollisionCmpt, MoveCmpt>()) {
correctColliRect(*bullets->Use<MoveCmpt>(),
*bullets->Use<CollisionCmpt>());
}
}
} }
void ColliRectCorrectSystem::correctColliRect(MoveCmpt& move, CollisionCmpt& collision) { void ColliRectCorrectSystem::correctColliRect(MoveCmpt& move, CollisionCmpt& collision) {
collision.rect.x = move.position.x; collision.rect.x = move.position.x - collision.rect.w / 2;
collision.rect.y = move.position.y; 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<CollisionCmpt>() &&
bullet->Get<BulletCmpt>()->owner != entity &&
IsRectsIntersect(bullet->Get<CollisionCmpt>()->rect,
entity->Get<CollisionCmpt>()->rect)) {
if (entity->Has<LifeCmpt>()) {
entity->Use<LifeCmpt>()->hp -= bullet->Get<BulletCmpt>()->damage;
}
bullet->Use<BulletCmpt>()->alive = false;
}
}
}
} }
void CleanupSystem::Update(float dt) { void CleanupSystem::Update(float dt) {
using EntityPtr = Entity*; using EntityPtr = Entity*;
Bullets.RemoveAll([](const EntityPtr& entity){ Bullets.RemoveAll([](const EntityPtr& entity){
return !IsPointInRect(entity->Get<MoveCmpt>()->position, return !entity->Get<BulletCmpt>()->alive || !IsPointInRect(entity->Get<MoveCmpt>()->position,
Rect{0, 0, GameWindowWidth, GameWindowHeight}); Rect{0, 0, GameWindowWidth, GameWindowHeight});
}); });
Entities.RemoveAll([](const EntityPtr& entity){
if (entity->Has<LifeCmpt>() &&
entity->Get<LifeCmpt>()->hp <= 0) {
return true;
} else {
return false;
}
},
[&](const EntityPtr& entity){
ECSContext.DestroyEntity(entity);
});
} }
void BulletCooldownSystem::Update(float dt) { void BulletCooldownSystem::Update(float dt) {
@ -75,24 +107,41 @@ void RenderEntitySystem::Render() {
for (auto& entity: Entities) { for (auto& entity: Entities) {
if (entity->Has<RenderCmpt>()) { if (entity->Has<RenderCmpt>()) {
renderEntity(entity, *entity->Get<RenderCmpt>()); renderEntity(entity, *entity->Get<RenderCmpt>());
renderCollideBox(entity);
} }
} }
for (auto& bullet: Bullets) { for (auto& bullet: Bullets) {
renderEntity(bullet, *bullet->Get<RenderCmpt>()); renderEntity(bullet, *bullet->Get<RenderCmpt>());
renderCollideBox(bullet);
}
}
void RenderEntitySystem::renderCollideBox(Entity* entity) {
if (entity && entity->Has<CollisionCmpt>()) {
Renderer::SetDrawColor(Color{0, 255, 0, 255});
Renderer::DrawRect(entity->Get<CollisionCmpt>()->rect);
} }
} }
void RenderEntitySystem::renderEntity(Entity* entity, const RenderCmpt& renderCmpt) { void RenderEntitySystem::renderEntity(Entity* entity, const RenderCmpt& renderCmpt) {
if (entity->Has<MoveCmpt>()) { if (entity->Has<MoveCmpt>()) {
auto& pos = entity->Get<MoveCmpt>()->position; auto& pos = entity->Get<MoveCmpt>()->position;
float degree = 0;
if (entity->Has<FightShipCmpt>()) {
degree = entity->Get<FightShipCmpt>()->degree;
}
if (renderCmpt.type == RenderCmpt::TypeTexture) { if (renderCmpt.type == RenderCmpt::TypeTexture) {
Renderer::DrawTexture(renderCmpt.texture, Renderer::DrawTexture(renderCmpt.texture,
nullptr, nullptr,
pos); pos,
Size{0, 0},
degree);
} else { } else {
Renderer::DrawTile(renderCmpt.tile, Renderer::DrawTile(renderCmpt.tile,
pos); pos,
Size{0, 0},
degree);
} }
} }
} }