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

Игровые экраны

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


Рис. 10.3

Рис. 10.3


Большинство игровых экранов используют специальную фоновую текстуру, чтобы показать больше информации на экране. На экране выбора миссии вы можете выбрать одну из четырех миссий и затем начать игру. Другие экраны просто отображают некоторую информацию и только экран настройки позволяет пользователю менять что-нибудь. Все игровые экраны возвращаются в главное меню после нажатия Back.

Чтобы автоматически обрабатывать все игровые экраны, вы используете в главном классе игры стек игровых экранов (рис. 10.4). Это позволяет вам использовать еще более сложную систему меню с несколькими уровнями, где вы всегда можете вернуться к предыдущему экрану. Если вы хотите вернуться к главному меню, просто удалите из стека все элементы, кроме самого нижнего. Другой трюк, который я часто использую в демонстрациях, — добавление перед главным меню еще одного игрового экрана, чтобы просто показать рекламный экран «купите теперь эту игру», когда пользователь выходит из игры. Сам класс — это всего несколько строк, и вам надо добавить только одну дополнительную строку к вашему главному классу. Большинство классов игровых экранов также очень просты.


Рис. 10.4

Рис. 10.4


Почему стек игровых экранов так хорош? Так вот, все, что вам надо сделать, это наследовать все ваши классы игровых экранов от IGameScreen (рис. 10.5) и тогда вы сможете использовать следующий код для их автоматической визуализации и обработки. Метод Render каждого класса игрового экрана возвращает true, если вы закончили работу с этим экраном и хотите вернуться к предыдущему. После того, как все игровые экраны удалены, вы выходите из игры.


Рис. 10.5

Рис. 10.5


// Нет больше игровых экранов?
if (gameScreens.Count == 0)
{
  // Тогда выходим
  Exit();
  return;
} // if (gameScreens.Count)

// Обработка текущего экрана
if (gameScreens.Peek().Render())
{
  // Воспроизведение звука возврата
  Sound.Play(Sound.Sounds.ScreenBack);
  gameScreens.Pop();
} // if (gameScreens.Peek)

Экран помощи

В качестве очень простого примера класса игрового экрана, вот полный код класса Help из пространства имен GameScreens. Другие классы игровых экранов не намного сложнее, за исключением класса Mission, который обрабатывает саму игру.

/// <summary>
/// Помощь
/// </summary>
class Help : IGameScreen
{
  #region Свойства
  /// <summary>
  /// Имя этого игрового экрана
  /// </summary>
  /// <returns>Строка</returns>
  public string Name
  {
    get
    {
      return "Help";
    } // get
  } // Name
  #endregion

  #region Run
  /// <summary>
  /// Запуск игрового экрана. Вызывается в каждом кадре
  /// </summary>
  /// <param name="game">Форма для доступа к диспетчеру астероидов</param>
  public bool Run(RocketCommanderGame game)
  {
    // Визуализация фона
    game.RenderMenuBackground();

    // Показываем текстуру экрана помощи
    game.helpScreenTexture.RenderOnScreen(
           new Rectangle(0,
           174 * BaseGame.Height / 768,
           BaseGame.Width,
           510 * BaseGame.Height / 768),
           new Rectangle(0, 0, 1024, 510));

    if (game.RenderMenuButton(MenuButton.Back,
              new Point(1024 - 210, 768 - 140)) ||
        Input.KeyboardEscapeJustPressed)
      return true;

    return true;
  } // Run(game)
} // class Help

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

Пользовательский интерфейс в игре

В этом разделе я хочу, чтобы вы проследовали за всеми этапами разработки внутриигрового UI для игры XNA Shhoter. UI не слишком сложен, но вы все-таки столкнетесь с несколькими проблемами. В нашей стрелялке отображаются следующие элементы:

Рис. 10.6 показывает все эти элементы, объединенные на экране с помощью следующих текстур:


Рис. 10.6

Рис. 10.6


Потом реализуем новый класс для отображения цифр из текстуры NumbersFont.png, и благодаря классу Texture и методу RenderOnScreen, добавление внутриигрового UI ничуть не сложно.

