Bagaimana cara membuat game tanpa OOP? [Tutup]


10

Saya saat ini sedang mempelajari pengembangan game dan berlatih membuat game.

Saya menggunakan banyak OOP di game saya. Misalnya, setiap rudal yang ditembak adalah turunan dari sebuah Missileobjek, dan ditambahkan ke daftar Missileobjek. Setiap tangki dalam game adalah Tankobjek. Dll

Seluruh desain program didasarkan pada ini. Sebagai contoh, memiliki daftar Missileobjek memungkinkan saya setiap frame untuk memindahkan rudal, menggambar mereka, dll. Dan memiliki instance Tankobjek untuk setiap tangki memungkinkan saya untuk memeriksa setiap tangki jika bertabrakan dengan sesuatu, dll.

Sulit bagi saya untuk membayangkan bagaimana sebuah game (yang lebih kompleks dari Pac-Man) dapat diprogram dalam bahasa non-OO. (Tanpa rasa tidak hormat kepada programmer non-OO tentu saja). Tidak hanya dalam hal berapa lama waktu yang dibutuhkan, tetapi sebagian besar dalam hal bagaimana sebuah game dapat dirancang dengan cara ini.

Saya tidak dapat membayangkan mendesain game tanpa menggunakan pemrograman berorientasi objek, karena seluruh pemahaman saya tentang bagaimana merancang sebuah game-program didasarkan pada OOP.

Saya ingin bertanya: Hari ini, apakah ada game yang tidak diprogram menggunakan OOP, serupa dengan yang saya jelaskan di atas? Apakah ada game 'profesional' yang tidak menggunakan OOP sebagai faktor utama dalam proses pengembangan?

Jika demikian, dapatkah Anda memberi saya gagasan tentang bagaimana, misalnya, deteksi tabrakan antara tank dan sejumlah rudal dapat diimplementasikan, tanpa OOP?


6
Apakah ini pertanyaan filosofis? Bahkan jika Anda tidak menyebut tank Anda "objek", Anda mungkin akan menginginkan "entitas", "aktor", "agen", "struct" atau hanya beberapa nama lain untuk ide yang sama, yang merupakan kumpulan dari atribut dan perilaku yang membentuk benda berbentuk kubus yang berputar dengan menara yang dapat menembak sesuatu, yang disebut tank. Bahasa pemrograman akan memiliki cara yang berbeda untuk memformalkan ide yang sama, tetapi pada akhirnya, itu akan menjadi tangki.
Anko

Banyak game menggunakan sistem berbasis Komponen seperti yang dijelaskan jawaban ini: gamedev.stackexchange.com/a/31491/9366
John McDonald

Ini sangat luas (yang mungkin bisa Anda perbaiki dengan mempersempit ruang lingkup) dan tidak benar-benar khusus untuk pengembangan game (karena membangun perangkat lunak tanpa teknik OO bukanlah sesuatu yang pengembang game akan memberikan jawaban yang lebih baik daripada pengembang perangkat lunak lain), yang membuatnya menjadi topik di sini, aku takut.

Mungkin cocok untuk StackOverflow, atau Anda dapat memeriksa pusat bantuan untuk menemukan pilihan situs yang spesifik untuk pengembangan game (seperti GDNet) yang akan memungkinkan topik yang luas dan berorientasi diskusi ini. Semoga berhasil!

Jawaban:


16

Saya tidak dapat membayangkan mendesain game tanpa menggunakan pemrograman berorientasi objek, karena seluruh pemahaman saya tentang bagaimana merancang sebuah game-program didasarkan pada OOP.

Maka mungkin akan baik bagi Anda untuk mencoba menulis beberapa program dengan gaya non-OO. Bahkan jika Anda menemukan bahwa ini tidak pragmatis untuk Anda, Anda mungkin akan belajar banyak di sepanjang jalan yang akan membantu Anda di masa depan.

Gaya OO sangat cocok untuk permainan karena permainan hampir selalu tentang manipulasi objek stateful. Sinar laser mengenai robot dan keadaan robot berubah sementara identitasnya tetap sama.

