Técnica para objetos seguindo um ao outro em movimento completo?


14

Eu estou querendo saber como os objetos se seguem, onde eles se movem sobre a posição anterior do objeto na frente deles. Quando o objeto principal para, todos os itens a seguir devem parar em sua posição. Então, como isso é alcançado?

Igual a:

insira a descrição da imagem aqui

Edit:
O que eu quero alcançar é que todos os objetos a seguir "andem" no caminho que o objeto principal está tomando. Todos os outros objetos apenas se movem na velocidade do objeto principal (isso seria passando o vetor de velocidade para todos os objetos a seguir). Mas como deixo todos os objetos se moverem / pausarem ao longo do caminho, mantendo distância também um do outro.

Respostas:


11

Use uma lista chamada "Caminho" para armazenar os pontos de referência que descrevem o seu caminho, e uma lista duplamente vinculada chamada "Cobra" para armazenar os objetos em movimento e o Caminho.

O objeto principal define novos pontos de referência à medida que viaja. Os seguintes objetos se movem ao longo do caminho, conforme definido por esses pontos de referência.

Cada objeto tem uma zona de segurança definida por alguma distância. Se o objeto principal parar, os objetos a seguir serão movidos apenas até que toquem na zona de segurança de seu predecessor.

Aqui está um pseudocódigo de como essas coisas podem ser implementadas. Esteja ciente de que essa pode não ser a solução mais elegante em termos de distribuição de responsabilidades e encapsulamento.

class Position {
    property x;
    property y;
}
class WayPoint extends ListNode {
    property position;
}
class Path extends List { 
    property WayPoints = array();

    // Find out the x, y coordinates given the distance traveled on the path
    function getPositionFromDistanceFromEnd(distance) {
        currentWayPoint = this->first();
        while(distance > 0) {
            distanceBetweenWayPoints = this->getDistance(currentWayPoint, currentWayPoint->next());
            if(distanceBetweenWayPoints > distance) {
                position = ... // travel remaining distance between currentWayPoint and currentWayPoint->next();
                return position;
            } else {
                distance -= distanceBetweenWayPoints;
                currentWayPoint = currentWayPoint->next();
            }
        }
    }
    function addWayPoint(position) {
        // Vector describing the current and new direction of movement
        currentDirection = this->first() - this->second();
        newDirection = position - this->first();
        // If the direction has not changed, there is no need to add a new WayPoint
        if( this->sameDirection(currentDirection, newDirection) {
            this->first->setPosition(position);
        } else {
            this->add(position);
        }
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject extends DoublyLinkedListNode {
    property Snake; // shared among all moving objects of the same snake
    property position;
    const securityDistance = 10;
    abstract function move() { }
}
class MovingObjectLeader extends MovingObject {
    property direction;
    function move() {
        this->position += this->direction * this->Snake->speed;
        this->Snake->Path->addWayPoint(this->position);
        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}
class MovingObjectFollower extends MovingObject {
    property distanceFromEnd;
    function move() {
        this->distanceFromEnd += this->Snake->speed;

        // If too close to leader: stop in order to respect security distance
        if(this->distanceFromEnd > this->leader()->distanceFromEnd - this->securityDistance) {
            this->distanceFromEnd = this->leader()->distanceFromEnd - this->securityDistance;
        }

        this->position = this->Snake->getPositionFromDistanceFromEnd(this->distanceFromEnd);

        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}

Caminho-> WayPoints se torna cada vez maior quanto mais o jogo continuar. Se o seu Snake existir há algum tempo, você precisará excluir o último WayPoint sempre que o último elemento do Snake tiver passado o penúltimo WayPoint do caminho. Lembre-se de reduzir também o distanceFromEnd em todos os MovingObjects of Snake.


Digamos que eu queira arrastar meu objeto principal com o mouse (não que eu queira, mas digamos que sim). Como isso funcionaria com o seu exemplo?
Sidar

A lista de objetos pode ser movida deixando primeiro o primeiro elemento sair de sua posição atual em uma determinada direção (com uma velocidade especificada) e depois deixar todos os outros elementos passarem de suas posições atuais em uma direção especificada por sua posição atual e $ this-> previousElement-> getPosition (). Se você arrastar seu primeiro elemento para algum lugar, basta chamar o método setPosition (). Quando a lista é renderizada, os outros objetos alteram seu caminho para seguir seus predecessores.
precisa saber é o seguinte

Corrija-me se eu estiver errado, mas isso também não resultaria nos objetos a seguir atalhos enquanto mudavam de direção? (como na parte inferior da imagem que eu dei). Parece que eles não seguiriam o caminho do objeto na frente. Em vez disso, eles iriam na direção do objeto principal na frente deles, tanto quanto possível. Causando os objetos fora do caminho e pegando atalhos?
Sidar

Sim, isso realmente aconteceria com essa implementação específica. Eu postei a resposta antes que você adicionou suas fotos, então vamos tentar de novo ...
BerndBrot

Bem. Que tal isso?
precisa saber é o seguinte

6

Essencialmente, você precisará de duas estruturas de dados (lógicas, intrusivas ou reais, dependendo do restante do seu código). O primeiro rastreará as cadeias de objetos e o outro o caminho.

Cadeia Simplesmente você precisa saber quais objetos estão seguindo outros objetos. No caso mais simples, isso será simplesmente A segue B, mas pode incluir mais seguidores. Existe um líder designado na cadeia.

Caminho Para cada cadeia, você precisará de um caminho. Dependendo de como o jogo funciona, determinará como isso está estruturado. Na maioria dos casos, será algum tipo de lista vinculada. Isso rastreará as posições que todos na cadeia precisam seguir.

Agora, o líder da cadeia estará adicionando itens ao caminho . Cada vez que se move, adiciona algo ao cabeçalho da lista. Cada objeto na cadeia lembra onde está a lista. Quando se trata de mover, simplesmente passa para o próximo item da lista (interpolado adequadamente, se necessário). À medida que o último item da cadeia passa por um item da lista, esse item pode ser descartado (estará na cauda).

Metaforicamente, o líder deixa uma trilha de migalhas para seus seguidores. O último seguidor na lista consome a trilha de navegação.

Se sua lista contém pontos individuais, ou apenas os vértices de um caminho, ou qualquer outra coisa, é determinado inteiramente pelo seu mecanismo de jogo. Mas, de qualquer forma, não vejo que você consiga evitar a própria lista.


Sim, eu imaginei isso. É a implementação que geralmente implode em minha mente. Obrigado pela resposta embora. O berndBrots aprovado responde, mas com o seu voto positivo.
Sidar

-3

Pesquisa A * pathfinding. Esta é uma maneira geral e fácil de fazer com que suas entidades / objetos do jogo sigam / sigam uma posição.


Eu sei o que é A *, não o que estou procurando e muito pesado para algo que parece muito mais simples.
Sidar

sua resposta não chega nem perto da resposta correta. A * é um algoritmo para encontrar um caminho. Enquanto ele não quer encontrar nada, ele só quer que o objeto se siga exatamente em todas as posições em que o último objeto estava.
precisa saber é o seguinte

Quando eu originalmente respondi a pergunta, não havia conserto para esclarecer mais / não havia uma imagem para mostrar o que ele queria dizer. Acabei de ler as duas primeiras frases e imaginei que ele estava tendo várias entidades tentando rastrear algo, não seguir um caminho. Desculpem a resposta ruim, eu acho
Thedeadlybutter

Eu disse seguir um ao outro = P não passar a um ponto.
Sidar

Eu sei, minhas desculpas.
thedeadlybutter
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.