Apa cara standar untuk menyinkronkan efek suara dengan animasi sprite?

8

Mari kita mengambil situasi di mana Anda memiliki RPG dengan mantra dan setiap animasi mantra memiliki jumlah bingkai yang berbeda dan mereka memiliki persyaratan yang sangat berbeda untuk efek suara. Mari kita asumsikan bahwa setiap mantra hanya memiliki 1 animasi berkelanjutan yang terkait dengannya (sebagai lawan dari beberapa potongan modular yang digunakan untuk membentuk animasi penuh) dari game 16-bit Final Fantasy lama.

Satu-satunya cara saya dapat memikirkan untuk memastikan bahwa suara dan animasi disinkronkan adalah dengan:

  • Dapatkan jumlah bingkai animasi.
  • Dapatkan waktu di antara setiap bingkai animasi. (jika 30 fps maka 1/30 detik per frame.)
  • Kemudian buat file suara yang panjangnya persis sama dengan animasi.

Jadi ini berarti bahwa jika animasi berdurasi 5 detik, berjalan pada 30 fps, dengan total 150 frame, file suara juga akan menjadi 5 detik. Jika animasi memiliki suara "benturan" pada bingkai ke-30, itu berarti file suara akan menyertakan suara benturan pada tanda 1,0 detik.

Pada akhirnya, kami memulai animasi dan efek suara pada waktu yang sama dan berharap bahwa frame dan suara sinkron.

Ini terdengar seperti itu dapat menimbulkan masalah ketika bingkai dilewati atau sesuatu terjadi selama animasi dan suara diputar sedikit terlalu cepat atau terlambat, dan akan menyebabkan suara dan animasi menjadi tidak selaras. Apakah ini pendekatan terbaik atau biasanya ada cara yang lebih baik yang tidak saya lihat?

Jawabannya tidak perlu untuk Cocos2D secara khusus jika konseptual, tetapi jika ada solusi spesifik untuk cocos2d, saya ingin mendengarnya.

EDIT: Saya juga baru menyadari bahwa dengan metode ini, jika kita masuk dan menyesuaikan jumlah frame atau waktu animasi nanti, kita juga harus kembali dan mengubah file suara. Ini kedengarannya seperti penyebab mengerikan kesalahan manusia (lupa memperbarui file suara setelah perubahan animasi.) Saya harap ada metode yang lebih baik di luar sana.

Jamornh
sumber
inilah mengapa loop permainan waktu konstan berguna: maka Anda tidak perlu khawatir tentang animasi tidak sinkron
ratchet freak
@ scratchetfreak Saya yakin cocos2d akan mengatur waktu animasi dengan benar. Jika saya membuat animasi dan memberi tahu cocos2d bahwa saya ingin tepat 1/30 detik di antara frame, itu akan memastikan ini dan melewati frame jika kinerjanya tidak cukup baik. Ini memastikan bahwa animasi selesai pada waktu yang tepat (yaitu dalam waktu yang konstan.) Mengingat, apakah Anda mengatakan bahwa metode yang saya uraikan di atas adalah cara yang tepat untuk pergi?
Jamornh

Jawaban:

6

Lakukan melalui acara.

Ejaan awal adalah suatu peristiwa . Mulai mainkan suara untuk acara itu.

Musuh yang terkena mantra juga merupakan peristiwa. Jika musuh lebih jauh dan Anda melempar panah, misalnya, Anda hanya memainkan suara kedua (panah memukul) setelah panah mencapai target (jika Anda menganggap Lempar sebagai mantra).

Jika Anda perlu mengikatnya ke sebuah bingkai (jadi misalnya, mainkan suara "meledak" 30 frame dari sekarang terlepas dari kecepatan bingkai real-time )), cara termudah untuk melakukannya adalah menggunakan callback . Callback hanyalah "blok kode yang Anda jadwalkan untuk dijalankan di masa mendatang". Ini adalah contoh pembuat kreasi callback saya:

- (void) addCallback:(Callback*)callback inHowManyTicks:(unsigned long long)execTicksIntoTheFuture
{
  callbacks.push_back( new TimedCallback( tick + execTicksIntoTheFuture, callback ) ) ;
}

