Як зв’язати кульовий випуск з анімацією стрільби


15

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

EDIT: Я думаю, що у мене виникають проблеми з правильним формулюванням питання.

My Question


Спасибі! Багато хороших ідей від усіх вас, мені подобається ідея використання зворотного дзвінка. Я думаю, я спробую це здійснити, я дуже не хотів покладатися на відстеження часу.
tp0w3rn

Відповіді:


8

По суті, ви на правильному шляху - вам потрібно знати, скільки часу триває анімація, щоб робити подібні речі. Анімації - це не просто колекція кадрів, навколо них є всяка інша інформація. Наприклад, скільки кадрів є, чи працює цикл анімації, як швидко відтворюється (наприклад, 10 кадрів анімації в секунду або 25, або 60?). Кожну анімацію можна визначити за допомогою декількох фрагментів даних, які деякі узагальнені коди анімації можуть переглядати та відтворювати. Вам слід укласти анімаційну частину у свій власний біт коду, який не знає нічого, крім цих визначень анімації та способів відображення окремих кадрів зображень. Тобто, майте об’єкт анімації, який ви можете завантажити, почати грати, припинити грати і сказати візуалізувати у певному місці на екрані.

Гнучкий підхід полягає у використанні свого роду анімаційного визначення для інкапсуляції подібної інформації. Тому замість того, щоб просто сказати, що «анімація X - це всі ці кадри, просто грайте через них», ви отримуєте щось трохи складніше.

Наприклад, з якимось форматируемим формою даних

анімації =
{
  {name = "walk", files = "walk * .png", frameCount = "12", loop = "true"},
  {name = "fire" files = "fire * .png" frameCount = "6",
       події = {
           {name = "bulletLeavesGun", frame = "4", param1 = "43", param2 = "30"}
       }
  }
}

Тож у вашому коді написано щось на кшталт:

currentAnimation = animations.Get("fire");
currentAnimation.Play();

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

List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
    if (event.name == "bulletLeavesGun")
    {
        Vector2 bulletPosition = new Vector2(event.param1, event.param2);
        Vector2 actualBulletPosition = new Vector2(
                 character.x + bulletPosition.x, 
                 character.y + bulletPosition.y);
        CreateBulletAt(actualBulletPosition);
    }
}

Бали, які слід зазначити:

  • Анімаційний код повинен існувати окремо від коду гри. Ви дійсно не хочете, щоб ваш ігровий код був занадто щільно прив’язаний до гайок і болтів відтворення анімації.
  • Код анімації знає, чи потрібно циклічно робити, залежно від визначення анімації
  • Код анімації знає, коли анімація зроблена, і може передзвонити на якийсь інший код, щоб сказати: «Ей, анімація під назвою« вогонь »щойно закінчена. Що ти хочеш зараз зробити?»
  • Код анімації нічого не знає про події, крім того, що вони мають ім'я та деякі довільні дані, пов’язані з ними (param1 та param2)
  • Код анімації знає, на якому кадрі він перебуває в даний момент, і коли він зміниться на новий кадр, він може перевірити і сказати "о, я зараз на кадрі 4, це означає, що ця подія під назвою" пожежа "щойно відбулася, додайте це до мій список останніх подій, тому я можу сказати кожному, хто про це запитує ».

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


Я не погоджуюся з тим, щоб тримати анімацію в розумінні логіки (зараз на кадрі 4 це означає, що ця подія під назвою "пожежа" щойно відбулася). Анімації повинні бути сліпими і німими. Мені довелося робити декілька логік на сервері та розривати анімацію, а користувальницький інтерфейс із гри - це те, що я не хочу робити знову. Я б дуже рекомендував використовувати дуже короткі та сегментовані анімації, відтворювати їх паралельно логіці, нехай логіка запускає послідовності анімації зі швидкістю, визначеною логікою. Ніколи не проводите логічний тест на статус анімації.
Койот

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

