|
JLI Spieleprogrammierung
|
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
|
Verfasst am: 08.10.2005, 00:05 Titel: Programmabsturz durch Schleife |
|
|
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 ^^) --
- Gut Nacht! |
|
Nach oben |
|
|
Patrick Dark JLI Master
Anmeldedatum: 25.10.2004 Beiträge: 1895 Wohnort: Düren Medaillen: Keine
|
Verfasst am: 08.10.2005, 07:39 Titel: |
|
|
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 |
|
|
Patrick Dark JLI Master
Anmeldedatum: 25.10.2004 Beiträge: 1895 Wohnort: Düren Medaillen: Keine
|
Verfasst am: 08.10.2005, 07:49 Titel: |
|
|
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 |
|
|
Mat Senior JLI'ler
Alter: 36 Anmeldedatum: 17.09.2005 Beiträge: 205 Wohnort: Koblenz Medaillen: Keine
|
Verfasst am: 08.10.2005, 09:22 Titel: |
|
|
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
=> 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 |
|
|
Patrick Dark JLI Master
Anmeldedatum: 25.10.2004 Beiträge: 1895 Wohnort: Düren Medaillen: Keine
|
Verfasst am: 08.10.2005, 10:11 Titel: |
|
|
Mat
Thema Engel: ich weiß
Thema Aufhängen: Naja hab das nur ausm Kopf gemacht, daher keine Garantie
Thema Eleganter: Ich weiß
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
- 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 |
|
|
|
|
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
|