XNA Change Game Service динамически во время выполнения - PullRequest
5 голосов
/ 29 октября 2010

У меня есть интерфейс (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 снова активируется, и все работает как положено.

Теперь у меня есть 2 вопроса по этому поводу:

  • Можно ли изменитьпоставщик услуг игрового сервиса в игровом цикле?
  • Есть ли лучший подход для управления различными типами камер в игре и легкого переключения между ними?

Заранее спасибо за любую помощь.

Ответы [ 3 ]

1 голос
/ 30 декабря 2010

Как вы ответили, используйте диспетчер камеры.Он действует как фабрика и контейнер для текущей камеры.Менеджер вы можете зарегистрировать как сервис.Менеджер будет выглядеть примерно так:

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

Это просто грубый код - его нужно будет заполнить больше.Одно ограничение - у вас может быть только одна камера для каждого типа.Если для камер задано имя строки или флаг перечисления, вы можете переключаться между произвольным числом камер.

0 голосов
/ 13 января 2011

Я думаю, что если вы прекратили код о добавлении и удалении службы в Обновлении, вы были бы хороши и добавили строки, изменяющие свойство Visible. Свойство Enable влияет на вызовы Update, а свойство Visible вызывает вызовы Draw.

Так что я бы предложил, чтобы обновление выглядело так:

 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);
  }
0 голосов
/ 29 октября 2010

Спасибо за совет.Я просто написал код из своей головы без моей IDE, поэтому, пожалуйста, не смотрите слишком подробно на синтаксические ошибки и т. Д.

В моей игре я использую классы-обертки для ввода.Код является лишь кратким примером проблемы - как заменить игровой сервис, если оба класса используют один и тот же интерфейс.

Моя новая идея: я мог бы использовать класс «manager» (например, CameraManager в этом случае), который имеет следующие методы

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

и затем помещает класс менеджера в службу (со своим собственным интерфейсом, таким как ICameraManager).

Редактировать: это считалоськак ответ на комментарий выше ... но, кажется, я нажал не ту кнопку - извините

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...