Microsoft xna framework что это
Аннотация: В данной лекции мы познакомимся с Microsoft XNA, рассмотрим различные варианты его применения, разработаем нашу первую программу на базе этой технологии.
Цель лекции: Обзор пакета Microsoft XNA, перспективы его применения в данной системе.
Из предыдущих лекций мы помним, что Microsoft XNA— набор инструментов с управляемой средой времени выполнения (. NET ), созданный Microsoft, облегчающий разработку и управление компьютерными играми. XNA стремится освободить разработку игр от написания "повторяющегося шаблонного кода" и объединить различные аспекты разработки игр в одной системе. Набор инструментов XNA был анонсирован 24 марта 2004 на Game Developers Conference в Сан-Хосе, Калифорния.
Пакет Microsoft XNA, по словам представителей Microsoft, позволит разработчикам игр избежать многих технических трудностей, возникающих при написании кода, а также обеспечит существенное снижение стоимости конечной продукции. Кроме того, благодаря XNA программисты смогут создавать принципиально новые игры с высококачественной графикой. В ходе демонстрации, Microsoft показала два анимационных ролика, созданных с применением технологии XNA. В одном из них облако вздымающегося сигаретного дыма в режиме реального времени меняло свою форму и направление движения под действием внешних факторов. Другой ролик демонстрировал разлетающиеся в разные стороны детали разбившегося о стену автомобиля.
Инструментарий XNA изначально разрабатывался с целью максимально облегчить процесс разработки игр для консоли Xbox и компьютеров, работающих под управлением операционной системы Windows . Вместе с тем, пакет XNA позволит распространить общие сервисы Xbox Live , такие как, например, аутентификация , на игры для персональных компьютеров. Инструментарий XNA позволяет Microsoft конкурировать с Sony на рынке видеоигр для следующего поколения игровых приставок.
Первое что нам предстоит сделать, написать простую программу, отображающую небольшое приветствие в центре экрана. Но сделать это здесь не так просто как в приложениях на Silverlight. В них текст обычно превалирует, а в видеоиграх его встретишь не часто. В играх роль текста сведена к описанию правил или отображению счета. Поэтому сама концепция приложения "здравствуй, мир" не вполне вписывается в общую идеологию программирования на XNA.
В XNA даже нет встроенных шрифтов. И приложение на XNA, выполняющееся на телефоне, не может использовать те же встроенные шрифты телефона, что и программы на Silverlight, как это можно было бы предположить. Silverlight применяет векторные шрифты TrueType, а XNA ничего не знает о таких экзотических концепциях. Для XNA все, включая шрифты, является растровыми изображениями.
Если в приложении на XNA требуется использовать определенный шрифт , он должен быть встроен в исполняемый файл как коллекция растровых изображений для каждого символа. XNA Game Studio (которая интегрирована в Visual Studio) очень упрощает сам процесс встраивания шрифта , но тут возникают некоторые серьезные правовые проблемы.
Вы можете легально распространять приложение на XNA, использующее тот или иной шрифт , только при условии, если имеете право на распространение этого встроенного шрифта, а это невозможно для большинства шрифтов, поставляемых с самой Windows или приложениями Windows .
Чтобы помочь в решении этого правового затруднения, Майкрософт предоставляет лицензию на использование шрифтов Ascender Corporation именно в целях их применения в приложениях на XNA. Вот эти шрифты:
Обратите внимание, что в шрифте Pericles в качестве строчных букв используются уменьшенные заглавные, поэтому, вероятно, он подойдет только для заголовков.
В Visual Studio в меню File выберите New и Project .
Visual Studio создает два проекта, один для логики приложения и другой для его содержимого. Приложения на XNA обычно включают большой объем содержимого, которым преимущественно являются растровые изображения и трехмерные модели, но также и шрифты.
Чтобы добавить шрифт в это приложение , щелкните правой кнопкой мыши проект, созданный для содержимого (он обозначен "XnaHelloPhoneContent ( Content )"), и во всплывающем меню выберите Add (Добавить) и New Item (Новый элемент). Выберите sprite Font , оставьте имя файла как есть, SpriteFont1.spritefont , и щелкните Add .
Слово " спрайт " (" sprite " в переводе на русский означает "эльф") широко распространено в игровых приложениях и обычно обозначает небольшое растровое изображение, которое может очень быстро перемещаться (так же как эльфы, живущие в волшебном лесу). В XNA даже шрифты являются спрайтами.
SpriteFont1.spritefont появится в списке файлов каталога Content , и вы можете редактировать изобилующий комментариями XML- файл , описывающий шрифт .
Проект XNA: XnaHelloPhone Файл : SpriteFont1.spritefont (полностью за исключением комментариев)
Между тегами FontName указан шрифт Segoe UI Mono, но его можно заменить любым другим шрифтом, из приведенных ранее. Если желаете использовать Pericles Light , укажите его полное имя , но для Miramonte Bold , Pescadero Bold или Segoe UI Mono Bold необходимо написать просто Miramonte, Pescadero или Segoe UI Mono и ввести Bold (Полужирный) между тегами Style (Стиль).
Bold может использоваться и для других шрифтов, но для них он будет синтезирован, тогда как для Miramonte, Pescadero или Segoe UI Mono будет использоваться специально разработанный полужирный шрифт .
В разделе CharacterRegions ( Диапазоны символов ) файла указываются диапазоны шестнадцатеричных кодировок Unicode. По умолчанию используется диапазон от 0x32 до 0x126, что включает все обычные символы набора символов ASCII .
ASCII (англ. American Standard Code for Information Interchange ) — американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов. ASCII представляет собой кодировку для представления десятичных цифр, латинского и национального алфавитов, знаков препинания и управляющих символов.
SpriteFont1.spritefont не является достаточно описательным именем. Если сохраняются стандартные настройки шрифта, переименуйте файл в Segoe14.spritefont. Если взглянуть на свойства этого файла – щелкните правой кнопкой мыши имя файла и выберите Properties – можно увидеть, что значением Asset Name (Имя ресурса) является имя файла без расширения: Segoe14. Значение Asset Name используется для ссылки на шрифт в приложении. Если хотите запутать себя, можете изменить Asset Name и задать ему значение , отличное от имени файла.
Чаще всего при создании небольших игр основная часть времени уходит на файл Game1.cs. Класс Game1 наследуется от Game ( Игра ). Первоначально в нем определены два поля: graphics (графические элементы) и spriteBatch (Пакет спрайтов). К этим двум полям добавим еще три:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент, демонстрирующий поля)
В этих трех новых полях просто указан текст для отображения, используемый для этого шрифт и месторасположения текста на экране. Координаты задаются в пикселах относительно верхнего левого угла экрана. Структура Vector2 имеет два поля: X и Y, типа float (число с плавающей точкой).
В целях обеспечения лучшей производительности в XNA все значения с плавающей точкой берутся с одинарной точностью. (В Silverlight – с двойной точностью.) Структура Vector2 часто используется для задания точек, размеров и даже векторов в двухмерном пространстве.
При запуске игры на телефоне, создается экземпляр класса Game1 и выполняется конструктор Game1. Рассмотрим стандартный код:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
По умолчанию частота кадров для Windows Phone составляет 30 кадр/с.
Первое выражение обеспечивает инициализацию поля graphics .
Во втором выражении для Game определяется свойство Content (Содержимое) типа ContentManager ( Диспетчер содержимого), и RootDirectory ( Корневой каталог ) является свойством этого класса. Значение " Content " этого свойства соответствует папке Content , в которой хранится шрифт Segoe размером 14 пунктов.
В третьем выражении задается время игрового цикла программы, что управляет частотой обновления изображения.
Когда экземпляр Game1 создан, вызывается его метод Run (Выполнить), и базовый класс Game инициирует процесс запуска игры. Один из первых шагов – вызов метода Initialize (Инициализировать), который может быть перегружен в производных от Game классах. XNA Game Studio автоматически формирует скелетный метод, в который мы не будем ничего добавлять:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
В методе Initialize шрифт или любое другое содержимое не должно загружаться. Это происходит несколько позже, когда базовый класс вызывает метод LoadContent (Загрузить содержимое). Добавим несколько строк, чтобы содержимое соответствовало следующему:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
Первое выражение данного метода формируется автоматически. Вскоре мы увидим, как этот объект spriteBatch используется для вывода спрайтов на экран.
Как можно заметить, перед всеми именами свойств, таких как Content и GraphicsDevice (Графическое устройство), было поставлено ключевое слово this , чтобы напомнить, что это свойства, а не статические классы. Как уже говорилось, свойство Content типа ContentManager. Универсальный метод Load (Загрузить) обеспечивает загрузку содержимого в приложение , в данном случае, это содержимое типа SpriteFont. Имя, указанное в кавычках, соответствует Asset Name, указанному в свойствах содержимого. Это выражение обеспечивает сохранение результата в поле segoe14 типа SpriteFont.
В XNA спрайты (включая текстовые строки) обычно позиционируются через задание координат в пикселах верхнего левого угла спрайта относительно верхнего левого угла экрана. Для расчета этих координат необходимо знать и размер экрана, и размер текста при отображении его конкретным шрифтом.
Как правило, для получения размера экрана в приложении на XNA используется свойство Viewport (Окно просмотра) класса GraphicsDevice. Оно доступно через свойство GraphicsDevice класса Game и предоставляет свойства Width (Ширина) и Height ( Высота ).
После этого довольно просто вычислить textPosition (Положение текста) – координаты точки относительно верхнего левого угла окна просмотра, в которой будет располагаться верхний левый угол текстовой строки.
На этом этап инициализации программы завершается, и начинается фактическое действие. Приложение входит в игровой цикл. Синхронно с обновлением экрана, которое происходит с частотой 30 кадров в секунду, в приложении вызываются два метода: Update (Обновить) и за ним Draw (Рисовать). Снова и снова: Update , Draw , Update , Draw , Update , Draw …. (На самом деле, все несколько сложнее; методу Update необходимо 1/30 секунды для выполнения.)
Метод Draw обеспечивает отрисовку образов на экране. И это все, что он может делать. Все подготовительные вычисления для отрисовки должны осуществляться в методе Update . Метод Update подготавливает программу к выполнению метода Draw . Очень часто приложения на XNA реализуют перемещение спрайтов по экрану на основании пользовательского ввода. Для телефона пользовательский ввод осуществляется преимущественно посредством сенсорного ввода. Вся обработка пользовательского ввода также должна происходить во время выполнения метода Update .
Следует избегать включения в методы Update и Draw кода, выполняющего рутинные операции по распределению памяти из локальной кучи приложения. В определенный момент времени сборщик мусора . NET захочет вернуть часть этой памяти, и пока он будет выполнять свою работу, игра может немного притормаживать.
В нашем приложении XnaHelloPhone метод Update абсолютно тривиальный. Отображаемый текст зафиксирован в одной единственной точке. Все необходимые вычисления уже выполнены в методе LoadContent. Поэтому оставляем метод Update без изменений, просто в том виде, в каком он был изначально создан XNA Game Studio:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
В формируемом по умолчанию коде для проверки события нажатия кнопки Back использует статический класс GamePad (Игровой планшет). Это событие является сигналом к выходу из игры.
И, наконец, метод Draw . Его автоматически созданная версия просто закрашивает фон голубым цветом:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
Васильковый цвет (CornflowerBlue) приобрел культовый статус в сообществе разработчиков на XNA. При работе над программой на XNA увидеть голубой экран очень утешительно, поскольку это означает, что программа , по крайней мере, дошла до метода Draw . Но в целях энергосбережения при использовании ОСИД-экранов желательно применять более темные фоны. Мы сделали фон темно-синим. Как и Silverlight, XNA поддерживает 140 цветов, которые уже считаются стандартными. Выводимый текст будет белого цвета:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
Спрайты выводятся на экран пакетами в составе объекта SpriteBatch, который был создан во время вызова метода LoadContent. Между вызовами Begin (Начало) и End (Конец) может осуществляться множество вызовов метода DrawString (Отрисовать строку) для отрисовки текста и Draw для отрисовки растровых изображений. Вызываться могут только эти методы. В данном конкретном вызове DrawString указан шрифт , выводимый текст, местоположение верхнего левого угла текста относительно верхнего левого угла экрана и цвет. Результат выполнения программы:
Обратите внимание, что по умолчанию программы на Silverlight отображаются в портретном режиме, а программы на XNA – в альбомном. Повернем телефон или эмулятор (с помощью панели в правом верхнем углу):
Ключевые термины
ASCII (англ. American Standard Code for Information Interchange ) — американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов. ASCII представляет собой кодировку для представления десятичных цифр, латинского и национального алфавитов, знаков препинания и управляющих символов.
Sprite — ( в переводе на русский означает "эльф") широко распространено в игровых приложениях слово ,обозначающее небольшое растровое изображение, которое может очень быстро перемещаться.
Краткие итоги
В данной лекции мы:
- ближе познакомились с Microsoft XNA, её возможностями и областью применения;
- написали первую программу на XNA;
- рассмотрели стандартные шрифты, предоставляемые Microsoft.
Набор для практики
Упражнения
Добавьте к нашей программе вторую строчку с другим текстом, располагающуюся немного ниже первой.
Несколько дней назад, бороздя просторы великого и могучего Интернета, наткнулся на Microsoft XNA Studio. Не то чтобы услышал об этом фреймворке в первый раз, но все предыдущие разы как-то проходил мимо, времени разбираться не было совершенно.
В этот раз что-то меня дернуло покопаться поглубже. Справедливо рассудив что для знакомства с библиотекой лучшего метода чем реализовать что нибудь на нем нет, а также имея в распоряжении свободный вечер, решил написать что нибудь простенькое, например любимый мною с детства Arkanoid (Brick Out), не корысти ради, а ознакомления для.
Это моя первая статья на хабре, убедительно прошу ногами не пинать
Смысл данной статьи показать как легко можно начать создавать свои игры при помощи XNA и, собственно, дать стимул для дальнейшего изучения этой платформы. Посему, на полноценную игру не претендует, графика — никакая, как и художник из меня. Да и физика могла бы быть пореалистичнее, но это уже выходит за рамки данной статьи, уверен что интересующиеся разработкой игр найдут немало достойных (и не очень) материалов в сети.
Исходники можно скачать тут
Итак, что же такое Microsoft XNA?
Последняя версия на момент написания статьти – Microsoft XNA Game Studio 3.1 (73.2 MB)
Создание проекта
Создадим новый проект – XNA Game Studio 3.1 – Windows Game (3.1)
Мастер создаст скелет игры:
Самый большой интерес для нас представляет файл Game1.cs, в котором определен класс Game1, наследованный от Microsoft.Xna.Framework.Game, где мы и будем разрабатывать нашу игру.
В классе Game1 переопределены следующие методы Game:
void Initialize() – Вызывается единожды, для инициализации ресурсов до начала игры
void LoadContent() – Вызывается единожды, используется для загрузки контента (спрайты и т.д.)
void UnloadContent() – Вызывается единожды, используется для выгрузки контента
void Update(GameTime gameTime) – В этом методе реализуется собственно логика игры, обработка коллизий, обработка событий клавиатуры или джойстика, проигрывание аудио и т.д.
void Draw(GameTime gameTime) – Вызывается для прорисовки игрового поля.
На данный момент скомпилированная игра выглядит вот так
Добавление контента
Добавим игровые ресурсы, в данном случае картинки фона кирпича, ракетки и мячика – Content (Right Click) -> Add -> Existing Item…
Обратите внимание на свойство Asset Name, его мы используем для создания обьекта Texture2D необходимого для дальнейшей анимации.
Рисуем фон игрового поля
Загрузим изображение для фона игрового поля:
- private Rectangle _viewPortRectangle; // Границы игрового поля
- private Texture2D _background; // Фон игрового поля
- protected override void LoadContent()
- // Границы игрового поля
- _viewPortRectangle = new Rectangle(0, 0,
- graphics.GraphicsDevice.Viewport.Width,
- graphics.GraphicsDevice.Viewport.Height);
- _background = Content.Load( @"background" );
- >
- protected override void Draw(GameTime gameTime)
- GraphicsDevice.Clear(Color.CornflowerBlue);
- spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
- // Рисуем фон
- spriteBatch.Draw(_background, _viewPortRectangle, Color.White);
- spriteBatch.End();
- base .Draw(gameTime);
- >
Метод SpriteBatch.Begin подготавливает графическое устройство к отрисовке спрайтов, SpriteBatch.End завершает процесс отрисовки и возвращает устройство к начальному состоянию. Все методы SpriteBatch.Draw должны быть заключены в SpriteBatch.Begin — SpriteBatch.End.
Создание игрового обьекта
Создадим класс GameObject инкапсулирующий любой из наших игровых обьектов:
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework. Graphics ;
- namespace Arkanoid
- public class GameObject
- public Texture2D Sprite < get ; set ; >// Спрайт
- public Vector2 Position; // Положение
- public Vector2 Velocity; // Скорость
- public int Width < get < return Sprite.Width; >> // Ширина
- public int Height < get < return Sprite.Height; >> // Высота
- public bool IsAlive < get ; set ; >// Жив ли обьект
- public Rectangle Bounds // Границы обьекта
- get
- return new Rectangle(( int )Position.X, ( int )Position.Y, Width, Height);
- >
- >
- // Разворачивание движения по горизонтальной оси
- public void ReflectHorizontal()
- Velocity.Y = -Velocity.Y;
- >
- // Разворачивание движения по вертикальной оси
- public void ReflectVertical()
- Velocity.X = -Velocity.X;
- >
- public GameObject(Texture2D sprite)
- Sprite = sprite;
- IsAlive = true ;
- Position = Vector2.Zero;
- Velocity = Vector2.Zero;
- >
- >
- >
Отрисовка и анимация ракетки
Сначала создадим обьект представляющий ракетку и расположим его в середине игрового поля чуть повыше от его нижнего края
- private GameObject _paddle; // Ракетка
- protected override void LoadContent()
- // Создание ракетки, начальное положение в середине игрового поля, повыше нижнего края
- _paddle = new GameObject(Content.Load( @"paddle" ));
- _paddle.Position = new Vector2((_viewPortRectangle.Width - _paddle.Width) / 2,
- _viewPortRectangle.Height - _paddle.Height - 20);
- >
Отрисовка ракетки на экране
- protected override void Draw(GameTime gameTime)
- spriteBatch.Draw(_paddle.Sprite, _paddle.Position, Color.White);
- >
На данном этапе, если скомпилировать приложение, получим что-то вроде этого:
Неплхо было бы заставить реагировать ракетку на нажатие клавиш, для этого добавим в метод Update следующий код
- protected override void Update(GameTime gameTime)
- KeyboardState keyboardState = Keyboard.GetState();
- // Двигаем ракетку вправо
- if (keyboardState.IsKeyDown(Keys.Right))
- _paddle.Position.X += 6f;
- // Двигаем ракетку влево
- if (keyboardState.IsKeyDown(Keys.Left))
- _paddle.Position.X -= 6f;
- // Ограничиваем движение ракетки игровым полем
- _paddle.Position.X = MathHelper.Clamp(_paddle.Position.X, 0, _viewPortRectangle.Width - _paddle.Width);
- >
Отрисовка кирпичей
Создадим массив GameObject представляющий кирпичи которые собственно и будем разбивать
- private int _brickPaneWidth = 10; // Сколько кипричей рисовать в ширину
- private int _brickPaneHeight = 5; // Сколько кипричей рисовать в высоту
- private Texture2D _brickSprite; // Спрайт кирпича
- private GameObject[,] _bricks; // Массив кирпичей
Добавим следующий код в метод LoadContent()
- protected override void LoadContent()
- // Создание массива кирпичей
- _brickSprite = Content.Load( @"brick" );
- _bricks = new GameObject[_brickPaneWidth,_brickPaneHeight];
- for ( int i = 0; i < _brickPaneWidth; i++)
- for ( int j = 0; j < _brickPaneHeight; j++)
- _bricks[i, j] = new GameObject(_brickSprite)
- Position = new Vector2(i * 55 + 120, j * 25 + 100)
- >;
- >
- >
- >
Отрисовка массива кирпичей, отисовка производится если кирпич “жив”, т.е. не разбит мячем
- protected override void Draw(GameTime gameTime)
- // Рисуем кирпичи
- foreach ( var brick in _bricks)
- if (brick.IsAlive)
- spriteBatch.Draw(brick.Sprite, brick.Position, Color.White);
- >
На данном этапе игровое поле выглядит следующим образом
Отрисовка мячика
Создаем обьект мячика
- private GameObject _ball; // Мячик
- protected override void LoadContent()
- // Создание мячика, начальное положение в середине на ракетке,
- // начальное направление - вправо, вверх
- _ball = new GameObject(Content.Load( @"ball" ));
- _ball.Position = new Vector2((_viewPortRectangle.Width - _ball.Width) / 2,
- _viewPortRectangle.Height - _paddle.Height - _ball.Height - 20);
- _ball.Velocity = new Vector2(3,-3);
- >
Для анимации мячика добавим новый метод UpdateBall(), и его вызов в в метод Update(). Данный метод нам понадобится в дальнейшем для обработки столкновений мячика с кирпичами и ракеткой
- private void UpdateBall()
- _ball.Position += _ball.Velocity;
- >
- protected override void Update(GameTime gameTime)
- // Двигаем мячик
- UpdateBall();
- >
Для отрисовки мячика добавим следующий код в метод Draw()
- protected override void Draw(GameTime gameTime)
- // Рисуем мячик
- spriteBatch.Draw(_ball.Sprite, _ball.Position, Color.White);
- >
На данный момент, мы имеем почти полностью готовое игровое поле, но без обработки столкновений мячик сразу же вылетает за пределы игрового поля. Добавим обработку столкновений мячика с игровым полем, кирпичами и ракеткой
Обработка столкновений
Создадим новый метод определяющий место столкновения обьектов и меняющий направление полета мяча.
- // Определение стороны столкновения и отражение направления полета мячика
- public void Collide(GameObject gameObject, Rectangle rect2)
- // Обьект столкнулся сверху или снизу, отражаем направление полета по горизонтали
- if (rect2.Left
- gameObject.ReflectHorizontal();
- // Обьект столкнулся слева или справа, отражаем направление полета по вертикали
- else if (rect2.Top
- gameObject.ReflectVertical();
- >
Добавим следующий код в метод UpdateBall()
- private void UpdateBall()
- // Будущее положение мяча, нужно для предотвращения "залипания" мяча на поверхности обьекта
- Rectangle nextRect = new Rectangle(( int )(_ball.Position.X + _ball.Velocity.X),
- ( int )(_ball.Position.Y + _ball.Velocity.Y),
- _ball.Width, _ball.Height);
- // Столкновение с верхним краем игрового поля
- if (nextRect.Y
- _ball.ReflectHorizontal();
- // При сталкивании мяча с нижним краем игрового поля, мячик "умирает"
- if (nextRect.Y >= _viewPortRectangle.Height - nextRect.Height)
- _ball.IsAlive = false ;
- >
- // Столкновение мячика с левым или правым краем игрового поля
- if ((nextRect.X >= _viewPortRectangle.Width - nextRect.Width) || nextRect.X
- _ball.ReflectVertical();
- >
- // Столкновение мячика с ракеткой
- if (nextRect.Intersects(_paddle.Bounds))
- Collide(_ball, _paddle.Bounds);
- // Столкновение мячика с кирпичами
- foreach ( var brick in _bricks)
- if (nextRect.Intersects(brick.Bounds) && brick.IsAlive)
- brick.IsAlive = false ;
- Collide(_ball, brick.Bounds);
- >
- >
- _ball.Position += _ball.Velocity;
- >
Итак, что получилось
Конечно физика в игре, мягко говоря, никакая, мячик иногда залипает при столкновении с движущейся ракеткой. Но, повторюсь, смысл данной статьи знакомство со средой Microsoft XNA Game Studio, и, надо сказать, она отлично справляется с рутиной, освобождая время разработчика для фокусировки внимания на логике игры.
Исходники можно скачать тут
PS. Большое спасибо ivv за приглашение.
PPS. Спасибо за карму, перенес в XNA
Что же всё-таки представляет собой XNA framework (далее просто XNA)?
XNA это надстройка над неуправляемым (классическим) DirectX. Во всяком случае такую картину можно наблюдать для операционной системы Windows. Дело в том, что XNA является кроссплатформенной библиотекой.
Библиотека разрабатывалась корпорацией Microsoft с целью создания единого инструмента для разработки игр на двух не совместимых платформах, принадлежащих той же компании. А именно: Microsoft Windows и Microsoft XBOX360.
В связи с этим XNA framework не является банальным враппером.
Во-первых, XNA предоставляет такие возможности, которые в DirectX в принципе не нужны. Например, работа с файловой системой в DirectX-приложениях происходит с помощью использования стандартных библиотек ОС Windows. В XNA же для этих целей предусмотрены специальные классы, которые так же легко работают на XBOX360, как и на Windows.
Во-вторых, математические классы XNA не являются обвёртками над неуправляемым DirectX, а полностью реализованы с нуля. Что, в большинстве случаев, позволяет добиться производительности на уровне классического DirctX.
В-третьих, используя специализированные классы библиотеки программист может лишить себя «удовольствия» писать обработчики на такие задачи, как обработка потери устройства, загрузка/выгрузка контента (модели, текстуры и др.), организация игрового цикла и многие другие «прелести», которые очень сильно омрачали жизнь каждому начинающему игроделу (профи от них, наверное, тоже не в восторге).
В-четвёртых, для этой библиотеки имеется среда разработки XNA Game Studio. При этом Express Edition (бесплатная версия) содержит, кроме основного функционала, так называемые Starter Kit'ы заготовки в виде простых игр, которые можно использовать, как для обучения, так и для принятия их за основу своих игр.
На что способен XNA framework?
На многое. Что бы не разводить болтологию и дать читателю первое представление о возможностях библиотеки, я решил в эту статью включить таблицу с описанием основных пространств имён XNA framework
Но не думайте, что я описал хоть десятую часть всех пространств имён библиотеки или всех её возможностей. В дальнейшем мы будем подробней рассматривать те или иные возможности XNA.
И на последок я хотел бы ответить на такой вопрос.
Какие технические характеристики и требования XNA framework?
Ну, во-первых, XNA построена полностью на принципе программированного конвеера. То есть разработчики полностью отказались от фиксированного конвеера и тем самым ужесточили требования к аппаратному обеспечению компьютера. А именно, библиотека может функционировать только если видеокарта поддерживает, как минимум, Pixel Shader v1.1. Но это не сильно должно нас волновать, так как поддержка этой технологии есть у видеокарт начиная с Geforce 2 (кроме серий MX)
Во-вторых, XNA поддерживает фрагментные (пиксельные) шейдеры от версий 1.1 до 3.0 Это объясняется тем, что основа XNA DirectX 9.0c, а так же тем фактом, что XBOX360 поддерживает шейдеры только до версии 3.0 В связи с этим, в ближайшее время, не предполагается добавление поддержки шейдеров 4-ой версии (DirectX 10)
Что же относительно остального, то возможности XNA практически такие же, как и у DirectX 9.0c
Так же следует указать, что официально XNA Game Studio поддерживает только такие операционные системы: Windows XP SP2 и Windows Vista
Ну и на последок, я думаю, тут не помешает несколько ссылок на тематические сайты.
Аннотация: В данной лекции мы познакомимся с Microsoft XNA, рассмотрим различные варианты его применения, разработаем нашу первую программу на базе этой технологии.
Цель лекции: Обзор пакета Microsoft XNA, перспективы его применения в данной системе.
Из предыдущих лекций мы помним, что Microsoft XNA— набор инструментов с управляемой средой времени выполнения (. NET ), созданный Microsoft, облегчающий разработку и управление компьютерными играми. XNA стремится освободить разработку игр от написания "повторяющегося шаблонного кода" и объединить различные аспекты разработки игр в одной системе. Набор инструментов XNA был анонсирован 24 марта 2004 на Game Developers Conference в Сан-Хосе, Калифорния.
Пакет Microsoft XNA, по словам представителей Microsoft, позволит разработчикам игр избежать многих технических трудностей, возникающих при написании кода, а также обеспечит существенное снижение стоимости конечной продукции. Кроме того, благодаря XNA программисты смогут создавать принципиально новые игры с высококачественной графикой. В ходе демонстрации, Microsoft показала два анимационных ролика, созданных с применением технологии XNA. В одном из них облако вздымающегося сигаретного дыма в режиме реального времени меняло свою форму и направление движения под действием внешних факторов. Другой ролик демонстрировал разлетающиеся в разные стороны детали разбившегося о стену автомобиля.
Инструментарий XNA изначально разрабатывался с целью максимально облегчить процесс разработки игр для консоли Xbox и компьютеров, работающих под управлением операционной системы Windows . Вместе с тем, пакет XNA позволит распространить общие сервисы Xbox Live , такие как, например, аутентификация , на игры для персональных компьютеров. Инструментарий XNA позволяет Microsoft конкурировать с Sony на рынке видеоигр для следующего поколения игровых приставок.
Первое что нам предстоит сделать, написать простую программу, отображающую небольшое приветствие в центре экрана. Но сделать это здесь не так просто как в приложениях на Silverlight. В них текст обычно превалирует, а в видеоиграх его встретишь не часто. В играх роль текста сведена к описанию правил или отображению счета. Поэтому сама концепция приложения "здравствуй, мир" не вполне вписывается в общую идеологию программирования на XNA.
В XNA даже нет встроенных шрифтов. И приложение на XNA, выполняющееся на телефоне, не может использовать те же встроенные шрифты телефона, что и программы на Silverlight, как это можно было бы предположить. Silverlight применяет векторные шрифты TrueType, а XNA ничего не знает о таких экзотических концепциях. Для XNA все, включая шрифты, является растровыми изображениями.
Если в приложении на XNA требуется использовать определенный шрифт , он должен быть встроен в исполняемый файл как коллекция растровых изображений для каждого символа. XNA Game Studio (которая интегрирована в Visual Studio) очень упрощает сам процесс встраивания шрифта , но тут возникают некоторые серьезные правовые проблемы.
Вы можете легально распространять приложение на XNA, использующее тот или иной шрифт , только при условии, если имеете право на распространение этого встроенного шрифта, а это невозможно для большинства шрифтов, поставляемых с самой Windows или приложениями Windows .
Чтобы помочь в решении этого правового затруднения, Майкрософт предоставляет лицензию на использование шрифтов Ascender Corporation именно в целях их применения в приложениях на XNA. Вот эти шрифты:
Обратите внимание, что в шрифте Pericles в качестве строчных букв используются уменьшенные заглавные, поэтому, вероятно, он подойдет только для заголовков.
В Visual Studio в меню File выберите New и Project .
Visual Studio создает два проекта, один для логики приложения и другой для его содержимого. Приложения на XNA обычно включают большой объем содержимого, которым преимущественно являются растровые изображения и трехмерные модели, но также и шрифты.
Чтобы добавить шрифт в это приложение , щелкните правой кнопкой мыши проект, созданный для содержимого (он обозначен "XnaHelloPhoneContent ( Content )"), и во всплывающем меню выберите Add (Добавить) и New Item (Новый элемент). Выберите sprite Font , оставьте имя файла как есть, SpriteFont1.spritefont , и щелкните Add .
Слово " спрайт " (" sprite " в переводе на русский означает "эльф") широко распространено в игровых приложениях и обычно обозначает небольшое растровое изображение, которое может очень быстро перемещаться (так же как эльфы, живущие в волшебном лесу). В XNA даже шрифты являются спрайтами.
SpriteFont1.spritefont появится в списке файлов каталога Content , и вы можете редактировать изобилующий комментариями XML- файл , описывающий шрифт .
Проект XNA: XnaHelloPhone Файл : SpriteFont1.spritefont (полностью за исключением комментариев)
Между тегами FontName указан шрифт Segoe UI Mono, но его можно заменить любым другим шрифтом, из приведенных ранее. Если желаете использовать Pericles Light , укажите его полное имя , но для Miramonte Bold , Pescadero Bold или Segoe UI Mono Bold необходимо написать просто Miramonte, Pescadero или Segoe UI Mono и ввести Bold (Полужирный) между тегами Style (Стиль).
Bold может использоваться и для других шрифтов, но для них он будет синтезирован, тогда как для Miramonte, Pescadero или Segoe UI Mono будет использоваться специально разработанный полужирный шрифт .
В разделе CharacterRegions ( Диапазоны символов ) файла указываются диапазоны шестнадцатеричных кодировок Unicode. По умолчанию используется диапазон от 0x32 до 0x126, что включает все обычные символы набора символов ASCII .
ASCII (англ. American Standard Code for Information Interchange ) — американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов. ASCII представляет собой кодировку для представления десятичных цифр, латинского и национального алфавитов, знаков препинания и управляющих символов.
SpriteFont1.spritefont не является достаточно описательным именем. Если сохраняются стандартные настройки шрифта, переименуйте файл в Segoe14.spritefont. Если взглянуть на свойства этого файла – щелкните правой кнопкой мыши имя файла и выберите Properties – можно увидеть, что значением Asset Name (Имя ресурса) является имя файла без расширения: Segoe14. Значение Asset Name используется для ссылки на шрифт в приложении. Если хотите запутать себя, можете изменить Asset Name и задать ему значение , отличное от имени файла.
Чаще всего при создании небольших игр основная часть времени уходит на файл Game1.cs. Класс Game1 наследуется от Game ( Игра ). Первоначально в нем определены два поля: graphics (графические элементы) и spriteBatch (Пакет спрайтов). К этим двум полям добавим еще три:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент, демонстрирующий поля)
В этих трех новых полях просто указан текст для отображения, используемый для этого шрифт и месторасположения текста на экране. Координаты задаются в пикселах относительно верхнего левого угла экрана. Структура Vector2 имеет два поля: X и Y, типа float (число с плавающей точкой).
В целях обеспечения лучшей производительности в XNA все значения с плавающей точкой берутся с одинарной точностью. (В Silverlight – с двойной точностью.) Структура Vector2 часто используется для задания точек, размеров и даже векторов в двухмерном пространстве.
При запуске игры на телефоне, создается экземпляр класса Game1 и выполняется конструктор Game1. Рассмотрим стандартный код:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
По умолчанию частота кадров для Windows Phone составляет 30 кадр/с.
Первое выражение обеспечивает инициализацию поля graphics .
Во втором выражении для Game определяется свойство Content (Содержимое) типа ContentManager ( Диспетчер содержимого), и RootDirectory ( Корневой каталог ) является свойством этого класса. Значение " Content " этого свойства соответствует папке Content , в которой хранится шрифт Segoe размером 14 пунктов.
В третьем выражении задается время игрового цикла программы, что управляет частотой обновления изображения.
Когда экземпляр Game1 создан, вызывается его метод Run (Выполнить), и базовый класс Game инициирует процесс запуска игры. Один из первых шагов – вызов метода Initialize (Инициализировать), который может быть перегружен в производных от Game классах. XNA Game Studio автоматически формирует скелетный метод, в который мы не будем ничего добавлять:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
В методе Initialize шрифт или любое другое содержимое не должно загружаться. Это происходит несколько позже, когда базовый класс вызывает метод LoadContent (Загрузить содержимое). Добавим несколько строк, чтобы содержимое соответствовало следующему:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
Первое выражение данного метода формируется автоматически. Вскоре мы увидим, как этот объект spriteBatch используется для вывода спрайтов на экран.
Как можно заметить, перед всеми именами свойств, таких как Content и GraphicsDevice (Графическое устройство), было поставлено ключевое слово this , чтобы напомнить, что это свойства, а не статические классы. Как уже говорилось, свойство Content типа ContentManager. Универсальный метод Load (Загрузить) обеспечивает загрузку содержимого в приложение , в данном случае, это содержимое типа SpriteFont. Имя, указанное в кавычках, соответствует Asset Name, указанному в свойствах содержимого. Это выражение обеспечивает сохранение результата в поле segoe14 типа SpriteFont.
В XNA спрайты (включая текстовые строки) обычно позиционируются через задание координат в пикселах верхнего левого угла спрайта относительно верхнего левого угла экрана. Для расчета этих координат необходимо знать и размер экрана, и размер текста при отображении его конкретным шрифтом.
Как правило, для получения размера экрана в приложении на XNA используется свойство Viewport (Окно просмотра) класса GraphicsDevice. Оно доступно через свойство GraphicsDevice класса Game и предоставляет свойства Width (Ширина) и Height ( Высота ).
После этого довольно просто вычислить textPosition (Положение текста) – координаты точки относительно верхнего левого угла окна просмотра, в которой будет располагаться верхний левый угол текстовой строки.
На этом этап инициализации программы завершается, и начинается фактическое действие. Приложение входит в игровой цикл. Синхронно с обновлением экрана, которое происходит с частотой 30 кадров в секунду, в приложении вызываются два метода: Update (Обновить) и за ним Draw (Рисовать). Снова и снова: Update , Draw , Update , Draw , Update , Draw …. (На самом деле, все несколько сложнее; методу Update необходимо 1/30 секунды для выполнения.)
Метод Draw обеспечивает отрисовку образов на экране. И это все, что он может делать. Все подготовительные вычисления для отрисовки должны осуществляться в методе Update . Метод Update подготавливает программу к выполнению метода Draw . Очень часто приложения на XNA реализуют перемещение спрайтов по экрану на основании пользовательского ввода. Для телефона пользовательский ввод осуществляется преимущественно посредством сенсорного ввода. Вся обработка пользовательского ввода также должна происходить во время выполнения метода Update .
Следует избегать включения в методы Update и Draw кода, выполняющего рутинные операции по распределению памяти из локальной кучи приложения. В определенный момент времени сборщик мусора . NET захочет вернуть часть этой памяти, и пока он будет выполнять свою работу, игра может немного притормаживать.
В нашем приложении XnaHelloPhone метод Update абсолютно тривиальный. Отображаемый текст зафиксирован в одной единственной точке. Все необходимые вычисления уже выполнены в методе LoadContent. Поэтому оставляем метод Update без изменений, просто в том виде, в каком он был изначально создан XNA Game Studio:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
В формируемом по умолчанию коде для проверки события нажатия кнопки Back использует статический класс GamePad (Игровой планшет). Это событие является сигналом к выходу из игры.
И, наконец, метод Draw . Его автоматически созданная версия просто закрашивает фон голубым цветом:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
Васильковый цвет (CornflowerBlue) приобрел культовый статус в сообществе разработчиков на XNA. При работе над программой на XNA увидеть голубой экран очень утешительно, поскольку это означает, что программа , по крайней мере, дошла до метода Draw . Но в целях энергосбережения при использовании ОСИД-экранов желательно применять более темные фоны. Мы сделали фон темно-синим. Как и Silverlight, XNA поддерживает 140 цветов, которые уже считаются стандартными. Выводимый текст будет белого цвета:
Проект XNA: XnaHelloPhone Файл : Game1.cs (фрагмент)
Спрайты выводятся на экран пакетами в составе объекта SpriteBatch, который был создан во время вызова метода LoadContent. Между вызовами Begin (Начало) и End (Конец) может осуществляться множество вызовов метода DrawString (Отрисовать строку) для отрисовки текста и Draw для отрисовки растровых изображений. Вызываться могут только эти методы. В данном конкретном вызове DrawString указан шрифт , выводимый текст, местоположение верхнего левого угла текста относительно верхнего левого угла экрана и цвет. Результат выполнения программы:
Обратите внимание, что по умолчанию программы на Silverlight отображаются в портретном режиме, а программы на XNA – в альбомном. Повернем телефон или эмулятор (с помощью панели в правом верхнем углу):
Ключевые термины
ASCII (англ. American Standard Code for Information Interchange ) — американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов. ASCII представляет собой кодировку для представления десятичных цифр, латинского и национального алфавитов, знаков препинания и управляющих символов.
Sprite — ( в переводе на русский означает "эльф") широко распространено в игровых приложениях слово ,обозначающее небольшое растровое изображение, которое может очень быстро перемещаться.
Краткие итоги
В данной лекции мы:
- ближе познакомились с Microsoft XNA, её возможностями и областью применения;
- написали первую программу на XNA;
- рассмотрели стандартные шрифты, предоставляемые Microsoft.
Набор для практики
Упражнения
Добавьте к нашей программе вторую строчку с другим текстом, располагающуюся немного ниже первой.
Ничего страшного, если у вас на первых порах будет рябить в глазах от обилия компонентов. По мере изучения XNA Framework всe встанет на свои места. В первой лекции мы познакомимся с некоторыми классами пространства имен Microsoft.Xna.Framework.Graphics , и научимся использовать их для визуализации относительно простых двухмерных изображений.
1.1. Создание простейшего приложения, использующего XNA Framework.
Рис. 1.3. Наше первое приложение(Ex01), использующее XNA. Graphic User Interface – графический пользовательский интерфейс
Следующий шаг – подключение сборки Microsoft.Xna.Framework.dll , содержащий компоненты слоя Core Framework , включая необходимый нам компонент Graphics .Для подключения сборки щeлкните правой кнопкой мыши на узле Reference в окне Solution Explorer и выберите в контекстном меню пункт Add Reference.. . (рисунок 1.4). В открывшемся окне выберете сборку Microsoft.Xna.Framework и нажмите кнопку Ok (рисунок 1.5).
Теперь мы можем приступать к собственно написанию программы. Откройте окно редактирования исходного кода, щелкнув правой кнопкой мыши по форме и выбрав пункт View Code контекстного меню (либо нажав на кнопке View Code в верхней части окна Solution Explorer ). Так как мы будем активно использовать классы из пространства имен Microsoft.Xna.Framework.Graphics , было бы логично добавить в начало программы следующую строку:
В XNA Framework все низкоуровневые графические операции выполняются с использованием класса GraphicsDevice , инкапсулирующим графическое устройство (трeхмерный ускоритель). Конструктор класса GraphicsDevice объявлен следующим образом:
- adapter - экземпляр класса GraphicsAdapter , соответствующей используемой видеокарте (многие современные компьютеры содержат две и более видеокарты). Для указания видеокарты по умолчанию достаточно передать в качестве данного параметра значение статического свойства GraphicsAdapter.DefaultAdapter .
- deviceType - тип устройства, задаваемый с использованием перечислимого типа DeviceType (таблица 1.4). На практике обычно используется значение DeviceType .Hardware .
- renderWindowHandle - дескриптор окна или элемента управления, который будет использоваться для вывода информации.
- creationOptions - набор битовых флагов перечислимого типа CreateOptions , задающих режим работы устройства (таблица 1.5). В нашем случае мы будем использовать режимы CreateOptions.SoftwareVertexProcessing и CreateOptions.SingleThreaded .
- PresentationParameters - набор структур PresentationParameters , описывающих представление данных на экране монитора. Каждому монитору соответствует своя структура PresentationParameters . Так как наши приложение будет осуществлять вывод только на один монитор, мы ограничимся одной структурой PresentationParameters . В таблице 1.6 приведено описание некоторых свойств структуры PresentationParameters .
Если попытка создания устройства заканчивается неудачей, конструктор генерирует исключение. Подобная ситуация возникает, к примеру, при попытке создания устройства с использованием флага CreateOptions.HardwareVertexProcessing на видеокарте, не имеющей аппаратных вершинных процессоров. Примерами таких видеокарт являются Intel GMA 900 и Intel GMA950 , интегрированные в чипсеты i915G и i945G соответственно. Так как флаг HardwareVertexProcessing влияют исключительно на выполнение вершинных шейдеров, в то время как примеры этой лекции не используют эту функциональность, применение данного флага некоим образом не повлияет на производительность наших приложений и лишь неоправданно увеличит требования к видеокарте. Поэтому в примерах первой лекции курса мы ограничимся использованием лишь флага SoftwareVertexProcessing .
Читайте также: