Skip to content

Commit

Permalink
Use STL list for enemies (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
drfiemost authored Nov 12, 2023
1 parent 379e4bc commit ea5b1ce
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 325 deletions.
210 changes: 61 additions & 149 deletions Hurrican/src/GegnerClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
// --------------------------------------------------------------------------------------

#include "GegnerClass.hpp"
#include <algorithm>
#include "Gegner_Helper.hpp"
#include "Player.hpp"
#include "stdafx.hpp"

#include <algorithm>
#include <memory>

// --------------------------------------------------------------------------------------
// Konstruktor
// --------------------------------------------------------------------------------------
Expand Down Expand Up @@ -540,25 +542,6 @@ bool GegnerClass::IsOnScreen() const {
// GegnerListClass Funktionen
// --------------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------
// Konstruktor : Initialisierung der GegnerDaten
// --------------------------------------------------------------------------------------

GegnerListClass::GegnerListClass() {
pStart = nullptr;
pEnd = nullptr;
NumGegner = 0;
}

// --------------------------------------------------------------------------------------
// Destruktor : Löschen der ganzen Liste und Freigabe der Gegner-Grafiken
// --------------------------------------------------------------------------------------

GegnerListClass::~GegnerListClass() {
// Gegner-Liste komplett leeren
ClearAll();
}

void GegnerListClass::LoadSprites() {
// Flamme der Drone laden
DroneFlame.LoadImage("droneflame.png", 164, 46, 82, 46, 2, 1);
Expand Down Expand Up @@ -1460,10 +1443,10 @@ void GegnerListClass::LoadSprites() {
// Gegner "Art" hinzufügen
// --------------------------------------------------------------------------------------

bool GegnerListClass::PushGegner(float x, float y, int Art, int Value1, int Value2, bool Light, bool atEnd) {
GegnerClass* GegnerListClass::PushGegner(float x, float y, int Art, int Value1, int Value2, bool Light, bool atEnd) {

if (NumGegner >= MAX_GEGNER) // Grenze überschritten ?
return false;
if (GetNumGegner() >= MAX_GEGNER) // Grenze überschritten ?
return nullptr;

GegnerClass *pNew; // Das wird der neue Gegner;

Expand Down Expand Up @@ -1903,7 +1886,7 @@ bool GegnerListClass::PushGegner(float x, float y, int Art, int Value1, int Valu
} break;

case SHOOTBUTTON: {
pNew = new GegnerShootButton(pEnd);
pNew = new GegnerShootButton(enemies.back().get());
} break;

case SHOOTPLATTFORM: {
Expand Down Expand Up @@ -2081,35 +2064,17 @@ bool GegnerListClass::PushGegner(float x, float y, int Art, int Value1, int Valu
pNew->xPosOld = x;
pNew->yPosOld = y;

if (pStart == nullptr) // Liste leer ?
{
pStart = pNew; // Ja, dann neuer Gegner gleich der erste
pEnd = pNew; // und letzte Gegner
std::unique_ptr<GegnerClass> uNew(pNew);

pStart->pNext = nullptr; // Next/Previous gibts nich, da wir
pStart->pPrev = nullptr; // nur 1 Gegner haben
} else // Liste ist NICHT leer
{
// Gegner am Ende einfügen?
if (atEnd == true) {
pEnd->pNext = pNew; // Letzter Gegner zeigt auf den neuen
pNew->pPrev = pEnd; // Letzter Gegner ist nicht mehr der letzte

pNew->pNext = nullptr; // Nach dem neuen Gegner kommt keiner mehr
pEnd = pNew; // da er jetzt der letzte in der Liste ist
}

// Gegner am Anfag einfügen?
else {
pStart->pPrev = pNew; // Erster Gegner zeigt auf den neuen
pNew->pNext = pStart; // Erster Gegner ist nicht mehr der erste

pNew->pPrev = nullptr; // Vor dem neuen Gegner kommt keiner mehr
pStart = pNew; // da er jetzt der erste in der Liste ist
}
// Gegner am Ende einfügen?
if (atEnd) {
enemies.push_back(std::move(uNew));
}

NumGegner++; // Gegneranzahl erhöhen
// Gegner am Anfag einfügen?
else {
enemies.push_front(std::move(uNew));
}

// Bei der ShootPlattform noch den Button anfügen
//
Expand All @@ -2118,112 +2083,57 @@ bool GegnerListClass::PushGegner(float x, float y, int Art, int Value1, int Valu
Gegner.PushGegner(pNew->xPos + 42, pNew->yPos - 9, SHOOTBUTTON, 0, 0, Light);
}

return true;
}

// --------------------------------------------------------------------------------------
// Bestimmten Gegner der Liste löschen
// --------------------------------------------------------------------------------------

void GegnerListClass::DelSel(GegnerClass *pTemp) {

if (pTemp != nullptr) // zu löschender Gegner existiert
{
GegnerClass *pN = pTemp->pNext;
GegnerClass *pP = pTemp->pPrev;

if (pP == nullptr) // Wird der erste Gegner gelöscht ?
pStart = pN; // Dann wird dessen Nächster zum Ersten
else
pP->pNext = pN; // ansonsten normal eins aufrücken

if (pN == nullptr) // Wird der letzte Gegner gelöscht ?
pEnd = pP; // Dann wir der letzte Gegner zum ersten
else
pN->pPrev = pP;

delete (pTemp); // Speicher freigeben
pTemp = nullptr;

NumGegner--; // Gegnerzahl verringern
}
return pNew;
}

// --------------------------------------------------------------------------------------
// Alle Gegner der Liste löschen
// --------------------------------------------------------------------------------------

void GegnerListClass::ClearAll() {
GegnerClass *pTemp = pStart; // Zeiger auf den ersten Gegner

while (pTemp != nullptr) // Ende der Liste erreicht ?
{
GegnerClass *pNaechst = pTemp->pNext; // Zeiger auf den nächsten Gegner (falls der eine gelöscht wird)
DelSel(pTemp); // Das aktuelle löschen
pTemp = pNaechst; // und das nächste bearbeiten
}

pStart = nullptr;
pEnd = nullptr;
enemies.clear();
}

// --------------------------------------------------------------------------------------
// Zahl der Gegner zurückliefern
// --------------------------------------------------------------------------------------

int GegnerListClass::GetNumGegner() const {
return NumGegner;

return enemies.size();
}

// --------------------------------------------------------------------------------------
// Alle Gegner der Liste animieren
// --------------------------------------------------------------------------------------

void GegnerListClass::RenderAll() {
GegnerClass *pTemp = pStart; // Anfang der Liste

// Zuerst die "Gegner" rendern, die als Background fungieren
// z.B. der große Lüfter, damit diese nicht die anderen Gegner verdecken können
//
while (pTemp != nullptr) // noch nicht alle durch ?
for (auto& enemy: Gegner.enemies)
{
if (pTemp->BackGround == false) // kein Background? Dann nächsten
{
pTemp = pTemp->pNext;
continue;
}

if (pTemp->Active == true) // aktueller Gegner aktiv ?
if (enemy->BackGround && enemy->Active)
{
// dann Gegner rendern
pTemp->AlreadyDrawn = false;
pTemp->Render();
enemy->AlreadyDrawn = false;
enemy->Render();
}

pTemp = pTemp->pNext; // Nächsten durchgehen
}

// Danach alle anderen "richtigen" Gegner rendern
//

pTemp = Gegner.pStart;

while (pTemp != nullptr) // noch nicht alle durch ?
for (auto& enemy: Gegner.enemies)
{
if (pTemp->BackGround == true) // Background? Dann nächsten
{
pTemp = pTemp->pNext;
continue;
}

if (pTemp->Active == true) // aktueller Gegner aktiv ?
if (!enemy->BackGround && enemy->Active)
{
// dann Gegner rendern
pTemp->AlreadyDrawn = false;
pTemp->Render();
enemy->AlreadyDrawn = false;
enemy->Render();
}

pTemp = pTemp->pNext; // Und nächsten Gegner rendern
}
}

Expand All @@ -2232,23 +2142,22 @@ void GegnerListClass::RenderAll() {
// --------------------------------------------------------------------------------------

void GegnerListClass::RunAll() {
GegnerClass *pTemp = pStart; // Anfang der Liste

// Alle Einträge der Gegnerliste durchgehen
//
while (pTemp != nullptr) // noch nicht alle durch ?
auto iter = enemies.begin();
while (iter != enemies.end())
{
GegnerClass *pNext = pTemp->pNext;

pTemp->Run();
GegnerClass* enemy = iter->get();
enemy->Run();

// ggf Gegner löschen (bei Energy <= 0)
if (pTemp->Energy <= 0.0f) {
pTemp->GegnerExplode(); // Jeder Gegner explodiert anders
DelSel(pTemp); // Gegner aus der Liste löschen
if (enemy->Energy <= 0.0f) {
enemy->GegnerExplode(); // Jeder Gegner explodiert anders
iter = enemies.erase(iter);
}

pTemp = pNext;
else
++iter;
}
}

Expand All @@ -2258,45 +2167,48 @@ void GegnerListClass::RunAll() {

void GegnerListClass::DamageEnemiesonScreen(float x, float y, int MaxDamage) {
// Gegner durchgehen und die auf dem Screen löschen
GegnerClass *pTemp = pStart; // Anfang der Liste

while (pTemp != nullptr) // Noch nicht alle durch ?
for (auto& enemy: enemies)
{
float const ax = x - pTemp->xPos;
float const ay = y - pTemp->yPos;
float const ax = x - enemy->xPos;
float const ay = y - enemy->yPos;
float const dx = sqrtf((ax * ax) + (ay * ay));

GegnerClass *pNext = pTemp->pNext; // Nächster Gegner in der Liste

// Stampfstein? Fällt runter bei Wackeln
if (pTemp->Active == true && pTemp->GegnerArt == STAMPFSTEIN && pTemp->Handlung == GEGNER::STEHEN && dx < 300 &&
pTemp->xPos + GegnerRect[pTemp->GegnerArt].right > TileEngine.XOffset &&
pTemp->xPos + GegnerRect[pTemp->GegnerArt].left < TileEngine.XOffset + RENDERWIDTH &&
pTemp->yPos + GegnerRect[pTemp->GegnerArt].bottom > TileEngine.YOffset &&
pTemp->yPos + GegnerRect[pTemp->GegnerArt].top < TileEngine.YOffset + RENDERHEIGHT) {
pTemp->Handlung = GEGNER::FALLEN;
pTemp->ySpeed = 20.0f;
pTemp->yAcc = 15.0f;
if (enemy->Active &&
enemy->GegnerArt == STAMPFSTEIN &&
enemy->Handlung == GEGNER::STEHEN &&
dx < 300 &&
enemy->xPos + GegnerRect[enemy->GegnerArt].right > TileEngine.XOffset &&
enemy->xPos + GegnerRect[enemy->GegnerArt].left < TileEngine.XOffset + RENDERWIDTH &&
enemy->yPos + GegnerRect[enemy->GegnerArt].bottom > TileEngine.YOffset &&
enemy->yPos + GegnerRect[enemy->GegnerArt].top < TileEngine.YOffset + RENDERHEIGHT) {
enemy->Handlung = GEGNER::FALLEN;
enemy->ySpeed = 20.0f;
enemy->yAcc = 15.0f;

// DKS - Added function WaveIsPlaying() to SoundManagerClass:
if (!SoundManager.WaveIsPlaying(SOUND::STONEFALL))
SoundManager.PlayWave(100, 128, 8000 + GetRandom(4000), SOUND::STONEFALL);
}

// Gegner in der Nähe? Dann Energie abziehen
if (pTemp->Active == true && dx < 300 && pTemp->Destroyable == true && pTemp->GegnerArt != POWERBLOCK &&
pTemp->GegnerArt < RIESENPIRANHA && pTemp->xPos + GegnerRect[pTemp->GegnerArt].right > TileEngine.XOffset &&
pTemp->xPos + GegnerRect[pTemp->GegnerArt].left < TileEngine.XOffset + RENDERWIDTH &&
pTemp->yPos + GegnerRect[pTemp->GegnerArt].bottom > TileEngine.YOffset &&
pTemp->yPos + GegnerRect[pTemp->GegnerArt].top < TileEngine.YOffset + RENDERHEIGHT) {
if (enemy->Active &&
dx < 300 &&
enemy->Destroyable &&
enemy->GegnerArt != POWERBLOCK &&
enemy->GegnerArt < RIESENPIRANHA &&
enemy->xPos + GegnerRect[enemy->GegnerArt].right > TileEngine.XOffset &&
enemy->xPos + GegnerRect[enemy->GegnerArt].left < TileEngine.XOffset + RENDERWIDTH &&
enemy->yPos + GegnerRect[enemy->GegnerArt].bottom > TileEngine.YOffset &&
enemy->yPos + GegnerRect[enemy->GegnerArt].top < TileEngine.YOffset + RENDERHEIGHT) {

int amount = static_cast<int>(MaxDamage - dx);

if (amount < 0)
amount = 0;

pTemp->Energy -= amount;
enemy->Energy -= amount;
}

pTemp = pNext; // Und nächsten Gegner anhandeln
}
}
18 changes: 6 additions & 12 deletions Hurrican/src/GegnerClass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#endif
#include "DX8Sprite.hpp"

#include <list>
#include <memory>

// --------------------------------------------------------------------------------------
// Defines
// --------------------------------------------------------------------------------------
Expand Down Expand Up @@ -100,43 +103,34 @@ class GegnerClass {
void TurnonWall(); // An der Wand umdrehen?
bool TurnonShot(); // Umdrehen, wenn angeschoßen
bool IsOnScreen() const; // Gegner grade sichtbar?
GegnerClass *pNext; // Zeiger auf den nächsten Gegner
GegnerClass *pPrev; // Zeiger auf den vorherigen Gegner
};

// --------------------------------------------------------------------------------------
// Gegner Klasse, Linked List, die alle Gegner beinhaltet
// --------------------------------------------------------------------------------------

class GegnerListClass {
private:
int NumGegner; // aktuelle Zahl der Gegner

public:
// DKS - Moved these three here, they used to be dynamic globals in Gegner_Helper.cpp:
// (Moved so they would always get destructed in a place we had control over)
DirectGraphicsSprite DroneFlame; // Flamme der Drone
DirectGraphicsSprite DroneGun; // Flamme der Zitrone

GegnerClass *pStart; // Erstes Element der Liste
GegnerClass *pEnd; // Letztes Element der Liste

GegnerListClass(); // Konstruktor
~GegnerListClass(); // Destruktor
std::list<std::unique_ptr<GegnerClass>> enemies;

// DKS - GegnerListClass is now a static global, instead of dynamically allocated
// pointer, so moved the loading of sprites from its constructor to this new
// function:
void LoadSprites();

bool PushGegner(float x,
GegnerClass* PushGegner(
float x,
float y,
int Art, // Gegner "Art" hinzufügen
int Value1,
int Value2,
bool Light,
bool atEnd = true);
void DelSel(GegnerClass *pTemp); // Ausgewählten Gegner entfernen
void ClearAll(); // Alle Gegner löschen
int GetNumGegner() const; // Zahl der Gegner zurückliefern
void RunAll(); // Alle Gegner der Liste animieren
Expand Down
Loading

0 comments on commit ea5b1ce

Please sign in to comment.