Como posso fazer a cauda de uma cobra seguir a cabeça?

10

Após uma tarefa e apenas começando com a libGDX , construindo um pequeno clone Snake, encontrei um problema pelo qual provavelmente terei vergonha daqui a pouco.

Atualmente, tenho uma cabeça de cobra (um simples retângulo nesta fase) movendo-se pela tela do jogo. A maneira mais direta de construir o resto da cobra era ter a cabeça proprietária de uma Java Linked LinkedList de SnakeElements que aumentaria / diminuiria de tamanho de acordo com o que o jogador faz.

Ter esta lista de elementos de cobra seguindo a cabeça, no entanto, provou não ser trivial.

A função atual que faz isso é a seguinte e é chamada toda vez que o cabeçote atualiza sua posição:

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

que infelizmente resulta neste comportamento:

gif

Qualquer dica sobre como fazer um rabo de cobra funcionando corretamente seria muito apreciada :)

Kilian
fonte

Respostas:

18

Pense no problema assim:
como uma cobra se move no jogo original?
A cobra se move na direção atual. O comportamento parece que a cabeça aparece do nada e a última parte da cauda desaparece.

Você pode ter uma lista de peças de cobra. O que você deseja fazer é remover o último item da lista que representa a última parte final.
Então você deseja criar uma nova parte principal onde deve ser posicionada e colocá-la na primeira posição da lista.
Isso significa que o restante da cobra não é movido, pois você altera apenas a primeira e a última posição.
Isso cria um comportamento parecido com uma cobra.

Pontus Magnusson
fonte
Whoa, obrigado! Isso faz muito sentido e deveria ter sido a idéia desde o início, parece que vou me divertir refatorando :) Sinto muito que minha triste quantidade de karma esteja me impedindo de votar em você. Eu prometo que voltarei no futuro!
Kilian
1
Uma maneira alternativa de pensar sobre isso é que cada elemento cobra segue apenas o elemento diretamente à sua frente, em vez de seguir a cabeça. Isso será útil se, posteriormente, as cobras forem texturizadas ou algo assim.
Nathan Reed
2
Aqui está a versão atual, a propósito, obrigado novamente :) i.imgur.com/IaT5PNH.gif
Kilian
1

A maneira como eu vejo isso é como um sistema semelhante à "Lagarta", onde cada parte da cobra segue a parte à frente.

Em outras palavras, cada parte da cobra seria um Objeto com Posição (x, y) , uma referência à parte à frente que ela usaria para se movimentar e uma função para processar a posição da parte à frente e mova-se de acordo. A cobra principal (a Cabeça) deve ter referências para todas as partes da cobra e chamaria a função responsável de fazer a parte seguir seu antecessor, sendo a Cabeça o predecessor da primeira parte.
Espero que ajude!

Lince Assassino
fonte
Essa foi a idéia, mas lidar com os cantos acabou sendo bastante complexo. E o que aconteceria se um jogador dobrasse uma esquina acentuada de 180 graus? Não tínhamos certeza de como lidar com isso corretamente, e o uso do método descrito por Pontus Magnusson resolve todos esses problemas.
Kilian
Entendo. A única vez que implementei um sistema lagarta, tinha uma grade com células no tamanho das peças, de modo que cada parte estava sempre dentro de uma célula específica, dessa forma, o problema não ocorria. Desculpe pelo meu inglês ruim.
Lince Assassino 5/05
Ah sim, que faz sentido e também deve funcionar, mas abandonou a idéia de ter uma grade por um motivo que não pode atualmente se lembrar;) Obrigado embora :)
Kilian