ゲーム用の動作/コンポーネントベースのシステムを作成する


11

バックグラウンド

私はゲーム開発を趣味として行っており、それらを設計するより良い方法を探しています。現在、私は標準のOOPアプローチを使用しています(8年間エンタープライズ開発を行ってきたので、最終的には実現しています)。たとえば、「バディ」

public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
    //sprite base will have things like what texture to use, 
    //what the current position is, the base Update/Draw/GetInput methods, etc..
    //an AnimatedSprite contains helpers to animated the player while 
    //a StaticSprite is just one that will draw whatever texture is there
}

問題

私が2Dプラットフォーマーを作っているとしましょう、そしてバッドがジャンプできるようにする必要があります。通常、私が行うことは、Update / GetInputメソッドに適切なコードを追加することです。その後、プレーヤーにクロール、アヒル、登山などをさせる必要がある場合、コードはそこに行きます。

注意しないと、これらのメソッドが乱雑になるので、このようなメソッドのペアを作成することになります

CheckForJumpAction(Input input) そして DoJump()

CheckforDuckAction(Input input) そして DoDuck()

GetInputは次のようになります

public void DoInput(Input input)
{
    CheckForJumpAction(input);
    CheckForDuckAction(input);
}

更新は次のようになります

public void Update()
{
    DoJump();
    DoDuck();
}

プレイヤーがジャンプしてアヒルする必要がある別のゲームを作成する場合、通常、機能を備えたゲームに移動してコピーします。乱雑です、分かります。それが私がもっと良いものを探している理由です。

解決?

Blendに要素にアタッチできるビヘイビアがあることは本当に気に入っています。私は自分のゲームで同じコンセプトを使用することを考えてきました。それでは、同じ例を見てみましょう。

基本的なBehaviorオブジェクトを作成します

public class Behavior
{
    public void Update()
    Public void GetInput()
}

そして、それを使用してビヘイビアを作成できます。JumpBehavior:BehaviorそしてDuckBehavior:Behavior

その後、ビヘイビアのコレクションをSpriteベースに追加し、必要なものを各エンティティに追加できます。

public class Baddie:AnimatedSprite
{
    public Baddie()
    {
        this.behaviors = new Behavior[2];
        this.behaviors[0] = new JumpBehavior();
        //etc...
    }

    public void Update()
    {
        //behaviors.update
    }

    public GetInput()
    {
        //behaviors.getinput
    }
}

だから今、もし私が多くのゲームでJumpとDuckを使いたいなら、私はただ行動をもたらすことができます。一般的なライブラリも作成できました。

動作しますか?

私が理解できないのは、それらの間で状態を共有する方法です。ジャンプとダックを見ると、どちらも描画中のテクスチャの現在の部分だけでなく、プレイヤーの状態にも影響します。(ジャンプは時間とともに減少する上向きの力を適用しますが、アヒルは動きを止め、バディのテクスチャと衝突サイズを変更します。

どうすればこれを連携させることができますか?動作間に依存関係プロパティを作成する必要がありますか?各動作に親について知ってもらい、直接変更する必要がありますか?考えられたことの1つは、デリゲートを各動作に渡して、トリガーされたときに実行されるようにすることでした。

私が見ている問題はまだまだあると思いますが、全体的な目的は、ゲーム間および同じゲーム内のエンティティ間でこれらの動作を簡単に再利用できるようにすることです。

だから私はあなたにそれを引き渡します。どのように/どのようにこれを行うことができるかを説明することに注意してください もっと良いアイデアはありますか?ぜひ聞きたいです。


これはgamedev.stackexchange.comでよりよく尋ねられるでしょうか?
-rcapote

私はあなたが行くところが好きですが、あなたが持ち出す問題にどのように対処するのか分かりません。非常に興味深く、ゲーム開発を超えた意味を持ちます。
エドワードストレンジ

@rcapoteは、このサイトがホワイトボード/ディスカッション用ではありませんか?

2
@ジョー-いいえ、いいえ。ここで「ディスカッション」について言及しないでください。さもないと、存在が変更されてしまいます。このサイトは、質問->回答->完了タイプのインタラクション専用です。
エドワードストレンジ

コンポーネントベースのエンティティシステムは、最近ゲーム開発者コミュニティでトレンドになり始めているので、ここでもっと注目を集めることができると思いましたが、とにかくここで良い答えが得られるでしょう。ここに、この問題に関するgamedev.netでの興味深い議論があります。gamedev.net
topic

回答:


1

見てみましょう。このプレゼンテーションを。探しているパターンの種類にかなり近いように聞こえます。このパターンは、動作とアタッチ可能なプロパティをサポートします。プレゼンテーションで言及されているとは思いませんが、添付可能なイベントを作成することもできます。この考え方は、WPFで使用される依存関係プロパティに似ています。


9

私には、これは戦略パターンを使用するためのほとんど教科書のように聞こえます。このパターンでは、一般的な動作をインターフェイスで定義できます。これにより、実行時に動作のさまざまな実装を入れ替えることができます(パワーアップがキャラクターのジャンプまたは実行能力にどのように影響するか考えてください)。

(不自然な)例:

// The basic definition of the jump behavior
public interface IJumpBehavior {
    void Jump();
}

これで、特定の各ジャンプの詳細を必ずしも知ることなく、キャラクターが使用できるさまざまなタイプのジャンプを実装できます。

// This is the jump the character may have when first starting
public class NormalJump : IJumpBehavior {

     public void Jump() {
         Console.WriteLine("I am jumping, and being pretty boring about it!");
     }

}

// This is the jump of a character who has consumed a power-up
public class SuperJump : IJumpBehavior {
    public void Jump() { 
         Console.WriteLine("I am all hopped up on star power, now my jumps can do damage!");
     }
}

ジャンプできるようにしたいキャラクターには、IJumpableへの参照を含めることができ、さまざまな実装の消費を開始できます

public class HeroCharacter {

    // By default this hero can perform normal jump.
    private IJumpBehavior _jumpBehavior = new NormalJump();

    public void Jump() {
        _jumpBehvaior.Jump();
    }

    // If you want to change the hero's IJumpable at runtime
    public void SetJump(IJumpBehavior jumpBehavior) {
      _jumpBehavior = jumpBehavior;
    }

}

次に、コードは次のようになります。

HeroCharacter myHero = new HeroCharacer();

// Outputs: "I am jumping, and being pretty boring about it!"
myHero.Jump()

// After consuming a power-up
myHero.SetJump(new SuperJump());

// Outputs: "I am all hopped up on star power, now my jumps can do damage!"
myHero.Jump();

これらのビヘイビアーを簡単に再利用したり、さらに多くの種類のジャンプを追加したり、単一のサイドスクロールプラットフォーム上に構築されたゲームを作成したりするために、後で拡張することもできます。


まさに私が探しているものではありませんが、これは非常に近く、気に入っています。確認するためにそれをいじります。ありがとう!

1

DCIアーキテクチャご覧ください。OOプログラミングの興味深い例が役立ちます。

C#でDCIスタイルのアーキテクチャを実装するには、単純なドメインクラスを使用し、拡張メソッドとインターフェイスでコンテキストオブジェクト(動作)を使用して、ドメインクラスが異なる役割の下で連携できるようにする必要があります。インターフェイスは、シナリオに必要な役割をマークするために使用されます。ドメインクラスは、意図した動作に適用されるインターフェイス(ロール)を実装します。ロール間のコラボレーションは、コンテキスト(動作)オブジェクトで行われます。

別々のプロジェクトのドメインオブジェクト間で共有できる共通の動作とロールのライブラリを作成できます。

C#のコード例については、C#のDCIを参照してください。


0

コンテキストオブジェクトをビヘイビアに渡して、ビヘイビアの影響を受けるスプライト/オブジェクトの状態を変更するメソッドを提供するのはどうですか?オブジェクトに複数の動作がある場合、それらはそれぞれループで呼び出され、コンテキストを変更する機会を与えます。プロパティの特定の変更が他のプロパティの変更を除外/制約する場合、コンテキストオブジェクトは、この事実を示すために何らかのフラグを設定するメソッドを提供したり、不要な変更を単に拒否したりできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.