完全に動きながら互いに追従するオブジェクトのテクニック?


14

オブジェクトが前にあるオブジェクトの前の位置を移動する場所で、オブジェクトがどのように互いに追従するのか疑問に思います。先行オブジェクトが停止すると、後続のすべてがその位置で停止するはずです。それで、これはどのように達成されますか?

そのようです:

ここに画像の説明を入力してください

編集:
私が達成したいのは、次のすべてのオブジェクトが、前の先頭のオブジェクトがたどるパスを「歩く」ことです。他のすべてのオブジェクトは、先頭のオブジェクトの速度で移動します(これは、速度ベクトルを後続のすべてのオブジェクトに渡すことによるものです)。しかし、お互いの距離も維持しながら、すべてのオブジェクトをパス上で移動/一時停止させるにはどうすればよいですか?

回答:


11

「パス」と呼ばれるリストを使用して、パスを記述するウェイポイントを保存し、「スネーク」と呼ばれる二重リンクリストを使用して、移動するオブジェクトとパスを保存します。

主要なオブジェクトは、移動する新しいウェイポイントを定義します。次のオブジェクトは、これらのウェイポイントによって定義されたパスに沿って移動します。

各オブジェクトには、ある距離で定義されたセキュリティゾーンがあります。先頭のオブジェクトが停止すると、後続のオブジェクトは、前のオブジェクトのセキュリティゾーンに触れるまで移動します。

これらを実装する方法の疑似コードを次に示します。これは、責任の分散とカプセル化の点で最もエレガントなソリューションではない可能性があることに注意してください。

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

Path-> WayPointsは、ゲームが長くなるほど大きくなります。Snakeがかなり長い間存在する場合、Snakeの最後の要素がPathの最後から2番目のWayPointを通過するたびに、最後のWayPointを削除する必要があります。それに応じて、SnakeのすべてのMovingObjectsでdistanceFromEndも減らすことを忘れないでください。


私がマウスで主なオブジェクトをドラッグしたいとしましょう(私がしたいのではなく、私がやったとしましょう)。それはあなたの例でどのように機能しますか?
Sidar

オブジェクトのリストは、最初に最初の要素を現在の位置から特定の方向に(特定の速度で)移動し、次に他のすべての要素を現在の位置から現在の位置と$で指定された方向に移動することで移動できますthis-> previousElement-> getPosition()。最初の要素をどこかにドラッグした場合、そのsetPosition()メソッドを呼び出すだけです。リストがレンダリングされると、他のオブジェクトはパスを変更して前のオブジェクトをたどります。
BerndBrot

私が間違っていても修正しますが、方向が変わるとオブジェクトがショートカットを取得することはありませんか?(私が与えた画像の下部のように)。彼らは前もってオブジェクトのパスをたどらないように思えます。代わりに、彼らは可能な限り彼らの前にある主要なオブジェクトの方向に行くでしょう。オブジェクトをパスから外し、ショートカットを取得しますか?
シダー

はい、実際にこの特定の実装で起こります。写真を追加する前に答えを投稿したので、もう一度試してみましょう...
BerndBrot

わかった。これはどうですか?
BerndBrot

6

基本的に、2つのデータ構造(残りのコードに応じて、論理、侵入、または実)が必要になります。1つ目はオブジェクトのチェーンを追跡し、もう1つはパスを追跡します。

チェーン単に、どのオブジェクトが他のオブジェクトをフォローしているかを知る必要があります。最も単純なケースでは、これは単にAがBに続きますが、より多くのフォロワーを含めることができます。チェーンには指定されたリーダーがいます。

パス各チェーンにはパスが必要です。ゲームの仕組みに応じて、ゲームの構造が決まります。ほとんどの場合、それはある種のリンクリストです。これは、チェーン内のすべての人が従う必要がある位置を追跡します。

これで、チェーンのリーダーパスにアイテムを追加します。移動するたびに、リストの先頭に何かが追加されます。チェーン内の各オブジェクトは、リスト上のどこにあるかを記憶しています。移動する場合は、リスト内の次の項目に移動するだけです(必要に応じて適切に補間されます)。チェーン内の最後のアイテムがリスト内のアイテムを通過すると、そのアイテムをドロップできます(末尾になります)。

比phor的に、リーダーはフォロワーのためにパンくずリストを残します。リストの最後のフォロワーがパンくずリストを消費します。

リストに個々のポイントが含まれているか、パスの頂点のみが含まれているかなどは、ゲームエンジンによって完全に決定されます。しかし、いずれにしても、リスト自体を避けることができるとは思いません。


うん、私はそのようなことを考え出した。通常、私の心を壊すのは実装です。答えてくれてありがとう。承認されたberndBrotsの回答が、あなたのものを支持しました。
シダー

-3

ルックアップA *パスファインディング。これは、ゲームエンティティ/オブジェクトを特定の位置に移動/追跡するための一般的かつ簡単な方法です。


私が探しているものではなく、A *が何であるかを知っています。
Sidar

あなたの答えは正しい答えにさえ近くありません。A *は、パスを見つけるためのアルゴリズムです。彼は何も見つけたくありませんが、彼はオブジェクトが最後のオブジェクトがあったすべての位置で正確にお互いに従うことを望んでいます。
Ali1S232

私が最初に質問に答えたとき、それはより明確にするために修正されませんでした/彼が何を意味したかを示す絵がありませんでした。最初の2つの文を読んだところ、パスをたどるのではなく、何かを追跡しようとしている複数のエンティティを持っていることがわかりました。私が推測する悪い答えを申し訳ありません
-thedeadlybutter

私はお互いにフォローする= Pはポイントに移動しないと言いました。
シダー

謝ります
thedeadlybutter
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.