Oyun kaynakları için bir örnek veya sınıf kullanın (ahşap, demir, altın)


31

Bu yüzden ahşap, demir, altın vb. Kaynakları satmak veya almak için yerlere gemi gönderebileceğiniz bir oyun yapıyorum.

Şimdi kaynakların oyunda nasıl yaratılması gerektiğini merak ediyordum. 2 seçenek buldum

  1. Her kaynak için bir sınıf oluşturun:

    public class ResourceBase {
        private int value;
        // other base properties
    }
    
    public class Gold : ResourceBase {
         public Gold {
             this.value = 40 // or whatever
         }
    }
    
  2. Kaynak sınıfının örneklerini oluşturma

    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);
    

İkinci seçenekle, oyun kaynaklarını bir resources.json dosyasından doldurmak mümkündür, bu yapıyı sevdim.

Yeni fikirler / tasarım desenleri / yapıları her zaman beklerim!

EDIT: Assassins Creed Black Flag'in arkadaşı uygulaması gibi biraz. Aşağıdaki resimde bulunan kaynak çubuğuna bakın

2 EDIT: "JSON dosyasından öğeleri / kaynakları yükleme" konusunda biraz daha araştırma yaptım ve şu blogu buldum: JSON'un Game Development'teki Gücü - Öğeler . Seçenek 1 ve seçenek 2'nin en iyisini gösterir. Hala her kaynağa işlevsellik ekleyebilirsiniz :)

görüntü tanımını buraya girin


1
Minecraft'ın her kaynak için ayrı sınıfları vardır (sizin yapmanız
gerekmiyor

@MCMastery ohh Minecraft açık kaynak nedir? Bu yapıya bir göz atmak istiyorum. Ve bahsettiğin için
teşekkürler

1
Öyle değil, ancak sunucular için her zaman engellenme durumu var ... bkz. Github.com/Wolf-in-a-bukkit/Craftbukkit/tree/master/src/main/…
MCMastery

12
Böyle bir dize kullanmayın. "Altın" kelimesini "glod" ya da benzerleriyle yanlış yazmak çok kolaydır ve hata ayıklamak için çok büyük bir acıdır. Bir kullan enumyerine.
Nolonar

Minecraft teknik olarak açık kaynaklı değildir , ancak neredeyse tamamen parçalanmış ve deobfuscated edilmiştir. İnternette herhangi bir yerde deobfuscated bir kaynak bulamamalısınız, ancak bunu yapmak için files.minecraftforge.net adresinden indirebilir ve çalıştırabilirsiniz (MDK indirmesi istediğiniz
olanıdır

Yanıtlar:


51

İkinci yaklaşıma geçin, yalnızca kodu yeniden yazmak veya güncellemek zorunda kalmadan istediğiniz zaman yeni kaynak türlerini veya öğelerini ekleyebildiğinizden ( veriye dayalı geliştirme ).


Düzenle:

Bunun genel olarak iyi uygulamada olmasının nedenini biraz daha fazla açıklamak için, bazı değerlerin asla değişmeyeceğinden% 100 emin olsanız bile.

Yorumlarda belirtilen konsol oyunu örneğini ele alalım, çünkü bu, örneğin şifreleme anahtarları, kendi adınız, vb.

Konsollarda bir oyun çıkarırken, bunlar genellikle konsol üreticisinin kendi QA'sının oyunu test edeceği, oynayacağı, sorunları arayacağı vs. bir gözden geçirme sürecinden geçmesi gerekir. Bu zorunludur ve çok paraya mal olur. Sanırım bir keresinde, yalnızca sertifikasyon için bir sürümün 30.000-50.000 $ 'a mal olacağını okudum.

Şimdi oyununu serbest bırakmak için bastırdığını, 30.000 $ ödeyeceğini ve beklediğini hayal et. Birdenbire oyundaki bazı değerlerin gerçekten bozulduğunu fark ettin. Diyelim ki 50 altın karşılığında demir çubuk satın alabilir ve bunları 55 altın karşılığında satabilirsiniz.

Ne yaparsın? Bu kodları zor kodladıysanız, bir kez daha gözden geçirilmesi gereken yeni bir güncelleme / sürüm sürümü oluşturmanız gerekecektir, bu nedenle en kötü durum yeniden sertifikalandırma için bir kez daha ödeyeceksiniz! Bahse girerim Ubisoft'un sakıncası yoktur, fakat kendi küçük indie oyun geliştirici cebiniz için… ah!

Ancak oyunun zaman zaman güncellenmiş oyun tanımlarını (örneğin bir JSON dosyası biçiminde) kontrol edeceğini hayal edin. Oyununuz, yeni bir güncelleme gerektirmeden en son sürümü herhangi bir zamanda indirebilir ve kullanabilir. Bu dengesizliği / istismar / hatayı herhangi bir zamanda yeniden sertifikalandırmaya veya ödenen başka bir paraya ihtiyaç duymadan düzeltebilirsiniz. Sadece küçük bir tasarım kararı, buna değeceğini düşünmedin, sadece 5 basamaklı bir para biriktirdim! Bu harika değil mi? :)

