Nehmen wir eine Situation, in der Sie ein Rollenspiel mit Zaubersprüchen haben und jede Zauberanimation eine andere Anzahl von Frames hat und sehr unterschiedliche Anforderungen an Soundeffekte stellt. Nehmen wir an, dass jedem Zauber nur eine fortlaufende Animation zugeordnet ist (im Gegensatz zu mehreren modularen Teilen, die zur Erstellung einer vollständigen Animation verwendet werden), wie bei den alten 16-Bit-Final-Fantasy-Spielen.
Der einzige Weg, den ich mir vorstellen kann, um sicherzustellen, dass die Sounds und Animationen synchronisiert werden, ist:
- Ermitteln Sie die Anzahl der Frames einer Animation.
- Holen Sie sich die Zeit zwischen jedem Bild der Animation. (Wenn es 30 fps ist, ist es 1/30 Sekunde pro Frame.)
- Erstellen Sie dann eine Audiodatei, die genau so lang ist wie die Animation.
Das heißt, wenn eine Animation 5 Sekunden lang ist und mit 30 fps und insgesamt 150 Bildern ausgeführt wird, ist die Audiodatei ebenfalls 5 Sekunden lang. Wenn die Animation im 30. Bild einen "Aufprall" -Sound haben soll, bedeutet dies, dass die Sounddatei den Aufprallton bei der 1,0-Sekunden-Marke enthält.
Am Ende starten wir die Animation und den Soundeffekt genau zur gleichen Zeit und hoffen, dass die Frames und der Sound synchronisiert werden.
Dies scheint Probleme zu verursachen, wenn Frames übersprungen werden oder während der Animation etwas passiert und der Sound etwas zu früh oder zu spät abgespielt wird und der Sound und die Animation nicht mehr synchron sind. Ist das der beste Ansatz oder gibt es normalerweise einen besseren Weg, den ich einfach nicht sehe?
Die Antwort muss nicht unbedingt speziell für Cocos2D sein, wenn es konzeptionell ist, aber wenn es eine spezifische Lösung für cocos2d gibt, würde ich sie gerne hören.
BEARBEITEN: Mir ist nur auch klar, dass wir bei dieser Methode, wenn wir die Anzahl der Frames oder das Timing der Animation später anpassen, auch zurückgehen und die Sounddatei ändern müssen. Dies klingt nach einer schrecklichen Ursache für menschliches Versagen (das Vergessen, Sounddateien nach dem Ändern der Animation zu aktualisieren). Ich hoffe, es gibt bessere Methoden.
Antworten:
Mach es über Events.
Der Zauberbeginn ist ein Ereignis . Starten Sie den Sound für dieses Event.
Ein Feind, der vom Zauber getroffen wird, ist ebenfalls ein Ereignis. Wenn der Feind weiter entfernt ist und Sie beispielsweise einen Pfeil werfen, spielen Sie den zweiten Ton (Pfeilschlag) erst, wenn der Pfeil das Ziel erreicht (wenn Sie Werfen als Zauber betrachten).
Wenn Sie es an einen Frame binden müssen (spielen Sie beispielsweise den "Explode" -Sound in 30 Frames unabhängig von den Echtzeit-Frameraten ab ), verwenden Sie am einfachsten Rückrufe . Rückrufe sind nur "Codeblöcke, die Sie in Zukunft ausführen möchten". Hier ist ein Beispiel für meinen Rückruferstellungs-Setter:
A
TimedCallback
ist nur ein Wrapper um astd::function
(oder Sie könnten ein Objective-C verwenden^{block}
. Dasstd::function
wird ausgeführt, wenn sein Frame aktiv ist.Eine andere Möglichkeit (weniger global) besteht darin, Ereignisse in Ihre Animation aufzunehmen . Wenn Sie also häufig bestimmte Sounds auf bestimmten Animationsframes abspielen müssen, speichern Sie a
map<int,Sound*>
in derAnimation
Klasse. Überprüfen Sie in jedem Frame der Animation, obSound*
für diesen Frame eine entsprechende Wiedergabe vorhanden ist .Sie können auch ein Objekt
map<int, std::function>
imAnimation
Objekt speichern , umfunction
während der Animation ein a zurückzurufen.quelle
{ 'images':'sprite-%02d.png', 'beginRange':1, 'endRange':32, 'sounds':{ 0 : 'startSpell.wav', 30 : 'impact.wav' } }
. Wenn sich Ihr Spiel in einem sehr frühen Stadium befindet und die Kompilierungszeit noch kurz ist, können Sie zunächst die Datenstrukturen fest codieren, um festzustellen, ob es funktioniert.So mache ich es, mache benutzerdefinierte Ereignis-Listener für meine Animationsklasse und lasse sie meinen Sound steuern. also wenn meine Animation gestartet wurde callback.start (); und starte meinen Sound in dieser Methode. Wenn meine Animation angehalten wurde, führen Sie callback.pause () aus. und pausiere den Ton. Wenn die Animation beendet ist, rufen Sie call.end () auf. und habe auch das Tonende.
aber für eine perfekte Synchronisation würde ich so weit gehen, Soundframes zu zählen und meinen Sound zu schlafen (anzuhalten), wenn es zu weit geht und dasselbe für meine Animation tun.
Ich musste das bis heute nie tun, weil der erste Vorschlag meine Bedürfnisse vorerst ganz gut befriedigt.
quelle