Техніка для об'єктів, що слідують один за одним у повному русі?


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

Шлях-> WayPoints стає більшим і більшим, чим довше триває гра. Якщо ваша Змія існує досить тривалий час, вам потрібно видалити останню WayPoint кожного разу, коли останній елемент Змії пройшов другий-останній WayPoint Шлях. Не забудьте також зменшити відстаньFromEnd у всіх MovingObjects of Snake відповідно.


Скажімо, я хотів би перетягнути провідний об’єкт мишею (не те, що хочу, але скажемо, що я роблю). Як би це працювало з вашим прикладом?
Сидар

Список об'єктів може переміщатися, спочатку дозволяючи першому елементу рухатися зі свого поточного положення у заданому напрямку (із заданою швидкістю), а потім дозволяючи всім іншим елементам рухатися зі своїх поточних позицій у напрямку, визначеному їх поточним положенням та $ це-> попереднійElement-> getPosition (). Якщо ви перетягнете кудись перший елемент, вам просто потрібно викликати його метод setPosition (). Коли список буде надано, інші об'єкти змінять шлях, щоб наслідувати своїх попередників.
BerndBrot

Виправте мене, якщо я помиляюсь, але чи не це також призведе до того, що об'єкти слідують за ярликами, коли вони змінюють напрямок? (як, наприклад, у нижній частині зображення, яке я дав). Здається, вони не йдуть шляхом об'єкта вперед. Натомість вони якнайбільше йдуть у напрямку провідного об'єкта, що знаходиться перед ними. Причиняє об'єкти відходити від шляху та брати ярлики?
Сидар

Так, це справді відбудеться саме з цією реалізацією. Я опублікував відповідь, перш ніж ви додали свої фотографії, тож давайте спробуємо ще раз ...
BerndBrot

Добре. Як що до цього?
BerndBrot

6

По суті, вам знадобляться дві структури даних (логічна, нав'язлива чи реальна, залежно від решти коду). Перший буде відстежувати ланцюги предметів, а другий шлях.

Ланцюжок Просто вам потрібно знати, які об’єкти слідують за іншими об’єктами. У найпростішому випадку це буде просто "А" за "В", але може включати більше послідовників. У ланцюжку є призначений лідер .

Шлях Для кожного ланцюга вам знадобиться шлях. Залежно від того, як працює ваша гра, буде визначатися, як це структуровано. У більшості випадків це буде якийсь пов'язаний список. Це дозволить відстежувати позиції, які повинні дотримуватися всі в ланцюжку.

Тепер лідер ланцюга додаватиме елементи до контуру . Кожен раз, коли він рухатиметься, він додаватиме щось на голову списку. Кожен об’єкт у ланцюжку запам’ятовує, де він у списку. Що стосується переміщення, він просто переходить до наступного пункту у списку (за потреби інтерполюється відповідним чином). Коли останній елемент у ланцюжку переміщається повз елемент у списку, цей елемент може бути викинутий (він буде в хвісті).

Метафорично лідер залишає хлібний слід для своїх послідовників. Останній підписник у списку споживає сухарі.

Чи ваш список містить окремі точки, або лише вершини шляху чи щось інше, повністю визначається вашим ігровим механізмом. Але в будь-якому випадку я не бачу, що ви зможете уникнути самого списку.


Так, я зрозумів таке. Це реалізація, яка зазвичай імпровізує мій розум. Дякую за відповідь, хоча. Затверджені berndBrots відповідають, але підтримали ваше.
Сидар

-3

Пошук A * наведення маршруту. Це загальний і простий спосіб, щоб ваші ігрові об'єкти / об'єкти йшли / слідували за позицією.


Я знаю, що таке A *, а не те, що я шукаю, і занадто важке для чогось, що здається набагато простішим.
Сидар

Ваша відповідь навіть не близька до правильної відповіді. A * - це алгоритм пошуку шляху. Поки він не хоче нічого знайти, він просто хоче, щоб об'єкт точно слідував один за одним у кожній позиції, в якій був останній об'єкт.
Ali1S232

Коли я спочатку відповів на це питання, я не зміг уточнити більше / не було картини, яка б відображала, що він має на увазі. Я просто прочитав перші 2 речення і зрозумів, що у нього є кілька сутностей, які намагаються щось відстежити, а не йти шляхом. Вибачте за погану відповідь, мабуть
thedeadlybutter

Я сказав сказати, що слідкуйте один за одним = P не рухайтесь до точки.
Сидар

Я знаю, мої вибачення.
thedeadlybutter
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.