netlib.narod.ru< Назад | Оглавление | Далее >

Подключаем больше игровых компонентов

Вы даже не заметили, как ваш графический движок подрос до солидных размеров и у вас образовалось множество полезных классов, которые упрощают визуализацию двухмерных и трехмерных данных и включают много тестовых модулей, доступных в большинстве классов (рис. 5.14).


Рис. 5.14

Рис. 5.14


Пока вы не использовали много игровых компонентов и, по-моему, не имеет большого смысла писать базовый графический движок с использованием компонентов. Вы не используете какие-либо методы Update или Draw тем способом, которым это делают игровые компоненты. Да, класс Model использует метод Render, а в классе Input есть метод Update, но помимо этого у вас нет никакой функциональности, совместимой с игровыми компонентами. Методы Render в классах модели и текстуры работают немного по-другому, поскольку ожидают, что пользователь будет вызывать их несколько раз в каждом кадре с различными параметрами. Я предполагаю, что класс Input может быть преобразован в игровой компонент, но эта идея оставляет меня равнодушным.

Вместо этого давайте подумаем о частях игры, которые замечательно соответствуют модели игровых компонентов. Это имеет смысл, если у вас есть класс, который должен быть обновлен и нарисован в каждом кадре. Примерами таких классов могут быть счетчик частоты кадров или класс камеры, которые пока отсутствуют в вашем движке.

Простой класс камеры

Для ваших тестовых модулей не нужна сложная камера, но было бы замечательно получить возможность перемещаться вокруг и иметь возможность рассматривать визуализируемые в тестовых модулях вашего движка объекты с разных сторон. С помощью матрицы вида и метода Matrix.CreateLookAt легко создать подобную функциональность и устанавливать ее там, где она требуется. Еще лучше использовать класс игрового компонента чтобы выполнять все это автоматически; все, что вам потребуется в этом случае, — создать экземпляр класса камеры в классе YourGame, наследуемом от класса BaseGame, и сразу все тестовые модули и другой код трехмерной графики будут использовать класс камеры без какого-либо дополнительного кода, поскольку Update вызывается автоматически для каждого игрового компонента, который есть в вашем классе YourGame.

public YourGame()
{
  // Инициализация простой камеры
  this.Components.Add(new SimpleCamera(this));
} // YourGame()

В классе SimpleCamera есть конструктор и вызываемые автоматически методы Initialize и Update (рис. 5.15). В классе также есть три поля для координат x, y и z камеры, которые инициализируются значениями 0, 0 и 15 соответственно. Метод Update меняет координаты x и y, основываясь на перемещениях мыши или, если у вас есть игровой пульт, на передвижениях правого джойстика. Кроме того, левым джойстиком вы можете приближать и отдалять камеру.


Рис. 5.15

Рис. 5.15


Класс весьма прост и достаточно легко прочитать весь его код:

/// <summary>
/// Класс простой, перемещающейся вокруг камеры.
/// Камера всегда направлена на центр и находится на одной высоте.
/// </summary>
class SimpleCamera : GameComponent
{
  #region Переменные
  float x = 0, y = 0;
  float zHeight = 15.0f;
  #endregion

  #region Конструктор
  public SimpleCamera(BaseGame game)
    : base(game)
  {
  } // SimpleCamera(game)
  #endregion

  #region Initialize
  public override void Initialize()
  {
    base.Initialize();
  } // Initialize
  #endregion

  #region Update
  public override void Update(GameTime gameTime)
  {
    base.Update(gameTime);
    // Обновление позиции камеры (поддерживает мышь и пульт)
    x += Input.MouseXMovement / 10;
    y += Input.MouseYMovement / 10;
    x += Input.GamePad.ThumbSticks.Right.X;
    y += Input.GamePad.ThumbSticks.Right.Y;
    zHeight += Input.GamePad.ThumbSticks.Left.Y;
    BaseGame.ViewMatrix = Matrix.CreateLookAt(
      new Vector3(x, y, zHeight), Vector3.Zero, Vector3.Up);
  } // Update(gameTime)
  #endregion
} // class SimpleCamera

Самая важная вещь здесь — это ViewMatrix из класса BaseGame, инициализируемая в конце метода Update. При визуализации шейдера в классе модели или любом другом классе, таком как менеджер линий, вы будете использовать эту матрицу вида и гарантировать, что все ваши трехмерные данные будут преобразованы в ваше пространство вида именно с этой матрицей, пока вы не измените ее снова в следующем кадре.

Теперь вы можете собрать все вместе для тестового модуля TestRenderOurNewGraphicEngine, написанного в начале этой главы, и если вы взглянете на все классы проекта, которые вы импортировали и написали, то увидите хороший движок, который является простым для использования и легко расширяемым, и который мы будем исследовать в нескольких следующих главах.

Класс ScreenshotCapturer

Вот еще один вспомогательный класс в движке, называемый ScreenshotCapturer, который позволяет вам делать снимки экрана нажатием клавиши Print Screen. Он также реализован как игровой компонент и инициализируется в конструкторе BaseGame. Метод Update вызывается автоматически и просто вызывает MakeScreenshot, если нажата клавиша Print Screen.

public override void Update(GameTime gameTime)
{
  if (Input.KeyboardKeyJustPressed(Keys.PrintScreen))
    MakeScreenshot();

  base.Update(gameTime);
} // Update(gameTime)

Метод MakeScreenshot создает временную текстуру и сохраняет в ней вторичный буфер с помощью метода устройства ResolveBackBuffer. Затем результат сохраняется на диске с помощью других вспомогательных методов класса:

using (Texture2D dstTexture = new Texture2D(
  BaseGame.Device, BaseGame.Width, BaseGame.Height, 1,
  ResourceUsage.ResolveTarget,
  SurfaceFormat.Color,
  ResourceManagementMode.Manual))
{
  // Получаем данные с помощью метода Resolve
  BaseGame.Device.ResolveBackBuffer(dstTexture);

  dstTexture.Save(
    ScreenshotNameBuilder(screenshotNum),
    ImageFileFormat.Jpg);
} // using (dstTexture)

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz