Penanganan input dalam desain berbasis komponen

12

Saya tahu pertanyaan ini telah ditanyakan beberapa kali, tetapi saya masih tidak yakin bagaimana menerapkan penanganan input pada mesin berbasis komponen.

Desain berbasis komponen yang saya gunakan didasarkan pada seri blog T = Machine dan pada Artemis di mana Entitas hanya id.

Ada tiga ide utama yang saya miliki dalam menerapkan penanganan input:

  1. Komponen input akan mengadakan acara yang menarik. Sistem input akan menerjemahkan peristiwa kunci dan mouse ke peristiwa permainan dan loop melalui entitas dengan komponen input dan jika mereka tertarik pada acara tersebut tindakan yang tepat akan diambil oleh sistem input. Tindakan ini akan sulit dikodekan ke sistem input.
  2. Tidak ada komponen input. Anda akan mendaftarkan entitas dengan acara khusus ke sistem input. Sistem input kemudian akan mengirim pesan (dengan id entitas dan tipe acara) ke sistem lain sehingga ini dapat mengambil tindakan yang sesuai. Atau seperti dalam kasus pertama, tindakan akan dikodekan ke sistem input.
  3. Mirip dengan metode pertama, tetapi alih-alih mengkodekan tindakan ke sistem input, komponen akan berisi peta peristiwa ke fungsi (yaitu std::map<std::function>) yang akan dipanggil oleh sistem input. Ini memiliki efek tambahan karena bisa memasangkan acara yang sama ke tindakan yang berbeda.

Apakah Anda merekomendasikan salah satu metode di atas atau apakah Anda memiliki saran yang akan membantu saya menerapkan sistem penanganan input yang fleksibel? Juga, saya belum terbiasa dengan multi-threading tetapi saran yang akan membuat implementasi thread-friendly juga diterima.

Catatan: Satu persyaratan tambahan yang ingin saya penuhi dari implementasi adalah bahwa saya dapat memberikan input yang sama ke banyak entitas, seperti misalnya memindahkan entitas kamera dan pemain pada saat yang sama.

Grieverheart
sumber
2
Biasanya (ketika kamera mengikuti pemain) Anda tidak ingin menerima input dalam kamera, Anda justru membuat kamera memeriksa posisi pemain dan mengikutinya.
Luke B.
1
Tidak masalah secara konseptual jika kamera mengikuti pemain, atau "itu sendiri". Meskipun demikian, saya tidak yakin bagaimana saran Anda akan diimplementasikan dalam desain berbasis komponen tanpa melanggar prinsip-prinsip desain.
Grieverheart
1
@ Lukas B .: Setelah memikirkannya, saya melihat bahwa Anda juga bisa menjadikan kamera sebagai kelas yang terpisah, dengan mengambil pointer ke suatu entitas untuk diikuti.
Grieverheart

Jawaban:

8

Saya pikir, sama seperti jawaban saya mengenai materi dalam sistem komponen , Anda mengalami masalah di mana Anda mencoba untuk mendorong semuanya menjadi "komponen." Anda tidak perlu melakukan ini dan dengan melakukan itu Anda mungkin membuat antarmuka yang benar-benar rumit dengan mencoba memasukkan sekelompok pasak persegi ke dalam lubang bundar.

Sepertinya Anda sudah memiliki sistem yang menangani perolehan input dari pemain. Saya akan memilih pendekatan yang kemudian menerjemahkan input itu ke dalam tindakan ("bergerak maju," atau "mundur") atau acara dan mengirimkannya ke pihak yang berkepentingan. Di masa lalu, saya melarang komponen mendaftarkan diri untuk peristiwa ini, lebih memilih pendekatan di mana sistem tingkat yang lebih tinggi secara eksplisit memilih "entitas yang dikendalikan." Tapi itu bisa bekerja dengan cara lain jika Anda mau, terutama jika Anda akan menggunakan kembali pesan yang sama untuk mengambil tindakan yang tidak dirangsang secara langsung oleh input.

Saya tidak akan menyarankan menerapkan perilaku mengikuti kamera dengan meminta entitas kamera dan entitas pemain merespons pesan "bergerak maju" (dan lain-lain). Ini menciptakan koneksi yang sangat kaku antara dua objek yang kemungkinan tidak akan terasa enak bagi pemain, dan itu juga membuatnya sedikit lebih sulit untuk menangani hal-hal seperti memiliki kamera yang mengorbit pemain ketika pemain berputar ke kiri atau kanan: Anda memiliki entitas merespons "putar ke kiri" dengan mengasumsikan bahwa slave adalah milik pemain, tetapi itu berarti ia tidak dapat merespons dengan benar jika tidak pernah diselamatkan ... kecuali jika Anda memperkenalkan konsep itu karena beberapa negara bagian dapat Anda periksa. Dan jika Anda akan melakukan itu, Anda mungkin juga menerapkan sistem yang tepat untuk mengikat dua benda fisik bersama-sama, lengkap dengan tweakable elastisitas yang sesuai dan sebagainya.

