Механізм зворотного часу в іграх


10

Мене цікавить, як типово розроблені механізми маніпуляції часом в іграх. Мене особливо цікавить зміна часу (як, наприклад, в останньому SSX або Prince of Persia).

Гра 2D шутер зверху вниз.

Механізм, який я намагаюся розробити / впровадити, має такі вимоги:

1) Дії суб'єктів, крім характеру гравця, повністю детерміновані.

  • Дія, яку здійснює суб'єкт господарювання, ґрунтується на кадрах, просунутих із початку рівня та / або позиції гравця на екрані
  • Суб'єкти породжуються у встановлений час протягом рівня.

2) Зворотний час працює шляхом реверсування назад у режимі реального часу.

  • Дії гравця також зворотні, він відтворює в зворотному порядку, що виконував гравець. Гравець не має контролю в зворотний час.
  • Немає обмеження часу, проведеного заднім ходом, ми можемо перевернути весь шлях до початку рівня, якщо захочемо.

Як приклад:

Рамки 0-50: За цей час гравець рухає вперед 20 одиниць. Ворог 1 породжує в кадрі 20 Ворог 1 рухається вліво 10 одиниць під час кадру 30-40 Гравець стріляє кулею в кадр 45 Куля рухається 5 вперед (45-50) і вбиває Ворога 1 на кадр 50

Повернення цього відтворюється в реальному часі: Гравець за цей час рухається назад на 20 одиниць. Ворог 1 відроджується в кадрі 50 Куля знову з'являється в кадрі 50 Куля рухається назад 5 і зникає (50-45) Ворог рухається ліворуч 10 (40-30) Ворог видалений у кадр 20.

Просто дивлячись на рух У мене були деякі ідеї, як цього досягти, я думав мати інтерфейс, який міняв би поведінку, коли час просувався або змінювався. Замість того, щоб робити щось подібне:

void update()
{
    movement += new Vector(0,5);
}

Я б зробив щось подібне:

public interface movement()
{
    public void move(Vector v, Entity e);
}

public class advance() implements movement
{
    public void move(Vector v, Entity e)
    {
            e.location += v;
    }
}


public class reverse() implements movement
{
    public void move(Vector v, Entity e)
    { 
        e.location -= v;
    }
}

public void update()
{
    moveLogic.move(new vector(5,0));
}

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


1
Я не переглядав усе це (YouTube хиткий кулачок на YouTube, 1,5 години) , але, можливо, є деякі ідеї Джонатана Удар, який працював над цим у своїй грі Braid.
MichaelHouse

Можливий дублікат gamedev.stackexchange.com/questions/15251 / ...
Hackworth

Відповіді:


9

Можливо, ви захочете поглянути на шаблон команди .

В основному всі оборотні дії, які здійснюють ваші сутності, реалізуються як командний об'єкт. Усі ці об'єкти реалізують щонайменше два способи: Execute () та Undo (), а також все, що вам потрібно, як властивість часової позначки для правильного встановлення часу.

Кожен раз, коли ваша сутність виконує оборотні дії, спершу ви створюєте відповідний командний об'єкт. Ви зберігаєте його на степі скасування, потім подаєте в ігровий движок і виконайте його. Коли ви хочете повернути час, ви виводите дії з верхньої частини стека і викликуєте їх метод Undo (), який робить протилежний методу Execute (). Наприклад, у випадку стрибка з точки A в точку B ви виконуєте стрибок з B в A.

Після того як ви здійснили дію, збережіть її на стеку Redo, якщо ви хочете рухатися вперед і назад за бажанням, як і функція скасування / повтору в текстовому редакторі або програмі малювання. Звичайно, ваші анімації також повинні підтримувати режим "перемотування назад" для відтворення їх назад.

Для отримання додаткових ігрових дизайнів, дозвольте кожній організації зберігати свої дії у власному стеку, щоб ви могли скасувати / повторити їх незалежно один від одного.

Командний шаблон має й інші переваги: ​​Наприклад, досить тривіально створити рекордер для повторного відтворення, оскільки вам потрібно просто зберегти всі об'єкти в стеках у файл, а під час перезавантаження просто ввести його в ігровий движок по одному один.


