XNA
GameDev.ru / Сообщества / XNA / Статьи / XNA – Быстрый старт

XNA – Быстрый старт

Автор:

Наша задача, быстро ввести вас в курс дела, — что такое XNA, как его использовать. Статья рассчитана на людей уже имеющих определённый опыт программирования (но не знакомых собственно с XNA), и желающих кратко ознакомиться с платформой.

articles_xna_quickstart_p2 | XNA – Быстрый старт

Так что же такое XNA?
  Почему XNA?
C чего начать?
Минимальный проект
Ближе к делу
Загрузка контента
Вывод графики
  Вывод 2D графики и текста при помощи SpriteBatch
  Вывод 3D графики
Управление
Аудио
Запуск игры на машине пользователя
Ccылки

Так что же такое XNA?

Само название шутливый рекурсивный акроним «не являющийся акронимом». XNA — XNA's Not Acronymed.

В целом, это набор из нескольких .NET сборок, который включает в себя:

  • обвёртку над DirectX (Direct3d, XINPUT, XACT);
  • каркас игрового приложения (классы Game, GameComponent, GameWindow);
  • набор вспомогательных классов/структур для работы с векторами, матрицами, лучами, кватернионами, а также разные математические функции в дополнение к стандартному System.Math;
  • инфраструктура Content Pipeline — специфической контент сиcтемы XNA.

При помощи XNA на данный момент можно разрабатывать игры для Windows (XP, Vista, 7), XBOX360, а также ZUNE (но только 2D, так как текущие модели ZUNE не поддерживают 3D).

Как видно, XNA не просто оболочка над DirectX, но в то же время и не готовый «двиг». В целом, XNA — это платформа, которая следует «философии» языка C# и платформы .NET — серьёзный упор на ООП и эффективность разработки.

Почему XNA?

XNA хороший выбор для вас:

  • если вы хотите создавать игры используя языки платформы .Net, а тем более используя C#;
  • если требуется высокая скорость и эффективность разработки (в противовес С++, который  может обеспечить большую производительность и мобильность, но требует больших  «затрат» при разработке);
  • если вы хотите попробовать свои силы на XBOX.

C чего начать?

Вам нужно иметь уже установленную Microsoft Visual Studio 2008 или же бесплатную версию – Microsoft Visual C# 2008. Должна быть в наличии видеокарта с поддержкой DirectX 9.0c и как минимум шейдеров версии 1.1. (разработчики XNA отказались от фиксированного графического конвейера, в связи с чем минимальная версия шейдеров 1.1 является  обязательным требованием). В добавок желательно иметь свежую версию DirectX, например за ноябрь 2008 года вполне подходит. Если эти условия выполнены, можете наконец перейти к установке XNA Game Studio (в конце статьи приведены ссылки на актуальные версии).

После установки в обоих студиях появляются проекты нового типа:

  • XNA Game Windows
  • XNA Game XBOX
  • XNA Game ZUNE
  • XNA Game Library (Windows,XBOX,ZUNE)
  • XNA Content Pipeline Extension Library

art_xna_qst_p3 | XNA – Быстрый старт

Собственно, минимальные проекты игр для разных платформ и минимальные проекты библиотек, с уже подключёнными референсами на сборки библиотек XNA. Кроме того, в зависимости от версии XNA Game Studio в типах проектов будут также доступны «starter-kits» — маленькие примеры готовых игр.

Минимальный проект

Как уже было сказано, XNA включает готовый каркас игрового приложения. Минимальный проект XNA игры в самом начале уже умеет инициализировать окно приложения и инициализировать устройства.

Основа каркаса – это класс Game, который используется как базовый в основе каждой игры. Класс Game содержит абстрактные методы типа – Draw, Update, LoadContent, UnloadContent, Initialize и так далее. То есть, каждая конкретная игра наследуется от этого класса  и переопределяет важные методы (события сущности Game) своим кодом. Кроме того свойствами базового класса Game выступают такие класы как GameWindow, GraphicDevice и другие.

Минимальный проект обычно уже умеет крутить игровой цикл, производить очистку экрана заливая приятным цветом, а также закрываться при нажатии определённой кнопки. Далее вам лишь необходимо заполнить методы Update и Draw своим кодом. И осуществить загрузку контента на LoadContent.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace WindowsGame1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // TODO: use this.Content to load your game content here
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
          // Allows the game to exit
          if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

          // TODO: Add your update logic here
          base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

Ближе к делу

Несложные игры обычно состоят из таких частей:

  • контент и его загрузка, то главное, из чего состоит игра, картинки, звуки, и так далее;
  • вывод графики – 2D или 3D;
  • обработка управления – мышка, клавиатура,  геймпады;
  • вывод аудио – звуки и музыка;
  • игровая логика и взаимодействие всего выше перечисленого (это, к счастью, не относится к теме статьи ;));

Будем разбирать по порядку.

Загрузка контента

Одна из главных особенностей XNA — специфическая система работы с контентом.

Заключается она в наборе специальных «контент процессоров» и «контент импортеров» (кроме использования стандартных вы можете добавлять и свои).

Задача контент импортеров — превращение (на этапе компиляции) контента из внешнего поддерживаемого формата во внутреннее привычное для XNA представление.

Проще говоря, к примеру добавленные в проект текстуры в формате dds, bmp и png в момент компиляции будут все переведены в один общий для текстур внутренний формат. Такой подход позволяет не зависеть от того в каком виде изначально представлен контент, скажем если вам вдруг понадобилось использовать модели формата Quake3 (.md3), вам нужно будет только написать дополнительный контент импортер, а в конечном виде модели не будут иметь ничего общего с изначальным форматом.

Задача контент процессоров — преобразование контента из внутреннего представления (файлов), в объекты управляемого (managed) кода. То есть, по сути сама загрузка контента в память на этапе исполнения.

Если вам это кажется излишни сложным для начала — не стоит беспокоится, XNA уже содержит готовые импортеры и процессоры для основных типов контента.

Обычно контент добавляется в проект через Solution Explorer студии, в специальную папку “Content”. Там же для каждого файла назначается (панель Properties при выборе конкретного файла) тот или иной процессор и импортер. Таки образом студия берёт на себя автоматизацию процесса компиляции контента.

art_xna_qst_p4.png | XNA – Быстрый старт

Со стороны управляемого кода контент уже представлен классами Texture, Texture2D, Model, ModelMesh, Effect  и другими.

Саму загрузку в коде следует осуществлять при помощи класса ContentManager (уже представленый полем Content класса Game), и советуют её осуществлять в методе LoadContent класса Game (точнее вашего класса — предка Game).

Texture2D myCoolPlayerSprite;  //декларация объекта - текстуры
Model myCoolModel;  //декларация объекта -  модели

protected override void LoadContent()
{
  spriteBatch = new SpriteBatch(GraphicsDevice);
  //загружаем текстуру с именем SomeTexture в объект myCoolPlayerSprite
  myCoolPlayerSprite = Content.Load<Texture2D>("SomeTexture");
  //загружаем модель
  myCoolModel = Content.Load<Model>("plane");
}

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

Стандартные импортеры XNA изначально поддерживают такие форматы:

  • текстуры — bmp, dds, dib, hdr, jpg, pfm, png, ppm, и tga;
  • модели — x, fbx;
  • аудио — wav, mp3(с версии xna 3.0);
  • шейдеры — fx.

Стандартные процессоры:

  • модели;
  • текстуры;
  • растровые шрифты (автоматическая генерация из системных и на основе текстур);
  • эффекты (шейдеры);
  • звуки и музыка(класс Song).

Особняком стоит также система аудио контента на базе Microsoft XACT, но начиная с версии XNA 3.0 кроме этого подхода также обеспечивается параллельно стандартный (такой же как для текстур и моделей) способ работы со звуками.

Вывод графики

Помимо того, что вам доступен GraphicsDevice — по сути то же Direct3D устройство, доступное «любителям попрограммировать на DirectX под с++», у нас также есть несколько готовых инструментов от XNA.

Для 3D — это группа состоящая из классов: ModelMesh, Model и Effect. А для 2D это специальный класс SpriteBatch.

Далее коротко обо всём.

Вывод 2D графики и текста при помощи SpriteBatch



Делается очень просто по средствам класса SpriteBatch. Всё что вам нужно сделать, это создать экземпляр SpriteBatch (в минимальном проекте обычно уже есть один такой).

При каждом проходе метода Draw:

  • начинаем работу при помощи SpriteBatch.Begin().
  • далее нужное вам количество раз вызываем SpriteBatch.Draw() для того, чтобы нарисовать каждый спрайт.
  • и в конце при помощи SpriteBatch.End() – завершаем процесс.


Метод SpriteBatch.Draw() — по сути, рисует всю текстуру или её фрагмент на экране.

В качестве параметров SpriteBatch.Draw() может принимать позицию на экране, где будет выведена текстура, поворот, наклон, масштаб. Также класс SpriteBatch поддерживает автоматическую сортировку по Z координате. Сама текстура передаётся в метод SpriteBatch.Draw() в виде референса на класс Texture2D которые вы предварительно должны были получить, в результате загрузки контента.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();

    spriteBatch.Draw(myCoolPlayerSprite, new Vector2(10f, 10f), Color.White);

    spriteBatch.End();

    base.Draw(gameTime);
}

SpriteBatch также содержит метод DrawString(), который аналогичен методу Draw(), за исключением того, что вместо текстуры он принимает как параметр растровый шрифт (объект класса SpriteFont), а также строчку текста, которую необходимо вывести.

Вывод 3D графики

Разработчики XNA решили избавиться от фиксированного графического конвейера, который широко использовался в MDX и MDX2. В XNA используется программируемый графический конвейер, то есть в основе процесса рендеринга — шейдер (по правде говоря, и в середине SpriteBatch лежит надстройка над конвейером и свой специальный шейдер). Как результат, если вы знакомы с данным подходом, работа с 3Д в XNA для вас не будет сложна.

Итак, за рендеринг у нас должен отвечать шейдер. К счастью в XNA уже реализован простой шейдер BasicEffect  (практически обеспечивает тот минимум, что был доступен с фиксированным конвейером).

Предварительно добавив модель в контент, и загрузив её, вы уже должны иметь объект класса Model. Такая модель в свою очередь содержит набор мешей (класс ModelMesh).

Всё, что нам нужно сделать, это перебрать все объекты класса ModelMesh в нашей модели, назначить (обычно он уже назначен) в качестве шейдера — BasicEffect. Далее, передать в шейдер необходимые параметры (в обязательном порядке — матрицы View, Projection и World). И в конце вызвать у каждого ModelMesh'а метод Draw.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    foreach (ModelMesh mesh in myCoolModel.Meshes)
    {
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.View = ViewMatrix;
            effect.Projection = ProjectionMatrix;
            effect.World = WorldMatrix;
        }
        mesh.Draw();
    }
    
    base.Draw(gameTime);
}

Управление

Тут всё предельно просто. Набор классов со статическими методами, и несколько перечислений. А именно — классы Keyboard, Mouse, GamePad, каждый их них отвечает за своё устройство. У каждого из них есть метод GetState(), который возвращает соответственно KeyboardState, MouseState, GamePadState, содержащие информацию о состоянии устройств ( к примеру позиция Х, Y курсора мыши, или состояние кнопки клавиатуры в текущий момент).

protected override void Update(GameTime gameTime)
{

    if (Keyboard.GetState().IsKeyDown(Keys.Escape))
        this.Exit();

    if (Keyboard.GetState().IsKeyDown(Keys.Up))
        PlayerPosition.Y -= 10f;
    if (Keyboard.GetState().IsKeyDown(Keys.Down))
        PlayerPosition.Y += 10f;
    if (Keyboard.GetState().IsKeyDown(Keys.Left))
        PlayerPosition.X -= 10f;
    if (Keyboard.GetState().IsKeyDown(Keys.Down))
        PlayerPosition.X += 10f;

    base.Update(gameTime);
}

Всё, что вам нужно — в Update проверять состояние устройства, и соотвественно работать с игровой моделью.

Аудио

Тут у нас хитрая история. Изначально звук в XNA (1.0-2.0) был возможен только при помощи XACT проектов.

Они создавались в отдельном редакторе, идущем вместе с XNA Game Studio. Такой проект содержал набор аудио файлов(точнее относительных ссылок на них, на диске), набор поименованных сущностей – звуков, каждый соответствовал тому или иному аудио файлу, а то и нескольким (случайный выбор конечного звука по таблице с вероятностями). Привязка звуков к группам (например, «Музыка» и «Эффекты», с отдельной регулировкой громкости на каждую). Ну, и так далее.

art_xna_qst_p5 | XNA – Быстрый старт

После чего XACT проект добавлялся в игру через специальный процессор и импортер, и работа дальше шла через специальный класс XNA – AudioEngine.

В версии XNA 3.0 появились новые классы: Song, SoundEffect. Новый контент процессор и импортер к ним (за одно и поддержка mp3 как внешнего формата). Появился класс MediaPlayer для воспроизведения музыки (с поддержкой очереди песен).

Работа со звуком упростилась, и в принципе стала на уровень с текстурами и моделями. Всё, что нужно – добавить звук в контент, установить нужный контент процессор/импортер, установить нужное имя (asset name), в коде загрузить в объект нужного типа, когда нужно – воспроизвести.

SoundEffect myCoolSfx;
Song mySuperSong;

protected override void LoadContent(){
   Content.RootDirectory = "Content";
   myCoolSfx= Content.Load<SoundEffect >("sfx2");
   mySuperSong= Content.Load<Song>("song1");
}

На этом с основными частями всё, конечно, каждый пункт можно раскрыть подробней, что возможно и будет сделано в будущем.

Напоследок ещё пару важных пунктов.

Запуск игры на машине пользователя

Для запуска на машине (Windows/PC) конечного пользователя, предварительно нужно установить:

  • .NET framework 2.0 Redistrubutable;
  • XNA Redistrubutable соответствующей версии;
  • Свежий выпуск DirectX Redistrubutable.

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

Ccылки

Последняя версия XNA Game Studio на данный момент, а именно 3.1, доступна тут.

XNA 3.1 Redistrubutable — необходимый конечному пользователю, тут.

Также работает официальный ресурс (от Microsoft, помимо раздела в MSDN) посвящённый XNA: http://creators.xna.com, где вас ждёт множество примеров и уроков по XNA.

27 июля 2009

#C#, #tutorial, #XNA, #XNA Game Studio, #основы


Обновление: 11 августа 2009

2001—2018 © GameDev.ru — Разработка игр