2010-10-29 23 views
5

Tengo una interfaz (ICamera) que se implementa mediante 2 clases (FreeCamera, StaticCamera). Las clases heredan de GameComponent.XNA Change Game Service dinámicamente durante el tiempo de ejecución

Ejemplo definiton:

public class FreeCamera : GameComponent, ICamera 
{ 
    ... 
} 

Ahora estoy añadiendo las clases a los componentes del juego y registrar uno de los componentes de un servicio de juegos

private FreeCamera freeCam; 
private StaticCamera staticCam; 

public Game1() 
{ 
    graphics = new GraphicsDeviceManager(this); 
    Content.RootDirectory = "Content"; 
    freeCam = new FreeCamera(this) { Enabled = true }; 
    staticCam = new StaticCamera(this) { Enabled = false }; 
    Services.AddService(typeof(ICamera, freeCam); 
    Components.Add(freeCam); 
    Components.Add(staticCam); 
    ... 
} 

entonces quiero cambiar el proveedor de el servicio durante el flujo de la aplicación con la ayuda de una función de alternar

namespace Game1 
{ 
    protected override void Update(GameTime gameTime) 
    { 
    var keyboard = Keyboard.GetState(); 
    if(keyboard.IsKeyDown(Keys.C)) 
    { 
     if(freeCam.Enabled) 
     { 
     Services.RemoveService(typeof(ICamera)); 
     Services.AddService(typeof(ICamera, staticCam); 
     freeCam.Enabled = !freeCam.Enabled; 
     staticCam.Enabled = !staticCam.Enabled; 
     } 
     else 
     { 
     Services.RemoveService(typeof(ICamera)); 
     Services.AddService(typeof(ICamera, freeCam); 
     freeCam.Enabled = !freeCam.Enabled; 
     staticCam.Enabled = !staticCam.Enabled; 
     }   
    } 
    base.Update(gameTime); 
    } 
} 

Th e StaticCamera solo toma entrada con el mouse (puede girar la cámara), la FreeCamera también se puede mover con la entrada del teclado. Cuando llamo al método anterior (presionando C en el teclado) la clase FreeCamera se desactiva pero la ventana gráfica parece congelada y no reacciona a ninguna entrada. Cuando vuelvo a llamar al método después de poco tiempo, FreeCamera se activa nuevamente y todo funciona como se esperaba.

Ahora tengo 2 preguntas relacionadas con esta:

  • ¿Es posible cambiar el proveedor de servicios de un servicio de juego en el bucle juego?
  • ¿Hay un mejor enfoque para manejar diferentes tipos de cámara en un juego y cambiar entre ellos fácilmente?

Gracias de antemano por cualquier ayuda.

+0

Sólo un consejo rápido por ahora: 'keyboard.IsKeyDown (Keys.C) && keyboardLastFrame.IsKeyUp (Keys.C)' –

Respuesta

0

Gracias por la sugerencia. Acabo de escribir el código de mi cabeza sin mi IDE a la mano, así que por favor no mire demasiado en los errores de sintaxis, etc.

En mi juego estoy usando clases contenedoras para la entrada. El código es solo un breve ejemplo del problema: cómo sustituir un servicio de juego si ambas clases usan la misma interfaz.

Mi nueva idea: podía utilizar una clase de "manager" (como CameraManager en este caso), que tiene los siguientes métodos

public void SetCameraType(CameraType type) //CameraType could be an enum 
public ICamera GetCamera() 

y luego poner la clase administrador en el servicio (con su propia interfaz como ICameraManager).

Editar: Esto fue considerado como una respuesta al comentario anterior ... pero parece que he hecho clic en el botón equivocado - lo siento

1

Al igual que su respuesta es, utilizar un gestor de cámara. Actúa como una fábrica y un contenedor para la cámara actual. El gerente puede registrarse como un servicio. El administrador se vería algo como esto:

public class CameraManager 
{ 
    private Dictionary<Type, ICamera> _cameras; 
    private ICamera _current; 

    public ICamera Current 
    { 
     get 
     { 
      return _current; 
     } 
    } 

    // Sets the current cammera to the internal instance of the camera type 
    public void SetCurrent<T>() where T : ICamera 
    { 
     if (!_cameras.ContainsKey(typeof(T))) 
     { 
      // TODO: Instantiate a new camera class here... 
     } 

     _current = _cameras[typeof(T)]; 
    } 
} 

Esto es solo un código áspero - necesitaría ser llenado más. Una limitación es que solo puedes tener una cámara por tipo. Darle a las cámaras un nombre de cadena o una bandera de enumeración le permitiría alternar entre una cantidad arbitraria de cámaras.

0

Creo que si dejó el código sobre agregar y eliminar el servicio en la Actualización estaría bien y agregó líneas que cambian la propiedad Visible. El Habilitar llamadas de efectos de propiedad a Actualizar, pero la propiedad Visible afecta a las llamadas a Dibujar.

así que te sugiero el aspecto de actualización de la siguiente manera:

protected override void Update(GameTime gameTime) 
    { 
    var keyboard = Keyboard.GetState(); 
    if(keyboard.IsKeyDown(Keys.C)) 
    { 
     if(freeCam.Enabled) 
     { 
     freeCam.Enabled = false; 
     freeCam.Visible = false; 

     staticCam.Enabled = true; 
     staticCam.Visible= true; 
     } 
     else 
     { 
     freeCam.Enabled = true; 
     freeCam.Visible = true; 

     staticCam.Enabled = false; 
     staticCam.Visible= false; 
     }   
    } 
    base.Update(gameTime); 
    } 
Cuestiones relacionadas