Beni yanlış anlama. Bu aynı zamanda diğer yazılım ve platform türleri için de geçerlidir. Güncelleştirilmiş veri dosyalarını indirmek, bir oyun ya da bir çeşit uygulama / araç olup olmadığına bakılmaksızın, standart kullanıcı için genel olarak çok daha kolaydır ve yapılabilir. Windows'ta Program Dosyaları altında kurulu bir oyun hayal edin. Güncelleyicinizin herhangi bir şeyi değiştirmek için yönetici hakları olması gerekir ve çalışan programları değiştiremezsiniz. DDD ile programınız sadece verileri indirir ve kullanır. Müzikçalar bir güncelleme olduğunu bile bilmiyor olabilir.


6
DDD için +1. Bu, kaynaklar gibi şeyler için çok uygundur.
Kromster Monica'ya destek diyor

@Funnydutchman eğer birisinin cevabı size yardımcı olduysa, soldaki sayının üstündeki oka tıklayarak cevaplarını yenmek için Stack Exchange'de alışılmış bir yöntemdir. Bir cevap size en çok yardımcı olduysa, cevaplarını kabul etmek için alttaki okun altındaki onay işaretini tıklamanız gerekir. Her iki eylem de yanıtlayıcıya itibar açısından bir bonus verir ve kullanılabilir cevapları topluma daha görünür hale getirir.
Nzall

2
İlk olarak nasıl kod yazmanız gerektiğini anlamıyorum; tek yapman gereken bir sınıf eklemek.
SirPython

4
Ve burada Nesne Yönelimli kod ile Nesne Takıntılı kod arasındaki fark. Sadece bir nesne hiyerarşisi oluşturabildiğiniz için mutlaka yapmanız gerektiği anlamına gelmez.
corsiKa

2
@ AgustínLado Bir müşteri her seferinde bir dolarım olsaydı "Bu asla değişmeyecek" dedi ve değiştiyse, akşam yemeğinde ikimizi de iyi bir restorana götürebilirim (biraz bahşiş olmasına rağmen, belki de sadece vasat bir restoran ... akşam yemeği için yine de iki kez yeteri kadar.)
corsiKa

29

Kural olarak, nesneler farklı kodlar gerektirdiğinde farklı sınıflar ve nesneler yalnızca farklı değerler gerektirdiğinde aynı sınıfın örneklerini kullanmanız gerekir.

Kaynaklar kendilerine özgü farklı oyun mekaniğine sahip olduğunda, bunları sınıflarla temsil etmek mantıklı olabilir. Örneğin, yarı ömürlü bir Plutonium ve buna göre üreyen Tavşanlar olduğunda Fibonacci dizisi , daha sonra bir taban sınıfı için mantıklı Resourcebir yöntem ile Updateno-op, iki türetilmiş sınıflar olarak uygulanır HalfLifeResourceve SelfGrowingResourcebu değeri azaltmak / artırmak için bu yöntemi geçersiz kılın (ve belki de ikisini de yan yana sakladığınızda ne olacağını yöneten bir mantık da olabilir).

Ancak, kaynaklarınız gerçekten sadece aptal sayılar olduğunda, bunları basit bir değişkenden daha süslü bir şeyle uygulamak hiç mantıklı değildir.


Cevabınız için @Phillipp teşekkürler. Ben de öyle düşünüyordum. Ancak kaynaklar, özellikler / yöntemler açısından gerçekten değişmeyecek, o yüzden şimdilik seçenek 2 ile devam
edeceğim

14

Ekstra iki seçenek daha eklemek isterim:
Arayüz: kaynak sınıfının 5 tamsayı için sadece bir "depolama" olup olmadığını ve diğer şirketlerin kaynaklar konusunda farklı mantıkları olacağını düşünebilirsiniz (örneğin, oyuncu harcaması / ganimet, şehir üretir) kaynak). Bu durumda, hiç bir sınıf istemeyebilirsiniz - yalnızca bazı varlıkların diğerlerinin etkileşime girebileceği bir değişkeni olduğunu ortaya koymak istediniz:

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

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

Buna ek olarak, bu, düşman filosunu yağmalayacağınız aynı kodla bir şehri yağmalayabileceğiniz ve kodun yeniden kullanılmasını teşvik edeceğiniz konusunda ters.
Dezavantajı, bu tür bir arayüzün uygulanması, eğer birçok sınıf bunu uygularsa can sıkıcı olabilir, bu yüzden arayüzleri kullanmaya başlayabilir, ancak orijinal problem için değil, seçenek 1 veya 2 ile çözebilirsiniz:

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

Örnekler (enum ile): Bazı durumlarda, kaynak türünü tanımlarken string yerine enum kullanmak istenebilir:

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

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

nokta yazdıktan sonra onu atarken IDE size tüm geçerli kaynakların listesini verecektir çünkü bu, "güvenlik" biraz sağlayacaktır ResourceType = Resource.ek olarak çeteleler daha "hile" vardır, belki açık Tipi veya kompozisyona / gibi ihtiyaç bayrakları işçiliği yaparken yararlı olacağını hayal edebiliyorum:

[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"


Neyin en iyisi olduğuna gelince - gümüş mermi yok, ama şahsen herhangi bir örnek formuna yaslanacağım, arayüz kadar süslü olmayabilirler ama basitler, kalıtım ağacını karıştırmazlar ve yaygın olarak anlaşılırlar.


2
Cevabınız için teşekkür ederim @wondra Enum seçeneğini ve bakırdan ve kalaydan bronz
çıkarımı beğendim

2
Bu topluluğa özel olarak katıldım, böylece enum çözümünü oylayabileyim. Ayrıca , enum'un ( ) bazı JSON temsilinden enum'un ( ) bazı C # temsiline eşlemek için enum Description niteliğini kullanmaya bakabilirsiniz . my-great-enumMyGreatEnum
Dan Forbes,

Görünüşe göre Java döngüsünden çok uzun zamandır uzaktayım. Ne zamandan beri arayüzler için saha bildirimlerine izin veriliyor? Bildiğim kadarıyla bunlar otomatik olarak statik ve nihai ve bu nedenle soruda açıklanan amaçlar için pek kullanılmıyorlar.
M.Herzkamp

2
@ M.Herzkamp bir alan değil, bir özellik - ve Java özellikleri desteklemiyor. Soru C #, C # etiketli arayüzlerde özelliklere izin verir - özellikler sonuçta başlıkların altındaki yöntemlerdir. Korkarım aynısı bayrak açıklamaları için de geçerli, Java ile desteklenmiyor, ancak tam olarak emin değilim.
wondra

Bunu temizlediğin için teşekkürler! C # etiketini özledim ve sorudaki kod çok Java'ya benziyordu: D
M.Herzkamp

2

3 avantajı olan seçenek 1'i kullanmalısınız:

  1. Bir kaynağın somutlaştırılması daha kolaydır - kaynağın türünü bir parametre olarak iletmek yerine, örneğin, new Gold(50)
  2. Bir kaynağa özel davranış vermeniz gerekirse, sınıfını değiştirerek yapabilirsiniz.
  3. Bir kaynağın belirli bir tür olup olmadığını kontrol etmek daha kolaydır - resource instanceof Gold

Tüm cevapların artıları ve eksileri var, hangisinin daha iyi olduğunu seçmek zor. Soruya bir düzenleme yaptım, bu yapı hakkında ne düşünüyorsunuz?
MDijkstra

1

Kaynaklarınızın kendilerine ait bir iş mantığı ya da çevre ile nasıl etkileşime girdiklerine ilişkin özel senaryolar yoksa, diğer kaynaklar (kapladığınız ticaretin yanı sıra) veya müzikçalar varsa, ikinci seçenek yenilerini eklemeyi çok kolaylaştırır.

El işi için iki kaynağı karıştırırsanız, kaynaklar çok farklı özelliklere sahipse (bir kova su kömürden çok farklıdır) veya diğer karmaşık ekonomik etkileşimler içeriyorsa, ne olacağını düşünmeniz gerekiyorsa, yaklaşım 1 motor için çok daha esnek, ancak veriler için değil.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.