Главная » Разработка для Windows Phone 7 » Перемещение по заданной траектории Windows Phone 7

0

Далее в данной главе я хочу сосредоточиться на методиках перемещения спрайтов по некоторой траектории. Чтобы добавить реализма, я поручил моей жене Дидре нарисовать в Paint небольшой гоночный автомобиль:

Размеры автомобиля составляют 48 пикселов в длину и 29 пикселов в ширину. Обратите внимание на пурпурный фон. Если требуется сделать часть изображения прозрачным в XNA, можно использовать 32-разрядный растровый формат, который поддерживает прозрачность, такой как PNG, например. Каждый пиксел в этом формате имеет 8-битовый красный, зеленый и синий компоненты, но также и 8-битовый альфа-канал для определения прозрачности. (Этот формат мы рассмотрим в следующей главе.) Приложение Paint в Windows не поддерживает прозрачности для растровых изображений, увы, но вместо этого может использоваться пурпурный цвет. В Paint для получения этого цвета задайте красному и синему каналам значение 255 и зеленому – 0.

Во все проекты данной главы файл этого изображения, car.png, включен как часть содержимого проекта. Первый проект, CarOnRectangularCourse (Объезд по прямоугольной траектории), демонстрирует достаточно неуклюжий подход к реализации перемещения автомобиля по периметру экрана. Он включает следующие поля:

Проект XNA: CarOnRectangularCourse Файл: Game1.cs (фрагмент, демонстрирующий поля)

public class Game1 : Microsoft.Xna.Framework.Game {

const float SPEED = 100;                   // пикселов в секунду

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

Texture2D car;

Vector2 carCenter;

Vector2[] turnPoints = new Vector2[4]; int sideIndex = 0; Vector2 position; float rotation;

}

Массив turnPoints (Точки разворота) включает четыре точки в углах экрана, в которых автомобиль делает резкий разворот. Вычисление координат этих точек – является одной из основных задач метода LoadContent, который также загружает Texture2D и инициализирует остальные поля:

Проект XNA: CarOnRectangularCourse Файл: Game1.cs (фрагмент)

protected override void LoadContent() {

spriteBatch = new SpriteBatch(GraphicsDevice);

car = this.Content.Load<Texture2D>("car");

carCenter = new Vector2(car.Width / 2, car.Height / 2);

float margin = car.Width;

Viewport viewport = this.GraphicsDevice.Viewport; turnPoints[0] = new Vector2(margin, margin);

turnPoints[1] = new Vector2(viewport.Width – margin, margin);

turnPoints[2] = new Vector2(viewport.Width – margin, viewport.Height – margin); turnPoints[3] = new Vector2(margin, viewport.Height – margin); position = turnPoints[0]; rotation = MathHelper.PiOver2;

}

Я использую поле carCenter в качестве аргумента origin для метода Draw, т.е. эта та точка автомобиля, которая должна совпадать с точкой траектории, определенной одним из четырех членов массива turnPoints. Благодаря значению margin эта траектория располагается на расстоянии одной ширины автомобиля от края экрана, таким образом, автомобиль отстоит от края экрана на половину своей ширины.

Я назвал это приложение «неуклюжим», и метод Update является абсолютным подтверждением этому:

Проект XNA: CarOnRectangularCourse Файл: Game1.cs (фрагмент)

protected override void Update(GameTime gameTime) {

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this .Exit();

float pixels = SPEED * (float)gameTime.ElapsedGameTime.TotalSeconds;

switch (sideIndex) {

case 0:                   // верх

position.X += pixels;

if (position.X > turnPoints[1].X) {

position.X = turnPoints[1].X;

position.Y = turnPoints[1].Y + (position.X – turnPoints[1].X); rotation = MathHelper.Pi; sideIndex = 1;

}

break;

case 1:                   // правый край

position.Y += pixels;

if (position.Y > turnPoints[2].Y) {

position.Y = turnPoints[2].Y;

position.X = turnPoints[2].X – (position.Y – turnPoints[2].Y); rotation = -MathHelper.PiOver2; sideIndex = 2;

}

break;

case 2:                   // низ

position.X -= pixels;

if (position.X < turnPoints[3].X) {

position.X = turnPoints[3].X;

position.Y = turnPoints[3].Y + (position.X – turnPoints[3].X); rotation = 0; sideIndex = 3;

}

break;

case 3:                            // левый край

position.Y -= pixels;

if (position.Y < turnPoints[0].Y) {

position.Y = turnPoints[0].Y;

position.X = turnPoints[0].X – (position.Y – turnPoints[0].Y); rotation = MathHelper.PiOver2; sideIndex = 0;

}

break;

}

base.Update(gameTime);

}

Этот тот тип кода, который просто кричит: «Есть лучший способ сделать это!» Он не элегантен и не универсален. Но прежде чем перейти к более гибкому подходу, рассмотрим абсолютно предсказуемый метод Draw, который включает обновленные значения position и rotation, вычисленные в ходе выполнения Update:

Проект XNA: CarOnRectangularCourse Файл: Game1.cs (фрагмент)

protected override void Draw(GameTime gameTime) {

GraphicsDevice.Clear(Color.Blue); spriteBatch.Begin();

spriteBatch.Draw(car, position, null, Color.White, rotation,

carCenter, 1, SpriteEffects.None, 0); spriteBatch.End();

base.Draw(gameTime);

}

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии