カメラシステムの設計


8

一般的なゲームについて考えると、ゲームのタイプは関係ありません。カメラのタイプが必要になる可能性が高いです。例えば:

  • デバッグカメラ:キーボードとマウスによって制御され、シーンの任意の場所を移動できます。
  • スクリプト化されたカメラ:これで、カメラに移動して、確定したパスをたどることができます。
  • プレーヤーのカメラ。
  • ...

これらの各カメラタイプには、独自の更新機能があります。最も簡単な(そして悪い)システムは、汎用の更新関数とすべてのカメラタイプに特化した更新関数を備えたカメラマネージャークラスを用意することです。一般的な更新関数の内部には、カメラタイプに基づいて適切な更新関数を呼び出すswitchステートメントがあります。

これの代わりに、私は戦略パターンという別のアプローチを考えました。各カメラの動作(更新メソッド)を、共通のインターフェースを実装する適切なクラスに移動します。カメラマネージャーには、そのインターフェイスのメンバーがあり、必要な動作を動的に設定できます。

あれについてどう思う?他にどんなシステムを提案しますか?ありがとう。

追加情報:反射など、複数のカメラをアクティブにする必要がある可能性があります。つまり、私もそのことを考慮に入れなければなりません。


追加情報メモをご覧ください。その後、編集内容を確認してください。
David Gouveia 2011

回答:


11

戦略パターンは私には良い賭けのようです。さらに一歩進めるために、カメラマネージャーは具体的なカメラタイプを知らないままにしておく必要があります。たとえば、IDを使用してカメラの実装を外部で登録および変更します(柔軟性を高めるために文字列を使用しましたが、enumまたはintでもかまいません)。例(エラーチェックなし):

public interface ICamera
{
    void Update(float dt);
    Matrix View { get; }
}

public class CameraManager
{
    private Dictionary<string, ICamera> cameras;
    private ICamera currentCamera;

    public void RegisterCamera(string id, ICamera camera) { cameras[id] = camera; }
    public void SetCamera(string id) { currentCamera = cameras[id]; }

    public void Update(float dt) { currentCamera.Update(dt); }
    public Matrix View { get { return currentCamera.View; } }
}

public class DebugCamera : ICamera {}
public class PlayerCamera : ICamera {}
public class ScriptedCamera : ICamera {}

void Test()
{
    // Create camera manager
    CameraManager cameraManager = new CameraManager();

    // Register cameras
    cameraManager.RegisterCamera("Debug", new DebugCamera());
    cameraManager.RegisterCamera("Player", new PlayerCamera());
    cameraManager.RegisterCamera("Scripted", new ScriptedCamera());

    // Change active camera
    cameraManager.SetCamera("Player");
}

編集する

追加情報:反射など、複数のカメラをアクティブにする必要があるという現実の可能性があります。つまり、私もそのことを考慮しなければなりません。

追加するのは簡単です。次のように変更currentCameraしてください:

List<ICamera> activeCameras = new List<ICamera>();

SetCameraToggleCameraに変更します(またはブール値をSetCameraに追加します)。

void ToggleCamera(string id)
{
    ICamera camera = cameras[id];
    if(activeCameras.Contains(camera))
        activeCameras.Remove(camera);
    else
        activeCameras.Add(camera);
}

またUpdate、現在のカメラだけでなく、アクティブなすべてのカメラを更新するようにメソッドを変更します。

void Update(float dt) { activeCameras.ForEach(c => c.Update(dt)); }

私の例では、ViewプロパティをGetViewカメラのIDをパラメーターとして取るメソッドに置き換える必要もあります。しかし、それはとにかくあなたのカメラインターフェースに依存する詳細です:

// You could optionally add a check to see if the camera is active
Matrix GetView(string id) { return cameras[id].View; }

はい、私はあなたのアプローチが好きです。実際、私の質問では、カメラマネージャーが特定のカメラタイプについて何も知らないことを忘れてしまいました。
enigma

ちなみに、私はあなたが2つの質問を持っているのに気づきましたが、答えを受け入れませんでした。それがどのように行われるか知っていますか?反対投票ボタンのすぐ下にあるボタンです。
David Gouveia

依存関係の注入、ファクトリーのファクトリー、カメラドメインスクリプト言語を追加して、ソリューションを過度に設計しすぎないでください。注:シーンに複数のカメラを接続することは完全に可能です。その概念を許可しないAPIにロックしないでください。
Patrick Hughes

@PatrickHughes、あなたは正しい。おそらく、シーンに複数のカメラを接続する必要があります(質問に追加しました)。
enigma 2011

1
複数のカメラがある場合は、各カメラがRenderTargetに表示するものを描画してから、SpriteBatchを使用してそれぞれを描画することをお勧めします。当然ながら、カメラの数に応じて各カメラをスケーリングします。
FrenchyNZ、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.