Conception d'un système de caméra

8

En pensant à un jeu commun, peu importe le type de jeu, il est très probable que nous ayons besoin d'un type de caméra. Par exemple:

  • Caméra de débogage: contrôlée par le clavier et la souris, avec laquelle nous pouvons nous déplacer à n'importe quel endroit de notre scène.
  • Caméra scriptée: avec cela, nous pouvons demander à la caméra de se déplacer, en suivant un chemin déterminé.
  • Caméra du joueur.
  • ...

Chacun de ces types de caméras possède sa propre fonction de mise à jour. Le système le plus simple (et le plus mauvais) consiste à avoir une classe de gestionnaire de caméras avec une fonction de mise à jour générique et des fonctions de mise à jour spécialisées pour chaque type de caméra. À l'intérieur de la fonction de mise à jour générique, nous avons une instruction switch qui, en fonction du type de caméra, appelle la fonction de mise à jour appropriée.

Au lieu de cela, j'ai pensé à une autre approche: le modèle de stratégie. Nous déplaçons chaque comportement de caméra (méthode de mise à jour) dans une classe appropriée qui implémente une interface commune. Dans le gestionnaire de caméras, nous avons un membre de cette interface, et nous pouvons définir de manière dynamique tout comportement que nous voulons.

Qu'est ce que tu penses de ça? Quels autres systèmes me proposez-vous? Merci.

Informations supplémentaires: il existe une possibilité réelle d'avoir besoin de plusieurs caméras actives, par exemple pour les réflexions. Bref, je dois aussi en tenir compte.

énigme
la source
Je viens de voir votre note d'information supplémentaire. Vérifiez ma modification alors.
David Gouveia

Réponses:

11

Les modèles de stratégie me semblent un bon pari. Pour aller plus loin, votre gestionnaire de caméras doit ignorer les types de caméras concrets. Vous enregistrez et modifiez les implémentations de la caméra en externe par id (j'ai utilisé une chaîne pour plus de flexibilité, mais peut aussi être une énumération ou un int), par exemple (sans vérification d'erreur):

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

Éditer

Informations supplémentaires: il existe une possibilité réelle d'avoir besoin de plusieurs caméras actives, par exemple pour les réflexions. Bref, je dois aussi en tenir compte.

C'est insignifiant à ajouter. Changez simplement currentCameraen:

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

Passez SetCameraà ToggleCamera (ou ajoutez un booléen à SetCamera, votre choix):

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

Et changez la Updateméthode pour mettre à jour toutes les caméras actives au lieu de seulement la caméra actuelle:

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

Dans mon exemple, vous devrez également remplacer la Viewpropriété par une GetViewméthode prenant l'id de la caméra en paramètre. Mais c'est un détail qui dépend de toute façon de votre interface d'appareil photo:

// You could optionally add a check to see if the camera is active
Matrix GetView(string id) { return cameras[id].View; }
David Gouveia
la source
Oui, j'aime votre approche. En fait, dans ma question, j'ai oublié que le gestionnaire de caméras ne sait rien des types de caméras spécifiques, sinon nous avons une autre déclaration de commutateur pour cela.
enigma
Au fait, j'ai remarqué que vous avez deux questions mais n'avez jamais accepté de réponse. Savez-vous comment cela se fait? C'est le bouton juste en dessous du bouton downvote.
David Gouveia
Ne devenez pas fou de sur-ingénierie d'une solution, en ajoutant l'injection de dépendances, l'usine d'usines, les langages de script de domaine de caméra; vous savez ce que je veux dire =) REMARQUE: Il est tout à fait possible que vous vouliez plus d'une caméra attachée à une scène, ne vous enfermez pas dans une API qui ne permettra pas ce concept.
Patrick Hughes
@PatrickHughes, vous avez raison. J'aurai probablement besoin de plus d'une caméra attachée à la scène (ajoutée dans ma question).
enigma
1
Pour avoir plusieurs caméras, je recommanderais de dessiner ce que chaque caméra voit dans un RenderTarget, puis d'utiliser SpriteBatch pour dessiner chacune, en mettant évidemment à l'échelle chacune en fonction du nombre de caméras.
FrenchyNZ