Status permainan dan penanganan input dalam sistem entitas berbasis komponen

16

Pertanyaanku adalah:

Bagaimana saya bisa menangani keadaan gim dalam sistem entitas saya, tanpa menggunakan tumpukan benda keadaan gim di sekitar?

Jadi desain sistem entitas saya berarti bahwa ketika entitas perlu mendaftar untuk acara input misalnya, komponen input memanggil sistem input dan mengatakan "daftarkan entitas ini untuk input ini". Ini semua baik-baik saja dan baik, namun jika Anda menambahkan ke dalam konsep ini kondisi permainan (katakanlah layar jeda), itu menjadi masalah untuk diselesaikan jika suatu entitas berada dalam kondisi saat ini dan harus menerima input.

Saya dapat menambah komponen input / sistem sehingga dikatakan, "daftarkan entitas ini untuk input ini saat berada di status permainan ini", tetapi ini mengharuskan setiap entitas tahu di mana menyatakan akan digunakan, dan itu mungkin tidak jelas. Selain itu, menjaga daftar status permainan sekitar per input yang terdaftar (dan sistem lain yang menggunakan panggilan balik) kedengarannya tidak terlalu efisien.

Gagasan lain yang saya miliki adalah karena akan ada entitas yang mewakili kondisi permainan, tandai sebagai dinonaktifkan, lalu saat membuat acara masukan, periksa apakah entitas tersebut bukan turunan dari entitas kondisi permainan yang dinonaktifkan. Tampaknya mahal untuk melatih orang tua untuk setiap panggilan balik.

Gagasan lain adalah membuat semua sistem menyimpan data mereka dikunci melawan keadaan saat ini, sehingga ketika menghasilkan input, entitas target bahkan tidak akan menjadi kandidat. Namun ini benar-benar menyakiti kemampuan untuk memungkinkan komunikasi antara entitas di negara yang berbeda (tidak begitu menjadi masalah untuk layar jeda, tetapi berpikir memilih kunci di Oblivion / Skyrim).

Satu-satunya ide lain yang saya miliki adalah meminta semua komponen menangani perubahan keadaan dan berkomunikasi dengan sistem yang relevan untuk menonaktifkan apa pun yang telah mereka daftarkan, dan mengaktifkannya kembali ketika beralih kembali ke keadaan ini.

Yang kedua (tandai objek sebagai dinonaktifkan) dan sebagainya (masing-masing komponen berurusan dengan perubahan keadaan) tampak seperti yang terbaik dari ide-ide saya, tetapi tidak satu pun dari mereka yang menganggap saya sangat hebat.

Apakah ada orang lain yang punya ide lain tentang cara melakukan ini?

sunting Sementara saya berbicara tentang input secara khusus dalam pertanyaan ini, ini dapat berarti sistem apa pun yang mampu mengirim pesan / acara ke entitas, seperti tabrakan, acara pengatur waktu, dll ...

elFarto
sumber
6
Saya melakukannya seperti ini: Saya memiliki Layar, MenuScreen PauseScreen GameScreen, setiap layar dapat membuat Dunia sendiri (wadah untuk Entitas) dan sistem (seperti RenderingSystem) dan kemudian di GameScreen saya membuat Dunia, Entitas dengan CameraComponent, dan mengatur CameraComponent.RenderTarget ke latar belakang layar. Dengan cara ini saya dapat menambahkan InventoryScreen yang akan memiliki entitas dan sistem sendiri (seperti renderer yang disederhanakan). Input dapat diteruskan dari layar ke dunia, sehingga antarmuka pengguna Anda akan memutuskan apakah akan meneruskan input ke layar (jika fokus, terlihat, dll.) Dan itu akan meneruskan input ke dunia dan entitas
Kikaimaru
2
@ Byte56 Tidak juga, hanya yang pertama berkaitan dengan gamestate (2 lainnya adalah status dalam entitas), dan itu tidak benar-benar menangani masalah yang sama yang saya alami. Ketika permainan dalam keadaan jeda, sesuatu harus terjadi pada sistem input untuk menghentikannya mengirim pesan gerakan ke entitas pemain (misalnya), saya tidak bisa menemukan cara yang baik untuk melakukan ini.
elFarto
1
OK, anggap mereka terkait kemudian. Pertanyaan bagus.
MichaelHouse
1
Sesuatu yang perlu diperhitungkan yang telah mengganggu sistem berbasis komponen saya di masa lalu: multi-layer UI. Dialog poping di atas layar dunia atau multi-level. Itu telah muncul sejauh ini di setiap game yang telah saya buat jadi saya akan mengatakan untuk memastikan untuk mempertimbangkan pendekatan yang dapat menyelesaikan masalah itu.
ADB

Jawaban:

14

Apa yang sering digunakan adalah perantara Intent Systemyang mengabstraksi input dan melacak konteks dan gamestate yang relevan.

Sistem Intent akan berhenti mengirimkan input ketika simulasi dijeda misalnya. Ini juga menangani pemetaan antara peristiwa dan niat pengontrol (bergerak ke arah, menjalankan, menembak, memuat ulang ...).

Dengan cara ini, pelanggan Anda yang lain tidak bergantung pada gamepad / input tertentu (BUTTON_A, BUTTON_B vs BUTTON_X, BUTTON_O ...) tetapi mereka semua bereaksi terhadap maksud yang sama (IntentRun, IntentReload ...).

