XNA在运行时动态更改游戏服务

时间:2010-10-29 09:22:40

标签: c# xna

我有一个接口(ICamera),由2个类(FreeCamera,StaticCamera)实现。这些类继承自GameComponent。

示例定义:

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

现在我将这些类添加到游戏组件中,并将其中一个组件注册到游戏服务

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

然后我想借助切换功能

在应用程序流程中更改服务的提供程序
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);
  }
}

StaticCamera只需用鼠标输入(你可以旋转相机),FreeCamera也可以通过键盘输入移动。当我调用上面的方法时(通过按键盘上的C键),FreeCamera类会被取消激活,但视口似乎已冻结,并且不会对任何输入做出反应。当我在短时间内再次调用该方法后,FreeCamera再次被激活,一切都按预期工作。

现在我有两个问题:

  • 是否可以更改服务 提供游戏服务的人 游戏循环?
  • 有更好的方法吗? 处理不同的相机类型 游戏并在它们之间轻松切换?

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

像你回答的那样,请使用相机管理器。它既可以作为当前相机的工厂,也可以作为容器。您可以将经理注册为服务。经理会看起来像这样:

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

这只是粗略的代码 - 需要填写更多。一个限制是每种类型只能有一个摄像头。为摄像机提供字符串名称或枚举标记可让您在任意数量的摄像机之间切换。

答案 1 :(得分:0)

感谢您的提示。我只是在没有我的IDE的情况下从头脑中编写代码,所以请不要过多考虑语法错误等。

在我的游戏中,我正在使用包装类进行输入。代码只是问题的一个简短示例 - 如果两个类都使用相同的接口,如何替换游戏服务。

我的新想法:我可以使用“管理器”类(在本例中类似于CameraManager),它具有以下方法

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

然后将管理器类放入服务(具有自己的接口,如ICameraManager)。

编辑:这被视为上述评论的答案......但似乎我点击了错误的按钮 - 抱歉

答案 2 :(得分:0)

我认为如果您在更新中省略了有关添加和删除服务的代码,那么您可以更好地添加更改Visible属性的行。 Enable属性会调用Update,但Visible属性会调用Draw。

所以我建议Update看起来像这样:

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