Bagaimana cara mengatur mesin game di C ++? Apakah saya menggunakan warisan adalah ide yang bagus?


11

Saya seorang pemula baik dalam pengembangan game dan pemrograman.

Saya mencoba mempelajari beberapa prinsip dalam membangun mesin game.
Saya ingin membuat game sederhana, saya pada titik di mana saya mencoba menerapkan mesin game.

Jadi saya pikir mesin permainan saya harus mengontrol hal-hal ini:

- Moving the objects in the scene
- Checking the collisions
- Adjusting movements based on collisions
- Passing the polygons to the rendering engine

Saya merancang objek saya seperti ini:

class GlObject{
private:
    idEnum ObjId;
    //other identifiers
public:
    void move_obj(); //the movements are the same for all the objects (nextpos = pos + vel)
    void rotate_obj(); //rotations are the same for every objects too
    virtual Polygon generate_mesh() = 0; // the polygons are different
}

dan saya memiliki 4 objek berbeda dalam permainan saya: pesawat, penghalang, pemain, peluru dan saya mendesainnya seperti ini:

class Player : public GlObject{ 
private:
    std::string name;
public:
    Player();
    Bullet fire() const; //this method is unique to the class player
    void generate_mesh();
}

Sekarang di mesin permainan saya ingin memiliki daftar objek umum di mana saya dapat memeriksa misalnya untuk tabrakan, memindahkan objek, dan sebagainya, tetapi saya ingin juga bahwa mesin permainan akan mengambil perintah pengguna untuk mengontrol pemain ...

Apakah ini Ide yang bagus?

class GameEngine{
private:
    std::vector<GlObject*> objects; //an array containg all the object present
    Player* hPlayer; //hPlayer is to be read as human player, and is a pointer to hold the reference to an object inside the array
public:
    GameEngine();
    //other stuff
}

konstruktor GameEngine akan seperti ini:

GameEngine::GameEngine(){
    hPlayer = new Player;
    objects.push_back(hPlayer);
}

Fakta bahwa saya menggunakan pointer adalah karena saya perlu memanggil fire()yang unik untuk objek Player.

Jadi pertanyaan saya adalah: apakah itu ide yang bagus? Apakah penggunaan warisan saya salah di sini?



Saya pernah melihatnya setelah memposting, dan sebenarnya komposisi adalah ide yang bagus! Saya selalu takut akhirnya menggunakan c dengan kelas daripada memiliki desain c ++ nyata!
Pella86

Saya pikir ada lebih banyak alasan untuk menggunakan komposisi daripada pewarisan ... Jawaban saya memberikan beberapa contoh tentang kelebihan fleksibilitas yang disediakannya. Untuk contoh implementasi yang baik, periksa artikel yang saya tautkan.
Coyote

Jawaban:


12

Tergantung pada apa yang Anda maksud dengan 'baik'. Itu akan menyelesaikan pekerjaan, tentu saja. Ini memiliki banyak sisi atas, dan sisi bawah. Anda tidak akan menemukannya sampai mesin Anda jauh lebih kompleks. Lihat pertanyaan ini di SO , untuk diskusi tentang masalah ini.

Bagaimanapun, ada banyak pendapat, tetapi jika kode mesin Anda masih pada tahap awal itu, akan sulit untuk menjelaskan kepada Anda mengapa itu mungkin buruk.

Secara umum, Scott Meyers memiliki beberapa hal besar untuk dikatakan tentang warisan. Jika Anda masih dalam tahap pengembangan, baca buku ini (Efektif C ++) sebelum Anda melanjutkan. Ini adalah buku yang fantastis, dan merupakan persyaratan untuk setiap coders yang bekerja di perusahaan kami. Tetapi untuk meringkas saran: jika Anda menulis kelas dan mempertimbangkan menggunakan warisan, jelaslah bahwa hubungan antara kelas dan leluhurnya adalah hubungan 'adalah'. Artinya, setiap B adalah A. Jangan hanya menggunakan pewarisan sebagai cara mudah untuk memberikan B akses ke fungsionalitas yang disediakan A, dengan cara itu akan menyebabkan masalah arsitektur yang parah, dan ada cara lain untuk melakukannya.

Sederhananya; untuk mesin dengan ukuran berapa pun, Anda akan dengan cepat menemukan bahwa benda-benda jarang jatuh ke dalam struktur hierarki yang rapi tempat warisan bekerja. Gunakan saat yang tepat, tetapi jangan jatuh ke dalam perangkap menggunakannya untuk semuanya - pelajari cara lain untuk saling berhubungan objek.


