¿Cómo puedo hacer que la cola de una serpiente siga a la cabeza?

10

Después de una tarea y de comenzar a usar libGDX creando un pequeño clon de Snake, me he encontrado con un problema del que probablemente me avergonzaré en un momento.

Actualmente tengo la cabeza de una serpiente (un rectángulo simple en esta etapa) moviéndose alrededor del lienzo del juego. La forma más directa de construir el resto de la serpiente era hacer que la cabeza poseyera una lista enlazada de colecciones de Java de elementos de serpiente que aumentaría / disminuiría de tamaño de acuerdo con lo que hace el jugador.

Sin embargo, tener esta lista de SnakeElements sigue a la cabeza ha demostrado no ser trivial.

La función actual que hace esto es la siguiente y se llama cada vez que la cabeza actualiza su posición:

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 desafortunadamente resulta en este comportamiento:

gif

Cualquier consejo sobre cómo hacer que una cola de serpiente funcione correctamente sería muy apreciada :)

Kilian
fuente

Respuestas:

18

Piensa en el problema de esta manera:
¿cómo se mueve una serpiente en el juego original?
La serpiente se mueve hacia su dirección actual. El comportamiento parece que la cabeza aparece de la nada, y la última parte de la cola desaparece.

Puedes tener una lista de partes de serpiente. Lo que desea hacer es eliminar el último elemento de la lista que representa la última parte de la cola.
Luego, desea crear una nueva cabecera donde debe colocarse y colocarla en la primera posición de la lista.
Esto significa que el resto de la serpiente no se mueve ya que solo modifica la primera y la última posición.
Esto crea un comportamiento de serpiente.

Pontus Magnusson
fuente
Whoa, gracias! Esto tiene mucho sentido y debería haber sido la idea desde el principio, parece que me divertiré refactorizando :) Lo siento, mi triste cantidad de karma me impide votarlo. ¡Prometo volver en el futuro!
Kilian
1
Una forma alternativa de pensarlo es que cada elemento de la serpiente solo sigue al elemento directamente frente a él, en lugar de seguir la cabeza. Esto será útil si, más tarde, las serpientes tienen textura o algo así.
Nathan Reed
2
Por cierto, aquí está la versión actual, gracias de nuevo :) i.imgur.com/IaT5PNH.gif
Kilian
1

La forma en que lo veo es como un sistema similar a "Caterpillar", donde cada parte de la serpiente sigue a la parte anterior.

En otras palabras, cada parte de la serpiente sería un Objeto con Posición (x, y) , una referencia a la parte por delante que usaría para moverse y una función para procesar la posición de la parte por delante y moverse en consecuencia. La serpiente principal (la Cabeza) debería tener referencias para cada parte de la serpiente, y llamaría a la función responsable de hacer que la parte siga a su predecesora, siendo la Cabeza la predecesora de la primera parte.
¡Espero eso ayude!

Lince Assassino
fuente
Esta fue la idea, pero manejar esquinas resultó ser bastante complejo. ¿Y qué pasaría si un jugador doblara una curva cerrada de 180 grados? No estábamos seguros de cómo manejar esto correctamente, y el uso del método descrito por Pontus Magnusson resuelve todos estos problemas muy bien.
Kilian
Veo. La única vez que implementé un sistema de oruga tenía una cuadrícula con celdas del tamaño de las partes, por lo que cada parte siempre estaba dentro de una celda específica, de esta manera, el problema no ocurrió. Perdón por mi mal ingles.
Lince Assassino
Ah sí, eso tiene sentido y también debería funcionar, pero abandonamos la idea de tener una cuadrícula por una razón que no puedo recordar actualmente;) Sin embargo, gracias :)
Kilian