Gunakan instance atau kelas untuk sumber daya game (kayu, besi, emas)

31

Jadi saya membuat permainan di mana Anda dapat mengirim kapal ke lokasi untuk menjual atau membeli sumber daya seperti kayu, besi, emas, dll.

Sekarang saya bertanya-tanya bagaimana sumber daya harus dibuat dalam game. Saya datang dengan 2 opsi

  1. Buat kelas untuk setiap sumber daya:

    public class ResourceBase {
        private int value;
        // other base properties
    }
    
    public class Gold : ResourceBase {
         public Gold {
             this.value = 40 // or whatever
         }
    }
    
  2. Buat instance dari kelas Sumber Daya

    public class Resource {
        string name;
        int value;
    
        public Resource(string name, int value) {
            this.name = name;
            this.value = value;
         }
     }
    
    // later on...
    
    Resource gold = new Resource("Gold",40);
    

Dengan opsi kedua adalah mungkin untuk mengisi sumber daya game dari file resources.json, saya agak suka struktur itu.

Ide / pola desain / struktur baru selalu diterima!

EDIT: Ini sedikit seperti aplikasi pendamping Assassins Creed Black Flag. Lihat bilah sumber daya pada gambar di bawah ini

EDIT 2: Saya telah melakukan penelitian lebih lanjut tentang "memuat item / sumber daya dari file JSON" dan menemukan blog ini: Kekuatan JSON dalam Pengembangan Game - Item . Ini menunjukkan yang terbaik dari opsi 1 dan opsi 2. Anda masih dapat menambahkan fungsionalitas untuk setiap sumber daya :)

masukkan deskripsi gambar di sini

MDijkstra
sumber
1
Minecraft memiliki kelas terpisah untuk setiap sumber daya (bukan yang seharusnya)
MCMastery
@MCMastery ohh adalah minecraft open-source? Saya ingin melihat ke dalam struktur itu. Dan
terima kasih lagi
1
Memang tidak, tetapi selalu dikaburkan untuk server ... lihat github.com/Wolf-in-a-bukkit/Craftbukkit/tree/master/src/main/…
MCMastery
12
Jangan gunakan string seperti itu. Terlalu mudah untuk salah ketik "emas" dengan "glod" atau sejenisnya, dan itu sangat menyebalkan untuk di-debug. Gunakan sebagai enumgantinya.
Nolonar
Minecraft bukan open source secara teknis , tetapi sudah hampir sepenuhnya didekompilasi dan didobobekan. Anda seharusnya tidak dapat menemukan sumber deobfusi di mana saja di Internet, tetapi Anda dapat mengunduh dan menjalankan proses untuk melakukannya dari files.minecraftforge.net (unduhan MDK adalah yang Anda inginkan)
JamEngulfer

Jawaban:

51

Gunakan pendekatan kedua, hanya karena Anda dapat memperkenalkan jenis atau item sumber daya baru kapan saja tanpa harus menulis ulang atau memperbarui kode ( pengembangan berbasis data ).


Edit:

Untuk menguraikan lebih jauh mengapa hal ini secara umum merupakan praktik yang baik, bahkan jika Anda 100% yakin beberapa nilai tidak akan pernah berubah.

Mari kita ambil contoh permainan konsol yang disebutkan dalam komentar, karena ini memberikan alasan yang sangat bagus tentang mengapa Anda tidak boleh melakukan hard-code apa pun, kecuali Anda benar-benar memiliki (atau ingin) untuk, misalnya kunci enkripsi, nama Anda sendiri, dll.

Ketika merilis game di konsol, ini biasanya harus melalui proses review, di mana QA produsen konsol sendiri akan menguji game, bermain melalui itu, mencari masalah, dll. Ini adalah wajib dan memerlukan biaya, banyak uang. Saya pikir saya pernah membaca bahwa rilis mungkin berharga $ 30.000-50.000 hanya untuk sertifikasi saja.

Sekarang bayangkan Anda mendorong game Anda untuk rilis, membayar $ 30.000 dan menunggu. Dan tiba-tiba Anda menyadari bahwa beberapa nilai gim Anda benar-benar rusak. Katakanlah Anda dapat membeli batangan besi dengan harga 50 emas dan menjualnya dengan harga 55 emas.

Apa yang kamu kerjakan? Jika Anda telah membuat kode sulit untuk hal itu, Anda harus membuat versi pembaruan / rilis baru, yang harus melalui peninjauan sekali lagi, jadi kasus terburuk Anda akan membayar sekali lagi untuk sertifikasi ulang! Saya yakin Ubisoft tidak akan keberatan, tetapi untuk kantong pengembang indie game kecil Anda sendiri ... aduh!

Tapi bayangkan permainan hanya sesekali memeriksa definisi game yang diperbarui (misalnya dalam bentuk file JSON). Game Anda dapat mengunduh dan menggunakan versi terbaru kapan saja tanpa memerlukan pembaruan baru. Anda dapat memperbaiki ketidakseimbangan / eksploitasi / bug ini kapan saja tanpa memerlukan sertifikasi ulang atau uang lain yang dibayarkan. Hanya beberapa keputusan desain kecil, Anda tidak berpikir itu sepadan, hanya menghemat uang 5 digit! Bukankah itu luar biasa? :)

Hanya saja jangan salah paham. Ini juga berlaku untuk jenis perangkat lunak dan platform lainnya. Mengunduh file data yang diperbarui secara umum jauh lebih mudah dan dapat dilakukan untuk pengguna standar, tidak peduli apakah itu permainan atau semacam aplikasi / alat. Bayangkan sebuah game terpasang di bawah Program Files di Windows. Pembaru Anda memerlukan hak administrator untuk memodifikasi apa pun dan Anda tidak dapat mengubah program yang sedang berjalan. Dengan DDD, program Anda hanya mengunduh data dan menggunakannya. Pemain mungkin bahkan tidak menyadari ada pembaruan.

Mario
sumber
6
+1 untuk DDD. Ini sangat pas untuk hal-hal seperti sumber daya.
Kromster mengatakan mendukung Monica
@Funnydutchman jika jawaban seseorang membantu Anda, sudah lazim di Stack Exchange untuk meningkatkan jawaban mereka dengan mengeklik panah di atas angka di sebelah kiri. Jika jawaban paling membantu Anda, Anda harus mengklik tanda centang di bawah panah bawah untuk menerima jawaban mereka. Kedua tindakan tersebut memberi penjawab bonus reputasi dan membuat jawaban yang dapat digunakan lebih terlihat oleh komunitas.
Nzall
2
Saya tidak mengerti bagaimana Anda harus menulis ulang kode dengan cara pertama; semua yang akan Anda lakukan adalah menambahkan kelas (kecuali saya kehilangan sesuatu).
SirPython
4
Dan inilah perbedaan antara kode Berorientasi Objek dan kode Obyek Terobsesi. Hanya karena Anda dapat membuat hierarki objek tidak selalu berarti Anda harus melakukannya.
corsiKa
2
@ AgustínLado Jika saya punya satu dolar untuk setiap kali seorang klien berkata "Ini tidak akan pernah berubah" dan itu berubah, saya bisa membawa kami berdua ke restoran yang layak untuk makan malam (walaupun kami harus berhemat sedikit di ujung, jadi mungkin hanya restoran biasa-biasa saja ... masih cukup waktu untuk makan malam untuk dua orang.)
corsiKa
29

Aturan praktisnya adalah Anda menggunakan kelas yang berbeda ketika objek membutuhkan kode yang berbeda dan instance dari kelas yang sama ketika objek hanya membutuhkan nilai yang berbeda.

Ketika sumber daya memiliki mekanisme permainan yang berbeda yang unik bagi mereka, mungkin masuk akal untuk mewakili mereka dengan kelas. Misalnya, ketika Anda memiliki Plutonium yang memiliki waktu paruh dan Kelinci yang berkembang menurut urutan fibonacci , maka mungkin masuk akal untuk memiliki kelas dasar Resourcedengan metode yang Updatediimplementasikan sebagai no-op dan dua kelas turunan HalfLifeResourcedan SelfGrowingResourceyang menimpa metode itu untuk mengurangi / menambah nilai (dan mungkin juga menyertakan logika untuk mengatur apa yang terjadi ketika Anda menyimpan keduanya di samping satu sama lain).

Tetapi ketika sumber daya Anda benar-benar hanya angka-angka bodoh, maka tidak masuk akal untuk mengimplementasikannya dengan sesuatu yang lebih mewah daripada variabel sederhana.

Philipp
sumber
Terima kasih @Phillipp atas jawaban Anda. Inilah yang saya pikirkan. Tetapi sumber daya tidak akan benar-benar berubah dalam hal properti / metode, jadi saya akan pergi dengan opsi 2 untuk saat ini
MDijkstra
14

Saya ingin menambahkan ada dua opsi tambahan:
Antarmuka: Anda dapat mempertimbangkannya jika kelas sumber daya hanya akan menjadi "penyimpanan" untuk 5 bilangan bulat dan setiap entitas lainnya akan memiliki logika yang berbeda mengenai sumber daya (misalnya pengeluaran pemain / jar, kota menghasilkan sumber). Dalam hal ini Anda mungkin tidak ingin kelas sama sekali - Anda hanya ingin mengekspos bahwa beberapa entitas memiliki variabel yang dapat berinteraksi dengan orang lain:

interface IHasResources {
  int Gold { get; set; }
  int Wood { get; set; }
  int Cloth { get; set; }
  // ....
}

class Player : IHasResources { }
class City: IHasResources { }

