Oyun eylemlerini gerçekleştirmek için desen


11

Bir oyun içinde çeşitli eylemleri gerçekleştirmek için genel kabul görmüş bir kalıp var mı? Bir oyuncunun eylemleri gerçekleştirmesinin bir yolu ve ayrıca bir AI'nın hareket, saldırı, kendini imha vb.

Şu anda çeşitli eylemler tarafından döndürülen farklı nesneleri belirtmek için .NET jeneriklerini kullanan soyut bir BaseAction var. Bu, her eylemin kendisinden sorumlu olduğu ve ihtiyaç duyduğu her şeyi yaptığı Komuta benzer bir desende uygulanır.

Soyut olma nedenim, tek bir ActionHandler'ım olabilir ve AI sadece baseAction'ı uygulayan farklı eylemleri sıralayabilir. Ve genel olmasının nedeni, farklı eylemlerin eylemle ilgili sonuç bilgilerini (farklı eylemler oyunda tamamen farklı sonuçlara sahip olabileceği için) yanı sıra bazı eylem öncesiAksiyon ve afterAction uygulamalarını döndürebilmesidir.

Yani ... bunu yapmanın daha kabul edilmiş bir yolu var mı, yoksa kulağa hoş geliyor mu?


Kulağa hoş geliyor, soru sıra ile ne demek istiyorsun? Çoğu oyunda çok hızlı tepki var mı? "AI farklı eylem sıraya alabilir"
AturSams

İyi bir nokta. Sıra yok. Sadece meşgul olup olmadığını bilmeli ve eğer değilse, eylemi gerçekleştirmelidir.
Arkiliknam

Yanıtlar:


18

Orada sanmıyorum biri bu kavramı uygulanması kabul yolu, ama gerçekten paylaşmak istiyorum nasıl ben genellikle benim oyunlarda bu başa. Komut tasarım deseni ile Kompozit tasarım deseninin bir kombinasyonudur .

UpdateHer çerçeve denilen bir yöntem ve bir Finishedeylemin ne zaman tamamlandığını gösteren bir bayrak etrafında bir sarıcı başka bir şey değildir eylemler için soyut bir temel sınıf var.

abstract class Action
{
    abstract void Update(float elapsed);
    bool Finished;
}

Bileşik tasarım desenini, diğer eylemleri barındırabilen ve yürütebilecek bir tür eylem oluşturmak için de kullanıyorum. Bu da soyut bir sınıf. İndirgenir:

abstract class CompositeAction : Action
{
    void Add(Action action) { Actions.Add(action); }
    List<Action> Actions;
}

Sonra, biri paralel yürütme ve diğeri sıralı yürütme için olmak üzere iki bileşik eylemim var . Ancak güzellik şu ki, paralel ve dizi eylemler kendileri olduğundan, daha karmaşık yürütme akışları oluşturmak için birleştirilebilirler .

class Parallel : CompositeAction
{
    override void Update(float elapsed) 
    {
        Actions.ForEach(a=> a.Update(elapsed));
        Actions.RemoveAll(a => a.Finished);
        Finished = Actions.Count == 0;
    }
}

Ve sıralı eylemleri yöneten.

class Sequence : CompositeAction
{
    override void Update(float elapsed) 
    {
        if (Actions.Count > 0) 
        {
            Actions[0].Update(elapsed);
            if (Actions[0].Finished)
                Actions.RemoveAt(0);
        }
        Finished = Actions.Count == 0;
    }
 }

Bunun yerinde olması, basitçe somut eylem uygulamaları yaratma ve yürütme akışını kontrol etmek için Parallelve Sequenceeylemlerini kullanma meselesidir . Bir örnekle bitireceğim:

// Create a parallel action to work as an action manager
Parallel actionManager = new Parallel();

// Send character1 to destination
Sequence actionGroup1 = new Sequence();
actionGroup1.Add(new MoveAction(character1, destination));
actionGroup1.Add(new TalkAction(character1, "Arrived at destination!"));
actionManager.Add(actionGroup1);

// Make character2 use a potion on himself
Sequence actionGroup2 = new Sequence();
actionGroup2.Add(new RemoveItemAction(character2, ItemType.Potion));
actionGroup2.Add(new SetHealthAction(character2, character2.MaxHealth));
actionGroup2.Add(new TalkAction(character2, "I feel better now!"));
actionManager.Add(actionGroup2);

// Every frame update the action manager
actionManager.Update(elapsed);

Bu sistemi daha önce bir grafik macerada tüm oyunu sürmek için başarıyla kullandım, ancak muhtemelen hemen hemen her şey için çalışmalıdır. Ayrıca, yürütme döngüleri ve koşullarını oluşturmak için kullanılan diğer bileşik eylem türlerini eklemek de yeterince basitti.


Çok güzel bir çözüm gibi görünüyor. Meraktan sonra, UI'nin ne çizeceğini bilmesini nasıl sağlıyorsunuz? Oyun nesneleriniz (karakterler gibi) görüntü oluşturma amacıyla neler olduğunu tanımlamak için kullanılan bir durum içeriyor mu yoksa eylemin kendisi bunu yapıyor mu?
Arkiliknam

1
Genellikle eylemlerim yalnızca varlıkların durumunu değiştirir ve oluşturulan çıktıda yapılan değişiklikler, eylemlerin kendileri aracılığıyla değil, bu durum değişikliğinin bir sonucu olarak gerçekleşir. Örneğin, anında mod oluşturucuda, Drawyöntem varlığın durumu üzerine zaten kurulduğundan ve değişiklikler otomatik olduğundan fazladan bir adım gerekmez . Flash gibi bir tutulan mod oluşturucusunda, varlıklarınızda görüntüleme nesnelerine yayılan değişiklikler yapmak veya bağlantıyı varlığın kendisinde manuel olarak yapmak için gözlemlenebilir deseni kullanabilirsiniz.
David Gouveia

1
İlk durumda, Charactersınıfınızın bir Positionözelliğine ve Drawgeçerli değerinin ne olduğunu okuyan Positionve orada doğru görüntüyü çizen bir yönteme sahip olduğunu varsayalım . Bu durumda, yalnızca Positionsonucun ekranda otomatik olarak görüleceği değeri güncellemeniz gerekir .
David Gouveia

1
İkinci durum, Characterbir Positionözelliğiniz olduğunda, ancak Spritebir sahne grafiği veya başka bir şey tarafından otomatik olarak oluşturulan bir tür nesneye dönüştürmeyi temsil eder. Bu durumda, hem karakterin hem de hareketli grafiğin konumunun her zaman senkronize olduğundan emin olmalısınız, bu da biraz daha fazla iş gerektirir. Yine de, her iki durumda da, eylem yöneticisinin neden bununla ilgisi olması gerektiğini anlamıyorum. :)
David Gouveia

1
Her iki yöntemin de avantajları ve dezavantajları var .. 2D oyunum için ikinci yöntemle gittim ve zaman zaman pişman oldum, çünkü her şeyi senkronize tutmak çok daha karmaşık. Ancak, örneğin, hangi varlığın tıklandığını veya neyin çizilmesi gerektiğini veya çizilmemesi gerektiğini belirlemeye çalışırken de avantajlar vardır, çünkü oluşturulacak her şey N varlık türleri arasında dağılmak yerine aynı veri yapısında bulunur.
David Gouveia
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.