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

Errschaffer

Alter Hase

  • »Errschaffer« ist der Autor dieses Themas

Beiträge: 865

Wohnort: Frankfurt

  • Private Nachricht senden

1

30.03.2009, 16:15

Immer diese Iteratoren

Hallo,
hab wieder ein Problem beim erweitern des SDL spieles.
Und zwar habe ich so Coins eingefügt die vom Himmel fallen und halt Bonuspunkte geben.

Hat auch alles erstmal geklappt nur das man das Spiel nur einmal spielen konnte nach einen Game Over hat er rumgemeckert das ein List Iterator ungültig ist.

Hab mich auf die Suche begeben und hab gesehen das der Fehler aus der Funktion kommt wo die Kollision mit den Coins geprüft wird.

Genauer gesagt an der Stelle wo ich einen Coin aus der Liste lösche.

Ich weiss nicht was da falsch sein soll.

Achja: Jetzt passiert auch beim ersten durchlauf weil ich die If Bedigung wo anders gesetzt habe.


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
void CGame::CheckCollisionsItem ()
{
    list<CShot> *ShotList = m_pPlayer->GetShotList ();
    list<CCoin>::iterator ItCoin;
    list<CShot>::iterator ItShot;

    SDL_Rect RectPlayer= m_pPlayer->GetRect ();
    SDL_Rect RectCoin;





  for (ItCoin = m_lCoinList.begin (); 
         ItCoin != m_lCoinList.end ();
         ++ItCoin)
    {

    
    RectCoin = ItCoin->GetRect ();
    
    

      // Überschneiden sich die Rects?

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

        //Coin  deaktivieren

        m_pPing->Play();
        ItCoin->SetALive (false);
        
       if(ItCoin->GetALive ()==false)
       {
           m_lCoinList.erase (ItCoin);

       }
      
      }
      
  }


  
}//ChecnCollisionsItem

Das Gurke

Community-Fossil

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

2

30.03.2009, 16:17

Iteratoren werden ja auch ungültig, sobald du was an der dazugehörigen Collection veränderst.

Workaround: Mach ne zweite Liste mit all den Elementen, die du am Ende (also nach der Iteration) noch löschen wolltest.

Errschaffer

Alter Hase

  • »Errschaffer« ist der Autor dieses Themas

Beiträge: 865

Wohnort: Frankfurt

  • Private Nachricht senden

3

30.03.2009, 16:19

Ich habs! Juhu!

Anstatt:


C-/C++-Quelltext

1
2
3
4
5
if(ItCoin->GetALive ()==false) 
       { 
           m_lCoinList.erase (ItCoin); 

       } 


Das hier:

C-/C++-Quelltext

1
2
3
4
5
if(ItCoin->GetALive ()==false) 
       { 
           ItCoin=m_lCoinList.erase (ItCoin);

       } 


Sowas einfaches aber auch!

Das Gurke

Community-Fossil

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

4

30.03.2009, 16:21

Hmm, auf die Idee bin ich bisher noch nicht gekommen. Scheint mir aber bestechend logisch. Muss ich gleich mal ausprobieren :D

5

30.03.2009, 16:24

Verswuchs mal mit

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
while (ItCoin != m_lCoinList.end()) {

   if(ItCoin->GetAlive()==false) {
      ItCoin = m_lCoinList.erase(ItCoin);
   } else {
      ItCoin++
   }

}


Edit:
Yay und da ich beim schreiben so getrödelt hab hab ich mal wieder vieeeeeeeel zu lang gebraucht ^-^

DasBlub

Alter Hase

Beiträge: 802

Wohnort: Schweiz

Beruf: Programmierer

  • Private Nachricht senden

6

30.03.2009, 17:15

Re: Immer diese Iteratoren

Zitat von »"Errschaffer"«

C-/C++-Quelltext

1
if(ItCoin->GetALive ()==false)

*würg*

du prüfst momentan einen boolschen wert auf einen boolschen wert und erhälst als ergebnis wieder einen boolschen wert... das ist nicht schön (auch wenns vmtl. vom compiler wegoptimiert wird):

C-/C++-Quelltext

1
if(!ItCoin->GetALive ())

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

30.03.2009, 19:26

Wenn wir schon dabei sind. Wenn man z.b. eine map und keine Liste hat, so besitzt die erase-Methode laut Standard keinen Iterator-Rückgabewert. Daher bin ich irgendwann auf folgende Lösung gekommen, die auch bei Listen geht:

container.erase(it++);
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

8

30.03.2009, 21:30

Laut Standard werden aber (glaub ich) alle Iteratoren einer Collection ungültig, wenn sie geändert wird. Deine Lösung wäre somit auch laut Standard falsch;)
Bei MS funzt sie zwar trotzdem, weil dort in einer Map nur Iteratoren ungültig werden, die gelöscht werden, aber dann kannste auch gleich den Rückgabewert nehmen;)

Ciao
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

9

30.03.2009, 21:54

Zitat von »"Das Gurke"«

Iteratoren werden ja auch ungültig, sobald du was an der dazugehörigen Collection veränderst.

Zitat von »"Helmut"«

Laut Standard werden aber (glaub ich) alle Iteratoren einer Collection ungültig, wenn sie geändert wird. Deine Lösung wäre somit auch laut Standard falsch;)

Nein, eure Aussagen sind falsch.

Container, die intern Zeiger verwalten (dazu gehören std::list, std::set, std::multiset, std::map, std::multimap), sind so konzipiert, dass sämtliche Referenzen, Zeiger und Iteratoren auf Elemente bei internen Operationen gültig bleiben, von gelöschten Elementen abgesehen.

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

10

31.03.2009, 13:34

Hm, stimmt hast Recht;)
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

Werbeanzeige