Невозможно пройти тесты, в окне с вопросами пусто |
Пользовательский интерфейс в XNA
Цель работы: Научиться разрабатывать пользовательский интерфейс для XNA-игр
20.1. Пример разработки пользовательского интерфейса
Пользовательский интерфейс для XNA-программ нужно разрабатывать самостоятельно, создавая собственные элементы управления. Если интерфейс игры не слишком сложен, его можно реализовать полностью на XNA, если же есть необходимость в использовании сложных элементов управления (наподобие выпадающих списков), есть смысл задуматься о применении Silverlight.
Мы разработаем систему интерфейса, состоящую из нескольких экранов.
При запуске игры на несколько секунд будет появляться стартовый экран. Обычно его называют splash-screen, иногда его называют, в виде русской транскрипции, сплэш-скрин. Он может содержать краткую информацию о программе. Обычно сплэш-скрин отображают до тех пор, пока игра или программа не будет готова к работе.
В нашем случае мы отображаем его определенное время, после чего будет выводиться экран, отображающий меню игры. С этого экрана можно попасть на экран игровой справки, запустить основную игровую программу, либо выйти из игры. Эти действия выполняются при помощи экранных кнопок, реакцию на прикосновения к которым мы задаём в коде. Кроме того, в данном проекте мы расширяем использование аппаратной кнопки Назад.
Ранее нажатие на эту кнопку завершало программу. Теперь мы построили на её основе систему перехода по экранам программы, выглядящую следующим образом. Если отображается экран меню, нажатие на эту кнопку приводит к выходу из программы. Если отображается основной экран игры либо экран справки, нажатие на эту кнопку приводит к переходу к экрану меню.
Такое поведение кнопки Назад характерно для приложений на Windows Phone, её нажатие на экране, не являющимся главным, не должно приводить к завершению работы приложения. Если это оправдано структурой интерфейса, вы вполне можете дополнить данную возможность экранными элементами управления. Например, в сложном многоуровневом меню это вполне логично. Но – лишь дополнить, помня о необходимости правильной обработки нажатия на кнопку Назад.
Создадим новый игровой проект P14_1. На рис. 20.1 вы можете видеть его окно Обозреватель Решений.
Проект включает в себя множество классов, основным является класс Screen. Он (листинг 20.1.) реализует процедуры управления экранами с помощью методов Show() и Hide(), которые используются для управления свойствами игрового компонента (DrawableGameComponent) Visible и Enabled.
Если Visible установлено в значение Истина, для этого компонента вызывается метод Draw, отвечающий за отрисовку данных, сгенерированных объектом. В противном случае этот метод не вызывается.
Свойство Enabled отвечает за вызов Update. Таким образом, если оба свойства установлены в значение Ложь – игровой объект, представленный данным классом (и классами-наследниками) не выводится на экран, его данные не обновляются.
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace P14_1 { /// <summary> /// Это игровой компонент, реализующий интерфейс IUpdateable. /// </summary> //Базовый класс, на основе которого создаются игровые экраны public class Screen : Microsoft.Xna.Framework.DrawableGameComponent { //Для объекта SpriteBatch, который используется //для вывода изображений в классах-наследниках public SpriteBatch sprBatch; public Screen(Game game) : base(game) { //При создании объекта он по умолчанию //невидим и неактивен Visible = false; Enabled = false; //получим объект SpriteBatch sprBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch)); } //Процедура для отображения и активации объекта public void Show() { Visible = true; Enabled = true; } //Процедура для скрытия и отключения объекта public void Hide() { Visible = false; Enabled = false; } } }Листинг 20.1. Код класса Screen
Ниже приведен код класса стартового экрана, листинг 20.2.
using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace P14_1 { class SplashScreen: Screen { //Текстуры для фона и справочной надписи Texture2D backTexture; Rectangle backRectangle; public SplashScreen(Game game, Texture2D _back, Rectangle _backRec) : base(game) { backTexture = _back; backRectangle = _backRec; } public override void Draw(GameTime gameTime) { //Выводим изображения sprBatch.Draw(backTexture, backRectangle, Color.White); base.Draw(gameTime); } } }Листинг 20.2. Код класса SplashScreen
Здесь мы, в конструкторе, принимаем данные для вывода изображения и выводим его в методе Draw. Стартовый экран вы можете видеть на рис. 20.2
В листинге 20.3 приведен код класса MenuScreen.
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace P14_1 { class MenuScreen: Screen { //Элементы меню будем хранить в массиве типа Menu //тип данных Menu хранит информацию об элементах меню Menu[] menu; //Текстуры и прямоугольники для вывода элементов меню Texture2D menuTxtStartGame; Texture2D menuTxtHelp; Texture2D menuTxtExit; Rectangle menuTxtStartGameR, menuTxtHelpR, menuTxtExitR; Texture2D menuBack, menuGameName; Rectangle menuBackR, menuGameNameR; public MenuScreen(Game game, Texture2D _menuBack, Texture2D _menuGameName, Texture2D _menuTxtStartGame, Texture2D _menuTxtHelp, Texture2D _menuTxtExit, Rectangle _menuTxtStartGameR, Rectangle _menuTxtHelpR, Rectangle _menuTxtExitR) : base(game) { menuBack = _menuBack; menuGameName = _menuGameName; menuBackR = new Rectangle(0, 0, 800, 480); menuGameNameR = new Rectangle(0, 0, 800, 200); menuTxtStartGame = _menuTxtStartGame; menuTxtStartGameR = _menuTxtStartGameR; menuTxtHelp = _menuTxtHelp; menuTxtHelpR = _menuTxtHelpR; menuTxtExit = _menuTxtExit; menuTxtExitR = _menuTxtExitR; //Создаем массив из 3-х элементов menu = new P14_1.Menu[3]; //Инициализируем элементы массива //Элемент с номером 0 активен menu[0] = new P14_1.Menu(game, menuTxtStartGame, menuTxtStartGameR, Color.Magenta); menu[1] = new P14_1.Menu(game, menuTxtHelp, menuTxtHelpR, Color.White); menu[2] = new P14_1.Menu(game, menuTxtExit, menuTxtExitR, Color.White); } //Метод вызывается для отображения смены пункта меню public void Change(int i) { //i=1 - первый пункт //i=2 - второй пункт //i=3 - третий пункт if (i == 1) { menu[0].color = Color.Magenta; menu[1].color = Color.White; menu[2].color = Color.White; } if (i == 2) { menu[0].color = Color.White; menu[1].color = Color.Magenta; menu[2].color = Color.White; } if (i == 3) { menu[0].color = Color.White; menu[1].color = Color.White; menu[2].color = Color.Magenta; } } //Рисование элементов public override void Draw(GameTime gameTime) { //Вывод фона и названия игры sprBatch.Draw(menuBack, menuBackR, Color.White); sprBatch.Draw(menuGameName, menuGameNameR, Color.White); //Вывод элементов меню for (int i = 0; i < 3; i++) sprBatch.Draw(menu[i].imageTexture, menu[i].imageRectangle, menu[i].color); base.Draw(gameTime); } } }Листинг 20.3. Код класса MenuScreen
Здесь мы выводим элементы меню, данные по которым хранятся в массиве, что позволяет удобно расширять меню. Кроме того, класс имеет метод Change, который позволяет активировать пункт меню, которого коснулся пользователь, меняя его цвет.