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 {
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 {}

View File

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

View File

@ -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:

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"
Entity* CreateFreightShip();
Entity* CreateFightShip();
Entity* CreateBullet(int damage, Entity* owner, float maxSpeedß);

View File

@ -5,14 +5,11 @@
extern Context ECSContext;
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::string TileSheetName;
extern QuickList<Entity*> Bullets;
using EntityList = std::vector<Entity*>;
extern EntityList Entities;
extern QuickList<Entity*> Entities;
void LoadResources();

View File

@ -9,11 +9,15 @@ public:
datas_.push_back(elem);
}
void RemoveAll(std::function<bool(const T&)> func) {
int idx = 0;
void RemoveAll(std::function<bool(const T&)> findFunc,
std::function<void(const T&)> 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 ++;

View File

@ -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<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&);
};
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);
};

View File

@ -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),

View File

@ -5,7 +5,7 @@ void Shoot(SpaceshipWeaponCmpt& weapon, const Point& dir) {
Point playerCenterPos = weapon.owner->Get<MoveCmpt>()->position;
auto bullet = weapon.ShootBullet(Normalize(dir) * weapon.shootSpeed);
auto bullet = weapon.ShootBullet(dir);
Bullets.Add(bullet);
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"
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<MotionCmpt>();
if (IsKeyPressing(GLFW_KEY_A)) {

View File

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

View File

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

View File

@ -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<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.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<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() {

View File

@ -1,22 +1,22 @@
#include "game/system.hpp"
void PhysicalSystem::Update(float dt) {
for (auto& entity: Entities) {
if (entity->Has<MoveCmpt>() && entity->Has<MotionCmpt>()) {
// update entities
for (auto& entity: Entities) {
if (entity->Has<MoveCmpt, MotionCmpt>()) {
physicalStep(entity, dt,
*entity->Use<MoveCmpt>(),
*entity->Use<MotionCmpt>());
// update bullets
for (auto& bullet : Bullets) {
if (bullet->Has<MoveCmpt>() && bullet->Has<MotionCmpt>()) {
physicalStep(bullet, dt,
*bullet->Use<MoveCmpt>(),
*bullet->Use<MotionCmpt>());
}
}
// update bullets
for (auto& bullet : Bullets) {
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) {
for (auto& entity: Entities) {
if (entity->Has<CollisionCmpt>() &&
entity->Has<MoveCmpt>()) {
if (entity->Has<CollisionCmpt, MoveCmpt>()) {
correctColliRect(*entity->Use<MoveCmpt>(),
*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) {
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<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) {
using 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});
});
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) {
@ -75,24 +107,41 @@ void RenderEntitySystem::Render() {
for (auto& entity: Entities) {
if (entity->Has<RenderCmpt>()) {
renderEntity(entity, *entity->Get<RenderCmpt>());
renderCollideBox(entity);
}
}
for (auto& bullet: Bullets) {
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) {
if (entity->Has<MoveCmpt>()) {
auto& pos = entity->Get<MoveCmpt>()->position;
float degree = 0;
if (entity->Has<FightShipCmpt>()) {
degree = entity->Get<FightShipCmpt>()->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);
}
}
}