add fight space ship and it's controller
This commit is contained in:
parent
71096200f6
commit
61fd49bb7d
Binary file not shown.
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 809 B |
|
@ -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 {}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
|
@ -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_;
|
||||
};
|
|
@ -5,4 +5,5 @@
|
|||
#include "game/global.hpp"
|
||||
|
||||
Entity* CreateFreightShip();
|
||||
Entity* CreateFightShip();
|
||||
Entity* CreateBullet(int damage, Entity* owner, float maxSpeedß);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 ++;
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)) {
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
#include "game/system.hpp"
|
||||
|
||||
void PhysicalSystem::Update(float dt) {
|
||||
// update entities
|
||||
for (auto& entity: Entities) {
|
||||
if (entity->Has<MoveCmpt>() && entity->Has<MotionCmpt>()) {
|
||||
// update 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue