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

1

15.03.2011, 16:04

Problem mit der Lebensanzeige des SDL Game

Hallo,

ich bin neu im Forum und hab auch schon eine Frage^^. Und zwar habe ich eine Lebensleiste eingebaut die aus 3 Bildern besteht. Mein Problem ist das sobald ich eine if Bedingung in meine Update Funktion schreibe mein Spiel nicht mehr startet und abstürzt. Ohne die if Bedingung läuft das Spiel ohne Probleme.

danke schonmal an alle die sich ein wenig Zeit nehmen um mir zu helfen :)

Lebensanzeige.hpp

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
#ifndef LEBENSANZEIGE_HPP
#define LEBENSANZEIGE_HPP

#include "Sprite.hpp"
#include "Player.hpp"

class CLebensanzeige
{
    public:
void Init ();
void Update ();
void Render ();
void Quit ();

    private:
CSprite *m_pSpriteLebensanzeige;// Zeiger auf Lebensanzeige-Sprite
CPlayer *m_pPlayer; //Zeiger auf die Player-Instanz
float m_fXPos; // X-Position der Lebensanzeige
float m_fYPos; // Y-Position der Lebensanzeige
float m_fAnimPhase; // Akt. Animationsphase der Lebensanzeige
};

#endif


Lebensanzeige.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
#include "Lebensanzeige.hpp"

// Init
//
// Aufgabe: Lebensanzeige initialisieren
//
void CLebensanzeige::Init()
{
    // Lebensanzeigesprite erstellen
    m_pSpriteLebensanzeige = new CSprite;

    m_pSpriteLebensanzeige->Load ("Data/Lebensanzeige.bmp", 3, 194, 31);
    m_pSpriteLebensanzeige->SetColorKey (255, 0, 255);
    m_fAnimPhase = 2.0f;

} // Init

// Update
//
// Aufgabe: Lebensanzeige auf dem Laufenden halten
//
void CLebensanzeige::Update()
{
    if(m_pPlayer->m_Leben == 2)  //Hier liegt mein Problem sobald ich die if Funktion einbinde funktioniert das Spiel nicht mehr
m_fAnimPhase = 2.0f;


} // Update

// Render
//
// Aufgabe: Lebensanzeige rendern
//
void CLebensanzeige::Render()
{
    m_pSpriteLebensanzeige->SetPos (5, 5);
    m_pSpriteLebensanzeige->Render (m_fAnimPhase);

} // Render

void CLebensanzeige::Quit()
{
    // Lebensanzeige-Sprite freigeben
    if (m_pSpriteLebensanzeige != NULL)
    {
delete (m_pSpriteLebensanzeige);
m_pSpriteLebensanzeige = NULL;
    }

} // Quit


Player.hpp und .cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
//In Public der hpp der Klasse CPlayer

int m_Leben;              // Leben des Spielers

//In Init der cpp der Klasse CPlayer

void CPlayer::Init ()
{
    //Leben festlegen
    m_Leben = 2;
}

2

15.03.2011, 16:31

Hallo, du hast offensichtlich vergessen, deinen Pointer auf deinen Spieler zu definieren, daher kann das m_pPlayer->m_Leben nicht funktionieren ;)
(In deiner CLebensanzeige::Init() fehlt die definition für m_pPlayer)
Bekommst eine zugriffsverletzung oder ;)
Gib deine Lebens - Variable doch in den private bereicht und schreib dir ne Zugriffsfunktion .. Schaut meiner meinung nach besser aus ;)

Liebe Grüße und welcome im forum ^^

3

15.03.2011, 16:33

Das liegt daran, dass dein Zeiger auf den Spieler nicht initialisiert wurde, er zeig also irgendwo hin und du bekommst einen Zugriffsfehler.
Mach einfach Init und Quit weg und mach das statt dessen in den Konstruktor + Destruktor, die sind ja eigentlich dafür da.
Dem Konstruktor musst du dann als Parameter einfach noch den Zeiger auf den Spieler übergeben.


lg chaia

4

15.03.2011, 16:51

Danke euch beiden, da hab ich das doch Glatt vergessen :whistling: . Eine Zugriffsfunktion werde ich mir noch schreiben wollte nur erstmal so testen ob es Funktioniert :).

5

15.03.2011, 21:34

Villeicht Interessiert es ja einen die Lösung zu sehen die ich mir zusammengebastelt habe. Bin gerne für Verbesserungen und Kritik zu haben :).
Danke nochmal an Chaia* und Architekt. Ihr habt vollkommen Recht ist wirklich besser mit Konstruktor und Destruktor :).

Lebensanzeige.hpp


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
#ifndef LEBENSANZEIGE_HPP
#define LEBENSANZEIGE_HPP

#include "Sprite.hpp"
#include "Player.hpp"

class CLebensanzeige
{
    public:
        CLebensanzeige();
        ~CLebensanzeige();
        void Render   (float m_fAnimPhase);
        

    private:
        CSprite *m_pSpriteLebensanzeige;// Zeiger auf Lebensanzeige-Sprite
        float    m_fXPos;               // X-Position der Lebensanzeige
        float    m_fYPos;               // Y-Position der Lebensanzeige
        float    m_fAnimPhase;          // Akt. Animationsphase der Lebensanzeige
};

#endif


Lebensanzeige.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
#include "Lebensanzeige.hpp"

// Init
//
// Aufgabe: Lebensanzeige initialisieren
//
CLebensanzeige::CLebensanzeige()
{
    // Lebensanzeigesprite erstellen
    m_pSpriteLebensanzeige = new CSprite;

    m_pSpriteLebensanzeige->Load ("Data/Lebensanzeige.bmp", 3, 194, 31);
    m_pSpriteLebensanzeige->SetColorKey (255, 0, 255);
    m_fAnimPhase = 2.0f;


} // Init

// Render
//
// Aufgabe: Lebensanzeige rendern
//
void CLebensanzeige::Render(float m_fAnimPhase)
{
    m_pSpriteLebensanzeige->SetPos (5, 5);
    m_pSpriteLebensanzeige->Render (m_fAnimPhase);

} // Render

CLebensanzeige::~CLebensanzeige()
{
    // Lebensanzeige-Sprite freigeben
    if (m_pSpriteLebensanzeige != NULL)
    {
        delete (m_pSpriteLebensanzeige);
        m_pSpriteLebensanzeige = NULL;
    }

} // Quit



Player.hpp und 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
class CPlayer
{

public:
float LebenAbfragen ();
void LebenRedu ();
private:
float m_Leben; // Leben des Spielers
}//Abgekürtzt


void CPlayer::Init ()
{
    //Leben festlegen
    m_Leben = 2.0f;

} // Init

//Leben reduzieren
void CPlayer::LebenRedu()
{
    m_Leben--;

    if(m_Leben < 0)
m_Leben = 0.0f;
}

//Leben abfragen
float CPlayer::LebenAbfragen()
{
    float Temp;
    Temp = m_Leben;
    return(Temp);
}


Game.hpp und 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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class CGame
{
private:
CLebensanzeige *m_pLebensanzeige;//Lebensanzeige-Instanz
float m_Leben; //Leben des Spielers
}

void CGame::Init ()
{

    // Lebensleiste initialisieren
    m_pLebensanzeige = new CLebensanzeige;
    m_Leben = m_pPlayer->LebenAbfragen();

} // Init

void CGame::Quit ()
{

    // Lebensanzeige freigeben
    if (m_pLebensanzeige != NULL)
    {
        delete (m_pLebensanzeige);
        m_pLebensanzeige = NULL ;
    }

} // Quit

void CGame::Run ()
{
    // Hauptschleife des Spiels durchlaufen
    //
    while (m_bGameRun == true)
    {
// Events bearbeiten
ProcessEvents ();

// Framework updaten und Buffer löschen
g_pFramework->Update ();
g_pFramework->Clear ();

// Hintergrundbild rendern
m_pSpriteBackground->Render ();

// Spieler updaten und rendern
m_pPlayer->Update ();
m_pPlayer->Render ();

//Lebensanzeige  rendern
m_pLebensanzeige->Render(m_Leben);

// Neue Asteroiden hinzufügen
SpawnAsteroids ();

// Kollisionen prüfen
CheckCollisions ();

// Asteroiden rendern
RenderAsteroids ();

// Buffer flippen
g_pFramework->Flip ();

    }

} // Run

void CGame::CheckCollisions ()
{
    // Kollision zwischen Spieler und Asteroid 

if (RectPlayer.y < RectAsteroid.y + RectAsteroid.h && 
RectPlayer.y + RectPlayer.h > RectAsteroid.y && 
RectPlayer.x < RectAsteroid.x + RectAsteroid.w && 
RectPlayer.x + 64 > RectAsteroid.x) 
{ 
// Ja, also gab es eine Kollision. 

//Asteroid löschen, Spieler Leben abziehen

ItAsteroid->SetAlive (false);
m_pPlayer->LebenRedu();
m_Leben = m_pPlayer->LebenAbfragen();

}
}// CheckCollision

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Chris13« (15.03.2011, 23:38)


Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

6

15.03.2011, 21:57

Ohne groß zu gucken: nimm Chaia*'s Tipp an

Zitat


Mach einfach Init und Quit weg und mach das statt dessen in den Konstruktor + Destruktor, die sind ja eigentlich dafür da.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

7

16.03.2011, 07:57

dinge die mir auffallen:

Zitat

RectPlayer.x + 64 > RectAsteroid.x

was soll da die +64? hardgecodede zahl? sollte vl rectplayer.h sein?


dann würde ich in header dateien nicht andere header includen. kA wie das andere sehen,aber afaik sollte man das vermeiden, denn wenn ich als benutzer die klasse player z.b. verwenden will, ist es für mich persönlich schlecht,wenn ich da,ohne es wirklich zu wissen, noch andere header automatisch mitincluded krige (gibt immer wieder ausnahmen,aber ich persönlich versuche es zumindest zu vermeiden).


weiters hältst du dich nicht durchgehend an fehlerabfragen, die das allokieren von speicher überprüfen.

Zitat

m_pSpriteLebensanzeige = new CSprite;

m_pSpriteLebensanzeige->Load ("Data/Lebensanzeige.bmp", 3, 194, 31);
m_pSpriteLebensanzeige->SetColorKey (255, 0, 255)

sollte new CSprite aus irgendeinem grund mal nicht mehr gehen, dann stürzt dir dasspiel ab, weil du dann auf die methoden load,setcolorkey zugreifst, von einem nicht existendem objekt.



weiters bringt glaub ich das nullen der pointer im destruktor nichts. das objekt wird ohnehin gelöscht,also wirst du deren pointer auch nicht mehr verwenden.




Zitat

float Temp;
Temp = m_Leben;
return(Temp);

das hast du bei getleben. warum nicht einfach return m_leben? was bringt dir diese unnütze zusatzvariable?




und dann noch diese init/quit methoden. sind geschmackssache und im buch werden sie afaik immer benutzt. ich persönlich empfinde sie jedoch als nutzlos,denn genau für solche dinge gibt es eben konstruktoren und destruktoren. würde mich jetzt bei diesem spiel zwar noch mit init/quit abfinden,da es eben im buch auch so gemacht wird, aber für später empfehle ich dir konstruktoren/destruktoren dafür zu verwenden.




alle tipps ohne gewähr :)

8

16.03.2011, 12:16

Danke für die guten Tipps.
Habe die 64 in RectPlayer.h geändert. Das mit den Header-dateien ist auch laut Buch schon so, ob es nun schlecht oder gut ist kann ich da nicht wirklich sagen, aber wenn ich den Code weitereichen würde kann man dieses ja vermerken(Werd mich mal in der Richtigung hin informieren wie man es am besten Handhaben sollte).
Das

C-/C++-Quelltext

1
2
3
float Temp;
Temp = m_Leben;
return(Temp);


Hatte ich noch so weil ich am Anfang als der Quelltext noch anders geschrieben war immer die Fehlermeldung m_Leben ist eine private Variable und kann nicht ...

Mit der Fehlerabfrage:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CSprite::Load (const string sFilename)
{
    // Bitmap laden
    m_pImage = SDL_LoadBMP (sFilename.c_str () );

    // Prüfen, ob alles glatt ging
    if (m_pImage == NULL)
    {
        cout << "Fehler beim Laden von: " << sFilename.c_str ();
        cout << endl;
        cout << "Fehlermeldung: " << SDL_GetError () << endl;

        // Framework herunterfahren
        g_pFramework->Quit ();

        // Gesamtes Spiel beenden
        exit (1);
    }


Ist in Sprite geregelt wen es nicht geladen werden kann fährt das Spiel herunter.

Das Nullen im Destruktor des Zeigers wird ausgeführt, habe dies mittels Logfile überprüft.

Das mit der Init/Quit Methode werde ich in dem Spiel erstmal so lassen. Werde mir für die nächsten Projekte aber merken auf Konstruktoren und Destruktoren einzugehen.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Chris13« (16.03.2011, 12:53)


9

16.03.2011, 15:28

Timer

Hey,

hab noch eine Frage und zwar wie kann ich einen Timer realisieren der jede viertel Sekunde insgesamt 4s eine Aktion ausführt. Ich wollte eine Explosion einbauen bin bis jetzt aber am Timer gescheitert, endweder hängt das Spiel in der Zeit in der, der Timer läuft oder es stürzt ab^^. Villeicht kann mir jemand helfen und mir mal einen Tipp geben wie ich so einen Timer realisieren kann. Danke schonmal :).

10

16.03.2011, 15:34

Man könnte z.B: in jedem Frame die Zeit hochzählen (Zeit seit dem letzten Frame draufaddieren) und wenn man drauf oder drüber kommt (also z.B. >=0.25sek) die AKtion ausführen.
Wenn man es alle 0.25 Sek haben will, kann man danach 0.25 sek abziehen und von vorne anfangen (das ist etwas genauer, wie den Timer einfach auf 0 zu setzen, weil man die 0.25 ja meist nicht genau erreicht).

Btw.: Für neue Fragen kann man auch gerne neue Threads aufmachen. Das erhöht die Übersichtlichkeit.
Lieber dumm fragen, als dumm bleiben!

Werbeanzeige