Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XNA Change Game Service dynamically during runtime

Tags:

c#

xna

I have an interface (ICamera) which is implemented by 2 classes (FreeCamera, StaticCamera). The classes are inheriting from GameComponent.

Example definiton:

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

Now I'm adding the classes to the Game Components and register one of the components to a game service

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

Then I want to change the provider for the service during the application flow with help of a toggle function

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

The StaticCamera takes only input by mouse (you can rotate the camera), the FreeCamera can also moved by keyboard input. When I call the method above (by pressing C on the keyboard) the FreeCamera class gets deactivated but the viewport seems frozen and does not react to any input. When I call the method again after a short time the FreeCamera gets activated again and everything works as expected.

Now I have 2 questions regarding this:

  • Is it possible to change the service provider of a game service in the game loop?
  • Is there a better approach to handle different camera types in a game and switch between them easily?

Thanks in advance for any help.

like image 939
organic Avatar asked Nov 14 '22 06:11

organic


1 Answers

Like you answered, use a camera manager. It acts as both a factory and a container for the current camera. The manager you can register as a service. Manager would look something like this:

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

This is just rough code - would need to be filled in more. One limitation is you can only have one camera per type. Giving cameras a string name, or an enum flag would let you toggle between an arbitrary number of cameras.

like image 67
Leniency Avatar answered Nov 29 '22 13:11

Leniency