Текстура NumbersFont.png обрабатывается в классе NumbersFont и это очень похоже на класс TextureFont из главы 4, но намного проще, поскольку здесь у вас только 11 прямоугольников: 10 для цифр от 0 до 9 и один для двоеточия для отображения времени.

private void RenderHud()
{
  // Визуализируем верхнюю часть дисплея
  hudTopTexture.RenderOnScreenRelative4To3(0, 0,
                        hudTopTexture.GfxRectangle);

  // Время
  BaseGame.NumbersFont.WriteTime(BaseGame.XToRes(73),
                                 BaseGame.YToRes(8),
                                 (int)Player.gameTimeMs);

  // Счет
  BaseGame.NumbersFont.WriteNumberCentered(BaseGame.XToRes(485),
                                           BaseGame.YToRes(8),
                                           Player.score);

  // Рекорд
  BaseGame.NumbersFont.WriteNumberCentered(BaseGame.XToRes(920),
                                           BaseGame.YToRes(8),
                                           Highscores.TopHighscore);

  // Визуализируем нижнюю часть дисплея
  Rectangle bottomHudGfxRect = new Rectangle(0, 24, 1024, 40);
  hudBottomTexture.RenderOnScreenRelative4To3(0, 768 - 40,
                                              bottomHudGfxRect);

  // Здоровье
  Rectangle healthGfxRect = new Rectangle(50, 0, 361, 24);
  hudBottomTexture.RenderOnScreenRelative4To3(50, 768 - 31,
                     new Rectangle(healthGfxRect.X, healthGfxRect.Y,
                                   (int)(healthGfxRect.Width * Player.health),
                     healthGfxRect.Height));

  // Оружие и бомбы!
  Rectangle weaponMgGfxRect = new Rectangle(876, 0, 31, 24);
  Rectangle weaponGattlingGfxRect = new Rectangle(909, 0, 27, 24);
  Rectangle weaponPlasmaGfxRect = new Rectangle(939, 0, 33, 24);
  Rectangle weaponRocketsGfxRect = new Rectangle(975, 0, 24, 24);
  Rectangle weaponEmpGfxRect = new Rectangle(1001, 0, 23, 24);
  TextureFont.WriteText(BaseGame.XToRes(606),
                        BaseGame.YToRes(768 - 20) - TextureFont.Height / 3,
                        "Weapon: ");

  // Показываем значок вооружения!
  Rectangle weaponRect =
         Player.currentWeapon == Player.WeaponTypes.MG ? weaponMgGfxRect :
         Player.currentWeapon == Player.WeaponTypes.Gattling ?
         weaponGattlingGfxRect :
         Player.currentWeapon == Player.WeaponTypes.Plasma ?
         weaponPlasmaGfxRect : weaponRocketsGfxRect;
  hudBottomTexture.RenderOnScreenRelative4To3(
                                    715, 768 - 31, weaponRect);
  // И название оружия
  TextureFont.WriteText(BaseGame.XToRes(717+weaponRect.Width),
                        BaseGame.YToRes(768 - 20) - TextureFont.Height / 3,
                        Player.currentWeapon.ToString());
  TextureFont.WriteText(BaseGame.XToRes(864),
                        BaseGame.YToRes(768 - 20) - TextureFont.Height / 3,
                        "EMPs: ");
  // Показываем значки бомб, если они у нас есть
  for (int num = 0; num < Player.empBombs; num++)
    hudBottomTexture.RenderOnScreenRelative4To3(
                               938 + num * 23, 768 - 31, weaponEmpGfxRect);
} // RenderHud()

Это решение замечательно работает на PC, но как только вы запустите игру (или тестовый модуль TestHud, который я написал даже раньше, чем метод RenderHud) на Xbox 360, подключенной к телевизору, то увидите, что информационный дисплей виден не полностью, или, еще хуже, вообще почти не виден.

