Tam hareket halinde birbirini takip eden nesneler için teknik?


14

Nesnelerin, önlerindeki nesnenin önceki konumu üzerinde hareket ettikleri yerde birbirlerini nasıl takip ettiklerini merak ediyorum. Önde gelen nesne durduğunda, takip edenlerin tümü konumlarında durmalıdır. Peki bu nasıl başarılıyor?

Şöyle ki:

resim açıklamasını buraya girin

Düzenleme:
Ne elde etmek istiyorum aşağıdaki tüm nesneler önde önde nesnenin yolunu "yürümek" olmasıdır. Diğer tüm nesneler sadece öndeki nesnenin hızında hareket eder (bu, hız vektörünü aşağıdaki tüm nesnelere geçirerek olur). Ancak, tüm nesnelerin birbirinden uzaklığını korurken yolun üzerinde hareket etmesine / duraklamasına nasıl izin verebilirim.

Yanıtlar:


11

Bir kullan Liste yolunu açıklayan yolu noktalarını saklamak için "Yol" denir ve bir çift bağlantılı liste "Yılan" adı verilen hareketli nesneleri ve Path depolamak için.

Önde gelen nesne, seyahat ederken yeni yol noktalarını tanımlar. Aşağıdaki nesneler, bu yol noktaları tarafından tanımlanan yol boyunca hareket eder.

Her nesnenin belirli bir mesafeyle tanımlanan bir güvenlik bölgesi vardır. Baştaki nesne durursa, aşağıdaki nesneler yalnızca selefinin güvenlik bölgesine dokunana kadar devam eder.

İşte bunların nasıl uygulanabileceğine dair bazı sahte kodlar. Bunun sorumlulukların dağılımı ve kapsülleme açısından en şık çözüm olmayabileceğini unutmayın.

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 oyun uzadıkça büyür. Yılanınız oldukça uzun bir süredir mevcutsa, Yılan'ın son öğesi ikinci-son Yol Noktası Geçişini geçtiğinde son WayPoint'i silmeniz gerekir. Snake'in tüm MovingObjects içindeki mesafesini de azaltmayı unutmayın.


Diyelim ki önde gelen nesneyi faremle sürüklemek istiyorum (istediğim gibi değil, diyelim). Bu sizin örneğinizle nasıl çalışır?
Sidar

Nesne listesi ilk olarak ilk öğenin geçerli konumundan belirli bir yönde (belirli bir hızda) hareket etmesine izin vererek ve sonra diğer tüm öğelerin geçerli konumlarından geçerli konumlarından ve $ ile belirtilen yönde hareket etmesine izin vererek hareket edebilir. bu-> previousElement-> getPosition (). İlk öğenizi bir yere sürüklerseniz, onun setPosition () yöntemini çağırmanız yeterlidir. Liste oluşturulduğunda, diğer nesneler seleflerini takip etmek için yollarını değiştirir.
BerndBrot

Yanılıyorsam beni düzeltin ama bu aynı zamanda nesnelerin yön değiştirdikçe kısayolları izlemesine neden olmaz mı? (verdiğim görüntünün alt kısmında olduğu gibi). Nesnenin önündeki yolu takip etmeyecekleri anlaşılıyor. Bunun yerine, mümkün olduğunca önde gelen nesnenin yönüne giderlerdi. Nesnelerin yoldan çıkmasına ve kısayollara mı neden oluyor?
Sidar

Evet, bu özel uygulamada gerçekten olur. Cevabınızı resimlerinizi eklemeden önce yayınladım, hadi tekrar deneyelim ...
BerndBrot

Peki. Peki buna ne dersin?
BerndBrot

6

Esasen iki veri yapısına ihtiyacınız olacaktır (kodunuzun geri kalanına bağlı olarak mantıksal, müdahaleci veya gerçek). Birincisi nesnelerin zincirlerini, diğeri yolu izler.

Zincir Sadece hangi nesnelerin diğer nesneleri takip ettiğini bilmeniz gerekir. En basit durumda bu A'nın B'yi izlemesi olacaktır, ancak daha fazla takipçi içerebilir. Zincirde belirlenmiş bir lider var .

Yol Her zincir için bir yola ihtiyacınız olacaktır. Oyununuzun nasıl çalıştığına bağlı olarak, bunun nasıl yapılandırıldığını belirleyecektir. Çoğu durumda bu bir tür bağlantılı liste olacaktır. Bu, zincirdeki herkesin izlemesi gereken pozisyonları izleyecektir.

Şimdi, zincirdeki lider yola öğeler ekleyecek . Her hareket ettiğinde listenin başına bir şeyler ekler. Zincirdeki her nesne listenin neresinde olduğunu hatırlar. Taşınma söz konusu olduğunda, listedeki bir sonraki öğeye geçer (gerekirse uygun şekilde enterpolasyon yapılır). Zincirdeki son öğe listedeki bir öğeyi geçtikçe, bu öğe bırakılabilir (kuyrukta olacaktır).

Mecazi olarak lider, takipçileri için bir kırıntı izi bırakır. Listedeki son takipçi, kırıntıyı tüketir.

Listenizin tek tek puanlar içerip içermediği veya sadece bir yolun köşeleri veya başka bir şey olup olmadığı tamamen oyun motorunuz tarafından belirlenir. Ancak her durumda listenin kendisinden kaçınabileceğinizi görmüyorum.


Evet, böyle bir şey düşündüm. Genellikle zihnimi zorlayan uygulama. Yine de cevap için teşekkürler. BerndBrots onayladı, ancak sizinkini onayladı.
Sidar

-3

Arama A * yol bulma. Bu, oyun varlıklarınızın / nesnelerinizin bir konuma gitmesini / takip etmesini sağlamanın genel ve kolay bir yoludur.


A * 'nın ne olduğunu biliyorum, aradığım şeyi değil ve çok daha basit görünen bir şey için çok ağır.
Sidar

cevabınız doğru cevabınkine bile yakın değil. A * bir yol bulmak için kullanılan bir algoritmadır. Hiçbir şey bulmak istemese de, nesnenin son nesnenin olduğu her pozisyonda tam olarak birbirini takip etmesini ister.
Ali1S232

Soruyu başlangıçta yanıtladığımda, daha fazla açıklığa kavuşturmak sabit değildi / ne demek istediğini gösteren bir resim yoktu. Sadece ilk 2 cümleyi okudum ve bir yolu izlemeye değil, bir şeyi izlemeye çalışan birden fazla varlığı olduğunu düşündüm. Sanırım kötü cevap için özür dilerim
thedeadlybutter

Birbirini takip et = P bir noktaya taşınmaz demiştim.
Sidar

Biliyorum, özür dilerim.
thedeadlybutter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.