Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

TigerClaw25

unregistriert

1

11.04.2013, 13:22

Animation bei Explosion

Ich versuche schon seit Stunden eine Explosion hinzubekommen, aber irgendwie klappt das nicht. Mein Programm stürzt ununterbrochen ab ...

Explosion.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef EXPLOSION_HPP
#define EXPLOSION_HPP

#include "Sprite.hpp"

class CExplosion
{
    public:
        void Init   (CSprite *pSpriteExplosion, float fXPos, float fYPos);
        void Update   ();
        void Render   ();
        bool IsAlive  () {return m_bIsAlive;}
        void SetAlive (bool bIsAlive);
        SDL_Rect GetRect () {return m_Rect;}
        
    private:
        CSprite *m_pSpriteExplosion; // Zeiger auf Explosion-Sprite
        float   m_fXPos;        // X-Position des Explosion
        float   m_fYPos;        // Y-Position des Explosion
        float   m_fAnimPhase;   // Akt. Animationsphase der Explosion
        bool    m_bIsAlive;     // "Lebt" die Explosion noch?
        SDL_Rect m_Rect;            // Rect der Explosion   
};

#endif


Explosion.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "Explosion.h"

// Init
//
// Aufgabe: Asteroid initialisieren
//
void CExplosion::Init (CSprite *pSpriteExplosion, float fXPos, float fYPos)
{
    // Zeiger auf Sprite kopieren und Koordinaten setzen
    m_pSpriteExplosion = pSpriteExplosion;
    m_fXPos = fXPos;
    m_fYPos = fYPos;

    // Animation beginnt beim ersten Einzelbild
    m_fAnimPhase = 0.0f;

    // Rect initialisieren
    m_Rect.x = static_cast<int>(fXPos);
    m_Rect.y = static_cast<int>(fYPos);
    m_Rect.w = pSpriteExplosion->GetRect().w;
    m_Rect.h = pSpriteExplosion->GetRect().h;

    // Asteroid aktivieren
    m_bIsAlive = true;

} // Init


// SetAlive
//
// Aufgabe: -
//
void CExplosion::SetAlive (bool bIsAlive) 
{
    m_bIsAlive = bIsAlive;
    }
// SetAlive


// Update
//
// Aufgabe: Asteroid bewegen und Position prüfen
//
void CExplosion::Update ()
{
    m_Rect.x = static_cast<int>(m_fXPos);
    m_Rect.y = static_cast<int>(m_fYPos);

    // Animieren
    m_fAnimPhase += 10.0f * g_pTimer->GetElapsed ();

    // Prüfen, ob die Animation am Ende angelangt ist
    if (m_fAnimPhase >= 128.0f)
    {
        m_fAnimPhase = m_fAnimPhase - 128.0f;
        m_bIsAlive = false;
    }   
} // Update

// Render
//
// Aufgabe: Asteroid rendern
//
void CExplosion::Render ()
{
    m_pSpriteExplosion->SetPos (m_fXPos, m_fYPos);
    m_pSpriteExplosion->Render (m_fAnimPhase);

} // Render


game.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
...
...
    // Sprite für Explosion laden
    m_pSpriteExplosion = new CSprite;
    m_pSpriteExplosion->Load ("Data/Player.bmp", 11, 64,64);
    m_pSpriteExplosion->SetColorKey (255, 0, 255);
...
...
...
.// Kollisionsüberprüfung (Funktion)
...
// Explosion des Asteroiden darstellen
                // Timer für nächsten Asteroiden erhöhen
            
            RectExplosion.x = RectAsteroid.x;
            RectExplosion.y = RectAsteroid.y;
            ItExplosion->Render();
...
...
...


Ich habe das Ganze in die Kollisionsfunktion rein gepackt, aber es läuft nicht ...

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

11.04.2013, 13:47

Debugger benutzen, dann weißt du auch wo es abstürzt und mit ein bisschen Nachdenken warum.

TigerClaw25

unregistriert

3

11.04.2013, 14:10

Bin ich überhaupt auf dem richtigen Weg? Ich bin der Meinung, dass Listen für Explosionen nicht das richtige sind. Oder etwa doch?

Immerhin habe ich es hinbekommen, dass ich jetzt bei Kollisionen zwischen Asteroiden und Player Punkte abgezogen werden, wobei das sehr lange dauert, bis der Kompiler das auch debuggt ... weiß nicht weshalb.


CGames::RUn beinhaltet folgende Zeile:

m_pFontNumb->WriteNumber(m_pPlayer->GetLives(), 510, 550, 255, 20, 50);

GetLives und SetLives sind Funktionen des CPlayers. Diese verarbeiten eine Membervariable.

Die Funktion, die für das Update zuständig ist, habe ich dann in die if Bedinung in der CGames::CheckCollision eingefügt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
// PlayerHit
//
// Aufgabe: Position und Animationsphase prüfen
//
void CGame::PlayerHit()
{
    m_HitCount = m_pPlayer->GetLives();
    m_HitCount--;
    m_pPlayer->SetLives(m_HitCount);
} // PlayerHit

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

11.04.2013, 14:19

Wieso manipuliert das Spiel die Lebenspunkte des Spielers über set und get? Und warum werden die Leben redundant in einer Member-Variable abgelegt?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TigerClaw25

unregistriert

5

11.04.2013, 14:27