selain itu, ini memiliki sisi positif Anda dapat menjarah kota dengan kode yang persis sama seperti Anda akan menjarah armada musuh, mempromosikan penggunaan kembali kode.
Kelemahannya adalah, mengimplementasikan antarmuka seperti itu dapat terbukti membosankan jika banyak kelas mengimplementasikannya, sehingga Anda mungkin berakhir menggunakan antarmuka tetapi tidak untuk masalah asli, menyelesaikannya dengan opsi 1 atau 2:

interface IHasResources { 
   IEnumerable<Resource> Resources { get; }
}

Instans (dengan enum): dalam beberapa kasus, akan diinginkan untuk menggunakan enum alih-alih string ketika mendefinisikan tipe sumber daya:

enum Resource {
   Gold, Wood, Cloth, //...
}

class ResourceStorage {
   public Resource ResourceType { get; set; }
   public int Value { get; set; }
}

ini akan memberikan sedikit "keamanan", karena IDE Anda akan memberi Anda daftar semua sumber daya yang valid ketika menetapkannya setelah menulis titik ResourceType = Resource., di samping itu ada lebih banyak "trik" dengan enum yang mungkin Anda butuhkan, seperti Jenis atau komposisi / bendera eksplisit. yang bisa saya bayangkan berguna ketika membuat kerajinan:

[Flags]
enum Metal {
 Copper = 0x01/*01*/, Tin = 0x02/*10*/, Bronze = 0x03/*11*/
}
Metal alloy = Metal.Copper; //lets forget Value(s) for sake of simplicity
alloy |= Metal.Tin; //now add a bit of tin
Console.WriteLine(alloy); //will print "Bronze"


Adapun apa yang terbaik - tidak ada peluru perak, tetapi secara pribadi saya akan condong ke segala bentuk contoh, mereka mungkin tidak semewah antarmuka tetapi mereka sederhana, tidak mengacaukan pohon warisan dan dipahami secara luas.

keajaiban
sumber
2
Terima kasih atas jawaban Anda @wondra Saya suka opsi enum dan bagaimana Anda membuat perunggu dari tembaga dan timah; p
MDijkstra
2
Saya bergabung dengan komunitas ini secara khusus sehingga saya dapat memilih solusi enum. Anda juga dapat melihat ke dalam menggunakan atribut Deskripsi enum untuk memetakan dari beberapa representasi JSON dari enum ( my-great-enum) ke beberapa representasi C # dari enum ( MyGreatEnum).
Dan Forbes
Rupanya saya sudah terlalu lama keluar dari Java-loop. Sejak kapan diizinkan untuk mendeklarasikan bidang untuk antarmuka? Sejauh yang saya tahu itu otomatis statis dan final, dan dengan demikian tidak banyak digunakan untuk tujuan yang dijelaskan dalam pertanyaan.
M.Herzkamp
2
@ M.Herzkamp ini bukan bidang, properti - dan Java tidak mendukung properti. Pertanyaan ditandai C #, C # memungkinkan properti di antarmuka - setelah semua properti adalah metode under-hood. Saya takut hal yang sama berlaku untuk anotasi bendera, tidak didukung di Jawa meskipun saya tidak sepenuhnya yakin.
wonderra
Terima kasih sudah membereskannya! Saya melewatkan tag C # dan kode dalam pertanyaan itu tampak sangat mirip Java: D
M.Herzkamp
2

Anda harus menggunakan opsi 1, yang memiliki 3 keunggulan:

  1. Lebih mudah untuk instantiate sumber daya - daripada harus melewati jenis sumber daya sebagai parameter, Anda hanya perlu melakukan, misalnya, new Gold(50)
  2. Jika Anda perlu memberikan perilaku khusus ke sumber daya, Anda bisa dengan mengubah kelasnya.
  3. Lebih mudah untuk memeriksa apakah sumber daya adalah tipe tertentu - resource instanceof Gold
Zac
sumber
Semua jawaban memiliki pro dan kontra, sulit untuk memilih mana yang lebih baik. Saya telah mengedit pertanyaan itu, apa pendapat Anda tentang struktur itu?
MDijkstra
1

Jika sumber daya Anda tidak memiliki logika bisnis sendiri, atau skenario kasus khusus dengan cara mereka berinteraksi dengan lingkungan, sumber daya lain (selain perdagangan yang telah Anda liput) atau pemain, maka opsi dua membuat menambahkan yang baru sangat mudah.

Jika Anda perlu mempertimbangkan situasi seperti apa yang akan terjadi jika Anda mencampur dua sumber daya untuk kerajinan, jika sumber daya tersebut dapat memiliki sifat yang sangat berbeda (seember air sangat berbeda dari segumpal batu bara) atau interaksi ekonomi kompleks lainnya, maka pendekatan 1 adalah jauh lebih fleksibel untuk mesin, tetapi bukan data.

Kristian Williams
sumber