JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=74739580a227f29a41a340438be132aaMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Programmabsturz durch Schleife

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Fragen, Antworten und Kritik
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Mat
Senior JLI'ler


Alter: 36
Anmeldedatum: 17.09.2005
Beiträge: 205
Wohnort: Koblenz
Medaillen: Keine

BeitragVerfasst am: 08.10.2005, 00:05    Titel: Programmabsturz durch Schleife Antworten mit Zitat

So, mal wieder eine Frage von mir, unter dem Motto "wer nicht fragt bleibt dumm":

Problemerläuterung:

In jedem durchlauf der Haupt-Spielschleife wird getestet ob ein bzw. der Ball eins von vielen Objekten berühert (Kollision).
Die Objekte, die in einer Liste gespeichert sind, werden durch die Kollision aus der Liste entfernt, und die Bewegungsrichtung des Balls wird umgedreht.

Soweit, so gut - alles klappt

Die Objekte der in der Liste verfügen über eine Anzahl von Leben, und erst wenn sie beispielsweise 3mal vom Ball getroffen wurden, sollen sie verschwinden .. hier die wichtigsten Quellcodezeilen:

1. Abfrage der Collision durch folgenden Aufruf
CPP:
if(m_pLevel->CheckCollision(m_pBall))
   {
      m_pBall->ChangeDirection();
      //m_pBall->SetPosition(10,19);
   }


2. Collisionerkennung durchführen:
CPP:
bool CLevel::CheckCollision(CSprite *Counterpart)
{
   list<CObject>::iterator it;
   int i = 0;
   //char Textbuffer[90];
    for(it = m_ObjectList.begin(); it != m_ObjectList.end();it++)
   {      
       if(it->CheckCollision(Counterpart))
       {
          if(it->GetSurvive()==1)
          {
              m_ObjectList.erase(it);
             //sprintf(Textbuffer, "A) Var: %d", (it->GetSurvive()));
             //m_opt->Textoutput(300,300,Textbuffer);
          }
          else if(!m_AlreadyCollision)
          {
             it->SetSurvive(-1);
            
             //sprintf(Textbuffer, "B) Var: %d", (it->GetSurvive()));
             //m_opt->Textoutput(445,445,Textbuffer);
          }
          it=m_ObjectList.end();
          //m_AlreadyCollision = true; //ACHTUNG PROGRAMM BLEIBT HÄNGEN !!!
          i++;
       }

   }
   if(i==0) m_AlreadyCollision = false;
   return (bool)i;
}


Wie man sieht habe ich schon durch viele Wege versucht auf das Problem zu stoßen, aber bisher erfolglos.

Die entscheidende Zeile ist
CPP:
//m_AlreadyCollision = true; //ACHTUNG PROGRAMM BLEIBT HÄNGEN !!!

Wären die Kommentarbalken vor m_Already.. nicht vorhanden, so stürzt das Programm am.
Das Programm stürzt immer dann ab, wenn it->SetSurvive(-1); nicht aufgerufen wird, und das Objekt nicht entfernt wird.

Eine starke Vermutung von mir war, dass sich der Ball an den Objekten aufhängt, und dadurch, falls die Leben nicht auf 1 herabgesenkt werden endlos lange in der for-Schleife hängen bleibt, bzw. immerwieder die Funktion aufgerufen wird sich die Richtung des Balls ändert(ohne das er sich bewegt) und der Ball desshalb an dem Objekt hängen bleibt.

Desshalb habe ich die Position des Balles auf eine bestimmte gesetzt (wie ganz oben zu sehen) nachdem eine Kollision erkannt wurde.. das Program bleibt trotzdem, ohne eine Bewegung desBalles, hängen.

(m_AlreadyCollision sorgt dafür, dass wenn der Ball einmal ein Objekt berühert, diese Berüherung auch nur als eine Kollision erkannt wird, und nur ein Lebensverlust des Objektes zur Folge hat)

PS: Das Programm hängt sich immer sofort auf, wenn es ein Objektberühert, aber nur dann wenn das Objekt nicht bei der Berüherung entfernt wird .. der BAll bleibt dabei stehen)

Vielleicht noch wichtig, dann bin ich aber auch erstmal fertig und gehe schlafen:
Egal wie viele Leben das Objekt hat, wenn eine Berührung stattfindet wird das Objekt entfernt, wenn nicht die Sperre anhand m_AlreadyCollision existiert.
Desshalb auch meine Annahme, dass sich der Ball an dem Objekt festgehangen hat.

Ich hoffe das hier jemand durchblickt, und mir evtl. helfen kann ..
Vielen Dank an alle die sich die Mühe machen (allein den Text zulesen ^^) -- Wink

