From 10f9c4792939e0bcba378705178307d6842e76ce Mon Sep 17 00:00:00 2001 From: Mikhail Romanko Date: Sun, 20 Jul 2025 10:06:04 +0300 Subject: [PATCH] Almost done --- Data/Sprites/Grenade.txt | 3 + src/Alarm.cpp | 14 ++++ src/Alarm.h | 1 + src/EntityManager.cpp | 1 + src/Gridmap.cpp | 6 ++ src/Gridmap.h | 1 + src/Main.cpp | 3 +- src/RoomEntity.cpp | 174 +++++++++++++++++++++++++++++++++++++-- src/RoomEntity.h | 30 ++++++- 9 files changed, 224 insertions(+), 9 deletions(-) create mode 100644 Data/Sprites/Grenade.txt diff --git a/Data/Sprites/Grenade.txt b/Data/Sprites/Grenade.txt new file mode 100644 index 0000000..b8bbf23 --- /dev/null +++ b/Data/Sprites/Grenade.txt @@ -0,0 +1,3 @@ +Texture Texture/Main.bmp +Frame 116 20 9 9 Normal +Frame 116 36 9 9 Live diff --git a/src/Alarm.cpp b/src/Alarm.cpp index 4a4fd0a..c576740 100644 --- a/src/Alarm.cpp +++ b/src/Alarm.cpp @@ -57,4 +57,18 @@ bool TAlarm::Next(TId& id) { return true; } +bool TAlarm::IsSet(TId id) const { + auto it = Alarms_.find(id); + + if (it == Alarms_.end()) { + return false; + } + + if (!it->second.Target) { + return false; + } + + return true; +} + } // namespace NGame diff --git a/src/Alarm.h b/src/Alarm.h index 730e2d5..c30bc6e 100644 --- a/src/Alarm.h +++ b/src/Alarm.h @@ -16,6 +16,7 @@ public: void Unset(TId id); void Update(std::uint32_t delta); bool Next(TId& id); + bool IsSet(TId id) const; private: struct TData { diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp index 003aa22..468f887 100644 --- a/src/EntityManager.cpp +++ b/src/EntityManager.cpp @@ -14,6 +14,7 @@ void TEntityManager::Run() { if (PendingReset_) { PendingReset_ = false; Entities_.clear(); + Gridmap_.Reset(); for (const auto& name : DeferredEntities_) { MakeEntityByName(name); } diff --git a/src/Gridmap.cpp b/src/Gridmap.cpp index 7365e8a..2fe1bfd 100644 --- a/src/Gridmap.cpp +++ b/src/Gridmap.cpp @@ -51,6 +51,12 @@ void TGridmap::Add(const Vec2i& position, const Vec2i& size, TEntity::TId id) { } } +void TGridmap::Reset() { + for (auto& cell : Grid_) { + cell.clear(); + } +} + TGridmap::TId TGridmap::GridId(const Vec2i& point) const { return std::hash{}(point) % Grid_.size(); } diff --git a/src/Gridmap.h b/src/Gridmap.h index 33f2799..1296d5f 100644 --- a/src/Gridmap.h +++ b/src/Gridmap.h @@ -16,6 +16,7 @@ public: std::unordered_set Query(const Vec2i& position, const Vec2i& size) const; void Remove(const Vec2i& position, const Vec2i& size, TEntity::TId id); void Add(const Vec2i& position, const Vec2i& size, TEntity::TId id); + void Reset(); private: using TId = size_t; diff --git a/src/Main.cpp b/src/Main.cpp index cf9f9c7..14d6487 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -37,8 +37,9 @@ static void InitApp(void) { app->EntityManager().RegisterEntity("OutroMenu"); app->EntityManager().RegisterEntity("EulaMenu"); app->EntityManager().RegisterEntity("TorchEntity"); + app->EntityManager().RegisterEntity("GrenadeEntity"); - app->EntityManager().AddToDeferred("RoomEntity"); + app->EntityManager().AddToDeferred("IntroMenu"); app->EntityManager().Reset(); } diff --git a/src/RoomEntity.cpp b/src/RoomEntity.cpp index 2c76888..48ebae7 100644 --- a/src/RoomEntity.cpp +++ b/src/RoomEntity.cpp @@ -145,6 +145,8 @@ void TExplosionEntity::Alarm(NGame::TAlarm::TId id) { dynamic_cast(other.get())->Destroy(); } else if (dynamic_cast(other.get())) { dynamic_cast(other.get())->Explode(); + } else if (dynamic_cast(other.get())) { + other->Remove(); } } } @@ -761,7 +763,6 @@ void THero::Input(SDL_Event* event) { } - void THero::Update(std::uint32_t delta) { auto& entityManager = App_->EntityManager(); @@ -780,6 +781,29 @@ void THero::Update(std::uint32_t delta) { Speed_.X = -100; } if (KeysPressed_[static_cast(EKeys::X)]) { + auto entity = entityManager.MakeEntityByName("GrenadeEntity"); + auto targetEntity = dynamic_cast(entity.get()); + + targetEntity->SetPosition(Position()); + if (FaceLeft_) { + targetEntity->SetSpeed({-300, 0}); + } else { + targetEntity->SetSpeed({300, 0}); + } + entityManager.UpdateCollision(entity); + } + if (KeysPressed_[static_cast(EKeys::Up)]) { + auto otherIds = entityManager.CollisionList(Position(), Size(), PASSAGE_GROUP, Id()); + + for (auto otherId : otherIds) { + auto other = entityManager.Entity(otherId); + if (dynamic_cast(other.get())) { + entityManager.AddToDeferred("EulaMenu"); + entityManager.Reset(); + } + } + } + if (KeysPressed_[static_cast(EKeys::C)]) { auto entity = entityManager.MakeEntityByName("FloatingTextEntity"); auto targetEntity = dynamic_cast(entity.get()); targetEntity->SetText("You died, LMAO"); @@ -931,6 +955,19 @@ void THero::Update(std::uint32_t delta) { case EState::Dead: Speed_.Y += MovementPerTick(delta, Gravity_); + + if (KeysPressed_[static_cast(EKeys::Z)] || + KeysPressed_[static_cast(EKeys::X)] || + KeysPressed_[static_cast(EKeys::C)] || + KeysPressed_[static_cast(EKeys::Left)] || + KeysPressed_[static_cast(EKeys::Right)] || + KeysPressed_[static_cast(EKeys::Up)] || + KeysPressed_[static_cast(EKeys::Down)]) { + if (DisplayEnd_) { + entityManager.AddToDeferred("MainMenu"); + entityManager.Reset(); + } + } break; } } @@ -939,6 +976,7 @@ void THero::Update(std::uint32_t delta) { { auto entityList = entityManager.CollisionList(Position(), Size(), DAMAGE_GROUP, Id()); auto outCenter = Position() + Size() / 2; + EState previousState = State_; for (auto& otherId : entityList) { auto other = entityManager.Entity(otherId); @@ -955,7 +993,7 @@ void THero::Update(std::uint32_t delta) { Speed_.Y += 500.0 / diff.Y; } } else if (dynamic_cast(other.get())) { - if (MovementPerTick(delta, Speed_.Y) < 1.0) { + if (MovementPerTick(delta, Speed_.Y) < 2.0) { continue; }; @@ -969,6 +1007,12 @@ void THero::Update(std::uint32_t delta) { } } } + + if (previousState != State_) { + if (!Alarm_.IsSet(1)) { + Alarm_.Set(1, 3000); + } + } } // Check if we need to flip sprite @@ -1111,6 +1155,11 @@ void THero::Draw() const { } } + if (DisplayEnd_) { + RenderManager_.SetLayer(NGame::TRenderManager::Interface); + App_->FontManager().Draw(NGame::TFontManager::Red, {}, "You are dead! Press X"); + } + if (FadeAmount_) { RenderManager_.SetLayer(NGame::TRenderManager::Interface); if (WhiteFade_) { @@ -1125,6 +1174,8 @@ void THero::Draw() const { void THero::Alarm(NGame::TAlarm::TId id) { if (id == 0) { AlternateRun_ = !AlternateRun_; + } else if (id == 1) { + DisplayEnd_ = true; } } @@ -1210,7 +1261,18 @@ TMainMenu::TMainMenu(NGame::TEntity::TId id) , App_(NGame::TApp::Instance()) , RenderManager_(App_->RenderManager()) , SpriteManager_(App_->SpriteManager()) { + RenderManager_.EnableLight(false); +} +void TMainMenu::Input(SDL_Event* event) { + switch (event->type) { + case SDL_KEYDOWN: + if (event->key.keysym.sym == 'x') { + App_->EntityManager().AddToDeferred("RoomEntity"); + App_->EntityManager().Reset(); + } + break; + } } void TMainMenu::Update(std::uint32_t delta) { @@ -1218,20 +1280,31 @@ void TMainMenu::Update(std::uint32_t delta) { } void TMainMenu::Draw() const { - + RenderManager_.SetLayer(NGame::TRenderManager::Interface); + App_->FontManager().Draw(NGame::TFontManager::Gold, {}, "Press X to start a game"); } void TMainMenu::Alarm(NGame::TAlarm::TId id) { } - TEulaMenu::TEulaMenu(NGame::TEntity::TId id) : NGame::TEntity(id) , App_(NGame::TApp::Instance()) , RenderManager_(App_->RenderManager()) , SpriteManager_(App_->SpriteManager()) { + RenderManager_.EnableLight(false); +} +void TEulaMenu::Input(SDL_Event* event) { + switch (event->type) { + case SDL_KEYDOWN: + if (event->key.keysym.sym == 'x') { + App_->EntityManager().AddToDeferred("RoomEntity"); + App_->EntityManager().Reset(); + } + break; + } } void TEulaMenu::Update(std::uint32_t delta) { @@ -1239,7 +1312,8 @@ void TEulaMenu::Update(std::uint32_t delta) { } void TEulaMenu::Draw() const { - + RenderManager_.SetLayer(NGame::TRenderManager::Interface); + App_->FontManager().Draw(NGame::TFontManager::Gold, {}, "Press X to gain debuff and continue"); } void TEulaMenu::Alarm(NGame::TAlarm::TId id) { @@ -1251,7 +1325,18 @@ TIntroMenu::TIntroMenu(NGame::TEntity::TId id) , App_(NGame::TApp::Instance()) , RenderManager_(App_->RenderManager()) , SpriteManager_(App_->SpriteManager()) { + RenderManager_.EnableLight(false); +} +void TIntroMenu::Input(SDL_Event* event) { + switch (event->type) { + case SDL_KEYDOWN: + if (event->key.keysym.sym == 'x') { + App_->EntityManager().AddToDeferred("MainMenu"); + App_->EntityManager().Reset(); + } + break; + } } void TIntroMenu::Update(std::uint32_t delta) { @@ -1259,7 +1344,8 @@ void TIntroMenu::Update(std::uint32_t delta) { } void TIntroMenu::Draw() const { - + RenderManager_.SetLayer(NGame::TRenderManager::Interface); + App_->FontManager().Draw(NGame::TFontManager::Gold, {}, "Made by an idiot. Press X to continue"); } void TIntroMenu::Alarm(NGame::TAlarm::TId id) { @@ -1271,7 +1357,18 @@ TOutroMenu::TOutroMenu(NGame::TEntity::TId id) , App_(NGame::TApp::Instance()) , RenderManager_(App_->RenderManager()) , SpriteManager_(App_->SpriteManager()) { + RenderManager_.EnableLight(false); +} +void TOutroMenu::Input(SDL_Event* event) { + switch (event->type) { + case SDL_KEYDOWN: + if (event->key.keysym.sym == 'x') { + App_->EntityManager().AddToDeferred("MainMenu"); + App_->EntityManager().Reset(); + } + break; + } } void TOutroMenu::Update(std::uint32_t delta) { @@ -1279,7 +1376,8 @@ void TOutroMenu::Update(std::uint32_t delta) { } void TOutroMenu::Draw() const { - + RenderManager_.SetLayer(NGame::TRenderManager::Interface); + App_->FontManager().Draw(NGame::TFontManager::Gold, {}, "Thanks for playing the game"); } void TOutroMenu::Alarm(NGame::TAlarm::TId id) { @@ -1313,3 +1411,65 @@ void TTorchEntity::Draw() const { void TTorchEntity::Alarm(NGame::TAlarm::TId id) { } + +TGrenadeEntity::TGrenadeEntity(NGame::TEntity::TId id) + : NGame::TEntity(id) + , App_(NGame::TApp::Instance()) + , RenderManager_(App_->RenderManager()) + , SpriteManager_(App_->SpriteManager()) { + SetSize(9); + Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Grenade.txt"); + Alarm_.Set(0, 3000 + rand() % 1000); + Alarm_.Set(1, 100); +} + +void TGrenadeEntity::Update(std::uint32_t delta) { + auto& entityManager = App_->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 TGrenadeEntity::Draw() const { + RenderManager_.SetLayer(NGame::TRenderManager::Foreground); + SpriteManager_.Draw(Sprite_, AlternateBlink_, Position()); +} + +void TGrenadeEntity::Alarm(NGame::TAlarm::TId id) { + if (id == 0) { + Explode(); + } else if (id == 1) { + AlternateBlink_ = !AlternateBlink_; + } +} + +void TGrenadeEntity::Explode() { + auto& entityManager = App_->EntityManager(); + + auto explosion = entityManager.MakeEntity(); + explosion->SetPosition(Position() + Size() / 2 - explosion->Size() / 2 + NGame::Vec2i{0, 4}); + Remove(); +} + +const NGame::Vec2f& TGrenadeEntity::Speed() const { + return Speed_; +} + +void TGrenadeEntity::SetSpeed(const NGame::Vec2f& speed) { + Speed_ = speed; +} \ No newline at end of file diff --git a/src/RoomEntity.h b/src/RoomEntity.h index cbfc757..d00b9b9 100644 --- a/src/RoomEntity.h +++ b/src/RoomEntity.h @@ -316,7 +316,7 @@ private: NGame::Vec2f Fraction_ = NGame::Vec2f(0.0, 0.0); NGame::Vec2i ExitPosition_; - + bool DisplayEnd_ = false; bool WhiteFade_ = false; std::size_t FadeAmount_ = 0; }; @@ -361,6 +361,7 @@ class TMainMenu : public NGame::TEntity { public: TMainMenu(NGame::TEntity::TId id); + virtual void Input(SDL_Event* event) override; virtual void Update(std::uint32_t delta) override; virtual void Draw() const override; virtual void Alarm(NGame::TAlarm::TId id) override; @@ -375,6 +376,7 @@ class TEulaMenu : public NGame::TEntity { public: TEulaMenu(NGame::TEntity::TId id); + virtual void Input(SDL_Event* event) override; virtual void Update(std::uint32_t delta) override; virtual void Draw() const override; virtual void Alarm(NGame::TAlarm::TId id) override; @@ -389,6 +391,7 @@ class TIntroMenu : public NGame::TEntity { public: TIntroMenu(NGame::TEntity::TId id); + virtual void Input(SDL_Event* event) override; virtual void Update(std::uint32_t delta) override; virtual void Draw() const override; virtual void Alarm(NGame::TAlarm::TId id) override; @@ -403,6 +406,7 @@ class TOutroMenu : public NGame::TEntity { public: TOutroMenu(NGame::TEntity::TId id); + virtual void Input(SDL_Event* event) override; virtual void Update(std::uint32_t delta) override; virtual void Draw() const override; virtual void Alarm(NGame::TAlarm::TId id) override; @@ -428,3 +432,27 @@ private: NGame::TSpriteManager& SpriteManager_; NGame::TRenderManager& RenderManager_; }; + +class TGrenadeEntity : public NGame::TEntity { +public: + TGrenadeEntity(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; + + void Explode(); + const NGame::Vec2f& Speed() const; + void SetSpeed(const NGame::Vec2f& speed); + +private: + NGame::TApp* App_; + NGame::TSpriteManager& SpriteManager_; + NGame::TRenderManager& RenderManager_; + + const float Gravity_ = 500; + std::shared_ptr Sprite_; + NGame::Vec2f Speed_ = NGame::Vec2f(0.0, 0.0); + NGame::Vec2f Fraction_ = NGame::Vec2f(0.0, 0.0); + bool AlternateBlink_ = false; +};