Главная » Разработка для Windows Phone 7 » Скольжение и инерция

0

В фильме «Особое мнение » (2002) Том Круз одним движением руки перетянул объект по экрану компьютера в сторону, и весь мир воскликнул: «Ух ты, здорово!»

Реализация инерции в интерфейсах обработки касания приложений, главным образом, является сферой ответственности разработчика. XNA помогает лишь немного, предоставляя жест Flick, который формируется, если пользователь быстро проводит пальцем по экрану. Свойство Delta объекта GestureSample отражает скорость перемещения пальца в пикселах в секунду. (Во всяком случае, так должно быть, но на самом деле, кажется, его значение ближе к половине фактической скорости.) Скорость представляется как Vector2, т.е. кроме величины, учитывается и направление.

Жест Flick не включает сведений о местоположении. По сути, это всегда один и тот же жест независимо от того, в каком месте экрана пользователь проводит пальцем. Если требуется реализовать инерцию на основании положения пальца и скорости его перемещения, вероятно, проще всего это сделать на основании жестов Drag через деление значений Delta на значение свойства ElapsedGameTime аргумента GameTime метода Update.

Чтобы реализовать инерцию, продолжайте перемещение объекта, взяв за основу исходную скорость и учитывая замедление. Если скорость выражена в единицах в секунду, вероятно, замедление выражается в единицах в секунду в квадрате. Каждую секунду скорость уменьшается на значение замедления до тех пор, пока модуль скорости не станет равным нулю. Для вызовов Update, которые формируются каждую долю секунды, скорость уменьшается пропорционально.

Проект Flicklnertia (Инерция скольжения) демонстрирует очень простую реализацию инерции. В нем описаны поля position, velocity (скорость) и константа замедления:

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

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

GraphicsDeviceManager graphics; SpriteBatch spriteBatch;

const float DECELERATION = 1000; // пикселов в секунду в квадрате

Texture2D texture; Vector2 position = Vector2.Zero; Vector2 velocity; SpriteFont segoe14;

StringBuilder text = new StringBuilder();

public Game1() {

graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content";

// Частота кадров по умолчанию для всех устройств Windows Phone – 30

кадров/с

TargetElapsedTime = TimeSpan.FromTicks(333333); TouchPanel.EnabledGestures = GestureType.Flick;

}

}

Конструктор активирует только жесты Flick. Перегруженный метод LoadContent загружает и Texture2D, и шрифт для вывода на экран данных состояния (местоположение и скорость):

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

protected override void LoadContent() {

// Создаем новый SpriteBatch, который может использоваться для отрисовки текстур spriteBatch = new SpriteBatch(GraphicsDevice);

texture = this.Content.Load<Texture2D>("PetzoldTattoo"); segoe14 = this.Content.Load<SpriteFont>("Segoe14");

}

Перегруженный Update выполняет несколько операций. Прежде всего, это чтение жестов и сбор всех дополнительных данных о скорости в поле velocity. Если скорость меняется, вектор velocity умножается на истекшее время в секундах для получения изменения местоположения. Полученное значение добавляется к вектору position. После этого вектор velocity должен быть уменьшен на величину, соответствующую произведению константы DECELERATION (замедление) и истекшего времени в секундах. Наконец, выполняется форматирование StringBuilder для вывода на экран этих двух векторов:

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

protected override void Update(GameTime gameTime) {

// Обеспечиваем возможность выхода из игры

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

// Задаем скорость на основании жеста Flick while (TouchPanel.IsGestureAvailable)

GestureSample gesture = TouchPanel.ReadGesture();

if (gesture.GestureType == GestureType.Flick) velocity += gesture.Delta;

}

// Используем скорость для корректировки местоположения и замедления

if (velocity != Vector2.Zero) {

float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; position += velocity * elapsedSeconds;

float newMagnitude = velocity.Length() – DECELERATION * elapsedSeconds; velocity.Normalize();

velocity *= Math.Max(0, newMagnitude);

}

// Выводим на экран текущие координаты и скорость text.Remove(0, text.Length);

text.AppendFormat("Position: {0} Velocity: {1}", position, velocity); base.Update(gameTime);

}

Перегруженный Draw отрисовывает и Texture2D, и StringBuilder:

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

protected override void Draw(GameTime gameTime) {

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

spriteBatch.Draw(texture, position, Color.White);

spriteBatch.DrawString(segoe14, text, Vector2.Zero, Color.White); spriteBatch.End();

base.Draw(gameTime);

}

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

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

По теме:

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