Как я могу заставить хвост змеи следовать за головой?

10

После выполнения задания и начала работы с libGDX путем создания небольшого клона Snake, я столкнулся с проблемой, за которую мне, вероятно, будет стыдно через некоторое время.

В настоящее время у меня есть голова змеи (простой прямоугольник на данном этапе), которая движется по холсту игры. Самый простой способ построения остальной части змеи - это иметь в голове собственный Java-коллекционный LinkedList SnakeElements, размер которого будет увеличиваться / уменьшаться в зависимости от того, что делает игрок.

Наличие этого списка SnakeElements следует за головой, однако оказалось не тривиальным.

Текущая функция, выполняющая это, выглядит следующим образом и вызывается каждый раз, когда голова обновляет свою позицию:

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

что, к сожалению, приводит к такому поведению:

GIF

Любые советы о том, как сделать правильно работающий змеиный хвост, будут очень благодарны :)

Kilian
источник

Ответы:

18

Подумайте о проблеме так:
как змея движется в оригинальной игре?
Змея движется в своем текущем направлении. Поведение выглядит так, будто голова появляется из ничего, а последняя часть хвоста исчезает.

Вы можете иметь список частей змеи. То, что вы хотите сделать, это удалить последний элемент в списке, который представляет последнюю часть хвоста.
Затем вы хотите создать новый заголовок, где он должен быть расположен, и поместить его в первую позицию списка.
Это означает, что оставшаяся часть змеи не перемещается, поскольку вы меняете только первую и последнюю позицию.
Это создает змееподобное поведение.

Понтус Магнуссон
источник
Оу, спасибо! Это имеет большой смысл и должно было быть идеей с самого начала, похоже, что я немного повеселился бы в рефакторинге :) Мне просто жаль, что моя грустная карма мешает мне отговорить вас. Я обещаю, что вернусь в будущем!
Килиан,
1
Альтернативный способ думать об этом состоит в том, что каждый элемент змеи следует только за элементом непосредственно перед ним, а не за головой. Это будет полезно, если позже змеи будут текстурированы или что-то в этом роде.
Натан Рид
2
Вот текущая версия, кстати, еще раз спасибо :) i.imgur.com/IaT5PNH.gif
Килиан,
1

Я вижу ее как систему, похожую на «гусеницу», где каждая часть змеи следует за предшествующей.

Другими словами, каждая часть змеи была бы Объектом с Позицией (x, y) , ссылкой на часть впереди нее, которую она будет использовать для перемещения, и функцией для обработки позиции части впереди нее и двигаться соответственно. Главная змея (Голова) должна иметь ссылки для каждой части змеи и должна вызывать функцию, ответственную за то, чтобы деталь следовала за своим предшественником, будучи Главой, предшественником первой части.
Надеюсь, поможет!

Линс Ассассино
источник
Это была идея, но обработка углов оказалась довольно сложной. И что произойдет, если игрок повернет на 180 градусов? Мы не были уверены, как правильно с этим справиться, и использование метода, описанного Pontus Magnusson, хорошо решает все эти проблемы.
Килиан
Понимаю. Единственный раз, когда я реализовал систему гусеницы, у меня была сетка с ячейками по размеру частей, поэтому каждая деталь всегда находилась внутри одной конкретной ячейки, таким образом, проблема не возникала. Извините за мой плохой английский.
Линс Ассассино
Ах, да, это имеет смысл и должно также работать, но мы отказались от идеи иметь сетку по причине, которую я сейчас не могу вспомнить;) Спасибо, хотя :)
Kilian