Давайте возьмем ситуацию, когда у вас есть RPG с заклинаниями, и каждая анимация заклинания имеет разное количество кадров, и у них очень разные требования к звуковым эффектам. Предположим, что каждое заклинание имеет только 1 непрерывную анимацию, связанную с ним (в отличие от нескольких модульных фигур, которые используются для формирования полной анимации), как в старых 16-битных играх Final Fantasy.
Единственный способ убедиться, что звуки и анимация синхронизированы, это:
- Получить количество кадров анимации.
- Получите время между каждым кадром анимации. (если это 30 кадров в секунду, то это 1/30 секунды на кадр.)
- Затем создайте звуковой файл точно такой же длины, что и анимация.
Таким образом, это означает, что если анимация длится 5 секунд, работает со скоростью 30 кадров в секунду и имеет в общей сложности 150 кадров, звуковой файл также будет иметь длину 5 секунд. Если анимация должна иметь «ударный» звук на 30-м кадре, это означает, что звуковой файл будет содержать звук удара на отметке 1,0 секунды.
В конце мы одновременно запускаем анимацию и звуковой эффект и надеемся, что кадры и звук синхронизируются.
Похоже, что это может создать проблемы, когда кадры пропускаются или что-то происходит во время анимации, и звук воспроизводится немного слишком рано или слишком поздно, что приведет к потере синхронизации звука и анимации. Это лучший подход, или я обычно не вижу лучшего способа?
Ответ не обязательно должен быть конкретно для Cocos2D, если это концептуально, но если есть конкретное решение для cocos2d, я бы хотел услышать его.
РЕДАКТИРОВАТЬ: Я просто также понимаю, что с этим методом, если нам случится войти и настроить количество кадров или время анимации позже, мы ДОЛЖНЫ также вернуться и изменить звуковой файл. Это звучит как ужасная причина человеческой ошибки (забыв обновить звуковые файлы после смены анимации). Я надеюсь, что есть лучшие методы.
Ответы:
Сделайте это с помощью событий.
Начало заклинания - это событие . Начните воспроизводить звук для этого события.
Враг, получивший заклинание, также является событием. Если враг находится еще дальше, и вы, например, бросаете дротик, вы воспроизводите второй звук (удар дротиком) только тогда, когда дротик достигает цели (если вы рассматриваете Бросок как заклинание).
Если вам нужно привязать его к кадру (например, воспроизводить звук «взрыва» через 30 кадров независимо от частоты кадров в реальном времени )), самый простой способ сделать это - использовать обратные вызовы . Обратные вызовы - это просто «блоки кода, которые вы планируете запускать в будущем». Вот пример моего метода создания обратного вызова:
A
TimedCallback
- это просто оболочка вокругstd::function
(или вы можете использовать Objective-C^{block}
. Thestd::function
выполняется, когда его фрейм поднят.Другой способ (менее глобальный) - включить события в анимацию . Итак, если вам нужно много раз проигрывать определенные звуки на определенных кадрах анимации, сохраните a
map<int,Sound*>
вAnimation
классе. На каждом кадре анимации проверьте, есть ли соответствующийSound*
кадр для этого кадра.Вы также можете сохранить объект
map<int, std::function>
вAnimation
объекте, что позволит вам вызвать егоfunction
во время анимации.источник
{ 'images':'sprite-%02d.png', 'beginRange':1, 'endRange':32, 'sounds':{ 0 : 'startSpell.wav', 30 : 'impact.wav' } }
. Если ваша игра находится на очень ранней стадии, а время компиляции все еще мало, вы можете начать с жесткого кодирования структур данных, чтобы посмотреть, работает ли она.То, как я это делаю, - это настраиваемые слушатели событий для моего класса анимации и позволяющие им контролировать мой звук. так что, если моя анимация началась callback.start (); и начать мой звук в этом методе. если моя анимация была приостановлена, делайте callback.pause (); и приостановить звук. когда анимация заканчивается, вы вызываете callback.end (); и имейте конец звука также.
но для идеальной синхронизации я бы пошел, считая звуковые кадры и спя (останавливая) мой звук, если он доходил до головы и делал то же самое для моей анимации.
Мне никогда не приходилось делать этого до сегодняшнего дня, потому что первое предложение на данный момент удовлетворяет мои потребности.
источник