A TimedCallbackhanyalah pembungkus di sekitar std::function(atau Anda bisa menggunakan Objective-C ^{block}. Ini std::functiondijalankan ketika bingkainya naik.

Cara lain (kurang global) adalah dengan memasukkan acara dalam animasi Anda . Jadi, jika Anda perlu sering memainkan suara pada frame animasi tertentu, maka simpan a map<int,Sound*>di Animationkelas. Pada setiap bingkai animasi, periksa apakah ada yang sesuai Sound*untuk bermain untuk Frame itu.

Anda juga bisa menyimpan a map<int, std::function>, di Animationobjek, yang akan memungkinkan Anda untuk memanggil kembali a functionselama animasi.

bobobobo
sumber
Saya pikir Anda mungkin salah menafsirkan pertanyaan itu sedikit. Metode Anda akan berfungsi untuk suara pendek yang dimaksudkan untuk jenis "pukulan", "memukul", "tendangan", "tembak" yang berlangsung tidak lebih dari sepersekian detik di mana sinkronisasi tidak menjadi masalah (Anda hanya dapat memainkan efek suara "pada Peristiwa "seperti yang Anda sarankan.) Namun dengan suara animasi + panjang (yaitu Armageddon, di mana 5-6 meteor jatuh dari langit dan menabrak tanah di frame yang berbeda, tetapi merupakan bagian dari 1 animasi sprite [seperti bagaimana fantasi terakhir melakukannya] hanya akan memiliki 1 acara mulai, bukan satu per meteorit) metode ini tidak akan memastikan sinkronisasi kan?
Jamornh
3
@Jamornh Dalam meteor shower contoh Anda menembak sebuah acara: untuk setiap meteor mulai jatuh, karena, setiap meteor mengenai tanah, mungkin satu untuk karakter yang berjuang melawan mantra. Menggunakan solusi ini, Anda bahkan dapat mengubah jumlah meteor dan tidak memiliki masalah dengan audio.
akaltar
1
@Jamornh Anda juga dapat mengantri acara untuk "memutar suara ledakan 30 frame dari sekarang", cara termudah untuk melakukannya adalah menggunakan fungsi panggilan balik . Saya akan menjelaskan ini dalam jawaban saya.
bobobobo
1
@Jamornh Animasi tidak harus modular untuk dapat memotret banyak acara (pada waktu yang telah ditentukan). Di editor efek Anda, Anda bisa mengatakan, mainkan suara booming di frame 32.
akaltar
1
Ya, itu akan berhasil. Jika Anda menggunakan JSON, saya akan menyarankan struktur data seperti { 'images':'sprite-%02d.png', 'beginRange':1, 'endRange':32, 'sounds':{ 0 : 'startSpell.wav', 30 : 'impact.wav' } }. Jika gim Anda masih sangat awal dan waktu kompilasi masih rendah, Anda bisa mulai dengan melakukan hardcoding pada struktur data untuk melihat apakah gim tersebut berfungsi.
bobobobo
1

Cara saya melakukannya adalah membuat pendengar acara khusus untuk kelas animasi saya dan minta mereka mengontrol suara saya. jadi jika animasi saya sudah mulai callback.start (); dan mulai suara saya dengan metode itu. jika animasi saya dijeda lakukan callback.pause (); dan jeda suara. ketika animasi telah berakhir, Anda panggil balik.end (); dan memiliki ujung suara juga.

tetapi untuk sinkronisasi yang sempurna saya akan pergi sejauh menghitung frame suara dan tidur (berhenti) suara saya jika sampai jauh di kepala dan melakukan hal yang sama untuk animasi saya.

Saya belum pernah melakukan itu sampai hari ini karena saran pertama memenuhi kebutuhan saya baik-baik saja untuk saat ini.

Jonathan Camarena
sumber
Bisakah Anda menguraikan bagaimana Anda akan menghitung "bingkai" suara? Apakah maksud Anda menghitung jumlah milidetik yang telah berlalu sejak suara dimulai dan melakukan hitungan per setiap interval yang telah ditentukan?
Jamornh
tidak tidak, saya benar-benar berarti frame pada suara. Saya tidak tahu bagaimana Anda melakukannya di cocos2D tetapi dalam suara java ada metode untuk mendapatkan suara framecount dan "frame" saat ini, ada juga cara untuk mengatur frame saat ini ke tertentu. Saya yakin jika Anda memeriksanya, Anda bisa menemukan variabel yang mirip di dalam antarmuka suara Anda, tetapi seperti yang ditunjukkan seseorang, yang terbaik adalah membuat pembaruan Anda menangani waktu animasi, dll. sehingga Anda tidak perlu melakukan peretasan sinkronisasi seperti itu.
Jonathan Camarena