Keuntungan lain adalah bahwa sistem niat dapat menyadari adanya pengendali yang ditambahkan / dihapus, karena dapat mengirim maksud ke pelanggan apa pun bahkan di luar simulasi Anda dapat menangani maksud seperti itu AddPlayer(controllerID).

Berapa banyak informasi tentang status permainan yang Anda berikan ke sistem baik melalui acara / pesan atau langsung terserah Anda. Tetapi waktu yang diinvestasikan dalam sistem Intent biasanya sepadan.

Anda dapat mengelola Konteks Intent yang akan menghasilkan intents ketika mereka dilampirkan ke sistem.

Konteksnya dapat diprioritaskan, yaitu:

  • SimulasiTersediaKonteks mengirimkan maksud ke simulasi saat tersedia (tetapi tidak berjalan) misalnya memindahkan kamera, memperbesar zoom out, menambah / menghapus pemain ...
  • SimulationRunningContext mengirim niat ke simulasi sementara itu tidak dihentikan, pindahkan pemain, kirim unit ke posisi, tembak ...

Dengan cara ini Anda dapat menambah dan menghapus konteks yang saat ini relevan.

Dan satu hal tentang seluruh sistem maksud adalah bahwa ia harus berjalan saat simulasi dijeda.

Salah satu cara yang sering digunakan untuk memainkan / menghentikan sementara simulasi permainan tanpa memutakhirkan pembaruan yang tidak terkait simulasi adalah dengan menggunakan rangkaian waktu yang berbeda. yaituGenericSystem::onTime(Long time, Long deltaTime, Long simTime, Long simDeltaTime) .

Dengan pendekatan ini, mesin Anda dapat dengan mudah memblokir kenaikan pada simTime gim yang pada gilirannya akan memblokir pembaruan pada animasi & mesin fisika yang relevan yang menggunakan simTime and simDeltaTimesementara memungkinkan pembaruan terus menerus dari efek pegas kamera Anda jika harus bergerak bahkan selama jeda, animasi dari efek pemuatan pada papan iklan dalam game virtual saat data sedang diunduh ...

Anjing hutan
sumber
Saya suka fakta bahwa ini tidak harus memanggil banyak fungsi "State Changed" pada semua entitas. Anda harus khawatir tentang maksud salah yang dikirim pada waktu yang salah, tetapi saya pikir itu lebih baik daripada alternatifnya.
Thomas Marnell
entitas Anda dapat mengabaikan maksud seperti Lompat sementara negara mereka tidak mengizinkannya untuk melompat (yaitu tidak menyentuh tanah). tetapi mereka tidak perlu khawatir tentang menerima niat seperti itu saat permainan dijeda.
Coyote
Saya sudah berpikir untuk membiarkan entitas memberi tahu sistem input tentang status pengiriman pesan, tetapi saya tidak berpikir untuk memasukkan status pada input itu sendiri, yang merupakan ide bagus. Juga membagi waktu dan memisahkan simTime juga bagus.
elFarto
Anda harus menghindari kembung keadaan terkait simulasi Anda dengan hal-hal terkait non simulasi. Pindahkan semua UI, dan kode terkait pemain sejauh mungkin dari simulasi itu sendiri dan dalam simulasi hanya berkonsentrasi pada maksud.
Coyote
Hey @Coyote, sistem ini kedengarannya sangat menarik. Bisakah Anda memberikan lebih banyak informasi dengan menjawab pertanyaan ini ? Terima kasih!
pek
2

Bagaimana dengan membuat sistem acara global dan kemudian memiliki komponen pendengar acara untuk masing-masing entitas Anda? Setelah acara "Perubahan Status Game" Anda dapat bermain-main dengan komponen secara individual untuk setiap entitas tertentu.

Katakanlah Anda memiliki komponen input. Setelah komponen pendengar acara menerima acara perubahan kondisi permainan, itu mengubah nilai yang sangat spesifik untuk komponen input tertentu, sehingga tidak akan menerima panggilan input apa pun atau tidak akan membuat gerakan atau panggilan respons apa pun ke sistem atau pemiliknya.

Ini berfungsi untuk saya karena sebagian besar komponen saya ditulis (melalui Lua). Yaitu saya memiliki komponen input, yang dipicu sekali ketika tombol ditekan dan itu api dari gerakan + arah dan kemudian dipicu ketika kunci dilepaskan dan itu api dari arah + berhenti. Ada juga komponen pendengar acara yang menghubungi komponen input (jika permainan dijeda) untuk berhenti melakukan fungsi menembak dan berhenti jika perlu. Saya kemudian dapat dengan mudah menambahkan entitas lain dengan reaksi berbeda terhadap peristiwa yang sama dan penekanan tombol menggunakan skrip lain. Dengan cara ini Anda akan menyimpan interaksi antara entitas yang berbeda di negara bagian yang berbeda dan bahkan membuatnya lebih dapat disesuaikan. Terlebih lagi, beberapa entitas bahkan mungkin tidak memiliki komponen pendengar acara di dalamnya.

Apa yang baru saja saya jelaskan pada dasarnya adalah contoh praktis dari solusi keempat Anda.

karmalis
sumber