Главная » Разработка для Windows Phone 7 » Эллиптическая траектория Windows Phone 7

0

Самым далеким от реалистичного движения в предыдущем приложении была реализация поворотов. В реальности, чтобы повернуть, автомобиль замедляется, но фактически он перемещается по искривленной траектории, изменяя направление движения. Чтобы добавить реализма в предыдущее приложение, заменим углы кривыми. Эти кривые могут быть аппроксимированы с помощью полилиний, но увеличивающееся число полилиний потребует реструктуризации класса PolylineInterpolator для обеспечения лучшей производительности.

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

Немного теории. Любая точка окружности с центром в точке (0, 0) и радиусом R может быть описана уравнением

х2 + у2 = R2

где (x, y) – координаты этой точки.

Эллипс имеет два радиуса. Если они параллельны горизонтальной и вертикальной осям, их обозначают Rx и Ry, и уравнение эллипса выглядит следующим образом:

2 + 2 = 1

Для наших целей удобнее представить эллипс в параметрической форме. В этих двух уравнениях x и y являются функциями угла а, допустимые значения которого лежат в диапазоне от 0 до 2?:

 

Если центром эллипса является точка (Cx, Cy), уравнения принимают такой вид:

Введем переменную t, допустимые значения которой лежат в диапазоне от 0 до 1, и уравнения тогда будут выглядеть следующим образом:

И это будет идеальным решением для наших целей. Пока t изменяется от 0 до 1, машина проходит один полный круг. Но как обеспечивать разворот автомобиля, чтобы создать эффект его перемещения по касательной к этому эллипсу? В этом случае на помощь приходит дифференциальное исчисление. Сначала найдем производные от наших параметрических уравнений:

 

С физической точки зрения эти уравнения представляют мгновенное изменение направления движения относительно осей X и Y, соответственно. Чтобы перейти к углу между двумя касательными, просто применим такой незаменимый Math.Atan2.

И теперь мы готовы к написанию кода. Задаем следующие поля:

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

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

const float SPEED = 0.25f;                 // циклов в секунду

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

Texture2D car;

Vector2 carCenter;

Point ellipseCenter;

float ellipseRadiusX, ellipseRadiusY; Vector2 position; float rotation;

Среди этих полей имеется три элемента, которые используются в параметрических уравнениях эллипса: центр и два радиуса. Они определяются во время выполнения метода LoadContent на основании размеров доступной области экрана:

Проект XNA: CarOnOvalCourse Файл: 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);

Viewport viewport = this.GraphicsDevice.Viewport;

ellipseCenter = viewport.Bounds.Center;

ellipseRadiusX = viewport.Width / 2 – car.Width;

ellipseRadiusY = viewport.Height / 2 – car.Width;

}

Обратите внимание, в приведенном ниже методе Update вычисляются значения двух углов. Первый под называнием ellipseAngle (Угол эллипса) зависит от t и определяет точку положения автомобиля на эллипсе. Этот угол передается в параметрические уравнения эллипса для получения местоположения автомобиля в виде координат x и y

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

protected override void Update(GameTime gameTime) {

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

float t = (SPEED * (float)gameTime.TotalGameTime.TotalSeconds) % 1; float ellipseAngle = MathHelper.TwoPi * t;

float x = ellipseCenter.X + ellipseRadiusX * (float)Math.Cos(ellipseAngle); float y = ellipseCenter.Y + ellipseRadiusY * (float)Math.Sin(ellipseAngle); position = new Vector2(x, y);

float dxdt = -ellipseRadiusX * (float)Math.Sin(ellipseAngle); float dydt = ellipseRadiusY * (float)Math.Cos(ellipseAngle); rotation = MathHelper.PiOver2 + (float)Math.Atan2(dydt, dxdt);

base.Update(gameTime);

}

Второй угол, вычисляемый в Update, называется rotation. Это угол, определяющий ориентацию автомобиля. Переменные dxdt и dydt являются производными параметрических уравнений, рассмотренных нами ранее. Метод Math.Atan2 определяет угол вращения относительно положительного направления оси X, и, учитывая исходную ориентацию автомобиля, к нему необходимо добавить еще 90 градусов.

К этому моменту метод Draw мы уже знаем наизусть: Проект XNA: CarOnOvalCourse Файл: 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.

По теме:

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