OOP olmadan oyun nasıl yapılır? [kapalı]


10

Şu anda oyun geliştirme ve oyun yapma çalışmaları yapıyorum.

Oyunlarımda çok fazla OOP kullanıyorum. Örneğin, atılan her füze bir Missilenesnenin örneğidir ve bir nesne listesine eklenir Missile. Oyundaki her tank bir Tanknesnedir. Vb.

Programın tüm tasarımı buna dayanmaktadır. Örneğin, bir Missilenesne listesine sahip olmak, her karenin füzeleri taşımamı, onları Tankçizmemi vb. Sağlar.

Bir oyunun (Pac-Man'dan daha karmaşık olan) OO olmayan bir dilde nasıl programlanabileceğini hayal etmek benim için zor. (Tabii ki OO olmayan programcılara saygısızlık). Sadece ne kadar süreceği değil, çoğunlukla oyunun bu şekilde nasıl tasarlanabileceği açısından.

Nesne yönelimli programlama kullanmadan bir oyun tasarlamayı hayal edemiyorum, çünkü bir oyun programının nasıl tasarlanacağına dair tüm anlayışım OOP'ye dayanıyor.

Sormak istiyorum: Bugün, yukarıda tarif ettiğim gibi benzer şekilde OOP kullanılarak programlanmayan oyunlar var mı? Geliştirme sürecinde OOP'u temel faktör olarak kullanmayan 'professionl' oyunlar var mı?

Eğer öyleyse, bana, örneğin, bir tank ve N sayıda füze arasındaki çarpışma tespitinin OOP olmadan nasıl uygulanabileceği hakkında bir fikir verebilir misiniz?


6
Bu felsefi bir soru mu? Tanklarınıza "nesne" demeseniz bile, muhtemelen "varlıklar", "aktörler", "aracılar", "yapılar" veya aynı fikir için başka bir ad isteyeceksiniz . tank denen şeyleri vurabilen bir taretle dönen küboid bir şey oluşturan özellikler ve davranışlar. Programlama dilleri aynı fikri resmileştirmenin farklı yollarına sahip olacak, ama sonunda bir tank olacak.
Anko

Birçok oyun Bileşen tabanlı bir sistem kullanarak bu cevap açıklamaktadır: gamedev.stackexchange.com/a/31491/9366
John McDonald

Bu hem son derece geniştir (kapsamı daraltarak düzeltebilirsiniz) ve oyun geliştirmeye gerçekten özgü değildir (çünkü OO teknikleri olmadan yazılım oluşturmak, oyun geliştiricisinin diğer yazılım geliştiricilerinden daha iyi bir cevap vereceği bir şey değildir), korkarım.

StackOverflow için uygun olabilir veya bu tür geniş, tartışma odaklı konulara izin verecek şekilde oyun geliştirmeye özgü (GDNet gibi) çeşitli siteler bulmak için yardım merkezine bakabilirsiniz. İyi şanslar!

Yanıtlar:


16

Nesne yönelimli programlama kullanmadan bir oyun tasarlamayı hayal edemiyorum, çünkü bir oyun programının nasıl tasarlanacağına dair tüm anlayışım OOP'ye dayanıyor.

O zaman bazı programları OO olmayan bir tarzda yazmayı denemeniz muhtemelen iyi olacaktır. Bunun sizin için pragmatik olmadığını keşfetseniz bile, gelecekte size yardımcı olacak çok şey öğreneceksiniz.

OO tarzı oyunlar için oldukça uygundur, çünkü oyunlar neredeyse her zaman durumsal nesnelerin manipülasyonu ile ilgilidir. Lazer ışını robota çarpar ve kimliği aynı kalırken robotun durumu değişir.

Ancak oyunları işlevsel bir tarzda programlamak mümkündür . İşlevsel bir tarzda durum kendiliğinden değişmez. Nesneler değişmez. Nesneleri değiştirmek yerine, bunu değiştirirsem evrenin nasıl farklı olacağını soruyorsunuz ? ve sonra değişmiş özelliğe sahip yepyeni bir evren üretiyoruz. Elbette, daha önce var olan evrenin çoğunu yeniden kullanabilirsiniz, çünkü değişmezdir .

Fonksiyonel programlamada her fonksiyonun dönüş değerini sadece iletilen bilgilerden hesaplaması gerekir; "küresel devlet" ten okuma yok.

Bunu yaparsanız, kafanızdan geçmeniz gereken temel sorun, her güncellemenin tahribatsız olmasıdır . Lazer robota çarptığında, robotun durumunu değiştirmezsiniz. Sonuçta, robotun farklı bir durumu olması dışında, eski evrenle tamamen yeni bir evreni hesaplarsınız; eğer o eski evrene ihtiyacınız varsa, o hala oradadır, değişmez.

Bu blog makaleleri dizisi, oyunları işlevsel bir tarzda yazma hakkında daha fazla düşünceye sahiptir:

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

Bu makalede "kabuk bir tanka çarpıyor" sorusu özellikle ele alınmaktadır:

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

Aslında, sadece blogun tamamını okuyun. Orada iyi şeyler var ve makaleler kısa.


12

Herhangi bir nesne yönelimli program, tüm sınıfları yapılarla değiştirerek ve tüm üye işlevlerini thisbağımsız değişken olacak nesneyi alan bağımsız bir işleve dönüştürerek yordamsal bir programa yeniden düzenlenebilir .

Yani

 missile.setVelocity(100);

olur

 setMissileVelocity(missile, 100);

veya bu işlev önemsiz olduğunda,

 missile.velocity = 100;

Nesneye yönelik programlama ile prosedürel programlama arasındaki temel fark, verilerinize nasıl davranacağınızdır. OOP'de veri akıllıdır . Kendini yönetir ve manipüle eder. Ancak prosedürel programlamada veriler aptaldır . Kendi başına bir şey yapmaz ve dışarıdan manipüle edilmesi gerekir.

Yapıları çok fazla nesne yönelimli olarak değerlendirdiğinizde, bir dizi yapıyı, bir füzenin değişkeni olacak her şey için birden çok diziyle değiştirebilirsiniz. Yani

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

Missile missiles[256];

olur

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

Bu tasarımda, aynı füze üzerinde birden fazla öznitelik içeren bir işlem yapan bir işlev artık bir yapıya başvuru yapmak yerine bir dizi dizini alacaktır. Uygulanması şöyle görünecektir:

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

1
Ancak missilebir nesnenin örneğidir. OOP olmayanlarda hiçbir örnek yok, doğru muyum? Öyleyse, setMissileVelocity'yi (füze, 100) nasıl yapabilirsiniz?
user3150201

1
@ user3150201 Tamamen doğru değilsiniz. OOP olmayan dillerin çoğu (ve ciddi oyun geliştirme için uygun olan her şeyi tartışırım) yapıları destekler. Bir yapı bir sınıf gibidir, sadece kamu değişkenleri dışında hiçbir şey içermez. Eğer bir türünü oluşturmak için olanak sağlayacak Yani Missilebir yapı çeşitli alanlarda, benzeri ile, x, y, angleve velocity.
Philipp

@ user3150201 Yanıt, yapıları olmadan nasıl yapılacağı ile ilgili bir bölümle güncellendi.
Philipp

Güzel cevap Philipp, bununla birlikte neden Nesneye Dayalı programlamak istemeyeceğinizi anlamıyorum. OOP olmayan dilleri okumak gerçekten zor ve sinir bozucu olabilir. Kod kısa sürede ortalığı karıştırabilir.
Zhafur

2
@Zhafur İfadenizin büyük bir flamebait olduğunun farkındasınız, değil mi?
Philipp

6

Bunu aşağıdaki gibi yapıyorum:

  • Tüm OOP sınıflarının / yöntemlerinin erişimi vardır this. thisOO olmayan bir yaklaşımda kullanmak thisiçin, ilk parametre olarak hangi örneğin (bir sonraki noktaya bakın) olması gerektiğini girin.
  • Şimdi, örneklerde structolduğu gibi this, işlevlerinize geçebilirsiniz , ancak varlıklar veya parçacıklar gibi üretken nesneler için iyi bir önbellek performansı elde etmenin en iyi yolunu buluyorum, sadece tek bir indeksi birkaç ilkel dizisine geçirmek veya küçük structs. Bu nedenle, bu dizin orijinal sınıfın her bir veri üyesi için kullanılır. Örneğin,

...

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

Onun yerine

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

Böylece, genellikle ne olacağını elde etmek için işleve bir dizin geçiriyorsunuz this.

Verilerinizin iyi önbellek yeri (başvuru yeri) için en iyi nasıl serpiştirilebileceğine bağlı olarak, yukarıdaki gibi ilkel dizilerini veyastruct s dizilerini kullanmak isteyebileceğinizi unutmayın . Elbette, iyi önbellek performansı bundan çok daha fazlasına dayanır - özellikle, kodunuzu hangi dilde / platformda yazdığınızı - ama Java gibi VM tabanlı, dinamik olarak ayrılmış dillerde bile, büyük doğrusal ilkel dizileri nesne örneklerinden daha iyi performans özellikleri gösterir. Bunun temel nedeni, nesnelere referansla erişilmesidir ve bu, verilere erişmek için tüm belleğe atladığınız anlamına gelir - ilkellere büyük bir diziden bitişik olarak erişmeye kıyasla verimsiz.

Bir dizi yapı veya ilkel olarak bina varlıkları vb. Hakkında daha fazla bilgi için, bkz. Mick West'in Hiyerarşinizi Evrimleşmesi .


0

Mevcut cevaplara ek olarak, prosedürel bir dilde polimorfizmin nasıl yapılacağını bilmek isteyebilirsiniz.

İki yaklaşım vardır:

Türü saklama

Bu durumda, yapı tip tanımlayıcı için bir alana, muhtemelen bir numaralamaya sahiptir, switchtüre özgü eylemin yapılması gerektiğinde bir ifade kullanılarak kontrol edilir .

Diğer yol:

İşlev işaretleyicilerini saklama

Hangi programlama dilini deneyimlediğinizden bahsetmediniz, ancak çeşitli dillerde bunlara geri çağrılar, delegeler, etkinlikler veya üst düzey işlevler veya basitçe işlev nesneleri denir.

Bu durumda, bir türü saklamaz, ancak belirli eylemi gerçekleştiren bir işleve bir işaretçi / başvuru depolarsınız. Türe özel eylemin yapılması gerektiğinde, bu işlevi çağırmanız yeterlidir. Bu, sıradan sanal yöntemlere çok benziyor.

Her fonksiyonun bağımsız olarak ayarlanmasına izin vererek, strateji düzenini serbest bırakırsınız .


Çarpışma tespiti ile son paragrafınız hakkında. Sanırım muhtemelen birden fazla tank türünüz var ve birden fazla füze türünüz var ve her kombinasyon çarpıştıklarında potansiyel olarak farklı bir sonuca sahip olabilir. Eğer aradığınız buysa, OOP dilleri tarafından bile henüz çözülmemiş bir sorununuz var: çoklu gönderim ve thisfarklı türde birden fazla parametreye sahip olabilen çoklu yöntemler . Bu sorun için yine iki alternatif var:

  • Her tank ve füze kombinasyonu için yuvalanmış anahtarlar.
  • Her tank ve füze kombinasyonu için işlevlere işaretçiler içeren iki boyutlu dağıtım dizileri.
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.