Як кодувати Time Stop або Bullet Time в грі?


11

Я розробляю платформу RPG для одного гравця в XNA 4.0. Я хотів би додати здатність, яка б змусила час "зупинятися" або сповільнюватись, і рухатись би лише персонажем гравця з початковою швидкістю (подібно до заклинання Time Stop з серії "Ворота Балдура"). Я не шукаю точної реалізації, скоріше деякі загальні ідеї та схеми дизайну.

EDIT: Дякую всім за чудовий вклад. Я придумав таке рішення

    public void Update(GameTime gameTime)
        {

            GameTime newGameTime = new GameTime(gameTime.TotalGameTime,
 new TimeSpan(gameTime.ElapsedGameTime.Ticks / DESIRED_TIME_MODIFIER));
            gameTime = newGameTime;

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

Відповіді:


8

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

Наприклад:

player.update(dt)
dt = dt * .5 --half speed
enemy.update(dt)

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

x = x + xspeed * dt * speed

Перша частина має ідеальний сенс, друга частина не зрозуміла
AturSams

2
Просто дайте кожному об'єкту, який рухає змінну швидкості, яку ви можете змінити, і коли у вас є перетворення (наприклад, x), помножте величину на змінну швидкості.
tesselode

Має сенс зараз. :)
AturSams

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

Що ти означає, ШІ міг би реагувати з нормальною швидкістю? Який код міг би AI, який не міг би застосовувати змінну швидкості?
tesselode

3

Використання дельта-часу (мілісекунд, що минув з останнього кадру) може бути недостатньо для уповільнення ворогів. Такі речі, як швидкість атаки, можуть бути реалізовані на основі часу останньої атаки. Хоча він сповільнить рух, якщо буде час, він нехтуватиме швидкістю атаки, заклинанням та іншими наслідками (відновлення здоров'я, тривалість ефектів заклинань) .. та ін

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

Коли повільний ефект припиняється, годинник все ще використовується і збільшується на 100% часу, який фактично пройшов.

Це також може допомогти поспішати з заклинаннями.

@Sidar: Я бачу два варіанти,

  1. Внутрішній годинник на істоту. Для того, щоб з’ясувати, чи істота готова знову напасти: збережіть останній раз, коли кожна атака була використана + час перезарядки та перевірте, чи внутрішній годинник вже пройшов цей час.

  2. Один таймер за атаку: Ви знаєте, скільки часу займає атака для поповнення, і ви просто встановлюєте таймер і віднімаєте час, що пройшов * (1-уповільнення%) кожного ходу.

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

Це дійсно до переваги (Це не так сильно впливає на продуктивність).


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

@Sidar Якщо уникнути цього, вам, ймовірно, знадобиться годинник за атаку, щоб лише час поповнення атаки, тривалість заклинання тощо. Принаймні таким чином вам потрібно оновити лише один годинник і просто зберегти час "останньої активації" для скидання властивостей.
AturSams

Однак його питання стосується уповільнення оточення, крім гравця. Для мене це звучить як найпростіша форма просто множення dt на число, що не перевищує 1. При цьому зберігаючи його так, як для програвача.
Сидар

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

2

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

Я пропоную вам реалізувати ієрархію годинника :

.
├── Main clock
│   └── UI clock
│   └── 3D clock
│       ├── GFX clock
│       └── Gameplay clock
│           └── Slowdown spell clock 01
│           └── Slowdown spell clock 02

Все, що у вашій грі, має використовувати дельта-часи від одного з годинників: графічні ефекти працюють на годиннику GFX, AI та анімація працює на ігровому годиннику, істоти, на яких впливає заклинання уповільнення, виконуються на тимчасовому годиннику заклинання уповільнення тощо. Потім різні речі впливають на різні частини вашої ієрархії: заклинання уповільнення створює та впливає на користувацький годинник, тоді як час кулі вплине на всю ієрархію 3D-годинників.


Дякую, це важливе розуміння. Однак я думаю, що я буду тримати думки простими, оскільки в моєму конкретному випадку не має сенсу, що одночасно виникатимуть декілька ефектів уповільнення.
Девід Мілер

1

Вам просто потрібні два різні годинники замість одного, один на час, відповідний геймплею, і один "справжній" час.

currentGameTime = 0;
gameSpeed = 1.0f;
[...]
currentApplicationTime = GetTime():
timeDelta = (currentApplicationTime - lastApplicationTime)*gameSpeed;
currentGameTime += timeDelta;
lastApplicationTime = currentApplicationTime;

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

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