Add more gameplay features
This commit is contained in:
@@ -62,3 +62,27 @@ g000l0000g
|
|||||||
gDDDlDDDDg
|
gDDDlDDDDg
|
||||||
gggggggggg
|
gggggggggg
|
||||||
|
|
||||||
|
Room
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
dddddddddd
|
||||||
|
gggggggggg
|
||||||
|
|
||||||
|
Room
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
dddddddddd
|
||||||
|
gggggggggg
|
||||||
|
|
||||||
|
Room
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
0000000000
|
||||||
|
dddddddddd
|
||||||
|
gggggggggg
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
+2
-1
@@ -31,12 +31,13 @@ static void InitApp(void) {
|
|||||||
app->EntityManager().RegisterEntity<TFloatingTextEntity>("FloatingTextEntity");
|
app->EntityManager().RegisterEntity<TFloatingTextEntity>("FloatingTextEntity");
|
||||||
app->EntityManager().RegisterEntity<TBackgroundTiler>("BackgroundTiler");
|
app->EntityManager().RegisterEntity<TBackgroundTiler>("BackgroundTiler");
|
||||||
app->EntityManager().RegisterEntity<TRoomEntity>("RoomEntity");
|
app->EntityManager().RegisterEntity<TRoomEntity>("RoomEntity");
|
||||||
|
app->EntityManager().RegisterEntity<TRubbleEntity>("RubbleEntity");
|
||||||
|
|
||||||
app->EntityManager().MakeEntityByName("RoomEntity");
|
app->EntityManager().MakeEntityByName("RoomEntity");
|
||||||
app->EntityManager().MakeEntityByName("BackgroundTiler");
|
app->EntityManager().MakeEntityByName("BackgroundTiler");
|
||||||
|
|
||||||
auto h = app->EntityManager().MakeEntityByName("Hero");
|
auto h = app->EntityManager().MakeEntityByName("Hero");
|
||||||
h->SetPosition({0, -64});
|
h->SetPosition({0, -16});
|
||||||
app->EntityManager().UpdateCollision(h);
|
app->EntityManager().UpdateCollision(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public:
|
|||||||
Effects,
|
Effects,
|
||||||
EffectsGlow,
|
EffectsGlow,
|
||||||
Light,
|
Light,
|
||||||
|
AfterLightEffects,
|
||||||
Interface,
|
Interface,
|
||||||
SentinelMax
|
SentinelMax
|
||||||
};
|
};
|
||||||
|
|||||||
+249
-43
@@ -16,7 +16,35 @@ TDirtEntity::TDirtEntity(NGame::TEntity::TId id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TDirtEntity::Update(std::uint32_t delta) {
|
void TDirtEntity::Update(std::uint32_t delta) {
|
||||||
|
auto entityList = NGame::TApp::Instance()->EntityManager().CollisionList(Position(), Size(), DAMAGE_GROUP, Id());
|
||||||
|
|
||||||
|
for (auto& otherId : entityList) {
|
||||||
|
auto other = NGame::TApp::Instance()->EntityManager().Entity(otherId);
|
||||||
|
|
||||||
|
if (dynamic_cast<TExplosionEntity*>(other.get())) {
|
||||||
|
auto explosionCenter = other->Position() + other->Size() / 2;
|
||||||
|
auto ourCenter = Position() + Size() / 2;
|
||||||
|
|
||||||
|
float distance = (ourCenter - explosionCenter).Length();
|
||||||
|
if (distance <= other->Size().X) {
|
||||||
|
Remove();
|
||||||
|
|
||||||
|
std::size_t rockCount = rand() % 3 + 1;
|
||||||
|
while (rockCount--) {
|
||||||
|
NGame::Vec2f speedVector;
|
||||||
|
|
||||||
|
auto rockEntity = NGame::TApp::Instance()->EntityManager().MakeEntity<TRubbleEntity>();
|
||||||
|
rockEntity->SetPosition(Position());
|
||||||
|
speedVector.X = rand() % 100 - 50;
|
||||||
|
speedVector.Y = rand() % 50;
|
||||||
|
speedVector = speedVector.Normilize() * 100;
|
||||||
|
dynamic_cast<TRubbleEntity*>(rockEntity.get())->SetSpeed(speedVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDirtEntity::Draw() const {
|
void TDirtEntity::Draw() const {
|
||||||
@@ -25,14 +53,7 @@ void TDirtEntity::Draw() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TGrassEntity::TGrassEntity(NGame::TEntity::TId id)
|
TGrassEntity::TGrassEntity(NGame::TEntity::TId id)
|
||||||
: NGame::TEntity(id) {
|
: TDirtEntity(id) {
|
||||||
SetCollisionGroup(TERRAIN_GROUP);
|
|
||||||
SetSize({16, 16});
|
|
||||||
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Wall.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TGrassEntity::Update(std::uint32_t delta) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGrassEntity::Draw() const {
|
void TGrassEntity::Draw() const {
|
||||||
@@ -95,12 +116,12 @@ void TLadderEntity::Draw() const {
|
|||||||
TExplosionEntity::TExplosionEntity(NGame::TEntity::TId id)
|
TExplosionEntity::TExplosionEntity(NGame::TEntity::TId id)
|
||||||
: NGame::TEntity(id) {
|
: NGame::TEntity(id) {
|
||||||
SetCollisionGroup(DAMAGE_GROUP);
|
SetCollisionGroup(DAMAGE_GROUP);
|
||||||
SetSize({16, 16});
|
SetSize({64, 64});
|
||||||
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Wall.txt");
|
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Light.txt");
|
||||||
|
Alarm_.Set(0, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TExplosionEntity::Update(std::uint32_t delta) {
|
void TExplosionEntity::Update(std::uint32_t delta) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TExplosionEntity::Draw() const {
|
void TExplosionEntity::Draw() const {
|
||||||
@@ -109,7 +130,9 @@ void TExplosionEntity::Draw() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TExplosionEntity::Alarm(NGame::TAlarm::TId id) {
|
void TExplosionEntity::Alarm(NGame::TAlarm::TId id) {
|
||||||
|
if (id == 0) {
|
||||||
|
Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TKeyEntity::TKeyEntity(NGame::TEntity::TId id)
|
TKeyEntity::TKeyEntity(NGame::TEntity::TId id)
|
||||||
@@ -132,19 +155,75 @@ TMineEntity::TMineEntity(NGame::TEntity::TId id)
|
|||||||
: NGame::TEntity(id) {
|
: NGame::TEntity(id) {
|
||||||
SetSize({16, 16});
|
SetSize({16, 16});
|
||||||
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Mine.txt");
|
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Mine.txt");
|
||||||
|
Blinking_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Flash.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMineEntity::Update(std::uint32_t delta) {
|
void TMineEntity::Update(std::uint32_t delta) {
|
||||||
|
auto& entityManager = NGame::TApp::Instance()->EntityManager();
|
||||||
|
switch (State_) {
|
||||||
|
|
||||||
|
case Dormant:
|
||||||
|
if (!entityManager.IsPlaceEmpty(Position() + Size() / 2 - TriggerRadius_ / 2, TriggerRadius_, HERO_GROUP)) {
|
||||||
|
Remaining_ = rand() % 5 + 5;
|
||||||
|
if (!(Remaining_ % 2)) {
|
||||||
|
Remaining_ += 1;
|
||||||
|
}
|
||||||
|
Alarm_.Set(0, 100);
|
||||||
|
State_ = Active;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Active:
|
||||||
|
if (!Remaining_) {
|
||||||
|
auto explosion = entityManager.MakeEntity<TExplosionEntity>();
|
||||||
|
explosion->SetPosition(Position() + Size() / 2 - explosion->Size() / 2 + NGame::Vec2i{0, 4});
|
||||||
|
Remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chain detonation
|
||||||
|
auto entityList = NGame::TApp::Instance()->EntityManager().CollisionList(Position(), Size(), DAMAGE_GROUP, Id());
|
||||||
|
|
||||||
|
for (auto& otherId : entityList) {
|
||||||
|
auto other = NGame::TApp::Instance()->EntityManager().Entity(otherId);
|
||||||
|
|
||||||
|
if (dynamic_cast<TExplosionEntity*>(other.get())) {
|
||||||
|
auto explosionCenter = other->Position() + other->Size() / 2;
|
||||||
|
auto ourCenter = Position() + Size() / 2;
|
||||||
|
|
||||||
|
float distance = (ourCenter - explosionCenter).Length();
|
||||||
|
if (distance <= other->Size().X) {
|
||||||
|
auto explosion = entityManager.MakeEntity<TExplosionEntity>();
|
||||||
|
explosion->SetPosition(Position() + Size() / 2 - explosion->Size() / 2 + NGame::Vec2i{0, 4});
|
||||||
|
Remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMineEntity::Draw() const {
|
void TMineEntity::Draw() const {
|
||||||
NGame::TApp::Instance()->RenderManager().SetLayer(NGame::TRenderManager::Background);
|
auto& renderManager = NGame::TApp::Instance()->RenderManager();
|
||||||
NGame::TApp::Instance()->SpriteManager().Draw(Sprite_, 0, Position());
|
auto& spriteManager = NGame::TApp::Instance()->SpriteManager();
|
||||||
|
|
||||||
|
renderManager.SetLayer(NGame::TRenderManager::Background);
|
||||||
|
spriteManager.Draw(Sprite_, 0, Position());
|
||||||
|
|
||||||
|
if (State_ == EState::Active) {
|
||||||
|
renderManager.SetLayer(NGame::TRenderManager::EffectsGlow);
|
||||||
|
spriteManager.Draw(Blinking_, AlternateBlink_, Position() + (Size() * NGame::Vec2f(0.5f, 0.75f)) - Blinking_->Frames[0].Size, {2, 2});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMineEntity::Alarm(NGame::TAlarm::TId id) {
|
void TMineEntity::Alarm(NGame::TAlarm::TId id) {
|
||||||
|
if (id == 0) {
|
||||||
|
AlternateBlink_ = !AlternateBlink_;
|
||||||
|
if (Remaining_) {
|
||||||
|
--Remaining_;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TCurseEntity::TCurseEntity(NGame::TEntity::TId id)
|
TCurseEntity::TCurseEntity(NGame::TEntity::TId id)
|
||||||
@@ -176,7 +255,15 @@ void TSpikeEntity::Update(std::uint32_t delta) {
|
|||||||
|
|
||||||
void TSpikeEntity::Draw() const {
|
void TSpikeEntity::Draw() const {
|
||||||
NGame::TApp::Instance()->RenderManager().SetLayer(NGame::TRenderManager::Background);
|
NGame::TApp::Instance()->RenderManager().SetLayer(NGame::TRenderManager::Background);
|
||||||
NGame::TApp::Instance()->SpriteManager().Draw(Sprite_, 0, Position());
|
NGame::TApp::Instance()->SpriteManager().Draw(Sprite_, IsBloody_, Position());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TSpikeEntity::IsBloody() const {
|
||||||
|
return IsBloody_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSpikeEntity::SetBloody(bool value) {
|
||||||
|
IsBloody_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEntranceEntity::TEntranceEntity(NGame::TEntity::TId id)
|
TEntranceEntity::TEntranceEntity(NGame::TEntity::TId id)
|
||||||
@@ -232,7 +319,7 @@ void TFloatingTextEntity::Draw() const {
|
|||||||
auto& renderManager = NGame::TApp::Instance()->RenderManager();
|
auto& renderManager = NGame::TApp::Instance()->RenderManager();
|
||||||
auto& fontManager = NGame::TApp::Instance()->FontManager();
|
auto& fontManager = NGame::TApp::Instance()->FontManager();
|
||||||
|
|
||||||
renderManager.SetLayer(NGame::TRenderManager::Effects);
|
renderManager.SetLayer(NGame::TRenderManager::AfterLightEffects);
|
||||||
fontManager.Draw(Color_, Position(), Text_);
|
fontManager.Draw(Color_, Position(), Text_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +561,9 @@ void TRoomEntity::GenerateRoom(int* maze, const NGame::Vec2i& position) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Passage:
|
case Passage:
|
||||||
entity = NGame::TApp::Instance()->EntityManager().MakeEntityByName("EntranceEntity");
|
if (roomType & (Start | Exit)) {
|
||||||
|
entity = NGame::TApp::Instance()->EntityManager().MakeEntityByName("EntranceEntity");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Curse:
|
case Curse:
|
||||||
@@ -534,8 +623,9 @@ THero::THero(NGame::TEntity::TId id)
|
|||||||
: NGame::TEntity(id) {
|
: NGame::TEntity(id) {
|
||||||
SetSize(NGame::Vec2i(4, 12));
|
SetSize(NGame::Vec2i(4, 12));
|
||||||
SetPosition(NGame::Vec2i(0, 0));
|
SetPosition(NGame::Vec2i(0, 0));
|
||||||
NGame::TApp::Instance()->RenderManager().EnableLight(true);
|
SetCollisionGroup(HERO_GROUP);
|
||||||
NGame::TApp::Instance()->RenderManager().SetDefaultLightColor(0, 0, 0);
|
NGame::TApp::Instance()->RenderManager().EnableLight(false);
|
||||||
|
NGame::TApp::Instance()->RenderManager().SetDefaultLightColor(255, 0, 0);
|
||||||
|
|
||||||
Alarm_.Set(0, 100);
|
Alarm_.Set(0, 100);
|
||||||
}
|
}
|
||||||
@@ -617,6 +707,7 @@ void THero::Input(SDL_Event* event) {
|
|||||||
|
|
||||||
void THero::Update(std::uint32_t delta) {
|
void THero::Update(std::uint32_t delta) {
|
||||||
auto app = NGame::TApp::Instance();
|
auto app = NGame::TApp::Instance();
|
||||||
|
auto& entityManager = app->EntityManager();
|
||||||
|
|
||||||
for (bool repeatState = true; repeatState; ) {
|
for (bool repeatState = true; repeatState; ) {
|
||||||
repeatState = false;
|
repeatState = false;
|
||||||
@@ -633,20 +724,20 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
Speed_.X = -100;
|
Speed_.X = -100;
|
||||||
}
|
}
|
||||||
if (KeysPressed_[static_cast<int>(EKeys::X)]) {
|
if (KeysPressed_[static_cast<int>(EKeys::X)]) {
|
||||||
auto entity = app->EntityManager().MakeEntityByName("FloatingTextEntity");
|
auto entity = entityManager.MakeEntityByName("FloatingTextEntity");
|
||||||
auto targetEntity = dynamic_cast<TFloatingTextEntity*>(entity.get());
|
auto targetEntity = dynamic_cast<TFloatingTextEntity*>(entity.get());
|
||||||
targetEntity->SetText("You died, LMAO");
|
targetEntity->SetText("You died, LMAO");
|
||||||
targetEntity->SetColor(NGame::TFontManager::Red);
|
targetEntity->SetColor(NGame::TFontManager::Red);
|
||||||
targetEntity->SetPosition(Position());
|
targetEntity->SetPosition(Position());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!app->EntityManager().IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
if (!entityManager.IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
||||||
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
||||||
State_ = EState::Climb;
|
State_ = EState::Climb;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!app->EntityManager().IsPlaceEmpty(Position() + NGame::Vec2i(-2, Size().Y), NGame::Vec2i(Size().X + 4, 1), TERRAIN_GROUP, Id())) {
|
if (!entityManager.IsPlaceEmpty(Position() + NGame::Vec2i(-2, Size().Y), NGame::Vec2i(Size().X + 4, 1), TERRAIN_GROUP, Id())) {
|
||||||
if (KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
||||||
if (KeysPressed_[static_cast<int>(EKeys::Z)]) {
|
if (KeysPressed_[static_cast<int>(EKeys::Z)]) {
|
||||||
IgnorePlanks_ = true;
|
IgnorePlanks_ = true;
|
||||||
@@ -667,13 +758,15 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LastStablePosition_ = Position();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EState::Jump:
|
case EState::Jump:
|
||||||
Speed_.X = 0;
|
Speed_.X = 0;
|
||||||
Speed_.Y += MovementPerTick(delta, Gravity_);
|
Speed_.Y += MovementPerTick(delta, Gravity_);
|
||||||
|
|
||||||
if (!app->EntityManager().IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
if (!entityManager.IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
||||||
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
||||||
State_ = EState::Climb;
|
State_ = EState::Climb;
|
||||||
continue;
|
continue;
|
||||||
@@ -695,7 +788,7 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
Speed_.X = 0;
|
Speed_.X = 0;
|
||||||
Speed_.Y += MovementPerTick(delta, Gravity_);
|
Speed_.Y += MovementPerTick(delta, Gravity_);
|
||||||
|
|
||||||
if (!app->EntityManager().IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
if (!entityManager.IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
||||||
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
||||||
State_ = EState::Climb;
|
State_ = EState::Climb;
|
||||||
continue;
|
continue;
|
||||||
@@ -703,9 +796,9 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
}
|
}
|
||||||
if (KeysHeld_[static_cast<int>(EKeys::Right)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Right)]) {
|
||||||
Speed_.X = 100;
|
Speed_.X = 100;
|
||||||
auto collisonIds = app->EntityManager().CollisionList(Position() + NGame::Vec2i(Size().X, 0), NGame::Vec2i(Size().X, 2), TERRAIN_GROUP, Id());
|
auto collisonIds = entityManager.CollisionList(Position() + NGame::Vec2i(Size().X, 0), NGame::Vec2i(Size().X, 2), TERRAIN_GROUP, Id());
|
||||||
auto containsWall = std::any_of(collisonIds.begin(), collisonIds.end(), [&](TEntity::TId id) {
|
auto containsWall = std::any_of(collisonIds.begin(), collisonIds.end(), [&](TEntity::TId id) {
|
||||||
auto other = app->EntityManager().Entity(id);
|
auto other = entityManager.Entity(id);
|
||||||
if (dynamic_cast<TPlankEntity*>(other.get())) {
|
if (dynamic_cast<TPlankEntity*>(other.get())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -713,7 +806,7 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (containsWall) {
|
if (containsWall) {
|
||||||
if (app->EntityManager().IsPlaceEmpty(Position() + NGame::Vec2i(0, -Size().Y), NGame::Vec2i(Size().X * 2, Size().Y), TERRAIN_GROUP, Id())) {
|
if (entityManager.IsPlaceEmpty(Position() + NGame::Vec2i(0, -Size().Y), NGame::Vec2i(Size().X * 2, Size().Y), TERRAIN_GROUP, Id())) {
|
||||||
State_ = EState::Hold;
|
State_ = EState::Hold;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -721,9 +814,9 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
}
|
}
|
||||||
if (KeysHeld_[static_cast<int>(EKeys::Left)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Left)]) {
|
||||||
Speed_.X = -100;
|
Speed_.X = -100;
|
||||||
auto collisonIds = app->EntityManager().CollisionList(Position() - NGame::Vec2i(Size().X, 0), NGame::Vec2i(Size().X, 2), TERRAIN_GROUP, Id());
|
auto collisonIds = entityManager.CollisionList(Position() - NGame::Vec2i(Size().X, 0), NGame::Vec2i(Size().X, 2), TERRAIN_GROUP, Id());
|
||||||
auto containsWall = std::any_of(collisonIds.begin(), collisonIds.end(), [&](TEntity::TId id) {
|
auto containsWall = std::any_of(collisonIds.begin(), collisonIds.end(), [&](TEntity::TId id) {
|
||||||
auto other = app->EntityManager().Entity(id);
|
auto other = entityManager.Entity(id);
|
||||||
if (dynamic_cast<TPlankEntity*>(other.get())) {
|
if (dynamic_cast<TPlankEntity*>(other.get())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -731,20 +824,20 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (containsWall) {
|
if (containsWall) {
|
||||||
if (app->EntityManager().IsPlaceEmpty(Position() - NGame::Vec2i(Size().X, Size().Y), NGame::Vec2i(Size().X * 2, Size().Y), TERRAIN_GROUP, Id())) {
|
if (entityManager.IsPlaceEmpty(Position() - NGame::Vec2i(Size().X, Size().Y), NGame::Vec2i(Size().X * 2, Size().Y), TERRAIN_GROUP, Id())) {
|
||||||
State_ = EState::Hold;
|
State_ = EState::Hold;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!app->EntityManager().IsPlaceEmpty(Position() + NGame::Vec2i(0, Size().Y), NGame::Vec2i(Size().X, 1), TERRAIN_GROUP, Id())) {
|
if (!entityManager.IsPlaceEmpty(Position() + NGame::Vec2i(0, Size().Y), NGame::Vec2i(Size().X, 1), TERRAIN_GROUP, Id())) {
|
||||||
State_ = EState::Normal;
|
State_ = EState::Normal;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EState::Climb:
|
case EState::Climb:
|
||||||
if (app->EntityManager().IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
if (entityManager.IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
||||||
State_ = EState::Normal;
|
State_ = EState::Normal;
|
||||||
repeatState = true;
|
repeatState = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -763,6 +856,7 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
if (KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
if (KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
||||||
Speed_.Y = 100;
|
Speed_.Y = 100;
|
||||||
}
|
}
|
||||||
|
LastStablePosition_ = Position();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EState::Hold:
|
case EState::Hold:
|
||||||
@@ -776,7 +870,48 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
State_ = EState::Jump;
|
State_ = EState::Jump;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
LastStablePosition_ = Position();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EState::Dead:
|
||||||
|
Speed_.Y += MovementPerTick(delta, Gravity_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explictly check damage sources and flick the body around the screen
|
||||||
|
{
|
||||||
|
auto entityList = entityManager.CollisionList(Position(), Size(), DAMAGE_GROUP, Id());
|
||||||
|
auto outCenter = Position() + Size() / 2;
|
||||||
|
|
||||||
|
for (auto& otherId : entityList) {
|
||||||
|
auto other = entityManager.Entity(otherId);
|
||||||
|
|
||||||
|
if (dynamic_cast<TExplosionEntity*>(other.get())) {
|
||||||
|
State_ = EState::Dead;
|
||||||
|
|
||||||
|
auto explosionCenter = other->Position() + other->Size() / 2;
|
||||||
|
auto diff = outCenter - explosionCenter;
|
||||||
|
if (diff.X) {
|
||||||
|
Speed_.X += 500.0 / diff.X;
|
||||||
|
}
|
||||||
|
if (diff.Y) {
|
||||||
|
Speed_.Y += 500.0 / diff.Y;
|
||||||
|
}
|
||||||
|
} else if (dynamic_cast<TSpikeEntity*>(other.get())) {
|
||||||
|
if (MovementPerTick(delta, Speed_.Y) < 1.0) {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
State_ = EState::Dead;
|
||||||
|
auto spike = dynamic_cast<TSpikeEntity*>(other.get());
|
||||||
|
spike->SetBloody(true);
|
||||||
|
|
||||||
|
Speed_.X = 0;
|
||||||
|
if (Speed_.Y > 5) {
|
||||||
|
Speed_.Y = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,19 +920,19 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
FaceLeft_ = 1;
|
FaceLeft_ = 1;
|
||||||
} else if (Speed_.X > 0) {
|
} else if (Speed_.X > 0) {
|
||||||
FaceLeft_ = 0;
|
FaceLeft_ = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform movement and collision
|
// Perform movement and collision
|
||||||
NGame::Vec2f resultSpeed = MovementPerTick(delta, Speed_);
|
NGame::Vec2f resultSpeed = MovementPerTick(delta, Speed_);
|
||||||
auto moveResult = MoveWithCondition(resultSpeed, Fraction_, [&](const NGame::Vec2i& position) {
|
auto moveResult = MoveWithCondition(resultSpeed, Fraction_, [&](const NGame::Vec2i& position) {
|
||||||
auto collisionList = app->EntityManager().CollisionList(position, Size(), TERRAIN_GROUP, Id());
|
auto collisionList = entityManager.CollisionList(position, Size(), TERRAIN_GROUP, Id());
|
||||||
if (collisionList.empty()) {
|
if (collisionList.empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check collision for planks
|
// Check collision for planks
|
||||||
for (auto& otherId : collisionList) {
|
for (auto& otherId : collisionList) {
|
||||||
auto other = app->EntityManager().Entity(otherId);
|
auto other = entityManager.Entity(otherId);
|
||||||
if (dynamic_cast<TPlankEntity*>(other.get())) {
|
if (dynamic_cast<TPlankEntity*>(other.get())) {
|
||||||
// Are we ignoring planks, because we are dropping down?
|
// Are we ignoring planks, because we are dropping down?
|
||||||
if (IgnorePlanks_) {
|
if (IgnorePlanks_) {
|
||||||
@@ -825,11 +960,26 @@ void THero::Update(std::uint32_t delta) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Fraction_ = moveResult.first;
|
Fraction_ = moveResult.first;
|
||||||
if (!moveResult.second.first) {
|
if (State_ != EState::Dead) {
|
||||||
Speed_.X = 0;
|
if (!moveResult.second.first) {
|
||||||
}
|
Speed_.X = 0;
|
||||||
if (!moveResult.second.second) {
|
}
|
||||||
Speed_.Y = 0;
|
if (!moveResult.second.second) {
|
||||||
|
// Fall damage
|
||||||
|
if (app->State().Variable("FallDamage").Bool() && (Position().Y - LastStablePosition_.Y > 40)) {
|
||||||
|
State_ = EState::Dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
Speed_.Y = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!moveResult.second.first) {
|
||||||
|
Speed_.X = Speed_.X * -0.5f;
|
||||||
|
}
|
||||||
|
if (!moveResult.second.second) {
|
||||||
|
Speed_.Y = Speed_.Y * -0.5f;
|
||||||
|
Speed_.X = Speed_.X * 0.8f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set camera to track hero
|
// Set camera to track hero
|
||||||
@@ -855,14 +1005,19 @@ void THero::Draw() const {
|
|||||||
case EState::Fall: spriteIndex = 0; break;
|
case EState::Fall: spriteIndex = 0; break;
|
||||||
case EState::Climb: spriteIndex = 5; break;
|
case EState::Climb: spriteIndex = 5; break;
|
||||||
case EState::Hold: spriteIndex = 1; break;
|
case EState::Hold: spriteIndex = 1; break;
|
||||||
|
case EState::Dead: spriteIndex = 4; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State_ == EState::Normal && Speed_.X != 0 && AlternateRun_) {
|
if (State_ == EState::Normal && Speed_.X != 0 && AlternateRun_) {
|
||||||
spriteIndex = 3;
|
spriteIndex = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteManager.Draw(hero, spriteIndex, Position() - NGame::Vec2i((16 - Size().X) / 2, 16 - Size().Y), {(FaceLeft_?-1.0f:1.0f), 1.0f});
|
if (State_ != EState::Dead) {
|
||||||
|
spriteManager.Draw(hero, spriteIndex, Position() - NGame::Vec2i((16 - Size().X) / 2, 16 - Size().Y), {(FaceLeft_?-1.0f:1.0f), 1.0f});
|
||||||
|
} else {
|
||||||
|
spriteManager.Draw(hero, spriteIndex, Position() - NGame::Vec2i((16 - Size().X) / 2, 16 - Size().Y - 3), {(FaceLeft_?-1.0f:1.0f), 1.0f});
|
||||||
|
}
|
||||||
|
|
||||||
renderManager.SetLayer(NGame::TRenderManager::Light);
|
renderManager.SetLayer(NGame::TRenderManager::Light);
|
||||||
auto light = spriteManager.Get("Sprites/Light.txt");
|
auto light = spriteManager.Get("Sprites/Light.txt");
|
||||||
spriteManager.Draw(light, 0, Position() - (light->Frames[0].Size * 4 / 2), {4, 4});
|
spriteManager.Draw(light, 0, Position() - (light->Frames[0].Size * 4 / 2), {4, 4});
|
||||||
@@ -894,4 +1049,55 @@ void TBackgroundTiler::Draw() const {
|
|||||||
spriteManager.Draw(Background_, 0, NGame::Vec2i(i * 16, j * 16) + cameraPosition - tileOffset);
|
spriteManager.Draw(Background_, 0, NGame::Vec2i(i * 16, j * 16) + cameraPosition - tileOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRubbleEntity::TRubbleEntity(NGame::TEntity::TId id)
|
||||||
|
: NGame::TEntity(id) {
|
||||||
|
SetSize(8);
|
||||||
|
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Stone.txt");
|
||||||
|
Alarm_.Set(0, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TRubbleEntity::Update(std::uint32_t delta) {
|
||||||
|
auto& entityManager = NGame::TApp::Instance()->EntityManager();
|
||||||
|
|
||||||
|
Speed_.Y += MovementPerTick(delta, Gravity_);
|
||||||
|
NGame::Vec2f resultSpeed = MovementPerTick(delta, Speed_);
|
||||||
|
auto moveResult = MoveWithCondition(resultSpeed, Fraction_, [&](const NGame::Vec2i& position) {
|
||||||
|
auto collisionList = entityManager.IsPlaceEmpty(position, Size(), TERRAIN_GROUP, Id());
|
||||||
|
if (collisionList) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!moveResult.second.first) {
|
||||||
|
Speed_.X = Speed_.X * -0.25f;
|
||||||
|
}
|
||||||
|
if (!moveResult.second.second) {
|
||||||
|
Speed_.Y = Speed_.Y * -0.25f;
|
||||||
|
Speed_.X = Speed_.X * 0.25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TRubbleEntity::Draw() const {
|
||||||
|
auto& renderManager = NGame::TApp::Instance()->RenderManager();
|
||||||
|
auto& spriteManager = NGame::TApp::Instance()->SpriteManager();
|
||||||
|
|
||||||
|
renderManager.SetLayer(NGame::TRenderManager::Foreground);
|
||||||
|
spriteManager.Draw(Sprite_, 0, Position());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TRubbleEntity::Alarm(NGame::TAlarm::TId id) {
|
||||||
|
if (id == 0) {
|
||||||
|
Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NGame::Vec2f& TRubbleEntity::Speed() const {
|
||||||
|
return Speed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TRubbleEntity::SetSpeed(const NGame::Vec2f& speed) {
|
||||||
|
Speed_ = speed;
|
||||||
}
|
}
|
||||||
+36
-7
@@ -8,6 +8,7 @@
|
|||||||
#define ITEM_GROUP 0x08
|
#define ITEM_GROUP 0x08
|
||||||
#define PASSAGE_GROUP 0x10
|
#define PASSAGE_GROUP 0x10
|
||||||
#define PLANK_GROUP 0x20
|
#define PLANK_GROUP 0x20
|
||||||
|
#define HERO_GROUP 0x40
|
||||||
|
|
||||||
class TDirtEntity : public NGame::TEntity {
|
class TDirtEntity : public NGame::TEntity {
|
||||||
public:
|
public:
|
||||||
@@ -16,19 +17,14 @@ public:
|
|||||||
virtual void Update(std::uint32_t delta) override;
|
virtual void Update(std::uint32_t delta) override;
|
||||||
virtual void Draw() const override;
|
virtual void Draw() const override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TGrassEntity : public NGame::TEntity {
|
class TGrassEntity : public TDirtEntity {
|
||||||
public:
|
public:
|
||||||
TGrassEntity(NGame::TEntity::TId id);
|
TGrassEntity(NGame::TEntity::TId id);
|
||||||
|
|
||||||
virtual void Update(std::uint32_t delta) override;
|
|
||||||
virtual void Draw() const override;
|
virtual void Draw() const override;
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TPlankEntity : public NGame::TEntity {
|
class TPlankEntity : public NGame::TEntity {
|
||||||
@@ -89,6 +85,11 @@ private:
|
|||||||
|
|
||||||
class TMineEntity : public NGame::TEntity {
|
class TMineEntity : public NGame::TEntity {
|
||||||
public:
|
public:
|
||||||
|
enum EState {
|
||||||
|
Dormant,
|
||||||
|
Active
|
||||||
|
};
|
||||||
|
|
||||||
TMineEntity(NGame::TEntity::TId id);
|
TMineEntity(NGame::TEntity::TId id);
|
||||||
|
|
||||||
virtual void Update(std::uint32_t delta) override;
|
virtual void Update(std::uint32_t delta) override;
|
||||||
@@ -96,7 +97,12 @@ public:
|
|||||||
virtual void Alarm(NGame::TAlarm::TId id) override;
|
virtual void Alarm(NGame::TAlarm::TId id) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool AlternateBlink_ = false;
|
||||||
|
std::size_t Remaining_ = 0;
|
||||||
|
EState State_ = Dormant;
|
||||||
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
||||||
|
std::shared_ptr<NGame::TSpriteManager::TSprite> Blinking_;
|
||||||
|
const NGame::Vec2i TriggerRadius_ = {8, 8};
|
||||||
};
|
};
|
||||||
|
|
||||||
class TCurseEntity : public NGame::TEntity {
|
class TCurseEntity : public NGame::TEntity {
|
||||||
@@ -116,8 +122,11 @@ public:
|
|||||||
|
|
||||||
virtual void Update(std::uint32_t delta) override;
|
virtual void Update(std::uint32_t delta) override;
|
||||||
virtual void Draw() const override;
|
virtual void Draw() const override;
|
||||||
|
bool IsBloody() const;
|
||||||
|
void SetBloody(bool value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool IsBloody_ = false;
|
||||||
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -241,6 +250,7 @@ public:
|
|||||||
Fall,
|
Fall,
|
||||||
Climb,
|
Climb,
|
||||||
Hold,
|
Hold,
|
||||||
|
Dead,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void Input(SDL_Event* event) override;
|
virtual void Input(SDL_Event* event) override;
|
||||||
@@ -257,6 +267,7 @@ private:
|
|||||||
EState State_ = EState::Normal;
|
EState State_ = EState::Normal;
|
||||||
|
|
||||||
const float Gravity_ = 500.0;
|
const float Gravity_ = 500.0;
|
||||||
|
NGame::Vec2i LastStablePosition_ = {};
|
||||||
NGame::Vec2f Speed_ = NGame::Vec2f(0.0, 0.0);
|
NGame::Vec2f Speed_ = NGame::Vec2f(0.0, 0.0);
|
||||||
NGame::Vec2f Fraction_ = NGame::Vec2f(0.0, 0.0);
|
NGame::Vec2f Fraction_ = NGame::Vec2f(0.0, 0.0);
|
||||||
NGame::Vec2i Want_;
|
NGame::Vec2i Want_;
|
||||||
@@ -269,4 +280,22 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<NGame::TSpriteManager::TSprite> Background_;
|
std::shared_ptr<NGame::TSpriteManager::TSprite> Background_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TRubbleEntity : public NGame::TEntity {
|
||||||
|
public:
|
||||||
|
TRubbleEntity(NGame::TEntity::TId id);
|
||||||
|
|
||||||
|
virtual void Update(std::uint32_t delta) override;
|
||||||
|
virtual void Draw() const override;
|
||||||
|
virtual void Alarm(NGame::TAlarm::TId id) override;
|
||||||
|
|
||||||
|
const NGame::Vec2f& Speed() const;
|
||||||
|
void SetSpeed(const NGame::Vec2f& speed);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const float Gravity_ = 500;
|
||||||
|
std::shared_ptr<NGame::TSpriteManager::TSprite> Sprite_;
|
||||||
|
NGame::Vec2f Speed_ = NGame::Vec2f(0.0, 0.0);
|
||||||
|
NGame::Vec2f Fraction_ = NGame::Vec2f(0.0, 0.0);
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user