Saya mendukung pendapat tentang pewarisan. Aturan praktis saya adalah: jangan lakukan itu kecuali Anda harus atau melakukannya dengan cara lain akan bodoh. Dengan kata lain, pewarisan adalah gagasan buruk dalam 99% kasus (setidaknya :)). Juga, mungkin baik untuk memisahkan logika game (rotate / move) dari rendering (generate_mesh ()). Hal lain adalah api () - pertimbangkan untuk memiliki daftar tindakan dan fungsi tindakan umum (my_action) - dengan cara ini Anda tidak akan berakhir dengan banyak sekali fungsi berbeda yang tersebar di semua kelas. Dalam kedua kasus itu, tetap sederhana dan refactor tanpa ampun saat Anda menemukan masalah.
Gilead

8

Untuk data logika dan fungsi objek game Anda (entitas), saya sangat merekomendasikan menggunakan komposisi di atas warisan. Awal yang baik adalah pendekatan berbasis komponen. Hal ini dijelaskan dengan baik dalam artikel Pemrograman Koboi yang menjelaskan bagaimana arsitektur ini dapat diimplementasikan dan bagaimana manfaatnya terhadap waralaba Tony Hawk.

Juga artikel tentang sistem entitas ini mengilhami saya ketika saya pertama kali membacanya.

Warisan adalah alat yang bagus untuk polimorfisme. Kecuali untuk proyek yang sangat sederhana, Anda harus menghindari menggunakannya sebagai cara untuk menyusun entitas dan logika game Anda. Jika Anda pergi dengan warisan Anda pasti akan berakhir dengan harus mereplikasi dan memelihara salinan kode yang sama untuk mengimplementasikan fungsi-fungsi yang tidak dapat diwarisi dari orang tua biasa. Dan Anda mungkin akan mulai mencemari kelas Anda dengan logika dan data yang paling umum digunakan untuk menghindari replikasi kode terlalu banyak.

Komponen sangat berguna dalam berbagai situasi. Anda dapat mencapai lebih banyak menggunakan mereka:

Fleksibilitas dengan jenis entitas Anda : Ada saat-saat dalam pengembangan game di mana beberapa entitas berkembang secara tiba-tiba dan sementara perancang game membuat keputusan, de developer harus mengimplementasikannya. Hanya perlu beberapa langkah untuk menambahkan perilaku yang ada tanpa mereplikasi kode. Sistem berbasis komponen memungkinkan lebih banyak perubahan dilakukan oleh yang bukan programmer. Misalnya setiap jenis entitas alih-alih diwakili oleh kelas dapat diwakili oleh file deskripsi yang berisi semua nama komponen dan parameter yang diperlukan untuk mengkonfigurasi tipe. Ini memungkinkan non programmer untuk melakukan dan menguji perubahan tanpa mengkompilasi ulang game. Cukup mengedit file deskripsi akan cukup untuk menambah, menghapus atau mengubah komponen yang digunakan oleh setiap jenis entitas.

Fleksibilitas dengan contoh khusus dan skenario tertentu : Ada kasus di mana Anda membutuhkan pemain Anda untuk dapat melengkapi senjata, atau item, Anda dapat menambahkan komponen inventaris ke pemain Anda. selama pengembangan gim Anda, Anda akan membutuhkan entitas lain untuk memiliki inventaris (misalnya musuh). Dan pada satu titik Anda miliki dalam skenario Anda situasi di mana pohon seharusnya mengandung semacam barang tersembunyi. Dengan komponen, Anda dapat menambahkan komponen inventaris bahkan ke entitas yang tipe awalnya tidak dirancang untuk memilikinya tanpa upaya pemrograman tambahan.

Fleksibilitas pada waktu berjalan : Komponen menawarkan cara yang sangat efektif untuk mengubah perilaku entitas saat runtime. Anda dapat menambah dan menghapus komponen saat runtime dan dengan demikian membuat atau menghapus perilaku dan properti saat diperlukan. Mereka juga memungkinkan Anda untuk memisahkan berbagai jenis data menjadi kelompok-kelompok yang dapat (kadang-kadang) dihitung secara paralel pada beberapa GPU.

Fleksibilitas dalam waktu : Komponen dapat digunakan untuk menjaga kompatibilitas antar versi. Misalnya ketika perubahan dibuat antara rilis game Anda dapat (tidak selalu) cukup menambahkan komponen baru yang menerapkan perilaku dan perubahan baru. Kemudian gim akan instantiate komponen yang tepat yang melekat pada entitas Anda tergantung pada menyimpan file yang dimuat, rekan yang terhubung atau server pemain bergabung. Ini sangat berguna dalam skenario di mana Anda tidak dapat mengontrol tanggal rilis versi baru di semua platform (Steam, Mac App Store, iPhone, Android ...).

Untuk wawasan yang lebih baik, lihat pertanyaan yang diberi tag [berbasis komponen] dan [entitas-sistem] .


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.