Ini adalah tindak lanjut dari pertanyaan ini , yang saya jawab, tetapi yang satu ini membahas topik yang jauh lebih spesifik.
Jawaban ini membantu saya memahami Sistem Entitas lebih baik daripada artikel.
Saya telah membaca (ya,) artikel tentang Sistem Entitas, dan itu memberi tahu saya hal berikut:
Entitas hanyalah id dan array komponen (artikel mengatakan bahwa menyimpan entitas dalam komponen bukanlah cara yang baik untuk melakukan sesuatu, tetapi tidak memberikan alternatif).
Komponen adalah potongan data, yang menunjukkan apa yang dapat dilakukan dengan entitas tertentu.
Sistem adalah "metode", mereka melakukan manipulasi data pada entitas.
Ini tampaknya sangat praktis dalam banyak situasi, tetapi bagian tentang komponen yang hanya kelas data mengganggu saya. Sebagai contoh, bagaimana saya bisa mengimplementasikan kelas Vector2D (Posisi) saya di Sistem Entitas?
Kelas Vector2D menyimpan data: koordinat x dan y, tetapi juga memiliki metode , yang sangat penting untuk kegunaannya dan membedakan kelas dari hanya dua elemen array. Metode contoh adalah: add()
, rotate(point, r, angle)
, substract()
, normalize()
, dan semua standar lainnya, metode yang berguna, dan benar-benar diperlukan bahwa posisi (yang merupakan contoh dari kelas Vector2D) harus memiliki.
Jika komponen itu hanya pemegang data, itu tidak akan dapat memiliki metode ini!
Salah satu solusi yang mungkin muncul adalah dengan mengimplementasikannya di dalam sistem, tetapi itu tampaknya sangat kontra-intuitif. Metode-metode ini adalah hal-hal yang ingin saya lakukan sekarang , membuatnya lengkap dan siap digunakan. Saya tidak ingin menunggu MovementSystem
sampai membaca beberapa set pesan mahal yang menginstruksikannya untuk melakukan perhitungan pada posisi suatu entitas!
Dan, artikel itu dengan sangat jelas menyatakan bahwa hanya sistem yang harus memiliki fungsionalitas apa pun , dan satu-satunya penjelasan untuk itu, yang dapat saya temukan, adalah "untuk menghindari OOP". Pertama-tama, saya tidak mengerti mengapa saya harus menahan diri dari menggunakan metode dalam entitas dan komponen. Memori overhead praktis sama, dan ketika digabungkan dengan sistem ini harus sangat mudah diimplementasikan dan digabungkan dengan cara yang menarik. Sistem, misalnya, hanya bisa memberikan logika dasar untuk entitas / komponen, yang mengetahui implementasinya sendiri. Jika Anda bertanya kepada saya - ini pada dasarnya mengambil barang dari ES dan OOP, sesuatu yang tidak dapat dilakukan menurut penulis artikel, tetapi bagi saya sepertinya praktik yang baik.
Pikirkan seperti ini; ada banyak jenis objek yang dapat digambar dalam game. Gambar lama yang polos, animasi ( update()
,, getCurrentFrame()
dll), kombinasi dari tipe primitif ini, dan semuanya dapat dengan mudah menyediakan draw()
metode untuk sistem render, yang kemudian tidak perlu peduli tentang bagaimana sprite dari suatu entitas diimplementasikan, hanya saja tentang antarmuka (menggambar) dan posisinya. Dan kemudian, saya hanya akan membutuhkan sistem animasi yang akan memanggil metode khusus animasi yang tidak ada hubungannya dengan rendering.
Dan satu hal lagi ... Apakah benar-benar ada alternatif untuk array ketika datang untuk menyimpan komponen? Saya tidak melihat tempat lain untuk menyimpan komponen selain array di dalam kelas Entity ...
Mungkin, ini adalah pendekatan yang lebih baik: menyimpan komponen sebagai properti entitas yang sederhana. Misalnya, komponen posisi akan dilem entity.position
.
Satu- satunya cara lain adalah dengan memiliki semacam tabel pencarian yang aneh di dalam sistem, yang mereferensikan entitas yang berbeda. Tapi itu tampaknya sangat tidak efisien dan lebih rumit untuk dikembangkan daripada sekadar menyimpan komponen dalam entitas.
Jawaban:
Saya pikir itu benar-benar baik untuk memiliki metode sederhana untuk mengakses, memperbarui atau memanipulasi data dalam komponen. Saya pikir fungsionalitas yang harus di luar komponen adalah fungsionalitas logis. Fungsi utilitas baik-baik saja. Ingat, sistem entitas-komponen hanyalah panduan, bukan aturan ketat yang perlu Anda ikuti. Jangan keluar dari jalan Anda untuk mengikuti mereka. Jika Anda pikir itu lebih masuk akal untuk melakukannya satu arah, maka lakukanlah seperti itu :)
EDIT
Untuk memperjelas, tujuan Anda bukan untuk menghindari OOP . Itu akan sangat sulit di sebagian besar bahasa umum yang digunakan hari ini. Anda mencoba meminimalkan warisan , yang merupakan aspek besar dari OOP, tetapi tidak diharuskan. Anda ingin menyingkirkan Object-> MobileObject-> Creature-> Bipedal-> Human type inheritance.
Namun, tidak masalah memiliki warisan! Anda berhadapan dengan bahasa yang sangat dipengaruhi oleh warisan, sangat sulit untuk tidak menggunakannya. Misalnya, Anda dapat memiliki
Component
kelas atau antarmuka yang diperluas atau diterapkan oleh semua komponen Anda yang lain. Kesepakatan yang sama denganSystem
kelas Anda . Ini membuat banyak hal lebih mudah. Saya sangat menyarankan Anda melihat kerangka Artemis . Ini open source dan memiliki beberapa proyek contoh. Buka hal-hal itu dan lihat cara kerjanya.Untuk Artemis, entitas disimpan dalam array, sederhana. Namun, komponennya disimpan dalam array atau array (terpisah dari entitas). Array level atas mengelompokkan array level bawah berdasarkan tipe komponen. Jadi setiap tipe komponen memiliki susunannya sendiri. Array level bawah diindeks oleh entitas ID. (Sekarang saya tidak yakin apakah saya akan melakukannya dengan cara itu, tetapi itulah yang dilakukan di sini). Artemis menggunakan kembali ID entitas, sehingga ID entitas maks tidak menjadi lebih besar dari jumlah entitas Anda saat ini, tetapi Anda masih dapat memiliki array jarang jika komponen tersebut bukan komponen yang sering digunakan. Lagi pula, saya tidak akan memilih terlalu banyak. Metode ini untuk menyimpan entitas dan komponennya tampaknya berfungsi. Saya pikir ini akan menjadi langkah pertama yang bagus untuk mengimplementasikan sistem Anda sendiri.
Entitas dan komponen disimpan dalam manajer yang terpisah.
Strategi yang Anda sebutkan, membuat entitas menyimpan komponen mereka sendiri (
entity.position
), agak bertentangan dengan tema komponen entitas, tetapi itu benar-benar dapat diterima jika Anda merasa yang paling masuk akal.sumber
EntityManager
di situlah barang disimpan.Artikel 'itu' bukan yang saya setujui secara khusus, jadi saya kira jawaban saya agak kritis.
Idenya bukan untuk memastikan bahwa tidak ada dalam program Anda selain ID entitas, komponen, atau sistem - itu untuk memastikan bahwa data entitas dan perilaku dibuat melalui penulisan objek daripada menggunakan pohon warisan yang kompleks atau lebih buruk lagi mencoba untuk letakkan semua fungsionalitas yang mungkin menjadi satu objek. Untuk mengimplementasikan komponen dan sistem ini, Anda tentu akan memiliki data normal seperti vektor yang, dalam sebagian besar bahasa, direpresentasikan sebagai kelas.
Abaikan sedikit dalam artikel yang menunjukkan ini bukan OOP - itu hanya sebagai OOP seperti pendekatan lainnya. Ketika kebanyakan kompiler atau runtime bahasa mengimplementasikan metode objek, pada dasarnya sama seperti fungsi lainnya, kecuali ada argumen tersembunyi yang disebut
this
atauself
, yang merupakan penunjuk ke tempat di memori tempat data objek disimpan. Dalam sistem berbasis komponen, ID entitas dapat digunakan untuk menemukan di mana komponen yang relevan (dan dengan demikian data) untuk entitas yang diberikan. Dengan demikian ID entitas setara dengan pointer / self ini, dan konsep-konsep pada dasarnya adalah hal yang sama, hanya disusun ulang sedikit.Baik. Metode adalah cara yang efektif untuk mengatur kode Anda. Hal penting untuk diambil dari gagasan "avoid OOP" adalah untuk menghindari penggunaan warisan di mana-mana untuk memperluas fungsionalitas. Sebagai gantinya, pisahkan fungsionalitas menjadi komponen yang dapat digabungkan untuk melakukan hal yang sama.
Gagasan sistem berbasis komponen adalah bahwa Anda tidak akan memiliki kelas terpisah untuk ini, tetapi akan memiliki kelas Obyek / Entitas tunggal, dan gambar akan menjadi Obyek / Entitas yang memiliki ImageRenderer, Animasi akan menjadi Obyek / Entity yang memiliki AnimationRenderer, dll. Sistem yang relevan akan tahu cara merender komponen ini sehingga tidak perlu ada kelas dasar dengan metode Draw ().
Tentu, tetapi ini tidak berhasil dengan komponen. Anda memiliki 3 pilihan:
Anda dapat menyimpan komponen dalam sistem. Array bukan masalah, tetapi di mana Anda menyimpan komponen.
sumber
Vektor adalah data. Fungsi-fungsinya lebih seperti fungsi utilitas - mereka tidak spesifik untuk instance data, mereka dapat diterapkan ke semua vektor secara independen. Cara berpikir yang baik adalah: Dapatkah fungsi-fungsi ini ditulis ulang sebagai metode statis? Jika demikian, itu hanya utilitas.
sumber