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

22.05.2010, 13:39

SDL_Game : Allgemeine Fragen (Lebensanzeige ?)

Schönen Tag erstmal =D



Ich bin seit ein paar Wochen mit Heikos Buch fertig und versuche das SDL_Game zu erweitern, und dadurch richtig zu verstehen.

Möchte daher dieses Thema einfach allgemein meinen Fragen widmen, sodass ich nix neues aufmachen muss. (Lieber ein paar Doppelposts als 10 neue topics :X)

Mein erster Streich war eine selbstgebaute Kollisionsabfrage zwischen Spieler und Asteroid. Das klappt zunächst ganz gut.



Als nächstes dachte ich mir, mache ich eine Lebensanzeige, bestehend aus 3 kleinen Bildchen (Miniaturversionen des Spielerraumschiffes).

Ich habe dann einfach eine Variable angelegt (int m_Life), 2 Zugriffsfunktionen (Setlife, Getlife) und dann noch einen Zeiger auf eine Instanz der Klasse CSprite, für die Bildchen.



Nun habe ich zwar eine Möglichkeite gefunden, die Lebensanzeige zu Rendern, finde diese aber sehr unschön. Habe mich auch generell gefragt, wie man eine Lebensanzeige am besten gestaltet. (Eine einfache Variable, oder eine Liste?)

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
// ------------------------------------ 
// Lebensanzeige Rendern 
// ------------------------------------ 
if (m_Life == 1) 
{ 
m_pSpriteLife->SetPos (690, 15); 
m_pSpriteLife->Render (); 
} 
else if (m_Life == 2) 
{ 
m_pSpriteLife->SetPos (690, 15); 
m_pSpriteLife->Render (); 
m_pSpriteLife->SetPos (710, 15); 
m_pSpriteLife->Render (); 
} 
else if (m_Life == 3) 
{ 
m_pSpriteLife->SetPos (690, 15); 
m_pSpriteLife->Render (); 
m_pSpriteLife->SetPos (710, 15); 
m_pSpriteLife->Render (); 
m_pSpriteLife->SetPos (730, 15); 
m_pSpriteLife->Render (); 
}


Das muss doch eleganter gehen. (Abgesehen von der Möglichkeit, ein animiertes Sprite zu erstellen und die jeweile AnimationsPosition zu rendern, die dann den Lebensstatus represäntiert.)


Ein zweites Problem gibt's bei mir komischerweise am Anfang des Spiels. Etwa nach 3 Sekunden scheint es so, als würde den Spieler ein unsichtbarer Asteroid treffen, denn er verliert ein Leben. Wenn ich aber kurz davor schiesse, treffe ich den unsichtbaren Asteroid anscheinend, denn meine Leben bleiben alle erhalten. Woran kann das denn liegen? Ist mir ein absolutes Rätsel wieso ein kleiner frecher Asteroid meint unsichtbar sein zu müssen!

Das war's erstmal.
Thx in advance! :)


//edit:

Bezügliche der unsichtbaren Kollision hab ich einen Anhaltspunkt. (Gerade entdeckt). Da scheint was mit den Rects der Asteroiden nicht zu 100% zu stimmen. Ich komme vielleicht erstmal selber drauf. Bleibt nur das mit der Lebensanzeige :)

2

22.05.2010, 13:52

Auch Hallo erstmal und Willkommen im Forum! :)

Zitat

... Lieber ein paar Doppelposts als 10 neue topics


Das würde ich nicht unbedingt empfehlen. ;)

Anyway: Viel Spass hier im Forum!
fka tm

3

22.05.2010, 13:55

Danke, allerdings bedanke ich mich im Normalfall für die Antworten in meinem Post. Wirft sich jetzt 2 Wochen später eine neue Frage auf, kann ich entweder ein neues Thema erstellen, oder hier nochmal reinposten. Schon haben wir den Doppelpost :[

Ich bezweifle, dass jemand alte Themen durchforst und guckt, ob denn der Themenersteller einen seiner posts editiert hat : D

4

22.05.2010, 14:01

Nun ja, Du könntest eine Schleife durchlaufen lassen, die das Miniaturbildchen so oft zeichnet, wie Du eben Leben hast. Dazu dann in der Schleife die Position einfach jedes Mal erhöhen, Da du ja 690, 710, 730 hast, eben immer x += 20;

Was den unsichtbaren Asteroid angeht… naja, da Du hier keinen Code dazu gepostet hast, kann man das schwer sagen. Du könntest aber auch einfach mal mit dem Debugger durchgehen und schauen, wo der Asteroid erstellt wird.

5

22.05.2010, 14:08

Also das mit der Schleife hatte ich auch schon im Kopf. War auch schon im code drin. Hätte allerdings die x-Position dann ausserhalb der Schleife schon deklarieren müssen (ausser ich habe da gerade einen Denkfehler), was ich dann für zu umständlich hielt. Im Rückblick wär's allerdings lange nicht so unübersichtlich wie mein jetziger code ;p

Wusste nicht, wo der Fehler liegen sollte und hab daher erstmal keine Codeausschnitte gepostet.
Es sieht so aus, als würde der erste Asteroid ein Rect besitzen, das etwa die halbe linke Bildschirmhälfte belegt. Ist mir auch wieder ein Rätsel wie das der Fall sein kann.

Das Rect wird hier ganz normal initialisiert:

C-/C++-Quelltext

1
2
3
4
5
6
7
    // ------------------------------------
    // Rect initialisieren
    // ------------------------------------
    m_Rect.x = static_cast<int>(fXPos);
    m_Rect.y = static_cast<int>(fYPos);
    m_Rect.w = pSpriteAsteroid->GetRect().w;
    m_Rect.h = pSpriteAsteroid->GetRect().h;


Hier gibt's die Kollisionsabfrage zwischen Spieler und Asteroid:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        // --------------------------------------
        // Überschneidung Spieler - Asteroid ???
        // --------------------------------------
        
            if (RectPlayer.y < RectAsteroid.y + RectAsteroid.h &&
                RectPlayer.y + RectPlayer.h > RectAsteroid.y &&
                RectPlayer.x < RectAsteroid.x + RectAsteroid.w &&
                RectPlayer.x + RectPlayer.w > RectAsteroid.x)

            {           
                // ------------------------------------
                // Asteroid und Spieler deaktivieren,
                // Spielerleben verringern
                // ------------------------------------
                ItAsteroid->SetAlive(false);
                m_pPlayer->SetLife(-1);
                m_pPlayer->Reset();
            }


Und das Rendern und Updaten des Asteroiden wurde ohne Schreibfehler dem Buch entnommen.
Am Rect des Spielers denke ich, liegt es nicht. Schließlich läuft nach dem ersten Asteroid alles prima.


Danke dir =)

6

22.05.2010, 14:10

Danke, allerdings bedanke ich mich im Normalfall für die Antworten in meinem Post. Wirft sich jetzt 2 Wochen später eine neue Frage auf, kann ich entweder ein neues Thema erstellen, oder hier nochmal reinposten. Schon haben wir den Doppelpost :[
Ich bezweifle, dass jemand alte Themen durchforst und guckt, ob denn der Themenersteller einen seiner posts editiert hat : D


Da hab ich ja Schwein gehabt, dass du dich zu einem "Danke" herablässt. :huh:

Was das Erstellen neuer Topics usw. angeht, eine Empfehlung eben.
Kannst du halten wie der berühmte Dachdecker.
fka tm

TSS

Frischling

  • Private Nachricht senden

7

22.05.2010, 14:17

Also die Lebensanzeige sollte mit folgender Schleife eigentlich funktionieren:

C-/C++-Quelltext

1
2
3
4
5
for(int i=0;i<m_Life;i++)
{
m_pSpriteLife->SetPos (690+20*i, 15); 
m_pSpriteLife->Render (); 
}

8

22.05.2010, 14:20

Also die Lebensanzeige sollte mit folgender Schleife eigentlich funktionieren:

C-/C++-Quelltext

1
2
3
4
5
for(int i=0;i<m_Life;i++)
{
m_pSpriteLife->SetPos (690+20*i, 15); 
m_pSpriteLife->Render (); 
}


Sehr schön! :)
Warum komme ich nicht auf sowas ~.~
Dankeschön =D

Und @ TrikkieMikkie:
Das kam dann wohl sehr blöd von mir rüber. Ich bedanke mich natürlich herzlichst bei dir für deinen netten Empfang hier =D


//
edit:

Also ich hänge hier echt fest. Ich habe mit dem Debugger mal alles durchlaufen lassen und festgestellt, dass der erste Asteroid der Liste (also [0]) ein falsches m_Rect.h und m_Rect.w erhält. Alle folgenden ([1], [2] ....) haben die Werte m_Rect.h = 64 und m_Rect.w = 64. Der erste hat allerdings die Werte des gesamten Bildes. Also 640x128. Ich kann mir nicht erdenken, wieso nur der erste Listeneintrag ein falsches Rect erhalten soll.

Also nochmal:

Hier wird der Asteroid initialisiert:

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
// ************************************
// INIT
// Aufgabe: Initialisiert Asteroiden
// ************************************
void CAsteroid::Init (CSprite *pSpriteAsteroid, float fXPos, float fYPos)
{
    // ------------------------------------------------------
    // Zeiger auf Sprite kopieren und Koordinaten setzen
    // ------------------------------------------------------
    m_pSpriteAsteroid = pSpriteAsteroid;
    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 = pSpriteAsteroid->GetRect().w;
    m_Rect.h = pSpriteAsteroid->GetRect().h;

        

    // ---------------------
    // Asteroid aktivieren
    // ---------------------
    m_bIsAlive = true;
}


In die Liste werden die Asteroiden ja hier geschoben:

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
// ************************************************************************
// SPAWNASTEROIDS
// Aufgabe: Nach Ablauf einer bestimmten Zeit neuen Asteroiden erzeugen
// ************************************************************************
void CGame::SpawnAsteroids()
{
    // --------------------------------------
    // Timer für nächsten Asteroiden erhöhren
    // --------------------------------------
    m_fAsteroidTimer += g_pTimer->GetElapsed();

    // ----------------------------------------------------------------------------
    // Wenn eine halbe Sekunde vergangen ist, dann neuen Asteroiden erzeugen
    // ----------------------------------------------------------------------------
    if (m_fAsteroidTimer >= 0.5f)
    {
        // -------------------
        // Neuer Asteroid
        // -------------------
        CAsteroid Asteroid;

        // ---------------------
        // Zufällige X-Position
        // ---------------------
        int XPos = rand()%736;

        // ------------------------
        // Asteroid initialisieren
        // ------------------------
        Asteroid.Init (m_pSpriteAsteroid, static_cast<float>(XPos), -60.0f);

        // --------------------------------------
        // Asteroid in Liste einfügen
        // --------------------------------------
        m_AsteroidList.push_back (Asteroid);

        // --------------------------------------
        // Zeitgeber wieder zurücksetzen
        // --------------------------------------
        m_fAsteroidTimer = 0.0f;
    
    }
}


Das sollten doch die beiden einzigen Funktionen sein, die ausschlaggebend sind, für Listeneintrag [0].
Oder fehlt noch etwas?
Die Funktionen meiner Sprite Klasse sollten doch fehlerfrei sein, wenn Sie es schafft, alle bis auf den ersten Asteroiden fehlerfrei zu erzeugen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »leckel« (23.05.2010, 21:51)


9

28.06.2010, 15:38

Ich hatte auch das selbe Problem und bin durch Zufall auf dein Posting gestoßen, was mich zu deiner Frage mit den Doppelpostings bringt. Ich wäre aus deiner Überschrift NIE auf die Idee gekommen, dass es hier um den Asteroiden - Bug geht.

Du kannst diesen Bug beheben, indem du die Collisionsprüfung etwas modifiziertst und die Rects für den Asteroiden manuell änderst.

Code zum einfügen in der Collisionsprüfung:

C-/C++-Quelltext

1
2
3
4
5
6
void CGame::CheckCollision()
{
    //Korrektur für das Rect des Asteroiden
    RectAsteroid.w = 64;
    RectAsteroid.h = 64;
}


PS.: Rechlich späte Antwort ^^

10

28.06.2010, 16:42

Hm, ich glaube man sollte aber noch auf den Thread hinweisen in dem deine Lösung diskutiert wird, @Ombalat ;)
Scheint mir nicht Optimal zu sein.

Werbeanzeige