@Coyote Я б сказав, що ви змішуєте дві окремі речі. Так, логіка на стороні сервера завжди повинна бути незалежною від візуальних засобів (тому що вам не потрібно запускати анімаційну систему, аби з'ясувати, коли вистрілена куля), але це не допоможе вам створити систему анімації на клієнті . Що стосується клієнта, ви абсолютно не хочете, щоб візуальні картини були безглуздо забиті на сервері, тому що це виглядатиме жахливо - кулі, що з’являються в непарні часи і не синхронізуються з персонажем, тому що між грою та сервером був спайк затримок . Немає причин, щоб у вас не було обох (продовження ...)
MrCranky

@Coyote (продовження ...), геймплей може управляти сервером, відокремленим від візуальних засобів. Таким чином, куля вистрілюється в часі X на сервер, і клієнт відображає цю дію, починаючи негайно відтворювати вогневу анімацію, при цьому куля, яка вистрілює візуально, відстає на кілька кадрів за імітацією геймплея кулі. Необхідно робити всілякі компроміси між візуальною вірністю та моделюванням геймплея, так що можна сказати, що "анімація повинна бути сліпою та німою" просто наївно. Іноді події абсолютно потрібно прив’язати до анімаційних кадрів, оскільки жоден інший метод не змусить їх виглядати чи звучати правильно.
MrCranky

@Coyote Насправді зараз я думаю про це, стрілянина кулями є жахливим прикладом цього, головним чином через відповідь, подану нижче. Стрільба повинна відбутися відразу. Кращим прикладом може бути пилова VFX стрілянина, коли персонаж приземляється - сервер і клієнт синхронізуються, коли символ починає стрибати, але візуальний дисплей залишається за клієнтом. А коли анімація потрапить у потрібний кадр, де ногою вдариться об землю, подія VFX повинна запуститись. Аналогічно, події необхідні, якщо потрібно прийняти рішення на певному анімаційному кадрі, чи слід переходити до іншої анімації.
MrCranky

3

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

Якщо налаштувати таймер, ви зможете встановити таймер. Як незначна зміна, у вас може бути код внутрішній для кулі, що змушує її непомітно почекати хвилину, перш ніж з’являтися та рухатися.

Залежно від вашої платформи розробки, у вас може бути якась функція оновлення анімації або зворотний виклик, який дозволить вам відповісти в той момент, коли анімація досягне потрібної точки. Ось як я це зробив, наприклад, з Flixel.


1
Метод Флікселя addAnimationCallbackможе бути використаний на вогнепальному об'єкті . У функції зворотного виклику ви можете бачити, чи поточний кадр анімації стрільби є кадром, який повинен створювати об'єкт кулі. Якщо це так, ви можете додати кулю на екран.
Снігові сліпи

2

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

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


Так, не змушуйте вогонь реагувати повільно. Це подібно до поширеного питання зі стрибками; аніматори роблять велику виграш, але гравці розраховують потрапити в повітря, як тільки натискають кнопку.
поштовх

2

Як говорить MrCranky; тримати розділення анімації та логіки.

Але найголовніше, що логіка повинна залишатися основною частиною.

  • Після натискання кнопки вогню слід запустити « дію » малювання у стані вашого персонажа (логіки).
  • Ця дія повинна викликати анімацію малювання з усіма параметрами (час жити тощо).
  • Once the draw action is finished you can trigger the fire action (could fire once or more depending on the weapon)
  • This action can generate bullets and trigger the fire animation.

Keep in mind that controlling the UI from the logics is the only way to ensure you will be able to keep, reuse and share your logics later (new renderer, new game, server version without a renderer...)


1

First off, I'd use an event system (observer pattern?) to decouple pieces of the code. This isn't just for the animation, but certainly applies there. Then the animation code can simply say dispatchEvent(event) and some other part of the code listens for that event, without either part of the code needing to know about each other.

Тепер анімаційний код повинен насправді мати посилання на диспетчер подій (легко це робиться з використанням ін'єкції залежності), і вам потрібно мати деякі XML або JSON, які фактично визначають ваші анімації. Щось на зразок:

{
  animation: {
    name: shoot,
    length: 12,
    spritesheet: shoot.png
    event: {
      frame: 4,
      name: bulletLeavesGun,
    },
  },
}

Читайте дані під час завантаження анімації та майте код анімації відправляти подію, коли вона знаходиться на цьому кадрі під час відтворення.

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