Mengenai multi-threading, saya tidak benar-benar melihat kebutuhan untuk menggunakannya di sini karena kemungkinan akan menyebabkan lebih banyak komplikasi daripada nilainya, dan Anda sedang berhadapan dengan masalah serial yang inheren sehingga Anda hanya perlu melibatkan banyak utas primitif sinkronisasi.

Komunitas
sumber
Saya memikirkan pertanyaan saya dan akan menjawabnya sendiri. Saya juga sampai pada kesimpulan bahwa saya harus lebih baik decoupling penanganan input dari sistem EC sehingga senang melihat konfirmasi ini. Bagaimana saya berpikir untuk melakukan ini adalah dengan menggunakan sinyal dan kemampuan untuk mengaitkan beberapa entitas dengan jenis peristiwa. Saya juga memutuskan untuk memisahkan kamera, meskipun ini tidak benar-benar diperlukan dan menjadikannya sebagai entitas yang sama-sama layak. Saya pikir ketika masih menjadi pemula dengan EC Anda benar-benar harus berpikir apa manfaatnya membuat sesuatu komponen atau entitas.
Grieverheart
4

Pengalaman saya mungkin bias tetapi dalam proyek multi platform perangkat input tidak langsung terkena sistem entitas.

Perangkat input ditangani oleh sistem level bawah yang menerima acara dari tombol, tombol, sumbu, mouse, permukaan sentuh, akselerometer ...

Peristiwa ini kemudian dikirim melalui lapisan generator niat niat konteks.

Setiap generator mendaftar untuk perubahan sate dari komponen, entitas dan sistem yang relevan dengan fungsinya.

Generator ini kemudian mengirim pesan / niat untuk dirutekan ke sistem niat di mana entitas memiliki komponen atau langsung ke komponen yang tepat.

Dengan cara ini Anda cukup mengandalkan "selalu" memiliki input yang sama yaitu JUMP_INTENT (1), JUMP_INTENT (0), AIM_INTENT (1) ...

Dan "semua" pekerjaan input bergantung platform kotor tetap berada di luar sistem entitas Anda.


Mengenai kamera jika Anda ingin memindahkannya di sekitar pemain itu dapat mendaftarkan komponen niatnya sendiri dan mendengarkan maksud yang akan Anda kirim.

Kalau tidak, jika mengikuti pemain, jangan pernah mendengarkan input yang ditujukan kepada pemain. Seharusnya mendengarkan perubahan status yang dipancarkan oleh pemain (ENTITY_MOVED (transform)) ... dan bergerak sesuai itu. Jika Anda menggunakan sistem fisika, Anda bahkan dapat memasang kamera ke pemain menggunakan salah satu dari berbagai sendi.

Anjing hutan
sumber
Coyote, terima kasih atas jawaban Anda. Saya juga membaca posting Anda yang lain di sini . Kekhawatiran terbesar saya bukanlah bagaimana mengabstraksi input. Saya sudah memiliki tingkat konstruksi yang lebih rendah yang menangani penekanan tombol dan semacamnya, dan menambahkan satu tingkat tipuan tidak akan sulit. Masalah saya adalah dalam menangani peristiwa yang dihasilkan oleh misalnya sistem niat Anda. Jika saya mengerti dengan benar, Anda tidak memiliki komponen input sama sekali dalam metode Anda. Bagaimana Anda tahu entitas mana yang perlu input dan bagaimana Anda menanganinya? Bisakah Anda memberikan beberapa contoh nyata?
Grieverheart
2

Apa manfaat yang dibawa oleh inputComponent? Tentunya itu adalah hak prerogatif dari perintah input untuk memutuskan entitas apa yang melakukan tindakan. Contoh klasik adalah membuat pemain melompat. Alih-alih memiliki InputComponent pada setiap entitas mendengarkan acara "Jump", mengapa tidak meminta perintah melompat mencari entitas yang ditandai "pemain" dan melakukan logika yang diperlukan itu sendiri?

Action jump = () =>
{
    entities["player"].Transform.Velocity.Y += 5;
};

Contoh lain, dari OP:

Action moveRight = () =>
{
    foreach (var entity in entities.Tagged("player", "camera"))
        entity.Transform.Position.X += 5;
};
AlexFoxGill
sumber