2
Зауважте, що оборотність дій в грі може бути дуже зворушливою справою через проблеми з точністю з плаваючою комою, змінні часові кроки тощо; набагато безпечніше зберегти цей стан, ніж перебудувати його в більшості ситуацій.
Стівен Стадницький

@StevenStadnicki Можливо, але це, безумовно, можливо. C&C Generals вгорі голови робить це так. У ньому є багатогодинний перегляд до 8 гравців, вагою в декілька сотень кБ в гіршому випадку, і, як я думаю, більшість, якщо не всі ігри RTS роблять своїх мультиплеєрів: Ви просто не можете передати повний стан гри з потенційно сотнями одиниць кожного кадру, ви повинні дозволити двигуну робити оновлення. Так так, це, безумовно, життєздатне.
Хакворт

3
Відтворення - це зовсім інша річ від перемотування назад, тому що операції, які послідовно відтворюються вперед (наприклад, знаходження позиції в кадрі n, x_n, починаючи з x_0 = 0 і додаючи дельти v_n для кожного кроку), не обов'язково відтворюються назад ; (x + v_n) -v_n не відповідає рівним x у математиці з плаваючою комою. І легко сказати "обійти це", але ви говорите про потенційно повний капітальний ремонт, включаючи неможливість використання багатьох зовнішніх бібліотек.
Стівен Стадницький

1
Для деяких ігор вашого підхід може бути можливим, але AFAIK більшість ігор , які використовують звернення часу механіка використовує що - то ближче до Memento підходу OriginalDaemon, де відповідний стан буде збережено для кожного кадру.
Стівен Стадницький

2
Що з перемотуванням шляхом перерахунку кроків, але збереження ключового кадру кожні пару секунд? Похибки з плаваючою комою, ймовірно, не суттєво зміниться за кілька секунд (звичайно, залежно від складності). Також показано, що він працює в стисканні відео: P
Tharwen

1

Ви могли поглянути на шаблон Memento; його основний намір полягає у здійсненні операцій скасування / повторення шляхом відкочування стану об'єкта, але для певних видів ігор цього має бути достатньо.

Для гри в циклі реального часу ви можете розглядати кожен кадр своїх операцій як зміну стану та зберігати його. Це простий підхід до реалізації. Альтернативою є пастка при зміні стану об'єкта. Наприклад, виявлення, коли сили, що діють на жорстке тіло, змінюються. Якщо ви використовуєте властивості для отримання та встановлення змінних, це також може бути відносно прямою реалізацією, важка частина визначає, коли потрібно повернути стан, оскільки це не буде одночасно для кожного об'єкта (ви можете зберігати час відкату як кількість кадрів від початку системи).


0

У вашому конкретному випадку обробка відката шляхом перемотування рухом має спрацювати нормально. Якщо ви використовуєте будь-яку форму накладання маршруту з підрозділами AI, просто не забудьте перерахувати його після відкату, щоб уникнути перекриття одиниць.

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


0

Хоча це цікава ідея. Я би радив проти цього.

Відтворення гри вперед працює добре, оскільки операція завжди матиме однаковий вплив на стан гри. Це не означає, що зворотна операція надає вам початковий стан. Наприклад, оцініть наступний вираз на будь-якій мові програмування (вимкніть оптимізацію)

(1.1 + 3 - 3) == 1.1

Принаймні, в C і C ++ він повертає значення false. Хоча різниця може бути невеликою, уявіть, скільки помилок може накопичуватися при 60 кадрів в секунду за 10 секунд хвилин. Будуть випадки, коли гравець лише щось пропускає, але влучає в нього, поки гра відтворюється назад.

Я рекомендую зберігати ключові кадри кожні півсекунди. Це не займе занадто багато пам’яті. Потім можна або інтерполювати між ключовими кадрами, або ще краще, імітувати час між двома ключовими кадрами, а потім повторно відтворювати його назад.

Якщо ваша гра не надто складна, просто зберігайте ключові кадри ігрового стану 30 разів на секунду і грайте назад. Якщо у вас було 15 об’єктів, які мають 2D-положення, знадобиться 1,5 хвилини, щоб піднятися до МБ, без стиснення. Комп'ютери мають гігабайти пам'яті.

Тому не надто ускладнюйте її, відтворити гру назад буде непросто, і це спричинить багато помилок.

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