Если вы раньше никогда не разрабатывали игры для консолей, подключаемых к телевизорам, это может стать для вас новой проблемой, поскольку на мониторе PC вы всегда можете использовать 100% видимой области без какой-либо безопасной зоны. Но на большинстве телевизионных экранов вы не видите 100% экрана, а лишь где-то около 90%, и это значит, что примерно 10% по ширине и высоте на границах экрана невидимы (рис. 10.7).


Рис. 10.7

Рис. 10.7


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

Как видите, недостаточно просто использовать на Xbox 360 90% экрана и больше не беспокоиться об этом. Результаты на экране могут сильно различаться в зависимости от ситуации, которая не может быть проверена ни вашей игрой, ни XNA Framework. Единственная вещь, в которой можно быть уверенным, это то, что на PC вы будете гарантированно видеть все 100% пикселей экрана, и по этой причине многие игры для PC используют края экрана для отображения элементов UI и другой информации. Если вы взглянете на Xbox 360 (или на любую консольную игру, если на то пошло), вы заметите, что у них часто упрощенный интерфейс, и они никогда не показывают какую-либо информацию на самом краю экрана.

Вы не можете просто поместить информационный дисплей в 90% безопасную область, поскольку если пользователь может видеть большую область, все будет выглядеть некрасиво, ведь у вас нет графики за пределами 90% области, а если пользователь видит меньше, у вас остается та же проблема, что и прежде. Вместо того, чтобы ходить кругами вокруг этой проблемы, вы должны здесь остановиться и переосмыслить задачу. Плохая идея — размещать элементы UI в игре для Xbox 360 как показано на рис. 10.6. Лучшее решение — изменить графику UI и помещать ее в безопасную область, если игра запущена в ситуации, когда пользователь не может видеть 100%, подобной запуску на Xbox 360. Рис. 10.8 показывает, как изменяется графика информационного дисплея, чтобы он работал как на PC, где вы помещаете его к границам экрана, так и на Xbox 360, где он помещен во внутренние 92% (остается видимым с безопасной областью 90%, становится трудным для чтения, если видимо только 85% или меньше, но я никогда не сталкивался с такими наихудшими случаями; у большинства телевизоров безопасная область около 90% – 95%).


Рис. 10.8

Рис. 10.8


Рис. 10.9 показывает итоговую раскладку экрана XNA Shooter после прохождения через все, описанные в этой главе, этапы. За подробностями обращайтесь к методу RenderHud из класса Mission. Все разрабатывалось главным образом для широкоэкранных разрешений и чтобы выглядеть хорошо на Xbox 360, но даже с меньшими разрешениями на PC все выглядит хорошо, подобно приведенному снимку экрана. Для тестирования меню и игровых экранов из этой главы запустите пример игрового проекта для этой главы, который по-прежнему основан на проекте XnaGraphicsEngine, начатом вами в главе 5, но теперь у вас в нем есть несколько новых и обновленных классов.


Рис. 10.9

Рис. 10.9


Советы

Согласно моему опыту есть несколько вещей, которые следует помнить, разрабатывая игры XNA для Xbox 360. Все эти вопросы не имеют большого значения на PC, но могут обойтись вам в дополнительное потраченное время, пока вы не решите их правильно. Одна из основных проблем заключается в том, что если вы разрабатываете вашу игру на PC, а затем тестируете ее на Xbox 360 только в самом конце, многие вещи могут оказаться сделанными неверно (плохая производительность на .NET Compact Framework; элементы UI по краям экрана, которые будут невидимы на некоторых телевизорах; плохая поддержка игрового пульта Xbox 360, являющегося главным устройством ввода для Xbox 360 и т.д.). Если вы заинтересовались, можете прочесть больше об этих вопросах в моем сетевом дневнике.

Чтобы получить дополнительную информацию о .NET Compact Framework и том, как ее лучше использовать для XNA Framework на Xbox 360, прочитайте замечательную статью от команды разработчиков .NET Compact Framework, которую можно найти по адресу http://blogs.msdn.com/netcfteam/archive/2006/12/22/ managed-code-performance-on-xbox-360-for-the-xna-framework-1-0.aspx.


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

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