From ae3049b610c26e98ff1dce08a7eee487068cb572 Mon Sep 17 00:00:00 2001 From: Mia Date: Sun, 3 Dec 2023 19:41:42 +0100 Subject: [PATCH] Replaced C style list with STL list --- Hurrican/src/Projectiles.cpp | 168 ++++++--------------- Hurrican/src/Projectiles.hpp | 22 +-- Hurrican/src/bosses/Boss_FahrstuhlBoss.cpp | 20 +-- 3 files changed, 60 insertions(+), 150 deletions(-) diff --git a/Hurrican/src/Projectiles.cpp b/Hurrican/src/Projectiles.cpp index e29fee4b..57dcae38 100644 --- a/Hurrican/src/Projectiles.cpp +++ b/Hurrican/src/Projectiles.cpp @@ -13,8 +13,8 @@ // -------------------------------------------------------------------------------------- +#include "Projectiles.hpp" #include "Console.hpp" -#include "DX8Font.hpp" #include "DX8Sound.hpp" #include "Gameplay.hpp" #include "Gegner_Helper.hpp" @@ -22,13 +22,9 @@ #include "Logdatei.hpp" #include "Partikelsystem.hpp" #include "Player.hpp" -#include "Projectiles.hpp" #include "Tileengine.hpp" #include "Timer.hpp" -#include -#include - // -------------------------------------------------------------------------------------- // Defines // -------------------------------------------------------------------------------------- @@ -1809,7 +1805,6 @@ void ProjectileClass::CreateShot(float x, float y, int Art, PlayerClass *pTemp) // -------------------------------------------------------------------------------------- void ProjectileClass::CheckCollision() { - for (auto& pEnemy: Gegner.enemies) // Noch nicht alle durch ? { if (pEnemy->Active && // Ist der Gegner überhaupt aktiv ? @@ -4116,9 +4111,6 @@ void ProjectileClass::ExplodeShot() { // Konstruktor : laden der Projektil Grafiken // -------------------------------------------------------------------------------------- ProjectileListClass::ProjectileListClass() { - pStart = nullptr; - pEnd = nullptr; - NumProjectiles = 0; } void ProjectileListClass::LoadSprites() { @@ -4677,7 +4669,6 @@ void ProjectileListClass::LoadSprites() { // -------------------------------------------------------------------------------------- ProjectileListClass::~ProjectileListClass() { - // Schuss-Liste komplett leeren ClearAll(); } @@ -4718,11 +4709,11 @@ bool ProjectileListClass::PushProjectile(float x, float y, int Art, PlayerClass* return true; } #endif // 0 + bool ProjectileListClass::PushProjectile(float x, float y, int Art, PlayerClass *pTemp) { - if (NumProjectiles >= MAX_SHOTS) + if (GetNumProjectiles() >= MAX_SHOTS) return false; - // DKS - added support for new, fast pooled mem-manager: #ifdef USE_NO_MEMPOOLING ProjectileClass *pNew = new ProjectileClass; #else @@ -4730,16 +4721,9 @@ bool ProjectileListClass::PushProjectile(float x, float y, int Art, PlayerClass #endif pNew->CreateShot(x, y, Art, pTemp); - pNew->pNext = nullptr; - if (pEnd) - pEnd->pNext = pNew; // If list isn't empty, insert this projectile on the end. - else - pStart = pNew; // Or, if list is empty, make this the new head of the list. - - pEnd = pNew; // Update end-of-list pointer + projectiles.push_front(pNew); - NumProjectiles++; return true; } @@ -4748,19 +4732,18 @@ bool ProjectileListClass::PushProjectile(float x, float y, int Art, PlayerClass // -------------------------------------------------------------------------------------- bool ProjectileListClass::PushBlitzBeam(int Size, float Richtung, PlayerClass *pSource) { - if (NumProjectiles >= MAX_SHOTS) // Grenze überschritten ? + if (GetNumProjectiles() >= MAX_SHOTS) // Grenze überschritten ? return false; - // DKS - added support for new, fast pooled mem-manager #ifdef USE_NO_MEMPOOLING - ProjectileClass *pNew = new ProjectileClass; // Neues zu erstellendes Projectile + ProjectileClass *pNew = new ProjectileClass; #else ProjectileClass *pNew = projectile_pool.alloc(); #endif pNew->ShotArt = BLITZBEAM; - pNew->xPos = pSource->xpos - Size / 2 + 20; - pNew->yPos = pSource->ypos - Size / 2 + 32; + pNew->xPos = pSource->xpos - Size / 2.0f + 20; + pNew->yPos = pSource->ypos - Size / 2.0f + 32; pNew->xPosOld = pNew->xPos; pNew->yPosOld = pNew->yPos; pNew->AnimPhase = 0; @@ -4806,101 +4789,66 @@ bool ProjectileListClass::PushBlitzBeam(int Size, float Richtung, PlayerClass *p ShotRect[BLITZBEAM].right = ShotRect[BLITZBEAM].left + Size / 2; ShotRect[BLITZBEAM].bottom = ShotRect[BLITZBEAM].top + Size / 2; - pNew->pNext = nullptr; - - if (pEnd) - pEnd->pNext = pNew; // If list isn't empty, insert this projectile on the end. - else - pStart = pNew; // Or, if list is empty, make this the new head of the list. + projectiles.push_front(pNew); - pEnd = pNew; // Update end-of-list pointer - - NumProjectiles++; // Projektilanzahl erhöhen return true; } // -------------------------------------------------------------------------------------- -// Bestimmtes Projektil der Liste löschen +// Remove all dead projectiles // -------------------------------------------------------------------------------------- -// DKS - Replaced DelSel() with DelNode(), which supports the now-singly-linked-list. It operates -// a bit differently: -// It is now up to the caller to splice the list, this blindly deletes what is passed to it -// and returns the pointer that was in pPtr->pNext, or NULL if pPtr was NULL. -ProjectileClass *ProjectileListClass::DelNode(ProjectileClass *pPtr) { - ProjectileClass *pNext = nullptr; - if (pPtr != nullptr) { - pNext = pPtr->pNext; - - if (pStart == pPtr) // Are we deleting the first node in the list? - pStart = pNext; +void ProjectileListClass::ClearDeadProjectiles() { + auto iter = projectiles.begin(); + while (iter != projectiles.end()) { + ProjectileClass* projectile = *iter; - // DKS - added support for new, fast pooled mem-manager: + if (projectile->Damage > 0) { + ++iter; + } else { #ifdef USE_NO_MEMPOOLING - delete (pPtr); + delete projectile; #else - projectile_pool.free(pPtr); + projectile_pool.free(projectile); #endif - - NumProjectiles--; + iter = projectiles.erase(iter); + } } - return pNext; } // -------------------------------------------------------------------------------------- // Alle Projectile der Liste löschen // -------------------------------------------------------------------------------------- -// DKS - Converted ProjectileListClass to a singly-linked list (depends on DelNode() now). -// and added support for new pooled memory manager. -void ProjectileListClass::ClearAll() { - if (pStart) { - ProjectileClass *pNext = pStart->pNext; - - while (pNext) // Delete everything but the head of the list - pNext = DelNode(pNext); - DelNode(pStart); // Finally, delete the head of the list +void ProjectileListClass::ClearAll() { +#ifdef USE_NO_MEMPOOLING + for (auto& projectile: projectiles) { + delete projectile; } - pStart = pEnd = nullptr; - -#ifndef NDEBUG - if (NumProjectiles != 0) - Protokoll << "ERROR: poss. mem leak / corruption in linked list of projectiles" << std::endl; -#endif - - // DKS - added support for new, fast pooled mem-manager: -#ifndef USE_NO_MEMPOOLING +#else projectile_pool.reinit(); #endif - - // Just to be safe: - NumProjectiles = 0; + projectiles.clear(); } // -------------------------------------------------------------------------------------- // Alle Projectiles eines Typs löschen // -------------------------------------------------------------------------------------- -// DKS - Adapted after converting ProjectileListClass to a singly-linked list: void ProjectileListClass::ClearType(int Type) { - ProjectileClass *pPrev = nullptr; - ProjectileClass *pCurr = pStart; - - while (pCurr != nullptr) { - if (pCurr->ShotArt == Type) { - // If this is the last node in the list, update the main class's pEnd pointer - if (pEnd == pCurr) - pEnd = pPrev; - - pCurr = DelNode(pCurr); // pCurr now points to the node after the one deleted + auto iter = projectiles.begin(); + while (iter != projectiles.end()) { + ProjectileClass* projectile = *iter; - if (pPrev) { - // This is not the first node in the list, so splice this node onto the previous one - pPrev->pNext = pCurr; - } + if (projectile->ShotArt != Type) { + ++iter; } else { - pPrev = pCurr; - pCurr = pCurr->pNext; +#ifdef USE_NO_MEMPOOLING + delete projectile; +#else + projectile_pool.free(projectile); +#endif + iter = projectiles.erase(iter); } } } @@ -4910,48 +4858,28 @@ void ProjectileListClass::ClearType(int Type) { // -------------------------------------------------------------------------------------- int ProjectileListClass::GetNumProjectiles() const { - return NumProjectiles; + return projectiles.size(); } // -------------------------------------------------------------------------------------- // Alle Proectile der Liste animieren und bewegen // -------------------------------------------------------------------------------------- -// DKS - Adapted after converting projectile list to singly-linked one void ProjectileListClass::DoProjectiles() { - ProjectileClass *pPrev = nullptr; - ProjectileClass *pCurr = pStart; - - CurrentShotTexture = -1; // Aktuelle Textur gibt es noch keine + CurrentShotTexture = -1; // Aktuelle Textur gibt es noch keine - while (pCurr != nullptr) { - if (!Console.Showing) - pCurr->Run(); - - if (pCurr->Damage > 0) - pCurr->Render(); + ClearDeadProjectiles(); + for (auto& projectile: projectiles) { if (!Console.Showing) { - if (pCurr->Damage <= 0) // ggf Schuss löschen (bei Damage <= 0) - { - // Projectile's time to die.. - // If this is the last node in the list, update the class's pEnd pointer - if (pEnd == pCurr) - pEnd = pPrev; - - pCurr = DelNode(pCurr); // pCurr now points to the node after the one deleted + projectile->Run(); + } + if (projectile->Damage > 0) { + projectile->Render(); - // If this is not the first node in the list, splice this node onto the previous one: - if (pPrev) - pPrev->pNext = pCurr; - } else { - pCurr->CheckCollision(); - pPrev = pCurr; - pCurr = pCurr->pNext; + if (!Console.Showing) { + projectile->CheckCollision(); } - } else { - pPrev = pCurr; - pCurr = pCurr->pNext; } } } diff --git a/Hurrican/src/Projectiles.hpp b/Hurrican/src/Projectiles.hpp index 3b685ed5..8aa95cd4 100644 --- a/Hurrican/src/Projectiles.hpp +++ b/Hurrican/src/Projectiles.hpp @@ -211,9 +211,6 @@ class ProjectileClass { void Render(); // Schuss rendern void CheckCollision(); // Kollision checken void ExplodeShot(); // Schuss explodiert und erzeugt Partikel - ProjectileClass *pNext; // Zeiger auf den nächsten Schuss - // DKS - Made a singly-linked list, there's no need or benefit for a doubly-linked list here. - // ProjectileClass *pPrev; // Zeiger auf den vorherigen Schuss PlayerClass *pParent; }; @@ -223,16 +220,13 @@ class ProjectileClass { class ProjectileListClass { private: - int NumProjectiles; // aktuelle Zahl der Schüsse - // DKS - New, very simple pooled memory manager decreases alloc/dealloc overhead: (see DataStructures.h) #ifndef USE_NO_MEMPOOLING MemPool projectile_pool; #endif public: - ProjectileClass *pStart; // Erstes Element der Liste - ProjectileClass *pEnd; // Letztes Element der Liste + std::list projectiles; // DKS - All of these 5 sprites are no longer globals, I moved them here cleaning up big messes // and fixing ambiguous orders of calls to destructors. @@ -264,17 +258,11 @@ class ProjectileListClass { float Richtung, PlayerClass *pSource); // BlitzBeam hinzufügen (in verschiedenen Größen und Richtungen möglich) - // DKS - Converted projectile linked-list to be singly-linked: - // DelNode() is new and takes the place of DelSel(), but operates a bit differently. - // It is now up to the caller to splice the list: DelNode() blindly deletes the node - // passed to it and returns the pointer that was in pPtr->pNext, or NULL if pPtr was NULL. - // void DelSel (ProjectileClass *pTemp); // Ausgewähltes Objekt entfernen - ProjectileClass *DelNode(ProjectileClass *pPtr); - - void ClearAll(); // Alle Objekte löschen - void ClearType(int type); // Alle Objekte eines Typs löschen + void ClearDeadProjectiles(); // Remove all dead projectiles + void ClearAll(); // Alle Objekte löschen + void ClearType(int type); // Alle Objekte eines Typs löschen int GetNumProjectiles() const; // Zahl der Schüsse zurückliefern - void DoProjectiles(); // Alle Schüsse der Liste animieren + void DoProjectiles(); // Alle Schüsse der Liste animieren }; // -------------------------------------------------------------------------------------- diff --git a/Hurrican/src/bosses/Boss_FahrstuhlBoss.cpp b/Hurrican/src/bosses/Boss_FahrstuhlBoss.cpp index 23b8cedd..cb2cfc68 100644 --- a/Hurrican/src/bosses/Boss_FahrstuhlBoss.cpp +++ b/Hurrican/src/bosses/Boss_FahrstuhlBoss.cpp @@ -526,14 +526,11 @@ void GegnerFahrstuhlBoss::DoKI() { pTemp = pTemp->pNext; // Zeiger auf das nächste Element } - ProjectileClass *pTemp2 = Projectiles.pStart; // Zeiger auf den ersten Schuss - while (pTemp2 != nullptr) // Ende der Liste erreicht ? - { - if (pTemp2->ShotArt != STELZLASER) { - pTemp2->yPos += Timer.sync(40.0f); // Nach unten bewegen - pTemp2->yPosOld += Timer.sync(40.0f); + for (const auto& projectile: Projectiles.projectiles) { + if (projectile->ShotArt != STELZLASER) { + projectile->yPos += Timer.sync(40.0f); // Nach unten bewegen + projectile->yPosOld += Timer.sync(40.0f); } - pTemp2 = pTemp2->pNext; // Zeiger auf das nächste Element } // Level-Hintergrund wiederholen und alle Objekte wieder nach oben setzen @@ -552,12 +549,9 @@ void GegnerFahrstuhlBoss::DoKI() { } } - ProjectileClass *pTemp4 = Projectiles.pStart; // Zeiger auf den ersten Schuss - while (pTemp4 != nullptr) // Ende der Liste erreicht ? - { - pTemp4->yPos -= A; // Nach oben bewegen - pTemp4->yPosOld -= A; - pTemp4 = pTemp4->pNext; // Zeiger auf das nächste Element + for (const auto& projectile: Projectiles.projectiles) { + projectile->yPos -= A; // Nach oben bewegen + projectile->yPosOld -= A; } PartikelClass *pTemp5 = PartikelSystem.GetPStart(); // Zeiger auf den ersten Partikel