Namun dimungkinkan untuk memprogram game dengan gaya fungsional . Dalam gaya fungsional, status tidak berubah. Objek tidak berubah. Daripada mengubah benda, Anda bertanya pertanyaan bagaimana jagat raya akan berbeda jika saya mengubah ini? dan kemudian menghasilkan seluruh alam semesta baru yang memiliki properti yang berubah. Tentu saja, Anda dapat menggunakan kembali banyak dari alam semesta yang ada sebelumnya karena tidak dapat diubah .

Dalam pemrograman fungsional setiap fungsi harus menghitung nilai kembalinya semata-mata dari informasi yang diteruskan; tidak ada bacaan dari "negara global".

Jika Anda melakukan ini, masalah mendasar yang harus Anda lewati adalah setiap pembaruan tidak merusak . Saat laser mengenai robot, Anda tidak mengubah kondisi robot. Pada akhirnya Anda menghitung semesta yang sama sekali baru yang identik dengan alam semesta lama kecuali bahwa robot memiliki keadaan yang berbeda; jika Anda membutuhkan alam semesta lama itu, ia masih ada di sana, tidak berubah.

Seri artikel blog ini memiliki lebih banyak pemikiran tentang menulis game dengan gaya fungsional:

http://prog21.dadgum.com/23.html

Artikel ini secara khusus menjawab pertanyaan "shell hits a tank" Anda:

http://prog21.dadgum.com/189.html

Bahkan, baca saja seluruh blog. Ada barang bagus di sana dan artikelnya pendek.


12

Setiap program berorientasi objek dapat dire-refored ke program prosedural dengan mengganti semua kelas dengan struktur dan mengubah semua fungsi anggota menjadi fungsi yang berdiri sendiri yang mengambil objek yang akan menjadi thisargumen.

Begitu

 missile.setVelocity(100);

menjadi

 setMissileVelocity(missile, 100);

atau ketika fungsi itu sepele, Anda cukup melakukannya

 missile.velocity = 100;

Perbedaan utama antara pemrograman berorientasi objek dan pemrograman prosedural adalah bagaimana Anda memperlakukan data Anda. Dalam OOP, data cerdas . Ia mengelola dan memanipulasi dirinya sendiri. Namun dalam pemrograman prosedural, data bodoh . Itu tidak melakukan apa-apa sendiri dan perlu dimanipulasi dari luar.

Ketika Anda bahkan menganggap struktur terlalu berorientasi objek, Anda dapat mengganti satu susunan struktur dengan banyak susunan, satu untuk semua yang merupakan variabel dari rudal. Begitu

struct Missile {
     int x;
     int y;
     int velocity;
}

Missile missiles[256];

menjadi

int missileX[256];
int missileY[256];
int missileVelocities[256];

Dalam desain ini, suatu fungsi yang melakukan operasi yang melibatkan banyak atribut pada rudal yang sama sekarang akan mengambil indeks array bukan referensi ke struktur. Implementasinya akan terlihat seperti ini:

function updateMissilePosition(int index) {
     missileX[index] += missileVelocity[index];
}

1
Tetapi missilemerupakan contoh dari suatu objek. Dalam non-OOP, tidak ada contoh, apakah saya benar? Jika demikian, bagaimana Anda bisa melakukan setMissileVelocity (rudal, 100)?
user3150201

1
@ user3150201 Anda tidak sepenuhnya benar. Sebagian besar bahasa non-OOP (dan saya berpendapat apa saja yang cocok untuk pengembangan game serius) mendukung struktur. Struktur itu seperti kelas, hanya saja tidak mengandung apa pun kecuali variabel publik. Sehingga akan memungkinkan Anda untuk membuat jenis Missile, yang merupakan struktur dengan beberapa bidang, seperti x, y, angledan velocity.
Philipp

@ user3150201 Jawaban yang diperbarui dengan bagian tentang cara melakukannya tanpa struktur.
Philipp

Jawaban yang bagus Philipp, walaupun, saya tidak mengerti mengapa orang tidak ingin program Berorientasi Objek. Sangat sulit untuk membaca bahasa non-OOP, dan bisa membuat fustrating. Kode dapat menjadi berantakan dalam waktu singkat.
Zhafur

2
@Zhafur Anda sadar bahwa pernyataan Anda adalah penipuan besar-besaran, bukan?
Philipp

6

Saya melakukannya sebagai berikut:

  • Semua kelas / metode OOP memiliki akses ke this. Untuk memanfaatkan thisdalam pendekatan non-OO, cukup berikan contoh apa pun (lihat poin berikutnya) this, sebagai parameter pertama.
  • Sekarang, sebagai contoh, Anda dapat meneruskan structfungsi-fungsi Anda this, tetapi saya menemukan cara terbaik untuk mencapai kinerja cache yang baik untuk objek yang produktif, seperti entitas atau partikel, adalah dengan hanya mengirimkan indeks tunggal ke beberapa array primitif. atau structs kecil . Jadi indeks ini digunakan untuk setiap anggota data individu dari kelas asli. Jadi misalnya jika Anda punya

...

class Entity //let's say you had 100 instances of this
{
   int a;
   char b;
   function foo() 
   {
      .../*can access 'this' herein*/
   }
}

Anda akan menggantinya dengan

int a[100];
char b[100];
function foo(int index);

Sehingga Anda sekarang melewati sebuah indeks ke dalam fungsi untuk mendapatkan apa yang biasanya this.

Ingatlah bahwa Anda mungkin ingin menggunakan array primitif seperti di atas, atau array structs, tergantung pada cara terbaik untuk interleave data Anda untuk lokalitas cache yang baik (lokalitas referensi). Tentu saja, kinerja cache yang layak bergantung pada lebih dari ini - terutama, bahasa apa / platform Anda menulis kode Anda - tetapi bahkan dalam VM berbasis, bahasa yang dialokasikan secara dinamis seperti Jawa, array linear besar primitif cenderung menampilkan karakteristik kinerja yang lebih baik daripada instance objek. Alasan utama untuk ini adalah bahwa objek diakses dengan referensi dan ini berarti Anda melompati seluruh memori untuk mengakses data - tidak efisien dibandingkan dengan mengakses primitif secara berdekatan dari array besar.

Untuk informasi lebih lanjut tentang membangun entitas dll sebagai array struct atau primitif, lihat Mick West's Evolve Hierarchy Anda .


0

Selain jawaban yang ada, Anda mungkin ingin tahu bagaimana melakukan polimorfisme dalam bahasa prosedural.

Ada dua pendekatan:

Menyimpan tipenya

Dalam hal ini struct memiliki bidang untuk pengenal tipe, mungkin enum, yang diperiksa menggunakan switchpernyataan ketika jenis tindakan spesifik perlu dilakukan.

Cara lainnya adalah:

Menyimpan pointer fungsi

Anda tidak menyebutkan bahasa pemrograman tempat Anda memiliki pengalaman, tetapi dalam berbagai bahasa mereka juga disebut panggilan balik, delegasi, acara atau fungsi urutan tinggi atau hanya objek fungsi.

Dalam hal ini Anda tidak akan menyimpan tipe, tetapi menyimpan pointer / referensi ke fungsi yang melakukan tindakan tertentu. Ketika jenis tindakan spesifik perlu dilakukan, Anda cukup memanggil fungsi ini. Yang ini sangat mirip dengan metode virtual biasa.

Dengan memungkinkan pengaturan setiap fungsi secara mandiri Anda mendapatkan pola strategi gratis.


Mengenai paragraf terakhir Anda dengan deteksi tabrakan. Saya pikir Anda mungkin memiliki beberapa jenis tank dan Anda memiliki beberapa jenis rudal, dan setiap kombinasi berpotensi memiliki hasil yang berbeda ketika mereka bertabrakan. Jika ini yang Anda cari, Anda memiliki masalah yang belum diselesaikan oleh bahkan bahasa OOP: pengiriman ganda dan multi-metode yang dapat memiliki banyak thisparameter dari jenis yang berbeda. Untuk masalah ini ada lagi dua alternatif:

  • Switch bersarang untuk setiap kombinasi tank dan rudal.
  • Array pengiriman dua dimensi, yang berisi pointer ke fungsi untuk setiap kombinasi tank dan rudal.
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.