Game State Sistemine Alternatif?


30

Söyleyebileceğim kadarıyla, çoğu oyun farklı oyun durumları arasında geçiş yapan bir tür "oyun durum sistemi"; bunlar "Intro", "MainMenu", "CharacterSelect", "Loading" ve "Game" gibi şeyler olabilir.

Bir yandan, bunları bir devlet sistemine ayırmak tamamen mantıklı geliyor. Ne de olsa, farklıdırlar ve aksi takdirde oldukça karışık olan büyük bir switch ifadesinde bulunmaları gerekir; ve kesinlikle bir devlet sistemi tarafından iyi temsil edilirler. Ancak aynı zamanda “Oyun” durumuna bakıyorum ve bu devlet sistemi yaklaşımıyla ilgili yanlış bir şey olup olmadığını merak ediyorum. Çünkü odadaki fil gibi; BÜYÜK ve aşikar ama hiç kimse oyun devlet sistemi yaklaşımını sorgulamıyor.

Bana “Oyun” un “Ana Menü” ile aynı seviyeye getirilmesi aptalca görünüyor. Oysa "Oyun" durumunu bölmenin bir yolu yok.

Bir oyun devlet sistemi gitmek için en iyi yol mu? “Oyun devletini” yönetmek için daha farklı teknikler var mı? Bir film çeken ve giriş dinleyen bir giriş durumu ve ardından kaynak yöneticisine giren yükleme durumu ve ardından hemen hemen her şeyi yapan oyun durumu olması uygun mudur? Bu senin için de dengesiz görünmüyor mu? Bir şey mi eksik?

Yanıtlar:


30

Bence burada anlambilimi tartışıyorsun. Buna Oyun Durumu denir, çünkü sınırlı sayıda durum ve aralarında geçişler olan bir Sonlu Durum Makinesi gibi davranır . 'Oyun Devleti Sistemindeki' Oyun 'genel sistemi ifade eder, oysa' Yükleniyor ',' MainMenu 'vb. Bunlar kolayca 'sahneler' veya 'ekranlar' veya 'seviyeler' olarak adlandırılabilir. Onun sadece anlambilimi.

Artık katı bir FSM'nin uygulandığından emin değilim. Yaptığım uygulamalarda 'Ekranlar' olarak adlandırıyorum ve istiflenmelerine izin veriyorum - yani. Ekranlar, altındaki ekranların güncellenip güncellenmeyeceğini kontrol ederek diğer ekranların üstüne çizilebilir. Bu şekilde, başka herhangi bir ekran için endişelenmek zorunda kalmadan, bağımsız mantık ve o ekrana özgü kod ile aynı anda etkin birden çok ekrana sahip olabilirim.

Örneğin, bir duraklatma ekranı, ana oyun ekranımın üstünde, güncellemeleri engelleyen, ancak aşağıda çizime izin veren bir ekran açılabilir. Bir karakter envanteri ekranı hem çizime hem de güncellemeye izin verebilir - böylece envanterinizde çalışırken oyun oynamaya devam eder.


Bu tam olarak nasıl yapılması gerektiğidir. Ekranlar, ağaç benzeri bir mimaride birden fazla başka ekran içerebilmelidir. Böylece, programınız bir ses ayarları ekranı ve bir oyun ayarları ekranı içeren bir duraklatma menüsü ekranı içeren bir oyun ekranı içerir. etc
Iain

1
Bunun için örnek kaynak kodunu görmek isterim! (Tercihen C ++ / C # / Java'da)
Zolomon

1
Ne yazık ki, şu anda yalnızca üretim kodum var, ancak XNA Game State örneğinde benzer bir konsept var: creators.xna.com/en-GB/samples/gamestatemanagement
DrDeth

7

Oyun durumunun çok büyük olacağından emin olabilirsiniz, ancak Oyun durumunun verilerini yönetmek için bir durum makinesi içerememesi için hiçbir neden yoktur. Hiyerarşik durum makineleri kullanışlıdır.


4

Her zaman "devlet" in bir "sahne" olduğunu düşünmeyi her zaman seviyorum. Yani açılış videosu bir sahne, sadece statik bir sahne. Krediler bir sahne. Menü bir sahne. Hepsi arasındaki tek fark etkileşim düzeyi ve oyun mantığı.


3

Aslında benim de sorunum var.

Diyelim ki bir Oyununuz var.

'Oyunu', 'Yükleniyor', 'Ana Menü' vb. Gibi bir durum haline getirmek yerine - IMO, Oyun'un çeşitli durumlara sahip olmasını sağlamak için daha iyidir :

"Yükleniyor" - "Menü gösteriliyor" - "duraklatıldı" vb.

Oyun hala çalışıyor, ancak ana menüyü gösterdiğinde 'show menu' modunda olacaktı.

Oyun herhangi bir durumda olmadığı zaman, sadece koşuyor.

En azından benim için çok daha anlamlı. :)


