Статьи

Анимация SpriteSheet в MonoGame для Windows 8

Использование SpriteSheets в вашей 2D-игре — это рекомендуемый способ повысить производительность и одновременно управлять своими активами. Существует тонкий баланс между количеством SpriteSheets, используемым для ресурсов в вашей игре, и объемом данных, которые необходимо загрузить в память и отправить на видеокарту. SpriteSheet — это просто один текстурный (графический) файл, содержащий серию спрайтов, которые представляют различные визуальные ресурсы вашей игры. Обычной практикой является использование SpriteSheet для анимации в вашей игре.

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

Чтобы лучше понять эту концепцию, давайте возьмем таблицу SpriteSample из образца XNA Platformer .

В этом SpriteSheet наш Герой празднует, бросая кулак в воздух. Простой способ понять, как работает эта анимация, — подумать об анимационном флипбуке . В этом случае вы должны вырезать каждое изображение спрайта, складывать их друг на друга и быстро пролистывать их, чтобы показать нашего Героя в движении.

Создание последовательности анимации в MonoGame для Windows 8

Давайте рассмотрим, как создать эту анимацию для игры для Windows 8. Я мог бы создать свою игру, используя HTML5 / JS или C ++, но я более эффективен в C # и XNA. К счастью,  MonoGame дает возможность использовать мои существующие навыки C # для создания игры, которую я могу продавать в Магазине Windows 8. (Если вы хотите узнать, как это сделать в HTML5, у Дэвида Руссе есть отличная статья об анимации спрайтов в HTML5 ).

Сначала прочитайте серию статей Боба Фамильяра о том, как запустить MonoGame в Windows 8 . Также просмотрите изменения, которые я должен был внести, когда столкнулся с проблемой с ContentPipeline в моем проекте MonoGame.

После того, как вы прошли все этапы, чтобы получить код MonoGame и шаблоны проектов на своем компьютере, вы готовы создать свою игру для Windows 8.

Если вы уже знаете, как создать проект MonoGame и импортировать ContentPipeline, переходите к шагу 5.

1.) В Visual Studio 2012 создайте новый проект, откройте шаблон проекта C # и выберите «Создать приложение MonoGame Metro для Windows».

2.) Добавьте проект MonoGame.Framework.Windows8 в свое Решение и добавьте ссылку из проекта MonoGame в проект MonoGame.Framework.Windows8. (это изменится, когда двоичные файлы станут доступны для MonoGame Framework для Windows 8).

3) Щелкните правой кнопкой мыши свой игровой проект и выберите «Добавить | Новая папка» и дайте ему имя «Контент».

ПРИМЕЧАНИЕ . В настоящее время MonoGame не имеет тип проекта ContentPipeline. Вам нужно выйти из Visual Studio 2012 и загрузить Visual Studio 2010 с XNA Game Studio 2010, создать пустой проект XNA и заполнить свой ContentPipeline ресурсами, необходимыми для вашего проекта MonoGame. Этот процесс описан в третьей части серии блогов Боба .

Для этого примера я скопировал таблицу SpriteSpng Celebrate.png из примера Platformer (Platformer \ Content \ Sprites \ Player \ Celebrate.png) и добавил его в проект ContentPipeline в Visual Studio 2010.

Вот мой проект XNA Game Studio из Visual Studio 2010:

 

4) Компиляция XNA Game приведет к созданию файла .XNB. Это ваш ContentPipeline все составлено. Добавьте этот файл .XNB в папку «Содержимое» в проекте MonoGame.

В вашем проекте MonoGame в Visual Studio 2012 щелкните правой кнопкой мыши папку «Содержимое», выберите «Добавить | Существующий элемент» и перейдите к файлу .XNB из своего проекта XNA Game (например, C: \ Users \ {You} \ Documents \ Visual Studio 2010 \ WindowsPhoneGame1 \ WindowsPhoneGame1 \ bin \ Windows Phone \ Debug \ Content \ Celebrate.XNB).

Теперь перейдем к коду анимации …

5) Во-первых, нам нужно определить некоторые переменные уровня класса, чтобы поддерживать некоторую информацию о состоянии нашей последовательности анимации. Добавьте следующее перед конструктором класса Game1 ():

// the spritesheet containing our animation frames
Texture2D spriteSheet;
// the elapsed amount of time the frame has been shown for
float time;
// duration of time to show each frame
float frameTime = 0.1f;
// an index of the current frame being shown
int frameIndex;
// total number of frames in our spritesheet
const int totalFrames = 10;
// define the size of our animation frame
int frameHeight = 64;
int frameWidth = 64;

 


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

6) В методе LoadContent () загрузите SpriteSheet в переменную Texture2D spriteSheet:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    spriteSheet = Content.Load<Texture2D>("Celebrate");
}

Методы Update () и Draw () вызываются в постоянном цикле, называемом Game Loop . Update () обрабатывает любой пользовательский ввод и игровую логику, которые необходимо обработать с момента последнего вызова метода (движение противника, столкновения, подсчет очков и т. Д.). Метод Draw () отвечает за отправку любых графических битов на экран. Идеальная ситуация состоит в том, чтобы эти два метода выполнялись не медленнее, чем ваша целевая частота кадров (т.е. 30 к / с — 60 к / с). Частота кадров измеряется тем, насколько быстро я могу записывать графические биты (мой метод Draw ()) на экран в секунду.

7) В методе Draw () мы разместим нашу логику для рисования последовательности анимации за определенный период времени:


Сначала мы рассчитываем, сколько времени прошло с момента последнего рисования одного из наших кадров анимации на экране.
frameTime содержит наше целевое время (0,1 миллисекунды), чтобы нарисовать наш следующий кадр в последовательности. Когда мы превысили это время, мы устанавливаем наш индекс на следующий кадр в SpriteSheet и сбрасываем наше время.
// Process elapsed time
time += (float)gameTime.ElapsedGameTime.TotalSeconds;
while (time > frameTime)
{
     // Play the next frame in the SpriteSheet
     frameIndex++;
   
     // reset elapsed time
     time = 0f;
}

Чтобы нарисовать последовательность циклов, мы определяем, превысил ли наш frameIndex количество кадров в нашем SpriteSheet. Если это так, мы возвращаем его обратно в кадр 1.

if (frameIndex > totalFrames) frameIndex = 1;

SpriteSheet — это одно изображение текстуры, которое содержит последовательность изображений одинакового размера. Мы используем информацию об известном размере и количестве, чтобы вычислить, насколько велик наш фрейм, и где в последовательности нам нужно извлечь изображение из SpriteSheet. Вычисление позиции в SpriteSheet легко выполняется путем создания прямоугольника на основе нашей известной информации: frameWidth, frameHeight и frameIndex. Умножьте frameIndex на frameWidth для ссылки на соответствующий кадр в последовательности.

// Calculate the source rectangle of the current frame.
Rectangle source = new Rectangle(frameIndex * frameWidth, 

                                   0, frameWidth, frameHeight);

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

// Calculate position and origin to draw in the center of the screen
Vector2 position = new Vector2(this.Window.ClientBounds.Width / 2, 
                               this.Window.ClientBounds.Height / 2);
Vector2 origin = new Vector2(frameWidth / 2.0f, frameHeight);

Метод spriteBatch.Draw выводит spriteSheet на основе всех наших инструкций. «Позиция» — это место, где рисуется наш спрайт, а «источник» содержит координаты прямоугольника для фрейма, содержащегося в spriteSheet, который мы хотим нарисовать.

spriteBatch.Begin();



// Draw the current frame.
spriteBatch.Draw(spriteSheet, position, source, Color.White, 0.0f,
origin, 1.0f, SpriteEffects.None, 0.0f);



spriteBatch.End();

Выполнив тонкий баланс для запуска и запуска MonoGame, конвейера контента, загруженного в ваш проект MonoGame, и выполнив вышеуказанные шаги, вы сможете нажать F5, чтобы запустить игру из Магазина Windows, и посмотреть, как наш Герой поднимает руки в воздух в праздник! (здесь я вставил бы анимированный GIF-файл с конечным результатом, если бы знал, как это сделать с помощью приложения для Магазина Windows)

Вот мой последний проект, если вы заблудились где-то вдоль линии. Это решение не включает исходный код для проекта MonoGame.FrameWork.Windows8. Вы захотите добавить свою локальную копию в решение, чтобы оно могло скомпилироваться. Надеемся, что мы сможем удалить этот шаг, как только появятся бинарные файлы MonoGame для Windows 8.

Исходный код: MonoGameSpriteSheetDemo.zip