Опубликован: 14.08.2012 | Доступ: свободный | Студентов: 881 / 20 | Оценка: 5.00 / 5.00 | Длительность: 09:59:00
Специальности: Программист
Самостоятельная работа 11:

Спрайтовая анимация

Аннотация: Эта лабораторная работа посвящена различным методам анимации двумерных изображений (спрайтов), в частности, покадровой анимации, трансформации, созданию скроллинговых игр.

Цель работы: Ознакомиться с методологией анимирования спрайтов и фонов

17.1. Трансформация спрайтов

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

Метод Draw() объекта класса SpriteBatch имеет 7 перегруженных вариантов. До этого мы пользовались простыми вариантами метода – теперь используем более сложный вариант, который предусматривает использование некоторых дополнительных параметров при выводе спрайта на экран. В листинге 17.1 вы можете видеть код объекта Game1, реализующий различные операции по трансформации спрайта.

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 P11_1
{
    /// <summary>
    /// Это главный тип игры
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //Текстура
        Texture2D texture;
        //Изображение стрелок
        Texture2D textureArrows;
        //Исходная позиция спрайта
        private Vector2 position = new Vector2(150, 200);
        //Угол поворота спрайта (в радианах)
        private float rotation = 0;
        //Исходный оттенок спрайта
        private Color color = new Color(255, 255, 255);
        //Генератор случайных чисел для задания нового цвета
        private Random rand = new Random();
        //Размер спрайта
        private Vector2 scale = new Vector2(1, 1);
        //Начало координат спрайта
        private Vector2 origin;
        //Прямоугольник, ограничивающий спрайт
        private Rectangle spRec = new Rectangle(0, 0, 17, 17);

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.IsFullScreen = true;
            // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
            //Разрешим использовать жесты
            TouchPanel.EnabledGestures = GestureType.DoubleTap|GestureType.Pinch;
            // Дополнительный заряд аккумулятора заблокирован.
            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);
            Services.AddService(typeof(SpriteBatch), spriteBatch);
            texture = Content.Load<Texture2D>("Ball");
            textureArrows = Content.Load<Texture2D>("Arrows");
           
        }
        /// <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();

            //Получаем коллекцию объектов, содержащих информацию о касаниях экрана
            TouchCollection touchLocations = TouchPanel.GetState();
            //Перебираем коллекцию, присваивая объекту координаты касания
            foreach (TouchLocation touchLocation in touchLocations)
            {
                if (touchLocation.State == TouchLocationState.Pressed||touchLocation.State==TouchLocationState.Moved)
                {
                    //Стрелка "Влево"
                    if (touchLocation.Position.X > 500 && touchLocation.Position.X < 600
                        && touchLocation.Position.Y > 380 && touchLocation.Position.Y < 480)
                    {
                        position.X -= 1;
                        rotation -= 0.1f;

                    }
                    //Стрелка "Вправо"
                    if (touchLocation.Position.X > 700 && touchLocation.Position.X < 800
                        && touchLocation.Position.Y > 380 && touchLocation.Position.Y < 480)
                    {
                        position.X += 1;
                        rotation += 0.1f;

                    }
                    //Стрелка "Вниз"
                    if (touchLocation.Position.X > 600 && touchLocation.Position.X < 700
                        && touchLocation.Position.Y > 380 && touchLocation.Position.Y < 480)
                    {
                        position.Y += 1;
                    }
                    //Стрелка "Вверх"
                    if (touchLocation.Position.X > 600 && touchLocation.Position.X < 700 
                        && touchLocation.Position.Y > 280 && touchLocation.Position.Y < 380)
                    {
                        position.Y -= 1;
                    }
                }

            }

            while (TouchPanel.IsGestureAvailable)
            {
                //прочитаем жест
                GestureSample gs = TouchPanel.ReadGesture();
                //Если обнаружен жест двойного касания экрана
                if (gs.GestureType == GestureType.DoubleTap)
                {
                    //случайным образом изменим цвет спрайта
                    color = new Color((byte)rand.Next(0, 255), (byte)rand.Next(0, 255), (byte)rand.Next(0, 255));
                }
                //Если обнаружен жест сведения или разведения пальцев
                if (gs.GestureType == GestureType.Pinch)
                {
                    //Найдем предыдущие координаты, вычтя из текущих координат приращение
                    Vector2 oldPos = gs.Position - gs.Delta;
                    Vector2 oldPos2 = gs.Position2 - gs.Delta2;
                    //Получим расстояние между текущими точками касания
                    float currentDist = Vector2.Distance(gs.Position, gs.Position2);
                    //Получим расстояние между предыдущими точками касания
                    float oldDist = Vector2.Distance(oldPos, oldPos2);
                    //Умножим переменную, отвечающую за масштабирование спрайта
                    //на результат деления текущего расстояния на предыдущее
                    scale *=currentDist/oldDist;
                }
            }


            origin = (new Vector2 (spRec.Width ,spRec.Height ))/2;
            base.Update(gameTime);
        }

        /// <summary>
        /// Вызывается, когда игра отрисовывается.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            //Сначала выведем изображение стрелок
            spriteBatch.Draw(textureArrows, new Rectangle(500, 280, 300, 200), Color.White);
            //Игровой объект будет выведен поверх изображения стрелок
            spriteBatch.Draw(texture, position, spRec, color, rotation, origin , scale , SpriteEffects.None, (float)0);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
Листинг 17.1. Трансформации спрайта

Назначение переменных, используемых в программе, указано в листинге. При касании стрелок "вверх" и "вниз" спрайт перемещается в соответствующем направлении. При нажатии стрелок "влево" и "вправо" спрайт так же перемещается в соответствующих направлениях, однако, вместе с изменением его координат по оси X модифицируется и переменная rotate, которая задает угол поворота спрайта.

Двойное касание экрана приводит к изменению цвета спрайта – новый цвет выбирается случайным образом.

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

Параметр origin задает начало координат для спрайта. По умолчанию координата позиции спрайта соответствует его левому верхнему углу. Относительно левого верхнего угла, в таком случае, осуществляется и вращение спрайта.

Для того, чтобы вращение происходило вокруг центра спрайта мы записываем в переменную Origin результат от деления длины и ширины спрайта на 2. В итоге спрайт, во-первых, выводится на экран с учетом нового для него начала координат, а во-вторых – при вращении спрайта оно осуществляется вокруг центра спрайта, а не вокруг его левого верхнего угла. Рассмотрим подробнее команду Draw, которую мы использовали для вывода спрайта на экран. В табл. 17.1. описан каждый из её параметров.

Таблица 17.1. Описание параметров команды Draw
Элемент Описание
texture Текстура спрайта
position Позиция спрайта
spRec Прямоугольник, ограничивающий спрайт в текстуре, может применяться для вывода различных участков текстуры
color Оттенок спрайта
rotation Угол поворота спрайта
origin Начало координат спрайта, относительно которого осуществляется поворот и вывод спрайта на экран
scale Размер спрайта.
SpriteEffects.None Эффект вывода спрайта – позволяет поворачивать спрайт на 180 градусов или, если установлен параметр None – никак не влияет на положение спрайта
(float)0 Глубина спрайта. Может изменяться от 0 до 1

На рис. 17.1 вы можете видеть игровой экран.

Игровой экран проекта P11_1

Рис. 17.1. Игровой экран проекта P11_1

Эмулятор запущен на компьютере с обычным экраном, поэтому жест Pinch мы испытать на нём не можем.

Теперь рассмотрим анимацию спрайтов.

Гулич Анна
Гулич Анна
Невозможно пройти тесты, в окне с вопросами пусто