Katılıyorum. Hiç kimse Duraklama Durumuna girmek için Oyun Devletinden çıkmak istemez . Öte yandan: Bu hala bir devlet sistemi .. sadece yuvalanmış :)
bummzack

2

Bir çevrimiçi program (çevrimiçi olan geleneksel anlamında, yani internete bağlı anlamdan ziyade sürekli çalışan ve girdiye yanıt veren) tipik olarak 3 şeyden oluşur:

  • girdi toplama ve kullanma
  • mantığın güncellenmesi
  • çıktı

Genel olarak konuşursak, bu 3 aynı anda ilişkili ve değişim. Örneğin, bir açılış ekranını görüntülerken tüm tuşlarınızı bir 'close screen' komutuyla eşleştirebilirsiniz ve güncelleme, yalnızca o grafiği gösteren çıktıyla yavaşça bir grafiği soluyor olabilir. Ancak oyun oynarken, tuşların tümü farklı komutlarla eşlenebilir ve güncelleme birçok oyun içi nesnenin özelliklerini değiştirir.

Bu şekilde gördüğünüzde, bir Intro'yu Karakter Oluşturma ve Oyundan uygun şekilde ayırmak mantıklıdır: her birinin kendi giriş, güncelleme ve çıkış kuralları vardır. Neredeyse bazı verileri ve kütüphane kodlarını paylaşan kendi kendine yeten programlar gibiler. Ve bu akılda tutularak, oyun boyunca oldukça homojen olduğundan, genellikle tek bir Oyun durumuna sahip olmak mantıklıdır.

Tabii ki, aslında farklı oyun türlerine sahipseniz (örneğin, RPG örneği - Dünya Haritası, Şehir Haritası, Cutscene, Savaş), farklı girdi, güncelleme ve çıktıya sahip olmanız durumunda, burada birden fazla devlet olmamanız için hiçbir neden yok. Çok sadece 1 Oyun durumu yerine. Ama bu senin oyununa bağlı.


1

Ona başka bir yoldan bakıyorum. 'Menü', 'Yüksek Skorlar', "krediler" veya ne olursa olsun, başka bir seviye olarak kabul edilebilir ve daha sonra bu durum sizin 'oyun' durumunuzdan daha hafif olmayabilir (oyun devletinin genel olarak daha fazla varlığı vardır), ve farklı olanları, ancak sonuçta, işletmelerin daha öngörülebilir davranışlar gösterdiği ve 'haritalar' genellikle daha az karmaşık olan başka bir seviyedir).
Düşüncelerinizde bu değişimin yapılması sizi kesinlikle "sıkıcı menü" sendromundan çıkarır.


Ben de aynısını söyleyecektim ... Bütün menülerim, ekranlarım, her neyse, sadece başka bir seviye.
hız

1

Oyunda, ben var:

İcra Müdürü (oyunu) başlatan , kaynakları yükler, uygulama çıkışıyla ilgili kaynakları serbest bırakır, vb. Uygulama Motorunu, GameViewEngine, GameLogicEngine'ı başlatır.

Oyun Devlet MüdürüGameLogicEngine'de bulunan ve oyunun ana döngüsüyle ilgili olan şeylerin kontrolünden sorumlu olan : çarpışma tespiti, fizik hesaplama, klavye okuma, matematik işlemleri, vb ...

Başlangıçta, GameLogicEngine'imin bir parçası olan yalnızca bir Game State Manager'a sahip olma eğilimindeydim. Ancak, ana alt sistemlerin içselleştirilmesi üzerinde kontrol konusunda bazı zorluklar yaşadım (GameLogic, ApplicationEngine, ...). Yapılabilirdi, ama daha dağınıktı, imo.

Artık işler benim için daha şeffaf görünüyor ve tasarımdan memnunum.


