Judulnya agak membingungkan, tetapi saya tidak bisa memikirkan bagaimana menjelaskan pertanyaan saya dalam frasa singkat. Jadi begini:
Setiap kali saya menulis mesin permainan, apakah itu fisika / dll berbasis, saya selalu sampai pada titik di mana saya tidak yakin bagaimana saya harus mengatur sesuatu. Haruskah entitas di dunia menangani sendiri, atau haruskah ada sistem global yang mengelolanya?
Ini contoh mudahnya: Memindahkan barang. Haruskah setiap objek melihat dunia di sekitarnya (periksa tabrakan) dan bergerak berdasarkan itu.
[perhatikan, ini adalah game berbasis ubin tempat objek bergerak per ubin, jadi saya tidak menggunakan fisika untuk berpindah dari ubin ke ubin]
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
if (world.getTile(location) != solid && world.objAtTile(location) == null)
{
Tweener.addTween(this, location);
}
}
}
Atau haruskah pergerakan setiap benda ditangani di dunia, di mana dunia memeriksa semuanya?
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
world.moveTo(location);
}
}
public class World
{
public void moveObject(GameObject obj, Vector2 location)
{
//called from object
if (getTile(location) != solid && objAtTile(location) == null)
{
Tweener.addTween(obj, location);
}
}
}
Saya kira tidak terlalu penting untuk contoh ini, tetapi saya bisa melihat diri saya mendapat masalah nanti. Terima kasih sebelumnya.
sumber
Actor
tahuworld
sama sekali?Jawaban:
Saya melihat contoh Anda di Jawa, tetapi tag Anda tidak menentukan bahasa apa pun. Dalam C ++, jawabannya adalah tidak - Anda tidak boleh menggunakan fungsi anggota untuk ini!
sumber
Tidak ada jawaban sederhana.
Seperti kebanyakan hal dalam pemrograman, ini merupakan trade off. Memberi lebih banyak daya ke objek individual membuatnya lebih besar - dan karenanya lebih lambat - tetapi membuat mesin lebih mudah dipahami dan diperluas. Memiliki kelas mega yang dapat menangani semuanya bersama mungkin lebih cepat, tetapi dengan biaya memiliki kelas mega; yaitu, umumnya dianggap bentuk buruk untuk membuat kelas supermasif.
Saya telah membaca beberapa artikel tentang komponen dan desain berbasis data, di mana Anda memiliki kelas tunggal yang mewakili semua objek dari jenis tertentu, menyimpan data mereka dalam daftar, dan hanya membagikan indeks untuk mendapatkan properti dari objek individual. Meskipun saya bisa melihat ini sebagai jenis arsitektur yang layak, saya merasa itu agak kacau dengan seluruh titik orientasi objek, yang juga mendapat banyak kritik.
Saya pribadi merekomendasikan memberi lebih banyak kekuatan ke objek. Itu lebih masuk akal dalam bahasa berorientasi objek, dan (saya akan membayangkan) lebih mudah untuk memahami dan memelihara dari waktu ke waktu.
sumber
Saya memperbarui jawaban saya karena banyak hal yang tidak jelas sebelum komentar. Tolong telanjang dengan saya saat saya menjelaskan pikiran saya.
Secara umum, dua aspek utama untuk dipertimbangkan dalam desain apa pun adalah kohesi dan kopling . Kita semua tahu bahwa kita membutuhkan kohesi yang tinggi dan kopling yang rendah untuk dapat membuat desain yang lebih dapat digunakan kembali dan diperluas.
Jadi, jika dunia harus mengatur segalanya, itu berarti ia memiliki kohesi yang rendah dan kopling yang ketat (karena itu perlu mengetahui dan melakukan segalanya). Namun, ini juga merupakan kasus ketika entitas game harus melakukan segalanya. Perbarui lokasinya, render teksturnya, dll. Dll
Apa yang benar-benar Anda minati adalah menciptakan sistem yang fokus pada satu aspek entitas. Misalnya, entitas game dapat memiliki Tekstur, tetapi Renderer akan bertanggung jawab untuk membuat tekstur itu di layar. Renderer tidak peduli dengan properti lain yang dimiliki entitas.
Mengambil sedikit lebih jauh, entitas permainan hanyalah sekumpulan properti. Properti ini dimanipulasi oleh sistem yang berfokus pada properti tertentu. Dan ini adalah tempat Sistem Entitas Berbasis Komponen (CBES) masuk, di mana properti = komponen.
Secara khusus, CBES dengan Sistem (atau SubSistem). Desain ini cenderung memiliki beberapa Sistem yang berfokus pada komponen spesifik suatu entitas sementara tidak peduli tentang apa komponen lain yang dimiliki entitas. Juga, Sistem hanya digabungkan dengan informasi yang mereka butuhkan untuk memproses komponen-komponen ini.
Mari kita ambil contoh. Karena input tempat untuk memindahkan entitas didasarkan pada pengontrol pemain, Anda mungkin akan memiliki PlayerControllerSystem. Sistem ini, akan mengendalikan, terlepas dari banyak hal lain, PositionComponent entitas. Dalam hal ini, PlayerControllerSystem perlu mengetahui tentang Level dan PositionComponent. Jika nanti Anda memutuskan untuk menambahkan deteksi tabrakan, Anda akan membuat CollisionSystem yang akan lagi menggunakan posisi entitas, tetapi kali ini untuk menghitung kotak pembatas (atau Anda bisa memiliki BoundingBoxComponent, panggilan Anda). Faktanya adalah, Anda dapat dengan mudah mengaktifkan atau menonaktifkan perilaku (bahkan dengan cepat) hanya dengan menambahkan / menghapus komponen. Jadi, lebih banyak perilaku berarti lebih banyak sistem memanipulasi komponen suatu entitas, tetapi mereka semua berada dalam kelas yang didefinisikan dengan baik dengan kopling rendah. Ingin membuat skrip? Tambahkan ScriptComponent. BAM! Anda baru saja menambahkan kemampuan scripting dengan 2 kelas. Fisika? Suara? Sama lagi.
Jadi, alasan saya mengadvokasi CBES dengan SubSystems adalah bahwa itu adalah OO yang sempurna dan keseluruhan sistem yang mudah dikelola / diperluas. Menambahkan perilaku ke suatu entitas sesederhana memutuskan data apa yang dibutuhkan perilaku dan entitas mana yang membutuhkannya.
Untuk informasi lebih lanjut tentang Sistem Entitas berbasis Komponen dengan SubSistem, ada serangkaian posting blog yang sangat baik oleh T = Machine di Entity Systems adalah masa depan pengembangan MMOG . Penulis bahkan membuat wiki untuk mengumpulkan berbagai implementasi bernama Entity Systems Project
Pos umum (dan terkenal) tentang Sistem Entitas Berbasis Komponen secara umum adalah Evolve hierarki Anda yang menciptakan sistem untuk Tony Hawk Pro.
Akhirnya, jika Anda mencari perpustakaan dengan kode contoh, jangan melangkah lebih jauh dari perpustakaan Artemis . Artemis terutama di Jawa tetapi di sini adalah port di C # (yang saat ini saya gunakan dalam proyek XNA saya).
sumber
Saya biasanya pergi dengan desain di mana objek menangani diri mereka sendiri (itu adalah metode untuk, setelah semua) tetapi Dunia dasar memiliki daftar semua objek dan menggunakan daftar tersebut untuk mengoordinasikannya. Jadi sesuatu seperti:
sumber
Tetap KERING, pemalu dan beri tahu orang lain.
Lebih baik meminta dunia untuk memindahkan aktor Anda daripada bertanya kepada dunia apakah Anda bisa pindah ke tempat yang ingin Anda tuju. Dengan cara ini Anda dapat mengubah algoritme pathfinding dengan mudah di kelas dunia dan semacamnya. Tentu saja, Anda bisa menyerahkan ini pada baseclass untuk aktor, tapi itulah arahan yang akan saya ambil dan alasan mengapa.
sumber
EDIT: Ditulis ulang karena umpan balik yang menyatakan saya belum menarik garis yang cukup jelas untuk jawaban pertanyaan awal ini.
Saya ingin mengklarifikasi pertanyaan sedikit lebih banyak jika memungkinkan. Haruskah logika yang bertindak atas suatu objek bersifat internal atau eksternal terhadap objek itu. Bagian terakhir dari pos secara khusus menyebutkan tentang umur panjang desain sebagai dasar untuk mengajukan pertanyaan, untuk menghindari masalah di kemudian hari.
Jawaban tingkat tinggi sederhana saya adalah untuk menjaga semua logika yang bertindak atas suatu objek di dalam objek itu.
Anda tidak perlu dunia untuk memindahkan objek, yang Anda butuhkan hanyalah objek yang akan dipindahkan dan vektor yang mewakili lokasi untuk dipindahkan. Dunia mungkin ikut bermain ketika suatu destinasi dipilih atau ketika reaksi terhadap lingkungan diperlukan karena tabrakan, tetapi itu adalah di luar contoh yang diberikan untuk dikerjakan.
Untuk mengatasi bagian mendasar dari pertanyaan dan mencapai umur panjang dari desain saya akan menyarankan arsitektur berorientasi komponen. Arsitektur komponen memecah suatu objek menjadi set data dan fungsionalitas diskrit (dengan asumsi Anda pergi dengan jawaban saya di atas yang menyatakan untuk menjaga logika dengan data). Jika struktur Anda terlihat seperti CEntity-> CHuman-> CSoldier-> CPlayerCharacter maka Anda akan selalu masuk ke masalah di mana Anda perlu mengubah beberapa logika dan tergantung di mana masuknya pohon itu (Berapa banyak jenis manusia yang ada misalnya?) itu dapat memiliki efek menyapu pada beberapa jenis objek.
Sistem komponen sebaliknya akan memiliki satu set antarmuka yang mendefinisikan objek CEntity terdiri dari seperti ICompRenderable, ICompMoveable, ICompHealth, ICompInventory dan sebagainya. Di mana Anda memiliki CCompMoveableHuman dan mungkin CCompMoveableSoldier dan CCompMoveablePlayer untuk menjaga pola gerakan masing-masing terpisah. Jadi katakanlah Prajurit diubah untuk berlari dalam formasi. Perubahan ini hanya akan memengaruhi entitas yang dibangun menggunakan komponen itu.
Jadi, singkatnya saya sarankan Anda mengandung logika dengan data yang berlaku untuk logika. Saya juga merekomendasikan memecah benda menjadi komponen diskrit untuk mengurangi 'Di mana saya meletakkan ini?' pertanyaan dan memberikan stabilitas ke masa depan dengan kemudahan perawatan dan diperpanjang.
Semoga ini membantu.
sumber
Saya sarankan Anda mencoba membaca tentang arsitektur berbasis komponen. Ada beberapa posting blog, presentasi dan menulis di luar sana tentang mereka yang dapat melakukan pekerjaan yang lebih baik daripada yang pernah saya bisa.
AltDevBlogADay memiliki beberapa posting tentang hal itu, yang sangat bagus adalah seri ini tentang entitas game: http://altdevblogaday.com/2011/07/10/the-game-entity-–-part-ia-retrospect/ Ada beberapa bagian yang fokus pada masalah yang Anda coba selesaikan.
sumber