Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use stl list for projectiles #68

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 48 additions & 120 deletions Hurrican/src/Projectiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,18 @@
// --------------------------------------------------------------------------------------


#include "Projectiles.hpp"
#include "Console.hpp"
#include "DX8Font.hpp"
#include "DX8Sound.hpp"
#include "Gameplay.hpp"
#include "Gegner_Helper.hpp"
#include "Globals.hpp"
#include "Logdatei.hpp"
#include "Partikelsystem.hpp"
#include "Player.hpp"
#include "Projectiles.hpp"
#include "Tileengine.hpp"
#include "Timer.hpp"

#include <cmath>
#include <algorithm>

// --------------------------------------------------------------------------------------
// Defines
// --------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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 ?
Expand Down Expand Up @@ -4116,9 +4111,6 @@ void ProjectileClass::ExplodeShot() {
// Konstruktor : laden der Projektil Grafiken
// --------------------------------------------------------------------------------------
ProjectileListClass::ProjectileListClass() {
pStart = nullptr;
pEnd = nullptr;
NumProjectiles = 0;
}

void ProjectileListClass::LoadSprites() {
Expand Down Expand Up @@ -4677,7 +4669,6 @@ void ProjectileListClass::LoadSprites() {
// --------------------------------------------------------------------------------------

ProjectileListClass::~ProjectileListClass() {
// Schuss-Liste komplett leeren
ClearAll();
}

Expand Down Expand Up @@ -4718,28 +4709,21 @@ 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
ProjectileClass *pNew = projectile_pool.alloc();
#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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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;
}
}
}
22 changes: 5 additions & 17 deletions Hurrican/src/Projectiles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -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<ProjectileClass, MAX_SHOTS> projectile_pool;
#endif

public:
ProjectileClass *pStart; // Erstes Element der Liste
ProjectileClass *pEnd; // Letztes Element der Liste
std::list<ProjectileClass*> 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.
Expand Down Expand Up @@ -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
};

// --------------------------------------------------------------------------------------
Expand Down
20 changes: 7 additions & 13 deletions Hurrican/src/bosses/Boss_FahrstuhlBoss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading