Oyun Motorunu sürümle birlikte benzer oyunlardaki oyun kodundan ayırma


15

Bitmiş bir oyunum var, diğer sürümlerde reddetmek istiyorum. Bunlar benzer oyunlar, az ya da çok aynı tasarıma sahip olacaktı, ama her zaman değil, temelde bazı şeyler değişebilir, bazen az, bazen büyük.

Çekirdek kodun oyundan ayrı olarak sürümlendirilmesini istiyorum, böylece A oyununda bulunan bir hatayı düzeltirsem, düzeltme B oyununda mevcut olacak.

Bunu yönetmenin en iyi yolunu bulmaya çalışıyorum. İlk fikirlerim şudur:

  • Oluşturduğunuz bir engineGenelleştirilebilen ve oyunun geri kalanından% 100 bağımsız olan her şeyi içeren modül / klasör / ne olursa olsun . Bu, bazı kodların yanı sıra oyunlar arasında paylaşılan jenerik varlıkları da içerir.
  • Bu motoru gitoyunlara dahil edilecek olan kendi deposuna koyun.git submodule

Mücadele ettiğim kısım, kodun geri kalanının nasıl yönetileceği. Diyelim ki menü sahneniz var, bu kod oyuna özgüdür, ancak çoğu genel olma eğilimindedir ve diğer oyunlarda yeniden kullanılabilir. Onu koyamıyorum engine, ancak her oyun için yeniden kodlamak verimsiz olurdu.

Belki bir çeşit git dalları varyasyonu kullanmak bunu yönetmek için etkili olabilir, ama bunun en iyi yol olduğunu düşünmüyorum.

Herkesin paylaşacağı bazı fikirler, deneyimler veya bununla ilgili bir şey var mı?


Motorunuz hangi dilde? Bazı diller git alt modüllerini kullanmaktan daha anlamlı olabilecek özel paket yöneticilerine sahiptir. Örneğin, NodeJS'nin npm değeri vardır (Git depolarını kaynak olarak hedefleyebilir).
Dan Pantry

Konfigürasyonun genel kodu nasıl yöneteceği veya "yarı jenerik" kodun nasıl yönetileceği veya kodun nasıl yapılandırılacağı, kodun nasıl tasarlanacağı veya ne yapılacağı ile ilgili sorunuz mu var?
Dunk

Bu, her Programlama Dili Ortamında değişiklik gösterebilir, ancak yalnızca Kontrol Sürümü Yazılımını değil, aynı zamanda oyun motorunun oyun kodundan (paketler, klasörler ve API gibi) ve daha sonra nasıl bölüneceği ile de başlayabilirsiniz. , Denetim Sürümü'nü uygulayın.
umlcat

Bir dalda bir klasörün temiz bir geçmişine sahip olmak: Motorunuzu yeniden düzenleyin, böylece ayrı (gelecekteki) repolar ayrı klasörlerde olur, son işiniz budur. Ardından yeni bir şube oluşturun, bu klasörün dışındaki her şeyi silin ve taahhüt edin. Ardından, repo'nun ilk taahhüdüne gidin ve bunu yeni şubenizle birleştirin. Artık yalnızca bu klasöre sahip bir şubeniz var: diğer projelerde çekin ve / veya mevcut projenizle birleştirin. Bu, kodunuz zaten ayrılmışsa, motorları dallardaki ayırmada bana çok yardımcı oldu. Git modüllerine ihtiyacım yok.
Barry Staes

Yanıtlar:


13

Genelleştirilebilen ve oyunun geri kalanından% 100 bağımsız olan her şeyi içeren bir motor modülü / klasör / ne olursa olsun oluşturun. Bu, bazı kodların yanı sıra oyunlar arasında paylaşılan genel varlıkları da içerir.

Bu motoru oyunlara git alt modülü olarak dahil edilecek olan kendi git deposuna koyun

Ben de öyle yapıyorum ve çok iyi çalışıyor. Bir uygulama çerçevem ​​ve bir oluşturma kitaplığım var ve bunların her biri projelerimin alt modülleri olarak kabul ediliyor. SourceTree'yi buluyorum altmodüllerin geldiğinde onlara iyi yönetir ve proje A'da motor alt modülünü güncellenen, eğer proje B'de değişiklikleri çekmeye size bildirir Eğer örneğin bir şey unutmak izin vermeyecek şekilde, yararlıdır

Tecrübe ile birlikte, motorda hangi kodun olması gerektiği ve proje başına ne olması gerektiği bilgisi de gelir. Eğer biraz emin değilseniz, şimdilik her projede saklamanızı öneririm. Zaman geçtikçe, çeşitli projeleriniz arasında neyin aynı kaldığını göreceksiniz ve daha sonra bunu motor kodunuza kademeli olarak aktarabilirsiniz. Başka bir deyişle: kodu, proje başına ayrı ayrı değişmediğinden% 100'e yakın olduğunuza kadar çoğaltın, sonra genelleştirin.

Kaynak Kontrolü ve İkililer Hakkında Not

İkili varlıklarınızın sık sık değişmesini bekliyorsanız, bunları git gibi metin tabanlı kaynak denetimine koymak istemeyeceğinizi unutmayın. Sadece diyorum ki ... ikili dosyalar için daha iyi çözümler var. "Motor kaynağı" deponuzu temiz ve performansınızı korumanıza yardımcı olmak için yapabileceğiniz en basit şey, projenizde bir alt modül olarak da eklediğiniz, yalnızca ikili dosyaları tutan ayrı bir "motor-ikili dosyalar" deposuna sahip olmaktır. Bu şekilde "motor kaynağı" deponuza yapılan performans hasarını her zaman değiştirerek hızlı yinelemelere ihtiyaç duyduğunuz şekilde azaltırsınız: taahhüt, itme, çekme vb. Git gibi metin kontrol yönetim sistemleri metin deltalarında çalışır ve ikili dosyaları tanıtır getirmez, metin açısından büyük deltaları tanıtırsınız - bu da sonuç olarak size dev zaman kazandırır.GitLab Ek . Google senin arkadaşın.


Gerçekten sık sık değişmiyorlar, ama bununla ilgileniyorum. İkili sürüm oluşturma hakkında hiçbir şey bilmiyorum. Hangi çözümler var?
Malharhak

@Malharhak Yorumunuzu cevaplamak için düzenlendi.
Mühendis

@Malharak İşte bu konuda güzel bilgiler .
Mühendis

1
Projede mümkün olan en uzun süre tutmak için +1 . Ortak kod daha yüksek karmaşıklık sağlar. Kesinlikle gerekli olana kadar bundan kaçınılmalıdır.
Gusdor

1
@Malharhak Hayır, özellikle de amacınız, yalnızca söz konusu kodun değişmez olduğunu ve ortak olarak değerlendirilebileceğini not edene kadar "kopyaları" tutmaktır. Gusdor bunu tekrarladı - uyarılmalıdır - kişi işleri çok erken faktoring ederek kolayca zaman harcayabilir, daha sonra bu kodu ortak kalacak kadar genel tutmanın yollarını bulmaya çalışabilir, ancak çeşitli projelere uyacak kadar uyarlanabilir ... bir bütün parametreler ve anahtarların sürü ve hala yeni proje başına değiştirmeyi sona çünkü ne ihtiyaç olmadığını çirkin bir hale dönüştürülür zaten . Çok erken hesaba katmayın . Sabırlı ol.
Mühendis

6

Bir noktada bir motor oyun hakkında uzmanlaşmalı ve Bilmeniz GEREKİR. Burada bir tanjantla gideceğim.

Kaynakları bir RTS'de alın. Bir oyun olabilir Creditsve Crystalbaşka MetalvePotatoes

OO kavramlarını düzgün kullanmalı ve maks. kod yeniden. Burada bir kavram olduğu açıktır Resource.

Bu yüzden kaynakların aşağıdakilere sahip olduğuna karar veriyoruz:

  1. Ana döngüdeki bir kanca, kendilerini arttırmak / azaltmak için
  2. Geçerli tutarı almanın bir yolu (döndürür int)
  3. Keyfi olarak çıkarma / ekleme için bir yol (oyuncular kaynak aktarımı, satın alma ....)

Bu a fikrinin Resourcebir oyundaki öldürme veya puanları temsil edebileceğine dikkat edin ! Çok güçlü değil.

Şimdi bir oyun düşünelim. Bir miktar para birimiyle başa çıkıp çıktıya ondalık nokta ekleyerek bir çeşit paraya sahip olabiliriz. Yapamayacağımız şey "anlık" kaynaklar. Gibi "güç şebekesi üretimi" demek

Diyelim ki InstantResourcebenzer yöntemlere sahip bir sınıf ekliyorsunuz . Artık motorunuzu kaynaklarla kirletmeye başlıyorsunuz.


Sorun

RTS örneğini tekrar alalım. Varsayalım ki oyuncu Crystalbaşka bir oyuncuya bağışta bulunursa . Gibi bir şey yapmak istiyorsunuz:

if(transfer.target == engine.getPlayerId()) {
    engine.hud.addIncoming("You got "+transfer.quantity+" of "+
        engine.resourceDictionary.getNameOf(transfer.resourceId)+
        " from "+engine.getPlayer(transfer.source).name);
}
engine.getPlayer(transfer.target).getResourceById(transfer.resourceId).add(transfer.quantity)
engine.getPlayer(transfer.source).getResourceById(transfer.resourceId).add(-transfer.quantity)

Ancak bu gerçekten çok dağınık. Genel amaçlı ama dağınık. Zaten bir dayatmasına rağmen resourceDictionary, kaynaklarınızın isimleri olması gerektiği anlamına geliyor! VE oyuncu başına, bu yüzden artık takım kaynaklarına sahip olamazsınız.

Bu "çok fazla" soyutlama (itiraf edeceğim mükemmel bir örnek değil), bunun yerine oyununuzun oyuncuları ve kristali olduğunu kabul ettiğiniz bir noktaya çarpmalısınız, o zaman sadece (örneğin)

engine.getPlayer(transfer.target).crystal().receiveDonation(transfer)
engine.getPlayer(transfer.source).crystal().sendDonation(transfer)

Bir sınıf ile Playerve bir sınıf bireyin nesne otomatik bağış gönderen / transferi için HUD şeyler gösterecektir.CurrentPlayerCurrentPlayercrystal

Bu, motoru kristalle, kristal bağışını, mevcut oyuncular için HUD'daki mesajları ve tüm bunları kirletir. Okuması / yazması / bakımı hem daha hızlı hem de daha kolaydır (bu, daha hızlı olmadığı için daha önemlidir)


Son açıklamalar

Kaynak durumu parlak değil. Umarım yine de noktayı görebilirsiniz. Belirli bir oyunun ihtiyaç duyduğu ve tüm kaynak kavramları için geçerli olan şeylerin "kaynaklar motora ait olmadığını " göstermiş olduğum bir şey varsa ÇOK farklı şeylerdir. Genellikle bulacağınız 3 (veya 4) "katman"

  1. "Çekirdek" - bu motorun ders kitabı tanımı, olay kancaları olan bir sahne grafiği, gölgelendiriciler ve ağ paketleri ve soyut bir oyuncu kavramı ile ilgileniyor
  2. "GameCore" - Bu, oyun türüne oldukça geneldir, ancak tüm oyunlara değil - örneğin RTS'deki kaynaklar veya FPS'lerde mühimmat. Oyun mantığı burada sızmaya başlar. Burası daha önceki kaynak anlayışımız olacaktı. Çoğu RTS kaynağı için anlamlı olan bu şeyleri ekledik.
  3. "GameLogic" Gerçek oyun ÇOK özel yapılır. creatureVeya shipveya gibi adlara sahip değişkenler bulacaksınız squad. Kullanımı devralma tüm 3 kat yayılan sınıfları alırsınız sizin (örneğin Crystal bir olduğunu Resource hangi bir olduğunu GameLoopEventListener söylemek)
  4. "Varlıklar" diğer oyunlarda işe yaramaz. Örneğin AI betiklerini yarı ömür 2'de birleştirin, aynı motorla bir RTS'de kullanılmayacaklar.

Eski bir motordan yeni bir oyun yapmak

