Saya sedang mengerjakan sistem komponen entitas di C ++ yang saya harap dapat mengikuti gaya Artemis (http://piemaster.net/2011/07/07/entity-component-artemis/) dalam komponen yang sebagian besar adalah tas data dan itu adalah Sistem yang mengandung logika. Saya berharap dapat memanfaatkan data-sentris dari pendekatan ini dan membangun beberapa alat konten yang bagus.
Namun, satu punuk yang saya temui adalah cara mengambil beberapa string pengenal atau GUID dari file data dan menggunakannya untuk membangun komponen untuk Entitas. Jelas saya hanya dapat memiliki satu fungsi parse besar:
Component* ParseComponentType(const std::string &typeName)
{
if (typeName == "RenderComponent") {
return new RenderComponent();
}
else if (typeName == "TransformComponent") {
return new TransformComponent();
}
else {
return NULL:
}
}
Tapi itu sangat jelek. Saya bermaksud menambah dan memodifikasi komponen, dan mudah-mudahan membangun semacam ScriptedComponentComponent, sehingga Anda bisa mengimplementasikan komponen dan sistem di Lua untuk keperluan prototyping. Saya ingin dapat menulis kelas yang diwarisi dari beberapa BaseComponent
kelas, mungkin melemparkan beberapa makro untuk membuat semuanya berfungsi, dan kemudian memiliki kelas yang tersedia untuk instantiation saat runtime.
Di C # dan Java ini akan sangat mudah, karena Anda mendapatkan API refleksi yang bagus untuk mencari kelas dan konstruktor. Tapi, saya melakukan ini di C ++ karena saya ingin meningkatkan kemahiran saya dalam bahasa itu.
Jadi Bagaimana ini dicapai dalam C ++? Saya sudah membaca tentang mengaktifkan RTTI, tetapi tampaknya kebanyakan orang khawatir tentang hal itu, terutama dalam situasi di mana saya hanya membutuhkannya untuk subset jenis objek. Jika sistem RTTI khusus adalah yang saya butuhkan di sana, di mana saya bisa mulai belajar menulis satu?
sumber
Jawaban:
Sebuah komentar:
Implementasi Artemis menarik. Saya datang dengan solusi yang serupa, kecuali saya menyebut komponen saya "Atribut" dan "Perilaku". Pendekatan pemisahan jenis komponen ini telah bekerja sangat baik untuk saya.
Mengenai solusinya:
Kode ini mudah digunakan, tetapi implementasinya mungkin sulit diikuti jika Anda tidak berpengalaman dengan C ++. Begitu...
Antarmuka yang diinginkan
Apa yang saya lakukan adalah memiliki repositori pusat dari semua komponen. Setiap tipe komponen dipetakan ke string tertentu (yang mewakili nama komponen). Ini adalah bagaimana Anda menggunakan sistem:
Pelaksanaan
Implementasinya tidak terlalu buruk, tetapi masih cukup rumit; membutuhkan pengetahuan tentang template dan pointer fungsi.
Catatan: Joe Wreschnig telah membuat beberapa poin bagus dalam komentar, terutama tentang bagaimana implementasi saya sebelumnya membuat terlalu banyak asumsi tentang seberapa bagus kompiler dalam mengoptimalkan kode; masalah ini tidak merugikan, imo, tapi itu memang mengganggu saya juga. Saya juga memperhatikan bahwa
COMPONENT_REGISTER
makro sebelumnya tidak berfungsi dengan templat.Saya telah mengubah kode dan sekarang semua masalah itu harus diperbaiki. Makro bekerja dengan templat dan masalah yang diangkat Joe telah ditangani: sekarang jauh lebih mudah bagi kompiler untuk mengoptimalkan kode yang tidak perlu.
komponen / komponen.h
komponen / detail.h
komponen / komponen.cpp
Memperluas dengan Lua
Saya harus mencatat bahwa dengan sedikit kerja (ini tidak terlalu sulit), ini dapat digunakan untuk bekerja dengan mulus dengan komponen yang didefinisikan dalam C ++ atau Lua, tanpa harus memikirkannya.
sumber
shared_ptr
, tetapi saran Anda masih bagus.Sepertinya yang Anda inginkan adalah pabrik.
http://en.wikipedia.org/wiki/Factory_method_pattern
Yang dapat Anda lakukan adalah meminta berbagai komponen Anda mendaftar ke pabrik untuk nama apa mereka bersesuaian, dan kemudian Anda memiliki beberapa peta pengenal string untuk tanda tangan metode konstruktor untuk menghasilkan komponen Anda.
sumber
Component
kelas saya , memanggilComponentSubclass::RegisterWithFactory()
, kan? Apakah ada cara untuk mengatur ini, lakukan secara lebih dinamis dan otomatis? Alur kerja yang saya cari adalah 1. Menulis kelas, hanya melihat header dan file cpp yang sesuai 2. Mengkompilasi ulang game 3. Editor level pemula dan kelas komponen baru tersedia untuk digunakan.Saya bekerja dengan desain Paul Manta dari jawaban yang dipilih untuk sementara waktu dan akhirnya sampai pada implementasi pabrik yang lebih umum dan ringkas di bawah ini yang saya ingin bagikan kepada siapa pun yang datang ke pertanyaan ini di masa depan. Dalam contoh ini, setiap objek pabrik berasal dari
Object
kelas dasar:Kelas Pabrik statis adalah sebagai berikut:
Makro untuk mendaftarkan sub-jenis
Object
adalah sebagai berikut:Sekarang penggunaannya adalah sebagai berikut:
Kapasitas untuk banyak string id per sub-tipe berguna dalam aplikasi saya, tetapi pembatasan untuk satu id per sub-tipe akan cukup mudah.
Semoga ini bermanfaat!
sumber
Membangun dari jawaban @TimStraubinger , saya membangun kelas pabrik menggunakan standar C ++ 14 yang dapat menyimpan anggota turunan dengan sejumlah argumen . Contoh saya, tidak seperti Tim, hanya membutuhkan satu nama / kunci per fungsi. Seperti milik Tim, setiap kelas yang disimpan berasal dari kelas Basis , kelas saya disebut Basis .
Base.h
EX_Factory.h
main.cpp
Keluaran
Saya harap ini membantu orang yang perlu menggunakan desain Pabrik yang tidak memerlukan pembangun identitas untuk bekerja. Desainnya menyenangkan, jadi saya harap ini membantu orang yang membutuhkan lebih banyak fleksibilitas dalam desain pabrik mereka .
sumber