Desain sistem kamera

8

Berpikir tentang permainan biasa, tidak masalah jenis permainannya, sangat mungkin kita membutuhkan beberapa jenis kamera. Sebagai contoh:

  • Kamera debug: dikendalikan oleh keyboard dan mouse, dengan itu kami dapat bergerak di mana saja di tempat kami.
  • Kamera skrip: dengan itu kita dapat menginstruksikan kamera untuk bergerak, mengikuti jalur yang ditentukan.
  • Kamera pemain.
  • ...

Masing-masing jenis kamera ini memiliki fungsi pembaruan sendiri. Sistem termudah (dan buruk), adalah memiliki kelas manajer kamera dengan fungsi pembaruan generik dan fungsi pembaruan khusus untuk setiap jenis kamera. Di dalam fungsi pembaruan umum kami memiliki pernyataan sakelar yang, berdasarkan pada jenis kamera, memanggil fungsi pembaruan yang tepat.

Alih-alih ini saya sudah memikirkan pendekatan lain: pola strategi. Kami memindahkan setiap perilaku kamera (metode pembaruan) dalam kelas yang sesuai yang mengimplementasikan antarmuka umum. Di manajer kamera kami memiliki anggota untuk antarmuka itu, dan kami dapat mengatur secara dinamis setiap perilaku yang kita inginkan.

Apa pendapatmu tentang itu? Sistem apa lagi yang Anda sarankan untuk saya? Terima kasih.

Info tambahan: ada kemungkinan nyata bahwa saya memerlukan lebih dari satu kamera aktif, misalnya untuk refleksi. Singkatnya, saya harus memperhitungkannya juga.

teka-teki
sumber
Baru saja melihat catatan info tambahan Anda. Periksa edit saya kemudian.
David Gouveia

Jawaban:

11

Pola strategi sepertinya taruhan yang bagus untuk saya. Untuk mengambil langkah lebih jauh, manajer kamera Anda harus tetap tidak tahu jenis kamera konkret. Anda akan mendaftar dan mengubah implementasi kamera secara eksternal oleh id (saya menggunakan string untuk fleksibilitas tetapi bisa juga enum atau int), misalnya (tanpa pengecekan kesalahan):

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");
}

Edit

Info tambahan: ada kemungkinan nyata bahwa saya memerlukan lebih dari satu kamera aktif, misalnya untuk refleksi. Singkatnya, saya harus memperhitungkannya juga.

Itu sepele untuk ditambahkan. Ubah saja currentCamerake:

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

Ubah SetCamerake ToggleCamera (atau tambahkan boolean ke SetCamera, pilihan Anda):

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

Dan ubah Update metode untuk memperbarui semua kamera yang aktif, bukan hanya yang saat ini:

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

Dalam contoh saya, Anda juga harus mengganti Viewproperti dengan GetViewmetode yang menggunakan id kamera sebagai parameter. Tapi itu detail yang tergantung pada antarmuka kamera Anda:

// You could optionally add a check to see if the camera is active
Matrix GetView(string id) { return cameras[id].View; }
David Gouveia
sumber
Ya, saya suka pendekatan Anda. Bahkan, dalam pertanyaan saya, saya lupa bahwa manajer kamera tidak tahu apa-apa tentang jenis kamera tertentu, kalau tidak, kami memiliki pernyataan switch lain untuk itu.
teka
Ngomong-ngomong, saya perhatikan bahwa Anda memiliki dua pertanyaan tetapi tidak pernah menerima jawaban. Apakah Anda tahu cara melakukannya? Ini tombol tepat di bawah tombol downvote.
David Gouveia
Hanya saja, jangan gila rekayasa berlebihan solusi, menambahkan injeksi ketergantungan, pabrik pabrik, bahasa scripting domain kamera; Anda tahu apa yang saya maksud =) CATATAN: Sangat mungkin bahwa Anda ingin lebih dari 1 kamera terpasang ke sebuah adegan, jangan mengunci diri Anda ke dalam API yang tidak akan mengizinkan konsep itu.
Patrick Hughes
@ PatrickHughes, kau benar. Mungkin saya akan membutuhkan lebih dari satu kamera yang terpasang pada adegan (ditambahkan dalam pertanyaan saya).
teka
1
Untuk memiliki beberapa kamera, saya akan merekomendasikan menggambar apa yang dilihat masing-masing kamera ke RenderTarget, kemudian menggunakan SpriteBatch untuk menggambar masing-masing, Jelas skala masing-masing tergantung pada berapa banyak kamera yang ada.
FrenchyNZ