Bu ÇOK yaygındır. Aşama 1, katman 3 ve 4'ü (ve oyun tamamen farklı bir türse 2) sökmektir. Eski bir RTS'den bir RTS yaptığımızı varsayalım. Hala kristal ve malzeme değil, kaynaklarımız var - bu nedenle katman 2 ve 1'deki temel sınıflar hala anlamlıdır, 3 ve 4'te atıfta bulunulan tüm kristal atılabilir. Biz de öyle. Ancak bunu yapmak istediğimiz şey için bir referans olarak kontrol edebiliriz.


Katman 1'deki kirlilik

Bu olabilir. Soyutlama ve performans düşmandır. Örneğin UE4 çok sayıda optimize edilmiş kompozisyon örneği sağlar (bu nedenle X ve Y'yi isterseniz biri X ve Y'yi birlikte gerçekten hızlı yapan bir kod yazdı - her ikisini de yaptığını biliyor) ve sonuç olarak oldukça büyük. Bu fena değil ama zaman alıcı. Katman 1, "verileri gölgelendiricilere nasıl aktardığınız" ve şeylere nasıl animasyon uyguladığınıza karar verecektir. Projeniz için en iyi yolu yapmak DAİMA iyidir. Sadece geleceği planlamaya çalışın, kodu yeniden kullanmak arkadaşınızdır, mantıklı olduğu yeri miras alın.


Katmanları sınıflandırma

LASTLY (söz veriyorum) katmanlardan çok korkma. Motor, motorların hemen hemen aynı şekilde grafiksel olarak aynı şekilde çalıştığı (ve sonuç olarak ortak bir noktaya sahip olduğu) sabit işlevli boru hatlarının eski günlerinden eski bir terimdir. geliştiricilerin ulaşmak istedikleri her türlü etkiyle. AI, motorların ayırt edici özelliğiydi (sayısız yaklaşım nedeniyle), şimdi AI ve grafikler.

Kodunuz bu katmanlara dosyalanmamalıdır. Ünlü Unreal motorunun bile her biri farklı bir oyuna özgü birçok farklı versiyonu vardır. Değişmeyen birkaç dosya (belki de veri yapıları dışında) vardır. Bu iyi! Başka bir oyundan yeni bir oyun yapmak istiyorsanız bu süre 30 dakikadan fazla sürecektir. Anahtar planlamak, kopyalamak ve yapıştırmak için hangi bitleri ve neyi geride bırakmak gerektiğini bilmek.


1

Genel ve spesifik bir karışımın içeriğinin nasıl işleneceğine dair kişisel önerim onu ​​dinamik hale getirmektir. Menü ekranınızı örnek olarak alacağım. Ne istediğini yanlış anladıysam, bilmek istediğini bana bildirin, cevabımı uyarlayacağım.

Bir menü sahnesinde (neredeyse) her zaman mevcut olan 3 şey vardır: arka plan, oyun logosu ve menünün kendisi. Bunlar genellikle oyuna göre farklıdır. Bu içerik için yapabileceğiniz, motorunuzda 3 nesne parametresi alan bir MenuScreenGenerator yapmaktır: BackGround, Logo ve Menu. Bu 3 parçanın temel yapısı da motorunuzun bir parçasıdır, ancak motorunuz aslında bu parçaların nasıl oluşturulduğunu, sadece hangi parametreleri vermeniz gerektiğini söylemez.

Daha sonra gerçek oyun kodunuzda BackGround, Logo ve Menü için nesneler yaratırsınız ve bunu MenuScreenGenerator'ınıza iletirsiniz. Yine, oyunun kendisi menünün nasıl üretildiğini ele almıyor, bu motor için. Oyununuz sadece motora neye benzemesi gerektiğini ve nerede olması gerektiğini söylemelidir.

Temel olarak, motorunuz oyunun ne göstereceğini söyleyen bir API olmalıdır. Düzgün yapılırsa, motorunuz zor işi yapmalı ve oyununuz da motora sadece hangi varlıkların kullanılacağını, hangi eylemlerin yapılacağını ve dünyanın nasıl göründüğünü söylemelidir.

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.