Also:

Lebensenergie gehört zum Spieler. Daher initialisiere ich im Konstruktor des Spielers CPlayer::CPlayer die Variable mit beispielsweise 15 Punkten.

Meine Beiden Funktionen in CPlayer sehen dann wie folgt aus:

C-/C++-Quelltext

1
2
int GetLives (){return m_PlayerLive;}               // Treffer übergeben (Spieler)
int SetLives (int i){m_PlayerLive = i; return 0;}       // Treffer setzen (Spieler)


Und die PlayerHit Funktion habe ich ja bereits gepostet.

In der CGame::RUn() habe ich dann alles so verpackt, dass sobald ich 0 Punkte erreicht habe, keine Asteroiden oder Ähnliches mehr gerendert wird ...


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Lebensenergie anzeigen
        m_HitCount = m_pPlayer->GetLives();
        
        if (m_HitCount>=5)
        {       
            m_pFontNumb->WriteFont("Energie: ", 530, 550, 255, 20, 50);
            m_pFontNumb->WriteNumber(m_HitCount, 610, 550, 255, 20, 50);
        
GAMESCHLEIFE

}
        else if (m_HitCount<=5 && m_HitCount !=0)
        {
            m_pFontNumb->WriteFont("Energie: ", 530, 550, 255, 20, 50);
            m_pFontNumb->WriteFont("Kritischer Zustand", 610, 550, 255, 20, 50);

GAMESCHLEIFE

        }
        else
        {
            m_pFontNumb->WriteFont("GAME OVER", 530, 550, 255, 20, 50);
        }

TigerClaw25

unregistriert

6

11.04.2013, 14:46

Ach und was die Animationen angeht, so denke ich, dass es ausreichen würde, wenn ich ohne Listen arbeite ... also wie bei SpawnAsteroid einfach eine einfache Instanz erstellen und rendern ...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

11.04.2013, 17:49

Und die PlayerHit Funktion habe ich ja bereits gepostet.

Genau, hast Du. Nur warum genau ist die jetzt in CGame und nicht in Player? Warum darf und muss CGame an den Lebenspunkten des Spielers rumfummeln? Ist das nicht Aufgabe der Spieler-Klasse das zu tun? Wenn nicht, wofür hast Du dann überhaupt eine Spieler-Klasse und nicht einfach nur eine Variable oder ein Struct in CGame? Warum hat CGame eine Variable namens "m_HitCounter" als MEMBER?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Sp3iky

Treue Seele

Beiträge: 232

Beruf: Entwicklungsingenieur

  • Private Nachricht senden

8

11.04.2013, 17:58

Es zeigt sich, dass du dir generell nochmal das das Konzept der objektorientierten Programmierung verinnerlichen solltest. Worauf BlueCobold hinaus wollte ist, dass Klassen dazu gedacht sind, objektbezogene Parameter zu kapseln. Wenn du für alles Getter- und Setter-Funktionen hast, kannst du dir das kapseln generell sparen. Genauso sollte deine Gameklasse nicht auch noch eine Membervariable haben, um das Leben des Players zu speichern, denn die Gameklasse hat das nicht zu interessieren.

Eine sinnvolle Kapselung wäre, dass nur der Player sein Leben speichert und bei Kollision eine Funktion "Treffer(int Leben)" oder so etwas des Players aufgerufen wird, die dann den Wert der internen Variable um den Wert "Leben" reduziert. Die Abfrage ob ein Spiel beendet ist würde dann über das Abfragen einer Funktion "Spielertot()" oder ähnliches erfolgen.
Sinn des ganzen ist, dass du zum Beispiel ganz einfach deinen Player austauschen kannst oder die Berechnung des Lebens intern beliebig verändern kannst, ohne deine ganze Gameklasse umzuschreiben. Das ist übrigens auch nur eine Variante, wie man das lösen könnte.

Und noch zum Thema Getter/Setter:

Eine Get-Funktion gibt dir einen Wert zurück und hat daher einen Rückgabewert.
Eine Set-Funktion setzt eine Variable auf einen übergebenen Wert und gibt eigentlich nichts zurück (außer vielleicht ein bool zur Überprüfung, ob es erfolgreich war bei komplexeren Dingen). Der Rückgabetyp sollte daher "void" und nicht "int" sein.

Wenn man es ganz genau nimmt, sollte man die Get-Funktion noch als const deklarieren, da diese den Wert nicht verändern sollte und das auch ersichtlich sein sollte.


Um deinen ursprünglichen Fehler betrachten zu können, wäre es wirklich von entscheidender Bedeutung, wo das Spiel abstürzt und vielleicht noch mit welcher Fehlermeldung.

TigerClaw25

unregistriert

9

11.04.2013, 23:00

Ok, das stimmt. Aber wenn in CGame nichts stehen darf, wie uebergebe ich dann einen bestimmten Wert an eine Funktion in CPlayer?
Treffer(int LebenL erwartet ja einen Wert oder eine Variable, die einen Wert enthaelt. Deshalb habe ich auch einen Membervatiable namens m_hitcount.

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

10

11.04.2013, 23:05

Wie wäre es damit, dass die Spielerklasse einen Member namens Health hat, sowie eine Funktion namens treffen (OHNE Parameter), die nichts anderes macht, als Health zu dekrementieren?
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

Werbeanzeige