Ich versuche, ein 2D-Plattformspiel (Mario-Typ) zu erstellen, und ich habe einige Probleme mit dem richtigen Umgang mit Kollisionen. Ich schreibe dieses Spiel in C ++ und verwende SDL für die Eingabe, das Laden von Bildern, das Laden von Schriftarten usw. Ich verwende OpenGL auch über die FreeGLUT-Bibliothek in Verbindung mit SDL, um Grafiken anzuzeigen.
Meine Methode zur Kollisionserkennung ist AABB (Axis-Aligned Bounding Box), was wirklich alles ist, mit dem ich beginnen muss. Was ich brauche, ist eine einfache Möglichkeit, sowohl zu erkennen, auf welcher Seite die Kollision aufgetreten ist, als auch die Kollisionen richtig zu behandeln. Wenn der Spieler mit der Oberseite der Plattform kollidiert, positionieren Sie ihn im Grunde genommen nach oben. Wenn die Seiten kollidieren, positionieren Sie den Spieler wieder auf der Seite des Objekts. Wenn es zu einer Kollision mit dem Boden kommt, positionieren Sie den Spieler unter der Plattform neu.
Ich habe viele verschiedene Methoden ausprobiert , z. B. den Versuch, die Eindringtiefe zu ermitteln und den Player anhand der Eindringtiefe rückwärts zu positionieren. Leider scheint nichts, was ich versucht habe, richtig zu funktionieren. Die Bewegung des Spielers ist sehr unangenehm und positioniert den Spieler neu, wenn ich das nicht möchte. Ein Grund dafür ist wahrscheinlich, dass ich das Gefühl habe, dass dies etwas so Einfaches ist, aber ich überlege es mir.
Wenn jemand glaubt, helfen zu können, schauen Sie sich bitte den folgenden Code an und helfen Sie mir, dies zu verbessern, wenn Sie können. Ich würde gerne darauf verzichten, eine Bibliothek zu verwenden, um damit umzugehen (wie ich selbst lernen möchte) oder so etwas wie das SAT (Separating Axis Theorem), wenn dies überhaupt möglich ist. Vielen Dank im Voraus für Ihre Hilfe!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ball
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
Um zu erklären, was ein Teil dieses Codes bedeutet:
Die Blockvariable ist im Grunde eine Ganzzahl, die die Anzahl der Blöcke oder Plattformen speichert. Ich überprüfe alle Blöcke mit einer for-Schleife, und die Nummer, auf der sich die Schleife gerade befindet, wird durch die Ganzzahl i dargestellt. Das Koordinatensystem mag etwas seltsam erscheinen, daher lohnt es sich, dies zu erklären. Koordinaten [0] repräsentieren die x-Position (links) des Objekts (wo es auf der x-Achse beginnt). Koordinaten [1] repräsentieren die y-Position (oben) des Objekts (wo es auf der y-Achse beginnt). Koordinaten [2] repräsentiert die Breite des Objekts plus Koordinaten [0] (rechts). Koordinaten [3] repräsentiert die Höhe des Objekts plus Koordinaten [1] (unten). de2dCheckCollision führt eine AABB-Kollisionserkennung durch. Hoch ist negativ y und runter ist positiv y, wie es in den meisten Spielen der Fall ist.
Hoffentlich habe ich genug Informationen bereitgestellt, damit mir jemand erfolgreich helfen kann. Wenn ich etwas ausgelassen habe, das von entscheidender Bedeutung sein könnte, lassen Sie es mich wissen und ich werde die erforderlichen Informationen bereitstellen. Für jeden, der helfen kann, wäre die Bereitstellung von Code sehr hilfreich und wird sehr geschätzt.
Nochmals vielen Dank für Ihre Hilfe!
Bearbeiten : Ich habe meinen Code mit einem neuen Algorithmus aktualisiert, der überprüft, wo sich der Ball vor der Kollision befand. Eckkästen funktionieren jetzt korrekt auf dieser einzelnen Plattform, aber wenn ich eine Wand aus Objekten habe, kann ich wirklich dagegen gleiten, aber wenn ich mich beim Gleiten zur Wand bewege, gehe ich durch sie hindurch und stehe im Wesentlichen jetzt auf einer Block innerhalb der Wand. Es gibt auch einen Jitter-Effekt, der auftritt, wenn ich am Boden bin und der Ball ständig auf und ab geht.
TheirPos-ourSize +- 1
die 1 zu entfernen, wenn Sie dies tun. Wenn Sie sich nicht sicher sind, wie Sie diesen Algorithmus herausfinden können, wäre ich mehr als bereit zu helfen. Mein Algorithmus ist im Moment perfekt =] (auch in welcher Reihenfolge checken Sie die Objekte ein?)