- Gut Nacht!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 08.10.2005, 07:39    Titel: Antworten mit Zitat

Ist klar!


it=m_ObjectList.end();

erst auf end setzen und dann nochmal inkrementieren?? Speicherschutzverletzung ganz klar, stopf da ein break rein und fertig wenn du die schleife beenden willst.
_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 08.10.2005, 07:49    Titel: Antworten mit Zitat

Habs mal etwas verfeinert, da ich aber in gewissen dingen deiner logik nicht folgen konnte, konnte ich es auch nicht so gut optimieren:
CPP:
bool level::checkCollision (sprite *Counterpart)
{
// int i = 0;  // << Braucht keiner

        // Immer ein std: davor! das prädige ich seit jahren / Inkrementierung hier raus bei der benutzung von erase!
    for (std::list<object>::iterator it = m_ObjectList.begin(); it != m_ObjectList.end(); /*it++*/)
    {       
         if(it->CheckCollision(Counterpart))
         {
            if(it->GetSurvive()<=1)
                m_ObjectList.erase(it); // Hier ein erease und oben inkrementieren??? gefährlich!
            else if(!m_AlreadyCollision)
                it->SetSurvive(-1);
            else
                ++it;
            // it=m_ObjectList.end();  << des ist quatsch! return(true); würde reichen
            return (true);
       }
    }
//   if(i==0) m_AlreadyCollision = false; // Wat soll dat?
//   return (bool)i;  // << outch! Man kann nicht auf bools casten! gefährlich, aber kräftigst!
// wenn dann schon: return (i != 0);
// aber wird hier net mehr gebraucht, ergo:
    return (false);
}

_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Mat
Senior JLI'ler


Alter: 36
Anmeldedatum: 17.09.2005
Beiträge: 205
Wohnort: Koblenz
Medaillen: Keine

BeitragVerfasst am: 08.10.2005, 09:22    Titel: Antworten mit Zitat

Very Happy
Du bist ein Engel .. allerdings musste ich noch die ein oder andere Änderung vornehmen:
CPP:
bool CLevel::CheckCollision(CSprite *Counterpart)
{
    for(std::list<CObject>::iterator it = m_ObjectList.begin(); it != m_ObjectList.end();)
   {      
       if(it->CheckCollision(Counterpart))
       {
          if(it->GetSurvive()<=1)
          {
              m_ObjectList.erase(it);
          }
          else
          {
             it->SetSurvive(-1);
          }
          return true;
       } ++it;
   }
   return false;
}


So sieht das schon viel besser aus Smile
=> Die Variale m_AlreadyCollision habe daher eingesetzt, weil ich verhindern wollte, dass eine Berührung mit einem Objekt dazu führt, dass ein Objekt mehrere Leben auf einmal verliert.
Also eine Kollision = ein Leben weniger
Ich habe am Anfang gedacht, dass da der fehler liegen könnte und desshalb diese Variable implementiert.

Ein kleiner Fehler in deiner Verbesserung:
Der Iterator wird nur dann als Zeiger auf das nächste Objekt gesetzt, wenn üerhaupt eine Kollision stattfindet => Spiel hängt sich beim Starten auf ..

Die Integer-Variable hatte ich (zu meiner Rechtfertigung ^^) verwendet, um möglicherweise mehrere Kollisionen gleichzeitig zu erkennen, und auch mehrere Kollisionen gleichzeitig zu entfernen.
(Ist jedoch nicht nötig - jetzt auf jeden Fall noch nicht)

Najo, dein Code ist schon wesentlich eleganter als meiner ;( ^^

PS: Eine Frage noch warum legst du wert darauf auf die STL über stl:: zuzugreifen ?
Damit es keine Namespace komplikationen gibt, oder gibt es sonst noch Vorteile - Geschwindigkeit, oder was auch immer ?

=> Noch mal ein dickes Danke!
_________________
- - - - - - - - - - - - - - - - - - - -
-> http://www.sea-productions.de
-> http://www.krawall.de
- - - - - - - - - - - - - - - - - - - -
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 08.10.2005, 10:11    Titel: Antworten mit Zitat

Mat
Thema Engel: ich weiß Very Happy

Thema Aufhängen: Naja hab das nur ausm Kopf gemacht, daher keine Garantie Very Happy

Thema Eleganter: Ich weiß Wink

Thema std::: Genau deshalb, da ich sehr viel mit Namespaces arbeite ist das für mich unabdingbar. Sieht meines erachtens auch schöner und eindeutiger aus.

Thema Danke: Kein Problem Wink

- Patrick
_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Fragen, Antworten und Kritik Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum