Разработка компьютерных игр для Windows Phone 7 с использованием технологий Silverlight и XNA

Введение в XNA, знакомство с проектом, первое приложение

Разбить на страницы
Показывать лекцию целиком

Цель работы: научиться работать со стандартным игровым проектом XNA

7.1. Игровой проект

Создадим новый игровой проект в Visual Studio 2010. Используем шаблон Игра для Windows Phone (4.0) из группы шаблонов XNA Game Studio 4.0. для языка Visual C#. Назовем проект P2_1. Подробности о создании проектов вы можете найти в лабораторной работе №1, на рис. 7.1. приведено окно создания проекта.

(рис 7.1) Создание проекта P2_1

После нажатия на кнопку ОК в окне s выберем в качестве целевой версии ОС Windows Phone – ОС Windows Phone 7.1. В итоге, будет создан новый игровой проект, точнее, решение, включающее в себя два проекта. Обратим, для начала, внимание на окно Обозреватель решений, рис. 7.22.

(рис 7.2) Обозреватель решений

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

Папка Properties содержит файлы, задающие различные параметры приложения. В частности, это следующие файлы:

  • AppManifest.xml – файл манифеста, содержащий данные, необходимые для построения сборки
  • AssemblyInfo.cs – метаданные в часности – общие сведения, сведения о версии сборки
  • WMAppManifest.xml – файл манифеста с данными, характерными для Windows Phone-приложений
  • Папка Ссылки – содержит ссылки на сборки (библиотеки), которые обеспечивают работу приложения.

    Папка Ссылки на контент – содержит ссылку на проект P2_1Content. Благодаря этой папке можно пользоваться игровым контентом – файлами различных форматов, которые применяются в игре.

    Background.png – здесь содержится изображение размером 173х173 пикселя, это изображение используется в том случае, если пользователь решит разместить ярлык на игру на стартовом экране смартфона. При разработке игры стандартное изображение следует заменить на собственное.

    Game.ico – стандартное изображение размером 32х32 пикселя.

    Файл Game1.cs – это файл, в котором хранится программный код игры. Как правило, вышеописанный Program.cs в модификации не нуждается, а вот Game1.cs – это файл, с которым приходится работать в процессе создания игры. Причем, игры обычно включает в себя множество файлов с программным кодом.

    PhoneGameThumb.png – изображение размером 64х64 пикселя, используется для отображения в списке программ на смартфоне.

    Файл Program.cs – это обычный файл программы на C#. Точно такие же файлы обычно генерируются при создании консольных Windows-приложений на C#. Данный файл играет важную роль – в нем содержится точка входа в программу, с него начинается исполнение игры, и именно в нем содержится команда, которая запускает игру.

    Второй проект – P2_1Content предназначен для хранения игрового контента – графики и звуков, например. В нем, по умолчанию, содержится одна папка Ссылки – она содержит ссылки на библиотеки, необходимые для работы с контентом разного вида.

    Разберемся с файлами PhoneGameThumb.png и Background.png. Изображения в этих файлах могут быть различными, однако, рекомендуется выполнить их таким образом, чтобы пользователю было бы понятно, при запуске из различных мест, что запускает он одну и ту же игру.

    Откроем файл Background.png, в нашем случае он открылся в редакторе Paint, можно пользоваться и другими редакторами и изменим изображение. Мы разместили на нем букву "B", рис. 7.3.

    (рис 7.3) Правка файла Background.png

    Сохраним изображение и запустим наше приложение для отладки на смартфоне. Приложение, после того, как мы из него выйдем, останется установленным, его ярлык можно обнаружить в списке программ. Как видите, для отображения в списке используется файл PhoneGameThumb.png (левая часть рис. 7.4.)

    (рис 7.4) Различные значки на разных экранах вызова приложений

    Если разместить ярлык для вызова приложения на стартовом экране (меню для выполнения этого действия появляется при длительном касании нужного элемента в списке программ), для отображения будет использоваться файл Backgroung.png (правая часть рис. 7.4)

    Обратите внимание на то, что обычные программы, устанавливаемые на устройство, размещаются в списке программ. В Windows Phone имеется хаб Xbox Live (Игры), чтобы ваша программа отображалась там, нужно отредактировать параметр Genre в файле WMAppManifest.xml. Вместо Apps.Normal он должен содержать значение Apps.Games.

    Рассмотрим код программных файлов стандартного проекта. Нам придется модифицировать этот код в процессе создания собственных игр.

    7.2. Разбор кода стандартного игрового проекта

    В листинге 7.1 приведено содержимое файла Program.cs.

    using System;
    
    namespace P2_1
    {
    #if WINDOWS || XBOX
        static class Program
        {
            /// <summary>
            /// Главная точка входа приложения.
            /// </summary>
            static void Main(string[] args)
            {
                using (Game1 game = new Game1())
                {
                    game.Run()>;
                }
            }
        }
    #endif
    }

    Этот файл применяется для запуска игры в том случае, если она разрабатывается для платформ Xbox или Windows, при запуске на Windows Phone данный файл не используется.

    Второй программный файл, Game1.cs, представляет собой игровой проект, который и содержит все то, что используется при создании игры. Естественно, в сложных игровых проектах основная часть кода выносится за пределы данного файла, но он, в любом случае, является центром игры.

    Упрощенно структуру игрового проекта можно представить так (Табл. 7.1.).

    Структура игрового проекта
    НазваниеОписание
    ИнициализацияНа этапе инициализации проекта проводится инициализация графической и звуковых подсистем, системы ввода данных.
    Загрузка ресурсовЗдесь загружаются игровые ресурсы, такие, как текстуры и трехмерные модели, звуки, шрифты
    Начало игрового циклаОсновные действия, которые выполняются при работе игры, организованы в виде игрового цикла. Фактически, игровой цикл – это обязательный элемент любой игры.
    Считывание данных пользовательского вводаПользователь управляет игрой с помощью различных устройств ввода данных. В нашем случае это – сенсорный экран смартфона и различные датчики.
    Игровые вычисленияИгровые вычисления включают в себя все вычисления, которые необходимы для организации игрового процесса. В частности, здесь обсчитываются позиции игровых объектов, проводятся вычисления, связанные с работой искусственного интеллекта, вычисления, связанные с проверкой столкновений игровых объектов, игровая физика, подсчет очков, набранных игроком и так далее. Если речь идет об оптимизации быстродействия игры, то такая оптимизация обычно касается именно игровых вычислений, так как на них тратится большая часть времени выполнения игрового цикла.
    Проверка критерия прекращения игрыИгровой цикл продолжается до тех пор, пока игра не будет прекращена. Например, критерием останова может быть истечение времени, выделенного игроку на выполнение игровой задачи, набор определенного количества очков, какое-то событие, произошедшее в процессе игры, принудительная остановка игры, если пользователь решил прекратить играть и так далее.
    Вывод изображений, проигрывание звуковПосле завершения этапа игровых вычислений в программе имеются данные для визуализации. В частности, имеются данные о новых позициях объектов, о сообщениях, которые нужно вывести на игровое поле, о звуках, которые нужно воспроизвести. На данном этапе проводится перемещение объектов по игровому полю, вывод сообщений, проигрывание звука.
    Конец игрового циклаИгровой цикл заканчивается после выполнения условия останова игры
    Освобождение ресурсовНа последнем этапе работы игры проводится освобождение системных ресурсов, занятых игрой и выход из игры.

    В стандартном игровом проекте все эти этапы представлены с помощью специальных методов. Эти методы унаследованы созданным игровым проектом от класса Game, который служит основой для проекта. Итак, это следующие методы (табл. 7.2.).

    Методы стандартного игрового проекта
    НазваниеОписание
    Game()Общая инициализация. Game() – это конструктор класса Game.
    Initialize()Инициализация игры
    LoadContent()Загрузка игровых ресурсов
    Update()Игровой цикл в стандартном проекте состоит из двух методов. Первый из них – это метод Update(), в котором выполняется прием пользовательского ввода, все необходимые вычисления, проверка критериев останова игры.
    Draw()Второй метод игрового цикла – это метод Draw(), который содержит код для визуализации игровой графики
    UnloadContent()По окончании игрового цикла этот метод освобождает системные ресурсы.

    Теперь, когда мы ознакомились с типичной структурой игры и назначением стандартных методов, рассмотрим код класса Game (Листинг 1.2). Помимо программного кода здесь приведены комментарии, включаемые в код автоматически.

    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.Input.Touch;
    using Microsoft.Xna.Framework.Media;
    
    namespace P2_1
    {
        /// <summary>
        /// Это главный тип игры
        /// </summary>
        public class Game1 : Microsoft.Xna.Framework.Game
        {
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;
    
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
    
                // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
                TargetElapsedTime = TimeSpan.FromTicks(333333);
    
                // Дополнительный заряд аккумулятора заблокирован.
                InactiveSleepTime = TimeSpan.FromSeconds(1);
            }
    
            /// <summary>
            /// Позволяет игре выполнить инициализацию, необходимую перед запуском.
            /// Здесь можно запросить нужные службы и загрузить неграфический
            /// контент.  Вызов base.Initialize приведет к перебору всех компонентов и
            /// их инициализации.
            /// </summary>
            protected override void Initialize()
            {
                // ЗАДАЧА: добавьте здесь логику инициализации
    
                base.Initialize();
            }
    
            /// <summary>
            /// LoadContent будет вызываться в игре один раз; здесь загружается
            /// весь контент.
            /// </summary>
            protected override void LoadContent()
            {
                // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
                spriteBatch = new SpriteBatch(GraphicsDevice);
    
                // ЗАДАЧА: используйте здесь this.Content для загрузки контента игры
            }
    
            /// <summary>
            /// UnloadContent будет вызываться в игре один раз; здесь выгружается
            /// весь контент.
            /// </summary>
            protected override void UnloadContent()
            {
                // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
            }
    
            /// <summary>
            /// Позволяет игре запускать логику обновления мира,
            /// проверки столкновений, получения ввода и воспроизведения звуков.
            /// </summary>
            /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
            protected override void Update(GameTime gameTime)
            {
                // Позволяет выйти из игры
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                    this.Exit();
    
                // ЗАДАЧА: добавьте здесь логику обновления
    
                base.Update(gameTime);
            }
    
            /// <summary>
            /// Вызывается, когда игра отрисовывается.
            /// </summary>
            /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
            protected override void Draw(GameTime gameTime)
            {
                GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // ЗАДАЧА: добавьте здесь код отрисовки
    
                base.Draw(gameTime);
            }
        }
    }
    

    Рассмотрим каждый из приведенных выше методов. В листинге 7.3. приведен код метода Game1().

    public class Game1 : Microsoft.Xna.Framework.Game
        {
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;
            
    	public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
    
                // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
                TargetElapsedTime = TimeSpan.FromTicks(333333);
    
                // Дополнительный заряд аккумулятора заблокирован.
                InactiveSleepTime = TimeSpan.FromSeconds(1);
            }

    В классе Game есть, по умолчанию, два поля. Это поле graphics, которое имеет тип GraphicsDeviceManager и представляет графические элементы, и поле spriteBatch с типом SpristeBatch, представляющее пакет спрайтов (изображений).

    Метод Game() – это конструктор класса Game. Команда graphics = new GraphicsDeviceManager(this);

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

    Команда Content.RootDirectory = "Content"; позволяет указать место (в нашем случае – это проект P2_1Content, или просто Content), где хранятся игровые ресурсы. Content.RootDirectory следует понимать как свойство Content (Содержимое) типа ContentManager (Диспетчер содержимого), RootDirectory (Корневой каталог) – это свойство данного класса.

    Команда TargetElapsedTime = TimeSpan.FromTicks(333333); задает время игрового цикла, ориентируясь на частоту обновления экрана в устройствах на Windows Phone. Это – 30 кадров в секунду. Наш игровой цикл, таким образом, будет выполняться 30 раз в секунду.

    Помимо описанных команд, автоматически включаемых в стандартный игровой проект, конструктор может содержать и другие команды. Например, команды дополнительной настройки объекта graphics.

    После того, как создан экземпляр класса Game, вызывается метод этого класса Run, после чего выполняется инициализация игры, загрузка контента, запускается игровой цикл.

    В листинге 7.4. приведен код метода Initialise().

    protected override void Initialize()
            {
                // ЗАДАЧА: добавьте здесь логику инициализации
    
                base.Initialize();
            }

    Команда base.Initialize(); вызывает метод Initialise() базового класса. Сюда же добавляют команды для инициализации звуковой подсистемы игры, здесь же выполняются игровые настройки. Надо отметить, что в этом методе инициализируется все, кроме графических ресурсов игры. Для них существует метод LoadContent(), листинг 7.5.

    >protected override void LoadContent()
            {
                // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
                spriteBatch = new SpriteBatch(GraphicsDevice);
    
                // ЗАДАЧА: используйте здесь this.Content для загрузки контента игры
            }

    SpriteBatch – это класс, который позволяет выводить изображения на устройство, задаваемое параметром GraphicsDevice. В этот же метод добавляют команды для загрузки графических ресурсов, шрифтов. Метод UnloadContent() (листинг 7.6.) предназначен для освобождения системных ресурсов.

    protected override void UnloadContent()
            {
                // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
            }

    Здесь размещают команды для выгрузки игровых ресурсов. В частности, в данном методе можно использовать команду base.UnloadContent(); - это метод базового класса, выгружающий ресурсы. Так же в этот метод добавляют команды для выгрузки шрифтов и других ресурсов.

    Игровой цикл состоит из двух методов, выполняющихся циклически это методы Update() и Draw()листинг 7.7.

    protected override void Update(GameTime gameTime)
            {
                // Позволяет выйти из игры
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                    this.Exit();
    
                // ЗАДАЧА: добавьте здесь логику обновления
    
                base.Update(gameTime);
            }
    
            /// <summary>
            /// Вызывается, когда игра отрисовывается.
            /// </summary>
            /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
            protected override void Draw(GameTime gameTime)
            {
                GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // ЗАДАЧА: добавьте здесь код отрисовки
    
                base.Draw(gameTime);
            }

    Сначала выполняется метод Update(), потом – метод Draw().

    Команда base.Update(gameTime); метода Update() ответственна за организацию игрового цикла. Она снова и снова вызывает метод Update() базового класса. Именно эта команда является "двигателем" игры. Если ее убрать – игровой цикл не будет работать. Параметр gameTime – представляет собой объект класса GameTime, который содержит информацию об игровом времени. Знание игрового времени нужно для организации взаимодействия внутри игры. По отношению к игровому времени можно выделить два типа игр. Первые – это игры реального времени, такие, как симуляторы. Вторые – это пошаговые игры, где игроку дается некоторое время – фиксированное либо нет – для обдумывания следующего хода. Знание игрового времени нужно для многих игровых вычислений. Класс GameTime имеет несколько важных свойств.

    Свойство ElapsedGameTime позволяет узнать время, которое прошло после последнего вызова игрового цикла. TotalGameTime – игровое время, прошедшее с момента старта игры.

    ElapsedRealTime – реальное время, прошедшее после последнего вызова игрового цикла. TotalRealTime – реальное время, прошедшее с момента старта игры.

    Свойство IsRunningSlowly принимает значение Истина в том случае, если игровой цикл занимает больше времени, чем TargetElapsedTime.

    Команда graphics.GraphicsDevice.Clear(Color.CornflowerBlue); метода Draw() очищает игровой экран, заливая его цветом CornflowerBlue. А команда base.Draw(gameTime); вызывает метод Draw() базового класса, который выводит на экран изображения.

    Поговорим о пространствах имен (компонентах), которые подключены к стандартному проекту по умолчанию. В листинге 7.8. приведены их вызовы. В таблице 7.3. приведено описание этих пространств имен

    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.Input.Touch;
    using Microsoft.Xna.Framework.Media;
    
    Пространства имен стандартного игрового проекта
    Пространство именОписание
    System;Поддержка основных механизмов .NET Framework
    System.Collections.Generic;Интерфейсы и классы, определяющие универсальные коллекции
    System.Linq;Поддержка запросов к данным с использованием LINQ (Language-Integrated Query)
    Xna.Framework;Поддержка общих игровых механизмов XNA – таймеры, игровой цикл.
    Xna.Framework.Audio;Инструменты для работы со звуком, с использованием XACT-проектов
    Xna.Framework.Content;содержит средства, обеспечивающие работу Content Pipeline.
    Xna.Framework.GamerServices;обеспечивает функции работы с сервисом LIVE
    Xna.Framework.Graphics;содержит средства для работы с графикой.
    Xna.Framework.Input;поддерживает работу со средствами ввода данных (геймпад, клавиатура, мышь)
    Xna.Framework.Input.Touch;Работа с тач-панелью, представленной чувствительным к касаниям экраном устройства
    Xna.Framework.Media;Работа с медиаданными – изображениями, аудио- и видеозаписями, списками воспроизведения

    7.3. Изменение цвета заливки экрана

    Изучив игровой проект, выполним небольшую практическую работу. А именно, изменим цвет заполнения экрана. Для этого откроем двойным щелчком в Обозревателе решений файл Game1.cs проекта P2_1 (или переключимся на закладку с именем файла в окне Visual Studio, если файл уже открыт), найдем метод Draw, и изменим в нем строку

    GraphicsDevice.Clear(Color.CornflowerBlue);

    На

    GraphicsDevice.Clear(Color.Yellow);

    На рис. 7.5 показан процесс редактирования кода – здесь мы можем пользоваться автоматической подсказкой.

    (рис 7.5) Редактирование кода

    Запустим программу для отладки в эмуляторе, убедимся, что фон теперь имеет желтый цвет, рис. 7.6

    (рис 7.6) Изменение цвета фона в эмуляторе

    7.5. Задание

    Создайте стандартный игровой проект XNA. Уясните назначение пространств имен, подключенных по умолчанию, методов. Для углубленного изучения материала воспользуйтесь справочной системой среды разработки или библиотекой MSDN. Измените цвет заливки экрана.

    7.6. Дополнительные материалы

    К данной лабораторной работе прилагается видеоурок

    и демонстрационный проект.

    Страницы:

    Цель работы: научиться работать со стандартным игровым проектом XNA

    7.1. Игровой проект

    Создадим новый игровой проект в Visual Studio 2010. Используем шаблон Игра для Windows Phone (4.0) из группы шаблонов XNA Game Studio 4.0. для языка Visual C#. Назовем проект P2_1. Подробности о создании проектов вы можете найти в лабораторной работе №1, на рис. 7.1. приведено окно создания проекта.

    (рис 7.1) Создание проекта P2_1

    После нажатия на кнопку ОК в окне s выберем в качестве целевой версии ОС Windows Phone – ОС Windows Phone 7.1. В итоге, будет создан новый игровой проект, точнее, решение, включающее в себя два проекта. Обратим, для начала, внимание на окно Обозреватель решений, рис. 7.22.

    (рис 7.2) Обозреватель решений

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

    Папка Properties содержит файлы, задающие различные параметры приложения. В частности, это следующие файлы:

  • AppManifest.xml – файл манифеста, содержащий данные, необходимые для построения сборки
  • AssemblyInfo.cs – метаданные в часности – общие сведения, сведения о версии сборки
  • WMAppManifest.xml – файл манифеста с данными, характерными для Windows Phone-приложений
  • Папка Ссылки – содержит ссылки на сборки (библиотеки), которые обеспечивают работу приложения.

    Папка Ссылки на контент – содержит ссылку на проект P2_1Content. Благодаря этой папке можно пользоваться игровым контентом – файлами различных форматов, которые применяются в игре.

    Background.png – здесь содержится изображение размером 173х173 пикселя, это изображение используется в том случае, если пользователь решит разместить ярлык на игру на стартовом экране смартфона. При разработке игры стандартное изображение следует заменить на собственное.

    Game.ico – стандартное изображение размером 32х32 пикселя.

    Файл Game1.cs – это файл, в котором хранится программный код игры. Как правило, вышеописанный Program.cs в модификации не нуждается, а вот Game1.cs – это файл, с которым приходится работать в процессе создания игры. Причем, игры обычно включает в себя множество файлов с программным кодом.

    PhoneGameThumb.png – изображение размером 64х64 пикселя, используется для отображения в списке программ на смартфоне.

    Файл Program.cs – это обычный файл программы на C#. Точно такие же файлы обычно генерируются при создании консольных Windows-приложений на C#. Данный файл играет важную роль – в нем содержится точка входа в программу, с него начинается исполнение игры, и именно в нем содержится команда, которая запускает игру.

    Второй проект – P2_1Content предназначен для хранения игрового контента – графики и звуков, например. В нем, по умолчанию, содержится одна папка Ссылки – она содержит ссылки на библиотеки, необходимые для работы с контентом разного вида.

    Разберемся с файлами PhoneGameThumb.png и Background.png. Изображения в этих файлах могут быть различными, однако, рекомендуется выполнить их таким образом, чтобы пользователю было бы понятно, при запуске из различных мест, что запускает он одну и ту же игру.

    Откроем файл Background.png, в нашем случае он открылся в редакторе Paint, можно пользоваться и другими редакторами и изменим изображение. Мы разместили на нем букву "B", рис. 7.3.

    (рис 7.3) Правка файла Background.png

    Сохраним изображение и запустим наше приложение для отладки на смартфоне. Приложение, после того, как мы из него выйдем, останется установленным, его ярлык можно обнаружить в списке программ. Как видите, для отображения в списке используется файл PhoneGameThumb.png (левая часть рис. 7.4.)

    (рис 7.4) Различные значки на разных экранах вызова приложений

    Если разместить ярлык для вызова приложения на стартовом экране (меню для выполнения этого действия появляется при длительном касании нужного элемента в списке программ), для отображения будет использоваться файл Backgroung.png (правая часть рис. 7.4)

    Обратите внимание на то, что обычные программы, устанавливаемые на устройство, размещаются в списке программ. В Windows Phone имеется хаб Xbox Live (Игры), чтобы ваша программа отображалась там, нужно отредактировать параметр Genre в файле WMAppManifest.xml. Вместо Apps.Normal он должен содержать значение Apps.Games.

    Рассмотрим код программных файлов стандартного проекта. Нам придется модифицировать этот код в процессе создания собственных игр.

    7.2. Разбор кода стандартного игрового проекта

    В листинге 7.1 приведено содержимое файла Program.cs.

    using System;
    
    namespace P2_1
    {
    #if WINDOWS || XBOX
        static class Program
        {
            /// <summary>
            /// Главная точка входа приложения.
            /// </summary>
            static void Main(string[] args)
            {
                using (Game1 game = new Game1())
                {
                    game.Run()>;
                }
            }
        }
    #endif
    }

    Этот файл применяется для запуска игры в том случае, если она разрабатывается для платформ Xbox или Windows, при запуске на Windows Phone данный файл не используется.

    Второй программный файл, Game1.cs, представляет собой игровой проект, который и содержит все то, что используется при создании игры. Естественно, в сложных игровых проектах основная часть кода выносится за пределы данного файла, но он, в любом случае, является центром игры.

    Упрощенно структуру игрового проекта можно представить так (Табл. 7.1.).

    Структура игрового проекта
    НазваниеОписание
    ИнициализацияНа этапе инициализации проекта проводится инициализация графической и звуковых подсистем, системы ввода данных.
    Загрузка ресурсовЗдесь загружаются игровые ресурсы, такие, как текстуры и трехмерные модели, звуки, шрифты
    Начало игрового циклаОсновные действия, которые выполняются при работе игры, организованы в виде игрового цикла. Фактически, игровой цикл – это обязательный элемент любой игры.
    Считывание данных пользовательского вводаПользователь управляет игрой с помощью различных устройств ввода данных. В нашем случае это – сенсорный экран смартфона и различные датчики.
    Игровые вычисленияИгровые вычисления включают в себя все вычисления, которые необходимы для организации игрового процесса. В частности, здесь обсчитываются позиции игровых объектов, проводятся вычисления, связанные с работой искусственного интеллекта, вычисления, связанные с проверкой столкновений игровых объектов, игровая физика, подсчет очков, набранных игроком и так далее. Если речь идет об оптимизации быстродействия игры, то такая оптимизация обычно касается именно игровых вычислений, так как на них тратится большая часть времени выполнения игрового цикла.
    Проверка критерия прекращения игрыИгровой цикл продолжается до тех пор, пока игра не будет прекращена. Например, критерием останова может быть истечение времени, выделенного игроку на выполнение игровой задачи, набор определенного количества очков, какое-то событие, произошедшее в процессе игры, принудительная остановка игры, если пользователь решил прекратить играть и так далее.
    Вывод изображений, проигрывание звуковПосле завершения этапа игровых вычислений в программе имеются данные для визуализации. В частности, имеются данные о новых позициях объектов, о сообщениях, которые нужно вывести на игровое поле, о звуках, которые нужно воспроизвести. На данном этапе проводится перемещение объектов по игровому полю, вывод сообщений, проигрывание звука.
    Конец игрового циклаИгровой цикл заканчивается после выполнения условия останова игры
    Освобождение ресурсовНа последнем этапе работы игры проводится освобождение системных ресурсов, занятых игрой и выход из игры.

    В стандартном игровом проекте все эти этапы представлены с помощью специальных методов. Эти методы унаследованы созданным игровым проектом от класса Game, который служит основой для проекта. Итак, это следующие методы (табл. 7.2.).

    Методы стандартного игрового проекта
    НазваниеОписание
    Game()Общая инициализация. Game() – это конструктор класса Game.
    Initialize()Инициализация игры
    LoadContent()Загрузка игровых ресурсов
    Update()Игровой цикл в стандартном проекте состоит из двух методов. Первый из них – это метод Update(), в котором выполняется прием пользовательского ввода, все необходимые вычисления, проверка критериев останова игры.
    Draw()Второй метод игрового цикла – это метод Draw(), который содержит код для визуализации игровой графики
    UnloadContent()По окончании игрового цикла этот метод освобождает системные ресурсы.

    Теперь, когда мы ознакомились с типичной структурой игры и назначением стандартных методов, рассмотрим код класса Game (Листинг 1.2). Помимо программного кода здесь приведены комментарии, включаемые в код автоматически.

    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.Input.Touch;
    using Microsoft.Xna.Framework.Media;
    
    namespace P2_1
    {
        /// <summary>
        /// Это главный тип игры
        /// </summary>
        public class Game1 : Microsoft.Xna.Framework.Game
        {
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;
    
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
    
                // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
                TargetElapsedTime = TimeSpan.FromTicks(333333);
    
                // Дополнительный заряд аккумулятора заблокирован.
                InactiveSleepTime = TimeSpan.FromSeconds(1);
            }
    
            /// <summary>
            /// Позволяет игре выполнить инициализацию, необходимую перед запуском.
            /// Здесь можно запросить нужные службы и загрузить неграфический
            /// контент.  Вызов base.Initialize приведет к перебору всех компонентов и
            /// их инициализации.
            /// </summary>
            protected override void Initialize()
            {
                // ЗАДАЧА: добавьте здесь логику инициализации
    
                base.Initialize();
            }
    
            /// <summary>
            /// LoadContent будет вызываться в игре один раз; здесь загружается
            /// весь контент.
            /// </summary>
            protected override void LoadContent()
            {
                // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
                spriteBatch = new SpriteBatch(GraphicsDevice);
    
                // ЗАДАЧА: используйте здесь this.Content для загрузки контента игры
            }
    
            /// <summary>
            /// UnloadContent будет вызываться в игре один раз; здесь выгружается
            /// весь контент.
            /// </summary>
            protected override void UnloadContent()
            {
                // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
            }
    
            /// <summary>
            /// Позволяет игре запускать логику обновления мира,
            /// проверки столкновений, получения ввода и воспроизведения звуков.
            /// </summary>
            /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
            protected override void Update(GameTime gameTime)
            {
                // Позволяет выйти из игры
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                    this.Exit();
    
                // ЗАДАЧА: добавьте здесь логику обновления
    
                base.Update(gameTime);
            }
    
            /// <summary>
            /// Вызывается, когда игра отрисовывается.
            /// </summary>
            /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
            protected override void Draw(GameTime gameTime)
            {
                GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // ЗАДАЧА: добавьте здесь код отрисовки
    
                base.Draw(gameTime);
            }
        }
    }
    

    Рассмотрим каждый из приведенных выше методов. В листинге 7.3. приведен код метода Game1().

    public class Game1 : Microsoft.Xna.Framework.Game
        {
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;
            
    	public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
    
                // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
                TargetElapsedTime = TimeSpan.FromTicks(333333);
    
                // Дополнительный заряд аккумулятора заблокирован.
                InactiveSleepTime = TimeSpan.FromSeconds(1);
            }

    В классе Game есть, по умолчанию, два поля. Это поле graphics, которое имеет тип GraphicsDeviceManager и представляет графические элементы, и поле spriteBatch с типом SpristeBatch, представляющее пакет спрайтов (изображений).

    Метод Game() – это конструктор класса Game. Команда graphics = new GraphicsDeviceManager(this);

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

    Команда Content.RootDirectory = "Content"; позволяет указать место (в нашем случае – это проект P2_1Content, или просто Content), где хранятся игровые ресурсы. Content.RootDirectory следует понимать как свойство Content (Содержимое) типа ContentManager (Диспетчер содержимого), RootDirectory (Корневой каталог) – это свойство данного класса.

    Команда TargetElapsedTime = TimeSpan.FromTicks(333333); задает время игрового цикла, ориентируясь на частоту обновления экрана в устройствах на Windows Phone. Это – 30 кадров в секунду. Наш игровой цикл, таким образом, будет выполняться 30 раз в секунду.

    Помимо описанных команд, автоматически включаемых в стандартный игровой проект, конструктор может содержать и другие команды. Например, команды дополнительной настройки объекта graphics.

    После того, как создан экземпляр класса Game, вызывается метод этого класса Run, после чего выполняется инициализация игры, загрузка контента, запускается игровой цикл.

    В листинге 7.4. приведен код метода Initialise().

    protected override void Initialize()
            {
                // ЗАДАЧА: добавьте здесь логику инициализации
    
                base.Initialize();
            }

    Команда base.Initialize(); вызывает метод Initialise() базового класса. Сюда же добавляют команды для инициализации звуковой подсистемы игры, здесь же выполняются игровые настройки. Надо отметить, что в этом методе инициализируется все, кроме графических ресурсов игры. Для них существует метод LoadContent(), листинг 7.5.

    >protected override void LoadContent()
            {
                // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
                spriteBatch = new SpriteBatch(GraphicsDevice);
    
                // ЗАДАЧА: используйте здесь this.Content для загрузки контента игры
            }

    SpriteBatch – это класс, который позволяет выводить изображения на устройство, задаваемое параметром GraphicsDevice. В этот же метод добавляют команды для загрузки графических ресурсов, шрифтов. Метод UnloadContent() (листинг 7.6.) предназначен для освобождения системных ресурсов.

    protected override void UnloadContent()
            {
                // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
            }

    Здесь размещают команды для выгрузки игровых ресурсов. В частности, в данном методе можно использовать команду base.UnloadContent(); - это метод базового класса, выгружающий ресурсы. Так же в этот метод добавляют команды для выгрузки шрифтов и других ресурсов.

    Игровой цикл состоит из двух методов, выполняющихся циклически это методы Update() и Draw()листинг 7.7.

    protected override void Update(GameTime gameTime)
            {
                // Позволяет выйти из игры
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                    this.Exit();
    
                // ЗАДАЧА: добавьте здесь логику обновления
    
                base.Update(gameTime);
            }
    
            /// <summary>
            /// Вызывается, когда игра отрисовывается.
            /// </summary>
            /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
            protected override void Draw(GameTime gameTime)
            {
                GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // ЗАДАЧА: добавьте здесь код отрисовки
    
                base.Draw(gameTime);
            }

    Сначала выполняется метод Update(), потом – метод Draw().

    Команда base.Update(gameTime); метода Update() ответственна за организацию игрового цикла. Она снова и снова вызывает метод Update() базового класса. Именно эта команда является "двигателем" игры. Если ее убрать – игровой цикл не будет работать. Параметр gameTime – представляет собой объект класса GameTime, который содержит информацию об игровом времени. Знание игрового времени нужно для организации взаимодействия внутри игры. По отношению к игровому времени можно выделить два типа игр. Первые – это игры реального времени, такие, как симуляторы. Вторые – это пошаговые игры, где игроку дается некоторое время – фиксированное либо нет – для обдумывания следующего хода. Знание игрового времени нужно для многих игровых вычислений. Класс GameTime имеет несколько важных свойств.

    Свойство ElapsedGameTime позволяет узнать время, которое прошло после последнего вызова игрового цикла. TotalGameTime – игровое время, прошедшее с момента старта игры.

    ElapsedRealTime – реальное время, прошедшее после последнего вызова игрового цикла. TotalRealTime – реальное время, прошедшее с момента старта игры.

    Свойство IsRunningSlowly принимает значение Истина в том случае, если игровой цикл занимает больше времени, чем TargetElapsedTime.

    Команда graphics.GraphicsDevice.Clear(Color.CornflowerBlue); метода Draw() очищает игровой экран, заливая его цветом CornflowerBlue. А команда base.Draw(gameTime); вызывает метод Draw() базового класса, который выводит на экран изображения.

    Поговорим о пространствах имен (компонентах), которые подключены к стандартному проекту по умолчанию. В листинге 7.8. приведены их вызовы. В таблице 7.3. приведено описание этих пространств имен

    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.Input.Touch;
    using Microsoft.Xna.Framework.Media;
    
    Пространства имен стандартного игрового проекта
    Пространство именОписание
    System;Поддержка основных механизмов .NET Framework
    System.Collections.Generic;Интерфейсы и классы, определяющие универсальные коллекции
    System.Linq;Поддержка запросов к данным с использованием LINQ (Language-Integrated Query)
    Xna.Framework;Поддержка общих игровых механизмов XNA – таймеры, игровой цикл.
    Xna.Framework.Audio;Инструменты для работы со звуком, с использованием XACT-проектов
    Xna.Framework.Content;содержит средства, обеспечивающие работу Content Pipeline.
    Xna.Framework.GamerServices;обеспечивает функции работы с сервисом LIVE
    Xna.Framework.Graphics;содержит средства для работы с графикой.
    Xna.Framework.Input;поддерживает работу со средствами ввода данных (геймпад, клавиатура, мышь)
    Xna.Framework.Input.Touch;Работа с тач-панелью, представленной чувствительным к касаниям экраном устройства
    Xna.Framework.Media;Работа с медиаданными – изображениями, аудио- и видеозаписями, списками воспроизведения

    7.3. Изменение цвета заливки экрана

    Изучив игровой проект, выполним небольшую практическую работу. А именно, изменим цвет заполнения экрана. Для этого откроем двойным щелчком в Обозревателе решений файл Game1.cs проекта P2_1 (или переключимся на закладку с именем файла в окне Visual Studio, если файл уже открыт), найдем метод Draw, и изменим в нем строку

    GraphicsDevice.Clear(Color.CornflowerBlue);

    На

    GraphicsDevice.Clear(Color.Yellow);

    На рис. 7.5 показан процесс редактирования кода – здесь мы можем пользоваться автоматической подсказкой.

    (рис 7.5) Редактирование кода

    Запустим программу для отладки в эмуляторе, убедимся, что фон теперь имеет желтый цвет, рис. 7.6

    (рис 7.6) Изменение цвета фона в эмуляторе

    7.5. Задание

    Создайте стандартный игровой проект XNA. Уясните назначение пространств имен, подключенных по умолчанию, методов. Для углубленного изучения материала воспользуйтесь справочной системой среды разработки или библиотекой MSDN. Измените цвет заливки экрана.

    7.6. Дополнительные материалы

    К данной лабораторной работе прилагается видеоурок

    и демонстрационный проект.

    Вернуться к учебному плану