Apakah ada teknik standar untuk mengelola input dalam game besar. Saat ini, dalam proyek saya, semua penanganan input dilakukan dalam loop game, seperti:
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
exit = 1;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym){
case SDLK_c:
//do stuff
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
switch(event.button.button){
case SDL_BUTTON_MIDDLE:
//do stuff
break;
}
}
break;
}
(Saya menggunakan SDL, tapi saya berharap praktik utama berlaku pustaka dan kerangka kerja juga). Untuk proyek besar ini sepertinya bukan solusi terbaik. Saya mungkin memiliki beberapa objek yang ingin tahu apa yang ditekan oleh pengguna, jadi akan lebih masuk akal jika objek tersebut menangani input. Namun, mereka tidak semua dapat menangani input, karena setelah seseorang mendapatkan suatu peristiwa, itu akan dikeluarkan dari buffer acara, sehingga objek lain tidak akan menerima input itu. Metode apa yang paling umum digunakan untuk mengatasi ini?
Jawaban:
Sejak ditanya oleh thread starter, saya menguraikan manajer acara. Saya pikir ini adalah cara yang baik untuk menangani input dalam game.
Seorang manajer acara adalah kelas global yang memungkinkan untuk mendaftarkan fungsi panggilan balik ke tombol dan untuk mematikan panggilan balik itu. Manajer acara menyimpan fungsi terdaftar dalam daftar pribadi yang dikelompokkan berdasarkan kunci mereka. Setiap kali kunci dipecat, semua panggilan balik yang terdaftar dijalankan.
Callback bisa menjadi
std::function
objek yang bisa menampung lambdas. Kuncinya bisa berupa string. Karena pengelola bersifat global, komponen aplikasi Anda dapat mendaftar ke kunci yang dipecat dari komponen lain.Anda bahkan dapat memperluas pengelola acara ini untuk memungkinkan nilai yang lewat sebagai argumen tambahan. Templat C ++ bagus untuk ini. Anda dapat menggunakan sistem seperti itu untuk, katakanlah, untuk suatu
"WindowResize"
peristiwa lulus ukuran jendela baru, sehingga komponen mendengarkan tidak perlu mengambilnya sendiri. Ini dapat sedikit mengurangi ketergantungan kode.Saya telah mengimplementasikan palungan acara untuk permainan saya. Jika Anda tertarik, saya akan memposting tautan ke kode di sini.
Dengan menggunakan manajer acara, Anda dapat dengan mudah menyiarkan informasi input dalam aplikasi Anda. Selain itu, ini memungkinkan cara yang bagus untuk memungkinkan pengguna menyesuaikan binding kunci. Komponen mendengarkan acara semantik alih-alih kunci secara langsung (
"PlayerJump"
bukan"KeyPressedSpace"
). Kemudian Anda dapat memiliki komponen pemetaan input yang mendengarkan"KeyPressedSpace"
dan memicu tindakan apa pun yang terikat pengguna pada kunci itu.sumber
[=]
dan referensi ke semua variabel lokal yang diakses dari lambda akan disalin. Jadi Anda tidak harus melewati pointer ini atau yang seperti ini. Tetapi perhatikan bahwa Anda tidak dapat menyimpan lambdas dengan klausa penangkapan di pointer fungsi C lama . Namun, C ++std::function
berfungsi dengan baik.Membagi ini menjadi beberapa lapisan.
Pada lapisan terendah Anda memiliki peristiwa input mentah dari OS. Input keyboard SDL, input mouse, input joystick, dll. Anda mungkin memiliki beberapa platform (SDL adalah penyebut yang paling tidak umum yang tidak memiliki beberapa bentuk input, misalnya, yang mungkin nanti Anda pedulikan).
Anda dapat mengabstraksi ini dengan jenis acara khusus tingkat sangat rendah, seperti "tombol keyboard bawah" atau sejenisnya. Ketika lapisan platform Anda (loop game SDL) menerima input, itu harus membuat acara tingkat rendah ini dan kemudian meneruskannya ke manajer input. Hal ini dapat dilakukan dengan panggilan metode sederhana, fungsi panggilan balik, sistem acara yang rumit, apa pun yang paling Anda sukai.
Sistem input sekarang memiliki tugas menerjemahkan input tingkat rendah ke peristiwa logis tingkat tinggi. Logika game sama sekali tidak peduli bahwa SPACE ditekan. Itu peduli bahwa JUMP ditekan. Tugas manajer input adalah mengumpulkan acara input tingkat rendah ini dan menghasilkan acara input tingkat tinggi. Ini bertanggung jawab untuk mengetahui bahwa spasi dan tombol gamepad 'A' keduanya memetakan ke perintah logis Jump. Ini berkaitan dengan kontrol tampilan gamepad vs mouse dan sebagainya. Ini memancarkan peristiwa logis tingkat tinggi yang seabstrak mungkin dari kontrol tingkat rendah (ada beberapa batasan di sini, tetapi Anda bisa mengabstraksi berbagai hal secara menyeluruh dalam kasus umum).
Pengontrol karakter Anda kemudian menerima peristiwa ini dan memproses peristiwa input tingkat tinggi ini untuk benar-benar merespons. Lapisan platform mengirim acara "Key down spacebar." Sistem input menerima itu, melihat tabel pemetaan / logikanya, dan kemudian mengirimkan acara "Lompatan yang ditekan." Kontroler logika / karakter permainan menerima peristiwa itu, memeriksa apakah pemain benar-benar diizinkan untuk melompat, dan kemudian memancarkan peristiwa "Pemain melompat" (atau hanya secara langsung menyebabkan lompatan terjadi), yang digunakan oleh sisa logika permainan untuk melakukan apa pun .
Apa pun yang bergantung pada logika game masuk ke pengontrol pemain. Apa pun yang bergantung pada OS berlaku di lapisan platform. Semua sisanya masuk ke lapisan manajemen input.
Inilah beberapa seni ASCII amatir untuk menggambarkan ini:
sumber