Prenons une situation où vous avez un RPG avec des sorts et chaque animation de sorts a un nombre différent d'images et leurs exigences en matière d'effets sonores sont très différentes. Supposons que chaque sort n'ait qu'une seule animation continue qui lui est associée (par opposition à plusieurs pièces modulaires qui sont utilisées pour former une animation complète) ala les anciens jeux Final Fantasy 16 bits.
La seule façon dont je peux penser afin de m'assurer que la synchronisation des sons et des animations est de:
- Obtenez le nombre d'images d'une animation.
- Obtenez le temps entre chaque image de l'animation. (si c'est 30 ips, alors c'est 1 / 30ème de seconde par image.)
- Créez ensuite un fichier son exactement de la même longueur que l'animation.
Cela signifie donc que si une animation dure 5 secondes, s'exécutant à 30 ips, avec un total de 150 images, le fichier son sera également de 5 secondes. Si l'animation doit avoir un son "d'impact" sur la 30ème image, cela signifie que le fichier son inclura le son d'impact à la marque de 1,0 seconde.
À la fin, nous démarrons l'animation et l'effet sonore exactement en même temps et espérons que les images et le son se synchroniseront.
Cela peut sembler poser des problèmes lorsque des images sont sautées ou que quelque chose se produit pendant l'animation et que le son est joué un peu trop tôt ou trop tard, et entraînera la désynchronisation du son et de l'animation. Est-ce la meilleure approche ou existe-t-il généralement une meilleure façon que je ne vois tout simplement pas?
La réponse ne doit pas nécessairement être pour Cocos2D spécifiquement si elle est conceptuelle, mais s'il existe une solution spécifique pour cocos2d, j'aimerais l'entendre.
EDIT: Je réalise aussi qu'avec cette méthode, si nous entrons et ajustons le nombre d'images ou le timing de l'animation plus tard, nous devons également revenir en arrière et changer le fichier son. Cela ressemble à une terrible cause d'erreur humaine (oublier de mettre à jour les fichiers audio après le changement d'animation.) J'espère qu'il existe de meilleures méthodes.
Réponses:
Faites-le via des événements.
Spell begin est un événement . Commencez à jouer le son de cet événement.
Un ennemi frappé par un sort est également un événement. Si l'ennemi est plus éloigné et que vous lancez une fléchette, par exemple, vous ne jouez le deuxième son (fléchette frappant) qu'une fois que la fléchette atteint la cible (si vous considérez lancer comme un sort).
Si vous avez besoin de le lier à une image (par exemple, jouez le son "exploser" dans 30 images à partir de maintenant, indépendamment des fréquences d'images en temps réel )), la façon la plus simple de le faire est d'utiliser les rappels . Les rappels ne sont que des "blocs de code que vous prévoyez d'exécuter à l'avenir". Voici un exemple de mon setter de création de callback:
A
TimedCallback
est juste un wrapper autour d'unstd::function
(ou vous pouvez utiliser un Objective-C^{block}
. Lestd::function
est exécuté lorsque son cadre est en place.Une autre façon (moins globale) consiste à inclure des événements dans votre animation . Donc, si vous devez beaucoup jouer des sons spécifiques sur des images d'animation spécifiques, stockez-
map<int,Sound*>
en un dans laAnimation
classe. Sur chaque image de l'animation, vérifiez s'il y a un correspondantSound*
à jouer pour cette image.Vous pouvez également stocker un
map<int, std::function>
, dans l'Animation
objet, ce qui vous permettrait de rappeler unfunction
pendant l'animation.la source
{ 'images':'sprite-%02d.png', 'beginRange':1, 'endRange':32, 'sounds':{ 0 : 'startSpell.wav', 30 : 'impact.wav' } }
. Si votre jeu est à un stade très précoce et que le temps de compilation est encore faible, vous pouvez commencer par coder en dur les structures de données pour voir si cela fonctionne.La façon dont je le fais est de créer des écouteurs d'événements personnalisés pour ma classe d'animation et de les faire contrôler mon son. donc si mon animation a commencé callback.start (); et commencer mon son dans cette méthode. si mon animation a été interrompue, faites callback.pause (); et mettre le son en pause. lorsque l'animation est terminée, vous callback.end (); et avoir la fin du son aussi.
mais pour une synchronisation parfaite, j'irais jusqu'à compter les images sonores et dormir (mettre en pause) mon son s'il arrive trop loin et faire de même pour mon animation.
Je n'ai jamais eu à le faire jusqu'à ce jour car la première suggestion répond très bien à mes besoins pour l'instant.
la source