Цель работы: Ознакомиться с методологией анимирования
XNA поддерживает различные операции по трансформации
Метод Draw() объекта класса SpriteBatch имеет 7 перегруженных вариантов. До этого мы пользовались простыми вариантами метода – теперь используем более сложный вариант, который предусматривает использование некоторых дополнительных параметров при выводе
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);
}
}
}
Назначение переменных, используемых в программе, указано в листинге. При касании стрелок "вверх" и "вниз" rotate, которая задает угол поворота
Двойное касание экрана приводит к изменению цвета
Сведение или разведение пальцев на экране приводит к модификации размера
Параметр
Для того, чтобы вращение происходило вокруг центра Draw, которую мы использовали для вывода
| Элемент | Описание |
| |
| Позиция |
spRec | Прямоугольник, ограничивающий |
color | Оттенок |
| Угол поворота |
| Начало координат |
| Размер |
SpriteEffects.None | Эффект вывода None – никак не влияет на положение |
(float)0 | Глубина |
На рис. 17.1 вы можете видеть игровой экран.
(рис 17.1) Игровой экран проекта P11_1
Эмулятор запущен на компьютере с обычным экраном, поэтому жест Pinch мы испытать на нём не можем.
Теперь рассмотрим анимацию
Для того, чтобы создать анимированный
Создадим
(рис 17.2) Заготовка для анимированного спрайта
Создадим стандартный игровой проект, назовем его P11_2. В листинге 17.2 приведен код класса 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_2
{
/// <summary>
/// Это главный тип игры
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D texture;
//Количество кадров в изображении
const int frames = 2;
//Частота анимации - кадров в секунду
const int framesPerSec =10;
//Текущий кадр для вывода на экран
int numberOfFrame=0;
//Время, в течение которого отображается один кадр
float timePerFrame;
//Время, которое прошло с начала отображения текущего кадра
float totalElapsed;
//Позиция вывода спрайта
Vector2 position;
//Прямоугольник для задания позиции кадра в изображении
Rectangle sprRec;
//Ширина кадра
int widthFrame = 64;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.IsFullScreen = true;
// Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
TargetElapsedTime = TimeSpan.FromTicks(333333);
// Дополнительный заряд аккумулятора заблокирован.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
/// <summary>
/// Позволяет игре выполнить инициализацию, необходимую перед запуском.
/// Здесь можно запросить нужные службы и загрузить неграфический
/// контент. Вызов base.Initialize приведет к перебору всех компонентов и
/// их инициализации.
/// </summary>
protected override void Initialize()
{
position = new Vector2(100, 100);
//Время для одного кадра вычисляется как результат деления 1 секунды
//на заданное количество кадров в секунду
timePerFrame = (float)1 / framesPerSec;
sprRec = new Rectangle(0, 0, 64, 64);
base.Initialize();
}
/// <summary>
/// LoadContent будет вызываться в игре один раз; здесь загружается
/// весь контент.
/// </summary>
protected override void LoadContent()
{
// Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
spriteBatch = new SpriteBatch(GraphicsDevice);
texture = Content.Load<Texture2D>("animation");
// ЗАДАЧА: используйте здесь this.Content для загрузки контента игры
}
/// <summary>
/// UnloadContent будет вызываться в игре один раз; здесь выгружается
/// весь контент.
/// </summary>
protected override void UnloadContent()
{
// ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
}
//Эта процедура используется для анимации спрайта
//Она принимает количество секунд, прошедших с предыдущего вызова
//процедуры Update
void ChangeFrame(float elpT)
{
//Увеличим общее время отображения спрайта на
//время, прошедшее с последнего вызова процедуры
totalElapsed += elpT;
//если общее время отображения спрайта больше времени,
//выделенного на один спрайт
if (totalElapsed > timePerFrame)
{
//Если номер кадра равен количеству кадров-1
if (numberOfFrame == frames-1)
{
//установим номер кадра в 0
numberOfFrame = 0;
}
//иначе увеличим номер кадра на 1
else numberOfFrame++;
//создадим новый прямоугольник
//Его координата X соответствует координате левого верхнего угла
//кадра, Y равно 0, длина и ширина всегда равны 64
sprRec = new Rectangle((int)widthFrame * numberOfFrame, 0, 64, 64);
//сбросим totalElapsed в 0
totalElapsed = 0;
}
}
/// <summary>
/// Позволяет игре запускать логику обновления мира,
/// проверки столкновений, получения ввода и воспроизведения звуков.
/// </summary>
/// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
protected override void Update(GameTime gameTime)
{
// Позволяет выйти из игры
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
ChangeFrame((float)gameTime.ElapsedGameTime.TotalSeconds);
base.Update(gameTime);
}
/// <summary>
/// Вызывается, когда игра отрисовывается.
/// </summary>
/// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(texture, position, sprRec, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Если кратко описать последовательность работы этого проекта, получится следующее: в цикле Update() мы вызываем процедуру ChangeFrame(), которой передаем время, прошедшее после последнего вызова Update(). Внутри этой процедуры мы проверяем, достаточно ли времени текущий кадр отображался на экране, и если его время вышло – меняем на следующий.
Можно заметить, что здесь мы анимировали
Для применения подобного приема на практике лучше всего включить код анимации
Рассмотрим анимацию фона, в частности – создание фона со скроллингом.
Существует класс двумерных игр, в которых применяется фон со скроллингом. Такой фон позволяет создать имитацию движения объекта. Обычно применяют горизонтальный или вертикальный скроллинг фона. В вертикальном варианте фон перемещается сверху вниз или снизу вверх, имитируя движение в соответствующем направлении. В горизонтальном варианте фон обычно перемещается справа налево, имитируя движение вправо.
Разработаем
(рис 17.3) Заготовка для анимации
Идея скроллинга фона заключается в следующем. Мы будем использовать два игровых объекта, символизирующих фон. Каждый из них в отдельности может выводить
Создадим новый игровой проект, P6_3. Управление
На рис. 17.4 вы можете видеть окно Обозреватель решений для нашего проекта.
(рис 17.4) Окно Обозреватель решений для проекта P11_3
В листинге 17.3 приведен код класса
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
namespace P11_3
{
class sprite
{
public Texture2D spTexture;
public Vector2 spPosition;
public sprite(Texture2D newSpTexture, Vector2 newSpPosition)
{
spTexture = newSpTexture;
spPosition = newSpPosition;
}
}
}
В листинге 17.4 приведен код класса 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_3
{
/// <summary>
/// Это главный тип игры
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//объекты для создания скроллингового фона
sprite road1;
sprite road2;
//скорость скроллинга
Vector2 scrolSpeed;
//позиции, на которые устанавливаются обе "дороги"
//в момент начала игры и каждый раз, когда они
//сдвинутся на определенное расстояние
Vector2 road1Start;
Vector2 road2Start;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.IsFullScreen = true;
//Установим параметры заднего буфера, на полный экран
//теперь будет выводить изображение размерами 600х400 пикселей
graphics.PreferredBackBufferHeight = 600;
graphics.PreferredBackBufferWidth = 400;
// Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
TargetElapsedTime = TimeSpan.FromTicks(333333);
// Дополнительный заряд аккумулятора заблокирован.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
/// <summary>
/// Позволяет игре выполнить инициализацию, необходимую перед запуском.
/// Здесь можно запросить нужные службы и загрузить неграфический
/// контент. Вызов base.Initialize приведет к перебору всех компонентов и
/// их инициализации.
/// </summary>
protected override void Initialize()
{
//скорость скроллинга - 5 пикселей по оси Y за один
//проход цикла Update
scrolSpeed = new Vector2(0, 5f);
//первая "дорога" будет изначально установлена в позиции 0,0
//вторая "дорога" - за пределами игрового экрана - в позиции 0,-600
road1Start = new Vector2(0, 0);
road2Start = new Vector2(0, -600);
base.Initialize();
}
/// <summary>
/// LoadContent будет вызываться в игре один раз; здесь загружается
/// весь контент.
/// </summary>
protected override void LoadContent()
{
// Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
spriteBatch = new SpriteBatch(GraphicsDevice);
road1 = new sprite(Content.Load<Texture2D>("road"), road1Start );
road2 = new sprite(Content.Load<Texture2D>("road"), road2Start );
// ЗАДАЧА: используйте здесь this.Content для загрузки контента игры
}
/// <summary>
/// UnloadContent будет вызываться в игре один раз; здесь выгружается
/// весь контент.
/// </summary>
protected override void UnloadContent()
{
road1.spTexture.Dispose();
road2.spTexture.Dispose();
spriteBatch.Dispose();
}
/// <summary>
/// Позволяет игре запускать логику обновления мира,
/// проверки столкновений, получения ввода и воспроизведения звуков.
/// </summary>
/// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
protected override void Update(GameTime gameTime)
{
// Позволяет выйти из игры
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
//если первая "дорога" не спустилась ниже, чем координата 0,600
//то есть все еще видна на экране
//тогда переместить обе "дороги" на дистанцию, задаваемую
//в scrolSpeed
if (road1.spPosition.Y < 600)
{
road1.spPosition += scrolSpeed;
road2.spPosition += scrolSpeed;
}
else
{
//если первая дорога ушла за пределы видимости
//это означает что вторая полностью выведена на экран
//вычислим новую позицию для установки объектов
//для того, чтобы не было скачков при установке
//предварительно вычислим новую позицию
road1Start.Y = road1.spPosition.Y - 600;
road2Start.Y = road2.spPosition.Y - 600;
road1.spPosition = road1Start;
road2.spPosition = road2Start;
}
base.Update(gameTime);
}
/// <summary>
/// Вызывается, когда игра отрисовывается.
/// </summary>
/// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//выведем первый и второй спрайт на экран
spriteBatch.Draw(road1.spTexture, road1.spPosition, Color.White);
spriteBatch.Draw(road2.spTexture, road2.spPosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
На рис. 17.5 вы можете видеть игровой экран.
(рис 17.5) Игровой экран проекта P11_3
Теперь рассмотрим горизонтальный скроллинг фона, использующий различные
В предыдущем примере мы использовали один и тот же
Создадим фоновые изображения, которые будем использовать. На рис. 17.6 вы можете видеть их.
(рис 17.6) Изображения для игры с боковым скроллингом
Создадим новый игровой проект P11_4 на основе P11_3. Класс нового проекта соответствует такому же классу проекта P11_3, а вот в класс Game1 внесены существенные изменения. Код этого класса вы можете найти в листинге 17.5
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_4
{
/// <summary>
/// Это главный тип игры
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//объекты для создания скроллингового фона
sprite back1, back2, back3, back4;
//скорость скроллинга
Vector2 scrolSpeed;
//позиции, на которые устанавливаются объекты
Vector2 back1Start, back2Start, back3Start, back4Start;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.IsFullScreen = true;
// Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
TargetElapsedTime = TimeSpan.FromTicks(333333);
// Дополнительный заряд аккумулятора заблокирован.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
/// <summary>
/// Позволяет игре выполнить инициализацию, необходимую перед запуском.
/// Здесь можно запросить нужные службы и загрузить неграфический
/// контент. Вызов base.Initialize приведет к перебору всех компонентов и
/// их инициализации.
/// </summary>
protected override void Initialize()
{
//скорость скроллинга - 5 пикселей по оси X за один
//проход цикла Update
scrolSpeed = new Vector2(-5f, 0);
back1Start = new Vector2(0, 0);
back2Start = new Vector2(800, 0);
back3Start = new Vector2(1600, 0);
back4Start = new Vector2(2400, 0);
base.Initialize();
}
/// <summary>
/// LoadContent будет вызываться в игре один раз; здесь загружается
/// весь контент.
/// </summary>
protected override void LoadContent()
{
// Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
spriteBatch = new SpriteBatch(GraphicsDevice);
//создаем игровые объекты
back1 = new sprite(Content.Load<Texture2D>("b1"), back1Start);
back2 = new sprite(Content.Load<Texture2D>("b2"), back2Start);
back3 = new sprite(Content.Load<Texture2D>("b3"), back3Start);
back4 = new sprite(Content.Load<Texture2D>("b4"), back4Start);
}
/// <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();
//прокручиваем каждый из спрайтов влево
back1.spPosition += scrolSpeed;
back2.spPosition += scrolSpeed;
back3.spPosition += scrolSpeed;
back4.spPosition += scrolSpeed;
//Если координата Х одного из спрайтов меньше
//чем -800 - то есть этот спрайт уже "ушел" влево
//и исчез за пределами экрана - перенести этот спрайт
//в позицию, которую занимает четвертый спрайт, то есть -
//в крайнюю правую позицию.
//Таким образом после первого прохода всех спрайтов
//первый спрайт будет следовать за четвертым, второй за первым и т.д.
if (back1.spPosition.X < -800)
{
float f = back1.spPosition.X + 800;
back1.spPosition.X = back4Start.X +f;
}
if (back2.spPosition.X < -800)
{
float f = back2.spPosition.X + 800;
back2.spPosition.X = back4Start.X + f;
}
if (back3.spPosition.X < -800)
{
float f = back3.spPosition.X + 800;
back3.spPosition.X = back4Start.X + f;
}
if (back4.spPosition.X < -800)
{
float f = back4.spPosition.X + 800;
back4.spPosition.X = back4Start.X + f;
}
base.Update(gameTime);
}
/// <summary>
/// Вызывается, когда игра отрисовывается.
/// </summary>
/// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//выведем спрайты на экран
spriteBatch.Draw(back1.spTexture, back1.spPosition, Color.White);
spriteBatch.Draw(back2.spTexture, back2.spPosition, Color.White);
spriteBatch.Draw(back3.spTexture, back3.spPosition, Color.White);
spriteBatch.Draw(back4.spTexture, back4.spPosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Особенности работы кода отражены в комментариях.
На рис. 17.7 вы можете видеть игровой экран проекта P11_4.
(рис 17.7) Игровой экран проекта P11_4
В этой лабораторной работе была рассмотрена методика анимации
Разработайте собственный вариант скроллингового авиасимулятора. Используйте для анимации фона 5 изображений, представляющих собой ландшафт, над которым "летит" самолет.
К данной лабораторной работе прилагается видеоурок
и демонстрационный проект.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.