Jak sprawić, by wąż podążał za głową?

10

Po przydzieleniu zadania i rozpoczęciu pracy z libGDX przez zbudowanie małego klona Węża natknąłem się na problem, który pewnie za chwilę się wstydzę.

Obecnie mam głowę węża (na tym etapie prosty prostokąt) poruszającą się po kanwie gry. Najprostszym sposobem na zbudowanie reszty węża było posiadanie przez szefa biblioteki Java Linked Linked List SnakeElements, która zwiększałaby / zmniejszała rozmiar w zależności od tego, co robi gracz.

Wykazanie, że lista SnakeElements podąża za tobą, nie okazało się jednak trywialne.

Bieżąca funkcja, która to robi, jest następująca i jest wywoływana za każdym razem, gdy głowa aktualizuje swoją pozycję:

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;
    }
}

co niestety powoduje takie zachowanie:

gif

Będziemy wdzięczni za wszelkie wskazówki, jak zrobić prawidłowo działający ogon węża :)

Kilian
źródło

Odpowiedzi:

18

Pomyśl o takim problemie:
jak porusza się wąż w oryginalnej grze?
Wąż porusza się w kierunku obecnego kierunku. Zachowanie wygląda na to, że głowa pojawia się z niczego, a ostatnia część ogona znika.

Możesz mieć listę snakepartów. Co chcesz zrobić, to usunąć ostatni element na liście, który reprezentuje ostatnią część ogona.
Następnie chcesz utworzyć nowy nagłówek, w którym powinien on zostać umieszczony, i umieścić go na pierwszej pozycji na liście.
Oznacza to, że reszta węża nie zostanie przesunięta, ponieważ zmieniasz tylko pierwszą i ostatnią pozycję.
To stwarza podobne do węża zachowanie.

Pontus Magnusson
źródło
Zaraz, dzięki! To ma sens i od samego początku powinienem był pomyśleć, wygląda na to, że będę się dobrze bawić refaktoryzacja :) Przepraszam, że moja smutna ilość karmy nie pozwala mi cię poprawić. Obiecuję, że wrócę w przyszłości!
Kilian
1
Alternatywnym sposobem myślenia o tym jest to, że każdy element węża podąża tylko za elementem bezpośrednio przed nim, zamiast podążać za głową. Będzie to przydatne, jeśli później węże będą teksturowane lub coś w tym stylu.
Nathan Reed
2
Nawiasem
Kilian
1

Widzę to jako system „gąsienicowy”, w którym każda część węża podąża za częścią przed sobą.

Innymi słowy, każda część węża byłaby Obiektem z Pozycją (x, y) , odniesieniem do części przed nią, której użyłby do poruszania się, oraz funkcją do przetworzenia pozycji części przed nią i przesuń się odpowiednio. Główny wąż (Głowa) powinien mieć odniesienia do każdej części węża i wywoływałby funkcję odpowiedzialną, aby część podążała za swoim poprzednikiem, będąc Głową poprzednikiem pierwszej części.
Mam nadzieję, że to pomoże!

Lince Assassino
źródło
To był pomysł, ale pokonywanie zakrętów okazało się dość skomplikowane. A co by się stało, gdyby gracz skręcił ostro o 180 stopni? Nie byliśmy pewni, jak sobie z tym poradzić poprawnie, a zastosowanie metody opisanej przez Pontusa Magnussona rozwiązuje wszystkie te problemy.
Kilian
Widzę. Jedyny raz, kiedy wdrożyłem system gąsienicowy, miałem siatkę z komórkami o rozmiarze części, więc każda część była zawsze w jednej konkretnej komórce, w ten sposób problem nie wystąpił. Przepraszam za mój zły angielski.
Lince Assassino
Ach tak, to ma sens i powinno również działać, ale porzuciliśmy pomysł posiadania siatki z powodu, którego obecnie nie pamiętam;) Mimo to dziękuję :)
Kilian