Saat membuat game, Anda sering membuat objek game berikut dari mana semua entitas mewarisi:
public class GameObject{
abstract void Update(...);
abstract void Draw(...);
}
Jadi saat Anda memutakhirkan loop, Anda mengulangi semua objek game dan memberi mereka kesempatan untuk mengubah status, kemudian pada loop undian berikutnya Anda mengulangi lagi semua objek game dan memberi mereka kesempatan untuk menggambar sendiri.
Meskipun ini bekerja dengan cukup baik dalam game sederhana dengan renderer maju sederhana, ini sering mengarah ke beberapa objek game raksasa yang perlu menyimpan model mereka, beberapa tekstur dan yang terburuk dari semua metode penarikan lemak yang menciptakan hubungan yang erat antara objek game, strategi render saat ini dan setiap kelas terkait rendering.
Jika saya mengubah strategi render dari maju ke ditangguhkan saya harus memperbarui banyak objek game. Dan objek game yang saya buat tidak dapat digunakan kembali sebagaimana mestinya. Tentu saja warisan dan / atau komposisi dapat membantu saya melawan duplikasi kode dan membuatnya sedikit lebih mudah untuk mengubah implementasi tetapi masih terasa kurang.
Cara yang lebih baik, mungkin, akan menghapus metode Draw dari kelas GameObject sekaligus dan membuat kelas Renderer. GameObject masih perlu memuat beberapa data tentang visualnya, seperti apa model untuk mewakilinya dan tekstur apa yang harus dicat pada model, tetapi bagaimana ini dilakukan akan diserahkan kepada penyaji. Namun sering ada banyak kasus perbatasan dalam rendering sehingga meskipun ini akan menghapus kopling ketat dari GameObject ke Renderer, Renderer masih harus semua mengetahui tentang semua objek game yang akan membuatnya gemuk, semua yang tahu dan berpasangan erat. Ini akan melanggar beberapa praktik baik. Mungkin Data-Oriented-Design bisa melakukan trik. Objek game tentu saja data, tetapi bagaimana penyaji akan didorong oleh ini? Saya tidak yakin.
Jadi saya bingung dan tidak bisa memikirkan solusi yang baik. Saya sudah mencoba menggunakan prinsip-prinsip MVC dan di masa lalu saya punya beberapa ide tentang bagaimana menggunakannya dalam game, tetapi baru-baru ini sepertinya tidak berlaku seperti yang saya pikirkan. Saya ingin tahu bagaimana Anda semua mengatasi masalah ini.
Pokoknya mari kita rekap, saya tertarik pada bagaimana tujuan desain berikut dapat dicapai.
- Tidak ada render logika dalam objek game
- Kopling longgar antara objek game dan render engine
- Tidak semua penyaji yang tahu
- Lebih disukai runtime switching antara mesin render
Pengaturan proyek yang ideal adalah 'logika permainan' yang terpisah dan proyek logika render yang tidak perlu saling rujukan.
Train pemikiran ini semua dimulai ketika saya mendengar John Carmack mengatakan di twitter bahwa ia memiliki sistem yang sangat fleksibel sehingga ia dapat menukar mesin render pada saat run time dan bahkan dapat memberi tahu sistemnya untuk menggunakan kedua renderer (renderer perangkat lunak dan renderer yang dipercepat perangkat keras) pada saat yang sama sehingga dia dapat memeriksa perbedaan. Sistem yang saya programkan sejauh ini bahkan tidak sedekat itu fleksibel
sumber
Apa yang saya lakukan untuk mesin saya sendiri adalah mengelompokkan semuanya menjadi modul. Jadi saya memiliki
GameObject
kelas saya dan memegang pegangan untuk:Jadi saya punya
Player
kelas danBullet
kelas. Keduanya berasal dariGameObject
dan ditambahkan keScene
. TetapiPlayer
memiliki modul-modul berikut:Dan
Bullet
memiliki modul-modul ini:Cara mengatur hal-hal ini menghindari "Diamond of Death" di mana Anda memiliki
Vehicle
,VehicleLand
danVehicleWater
dan sekarang Anda menginginkannyaVehicleAmphibious
. Sebaliknya Anda memilikiVehicle
dan dapat memilikiModuleWater
danModuleLand
.Bonus tambahan: Anda dapat membuat objek menggunakan serangkaian properti. Yang perlu Anda ketahui adalah tipe dasar (Player, Musuh, Bullet, dll.) Dan kemudian buat pegangan untuk modul yang Anda butuhkan untuk tipe itu.
Dalam Adegan saya, saya melakukan hal berikut:
Update
untuk semuaGameObject
pegangan.ModuleCollision
pegangan.UpdatePost
semuaGameObject
pegangan untuk memberi tahu posisi akhir mereka setelah fisika.m_ObjectsCreated
daftar kem_Objects
daftar.Dan saya bisa mengaturnya lebih lanjut: dengan modul bukan dengan objek. Lalu saya akan membuat daftar
ModuleSprite
, memperbarui banyakModuleScriptingBase
dan melakukan tabrakan dengan daftarModuleCollision
.sumber
GameObject
(misalnya cara untuk membuat "ular" Sprite), Anda harus membuat anakModuleSprite
untuk fungsionalitas tertentu (ModuleSpriteSnake
) atau menambahkan modul baru sama sekali (ModuleSnake
). Untungnya mereka hanya petunjuk, tetapi saya telah melihat kode di manaGameObject
benar-benar semua yang dapat dilakukan objek.