Wie kann ich einen Schlangenschwanz dem Kopf folgen lassen?

10

Nach einer Aufgabe und dem Einstieg in libGDX durch Erstellen eines kleinen Snake-Klons bin ich auf ein Problem gestoßen, für das ich mich wahrscheinlich in Kürze schämen werde.

Ich habe derzeit einen Schlangenkopf (zu diesem Zeitpunkt ein einfaches Rechteck), der sich auf der Leinwand des Spiels bewegt. Der einfachste Weg, den Rest der Schlange aufzubauen, bestand darin, dass der Kopf eine Java Collections LinkedList of SnakeElements besaß, deren Größe je nach den Aktivitäten des Spielers abnahm.

Es hat sich jedoch als nicht trivial erwiesen, dass diese Liste von SnakeElements dem Kopf folgt.

Die aktuelle Funktion, die dies tut, ist wie folgt und wird jedes Mal aufgerufen, wenn der Kopf seine Position aktualisiert:

private void moveTail (float x, float y, int direction) {
    float tmpx, tmpy;
    int tmpdirection;
    int offset_x, offset_y;

    for (SnakeSegment snse : tail) {
        offset_x = 0;
        offset_y = 0;

        tmpx = snse.getX();
        tmpy = snse.getY();
        tmpdirection = snse.getDirection();

        switch(direction) {
            case 0:
                offset_x = 0;
                offset_y = -(2 + snse.width);
                break;
            case 1:
                offset_x = -(2 + snse.width);
                offset_y = 0;
                break;
            case 2:
                offset_x = 0;
                offset_y = (2 + snse.width);
                break;
            case 3:
                offset_x = (2 + snse.width);
                offset_y = 0;
                break;
            default:
                System.out.println("wrong direction");
        }

        snse.setX(x + offset_x);
        snse.setY(y + offset_y);
        snse.setDirection(direction);

        x = tmpx;
        y = tmpy;
        direction = tmpdirection;
    }
}

was leider zu diesem Verhalten führt:

gif

Alle Tipps, wie man einen richtig funktionierenden Schlangenschwanz macht, wären sehr dankbar :)

Kilian
quelle

Antworten:

18

Stellen Sie sich das Problem folgendermaßen vor:
Wie bewegt sich eine Schlange im ursprünglichen Spiel?
Die Schlange bewegt sich in ihre aktuelle Richtung. Das Verhalten sieht so aus, als ob der Kopf aus dem Nichts erscheint und der letzte Schwanzteil verschwindet.

Sie können eine Liste von Schlangenteilen haben. Was Sie tun möchten, ist das letzte Element in der Liste zu entfernen, das den letzten Endteil darstellt.
Dann möchten Sie ein neues Headpart erstellen, in dem es positioniert werden soll, und es an die erste Position der Liste setzen.
Dies bedeutet, dass der Rest der Schlange nicht bewegt wird, da Sie nur die erste und letzte Position ändern.
Dies erzeugt ein schlangenartiges Verhalten.

Pontus Magnusson
quelle
Whoa, danke! Das macht sehr viel Sinn und hätte von Anfang an die Idee sein sollen. Es sieht so aus, als hätte ich Spaß beim Refactoring :) Es tut mir nur leid, dass meine traurige Menge an Karma mich daran hindert, dich zu verbessern. Ich verspreche, dass ich in Zukunft zurück sein werde!
Kilian
1
Eine alternative Möglichkeit, darüber nachzudenken, besteht darin, dass jedes Schlangenelement nur dem Element direkt vor ihm folgt, anstatt dem Kopf zu folgen. Dies ist nützlich, wenn die Schlangen später strukturiert sind oder ähnliches.
Nathan Reed
2
Hier ist übrigens die aktuelle Version, nochmals vielen
Kilian
1

Ich sehe es als ein "Caterpillar" -ähnliches System, bei dem jeder Teil der Schlange dem vorhergehenden Teil folgt.

Mit anderen Worten, jeder Teil der Schlange wäre ein Objekt mit Position (x, y) , ein Verweis auf den Teil vor ihm, mit dem er sich bewegen würde, und eine Funktion, um die Position des Teils vor und zu verarbeiten entsprechend bewegen. Die Hauptschlange (der Kopf) sollte Referenzen für jeden Teil der Schlange haben und würde die Funktion aufrufen, die dafür verantwortlich ist, dass der Teil seinem Vorgänger folgt, wobei der Kopf der Vorgänger des ersten Teils ist.
Ich hoffe es hilft!

Lince Assassino
quelle
Dies war die Idee, aber der Umgang mit Ecken erwies sich als recht komplex. Und was würde passieren, wenn ein Spieler eine scharfe 180-Grad-Ecke drehen würde? Wir waren uns nicht sicher, wie wir damit richtig umgehen sollten, und die von Pontus Magnusson beschriebene Methode löst all diese Probleme gut.
Kilian
Aha. Das einzige Mal, als ich ein Raupensystem implementierte, hatte ich ein Gitter mit Zellen in der Größe der Teile, sodass sich jedes Teil immer in einer bestimmten Zelle befand. Auf diese Weise trat das Problem nicht auf. Entschuldigung für mein schlechtes Englisch.
Lince Assassino
Ah ja, das macht Sinn und sollte auch funktionieren, aber wir haben die Idee, ein Raster zu haben, aus einem Grund verworfen, an den ich mich derzeit nicht erinnern kann;) Danke :)
Kilian