0

'Oyun' durumunu 'Oyun' gibi bir şeyle yeniden adlandırın. O zaman mantığınız daha iyi görünüyor; Th menüsüne gitmek için oynamayı bırakırsınız: MainMenu durumuna gitmek için Oyun durumundan çıkarsınız.

Ayrıca, oyunu duraklattığınız gibi, oyunu duraklattığınız gibi aynı durumda olmanızı gerektiren şeylerin ayrı durumlar olmaması gerektiğini düşünüyorum. Belki de çocuk devletler ve yuvalar? Oyun-bir duraklatma menüsü vardır.


0

Oyun durumu yığını olarak adlandırılan iyi bir yöntem olduğunu düşünüyorum. Bununla ilgili herhangi bir makale veya makale görmedim, ancak sesle biraz yayılıyor. Temelde, yığındaki en üst düzey oyun durumu ilk olarak adlandırılır ve giriş / görüntü oluşturma vb. İle ne isterse onu yapar. En üst düzey oyun durumu, basma ya da açma durumlarına izin verilen tek kişidir.

Motorumda oyun durumları aslında sadece oyun varlıklarının listesi. Daha sonra menü olarak çalışan varlıklar var. Menü durumlarım ya oyunu duraklatır (yığındaki bir sonraki öğeyi güncelleyerek değil) ancak diğer durumların modellerini işleyiciye göndermesine izin verir, böylece duraklatma menüm (ekranın tamamını kapsamaz) arka tarafta oyun sunumu var.

Umarım bu, bir devlet makinesine dayanmayan biraz farklı bir sistem hakkında fikir verir.


0

Bir film çeken ve giriş dinleyen bir giriş durumu ve ardından kaynak yöneticisine giren yükleme durumu ve ardından hemen hemen her şeyi yapan oyun durumu olması uygun mudur? Bu senin için de dengesiz görünmüyor mu? Bir şey mi kaçırıyorum?

Bu tamamen iyi. Ya da en azından "oyuna bağlı olarak büyük çirkin bir anahtara sahip olmak" konusunda bir gelişmedir.

Çoğu oyunda basit varlık AI ile başa çıkmak için sonlu bir durum makinesine ihtiyaç duyacağınızı belirtmek isterim. Tipik örnek, Boşta, Saldırgan veya Ölüm durumundaki düşmanlar.

Yeterince soyutlanmış bir Sonlu Durum Makineniz varsa, onu hem Oyun nesnesi hem de AI'nız için tekrar kullanabilirsiniz; Birdenbire Oyun durumuna çok fazla çaba harcamazsınız - bunun yerine yine de kullandığınız kodu yeniden kullanıyorsunuz.

Utanmaz kendinden fişli ürünler: Bu tür bir Sonlu Durum Makinesi'ni Lua oyun kütüphanem MiddleClass'a (somut olarak, MindState denilen eklenti) yerleştirdim. İşte bununla Oyun Halini nasıl yaptığınız .


0

Buna farklı bir yaklaşım, Ayrımcılık Birliği olarak adlandırılan işlevsel programlama dünyasındaki bir kavramı kullanmaktır . Bunlar genellikle FP dillerinde bulunurken, bunları sınıfları kullanarak taklit edebilirsiniz .

Temel olarak, Ayrımcı Birlik , her zaman biri olan bir türdür.n vakalardan ve depolanan veriler her bir olayla değişebilir.

Örneğin:

type GameState =
  | Menu of MenuState
  | Playing of SimulationState

Burada bizim GameStatetipimiz Menuyada olabilir Playing. Eğer öyleyse Menu, o zaman bir MenuStatenesne içerecektir . Eğer öyleyse, Playingo zaman bir içerecekSimulationState nesne .

Güncellemek matchiçin durumdayız ve buna göre farklı bir işlev çağırırız:

let update gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> updateMenu gameTime menuState
    | Playing simulationState -> updateSimulation gameTime simulationState

  // Mutate the current state
  gameState <- nextState

Ve benzer şekilde render için:

let render gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> renderMenu menuState
    | Playing simulationState -> renderSimulation simulationState

Bu yaklaşımın bir avantajı, devletler arası (kaynaklar gibi) olayları globalsız veya "servis" nesnelerinin etrafından dolaşmadan daha kolay idare edebilmenizdir.

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.