Главная » Разработка для Windows Phone 7 » От жестов к трансформациям Windows Phone 7

0

Основным средством пользовательского ввода в приложении для Windows Phone 7 является касание. Устройство, работающее под управлением Windows Phone 7, имеет экран, который поддерживает минимум четыре точки касания. Распознавание и интерпретация касаний должны быть реализованы приложениями так, чтобы это было естественно и интуитивно понятно для пользователя.

Как уже было продемонстрировано, в распоряжении разработчиков на XNA имеется два основных подхода к обработке сенсорного ввода. Метод TouchPanel.GetState позволяет отслеживать простые одиночные касания, каждое из которых идентифицируется с помощью ID, от момента первого соприкосновения пальца с экраном, в ходе перемещения и вплоть до снятия касания. Метод TouchPanel.ReadGesture обеспечивает более высокоуровневый интерфейс для элементарной обработки инерции и касания двумя пальцами в форме жестов «pinch» (сведение) и «stretch» (растяжение).

Жесты и свойства

Жесты, поддерживаемые классом TouchPanel, соответствуют членам перечисления GestureType:

•                                    Tap — быстрое касание и снятие

•                                   DoubleTap — последовательность двух коротких касаний

•                                   Hold — нажатие и удержание в течение одной секунды

•                                   FreeDrag — перемещение пальца по экрану

•                                   HorizontalDrag — горизонтальная составляющая FreeDrag

•                                    VerticalDrag — вертикальная составляющая FreeDrag

•                                   DragComplete —касание снято

•                                   Flick — движение скольжения одного пальца по экрану

•         Pinch — перемещение двух пальцев навстречу друг другу или в противоположные стороны

•                                   PinchComplete — пальцы сняты с экрана

Для работы с жестами их необходимо активировать посредством свойства TouchPanel.EnabledGestures (Жесты активированы). После этого приложение принимает жесты в ходе выполнения перегруженного Update класса Game в форме структур GestureSample, которые включают свойство GestureType для идентификации жеста.

GestureSample также определяет четыре свойства типа Vector2. Ни одно из этих свойств не действительно для жестов DragComplete и PinchComplete. Также:

•                                   Position действительно для всех жестов, кроме Flick.

•                                   Delta действительно для всех жестов Drag, Pinch и Flick.

•                                   Position2 и Delta2 действительны только для Pinch.

Свойство Position указывает на текущее положение точки касания относительно экрана. Свойство Delta соответствует перемещению точки касания относительно последнего местоположения. Для объекта типа GestureSample под именем gestureSample:

Vector2 previousPosition = gestureSample.Position – gestureSample.Delta;

Вектор Delta равен нулю в первый момент касания, или если точка касания остается неподвижной.

Предположим, нас интересуют только операции перетягивания. Для этого активируем жесты FreeDrag и DragComplete. Если требуется отслеживать весь путь пальца по экрану с момента первого касания до момента снятия, воспользуемся одной из двух стратегий: либо будем сохранять значение Position первого FreeDrag после DragComplete и сравнивать его с последующими значениями Position, либо будем накапливать значения Delta в виде промежуточной суммы.

Рассмотрим простое приложение, в котором пользователь может перемещать небольшое растровое изображение по экрану. В проекте OneFingerDrag (Перетягивание одним пальцем) класс Game1 имеет поля для хранения Texture2D и его местоположения:

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

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

GraphicsDeviceManager graphics; SpriteBatch spriteBatch;

Texture2D texture;

Vector2 texturePosition = Vector2.Zero;

public Game1() {

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

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

кадров/с

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

}

}

Обратите внимание, жест FreeDrag активируется в конце конструктора.

Перегруженный LoadContent загружает тот же Texture2D, который мы использовали в проекте RippleEffect в предыдущей главе:

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

protected override void LoadContent() {

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

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

Перегруженный метод Update обрабатывает жест FreeDrag, просто увеличивая вектор texturePosition на значение свойства Delta объекта GestureSample:

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

protected override void Update(GameTime gameTime) {

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

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

while (TouchPanel.IsGestureAvailable) {

GestureSample gesture = TouchPanel.ReadGesture();

if (gesture.GestureType == GestureType.FreeDrag) texturePosition += gesture.Delta;

}

base.Update(gameTime);

}

И хотя texturePosition – это точка, а значение свойства Delta объекта GestureSample – это вектор, они оба являются значениями Vector2, поэтому могут складываться.

Применение цикла while в данном приложении может показаться нецелесообразным, потому что нас интересует лишь один тип жестов. Разве нельзя было бы просто использовать выражение if? На самом деле, нет. Мой опыт показывает, что в ходе одного вызова Update могут быть доступны несколько жестов одного типа.

Перегруженный Draw просто отрисовывает Texture2D в точке, соответствующей новому местоположению:

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

protected override void Draw(GameTime gameTime) {

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

spriteBatch.Draw(texture, texturePosition, Color.White); spriteBatch.End();

base.Draw(gameTime);

}

Изначально Texture2D располагается в верхнем левом углу экрана, но пользователь может перемещать его , проводя пальцем по экрану:

Пользователь может перемещать палец по экрану абсолютно произвольно, и текстура будет перемещаться за ним! Данное приложение не проводит проверки попадания точки касания в область Texture2D, но это несложно добавить:

while (TouchPanel.IsGestureAvailable) {

GestureSample gesture = TouchPanel.ReadGesture();

if (gesture.GestureType ==                GestureType.FreeDrag) {

if (gesture.Position.X > texturePosition.X &&

gesture.Position.X < texturePosition.X + texture.Width && gesture.Position.Y > texturePosition.Y &&

gesture.Position.Y < texturePosition.Y + texture.Height) {

texturePosition += gesture.Delta;

}

}

}

Как же работает данная логика? При проведении пальцем по экрану вне текстуры она перемещаться не будет, но если в какой-то момент точка касания попадает в область текстуры, последняя начинает перемещаться. Вероятно, желательно сделать так, чтобы текстура перемещалась только в том случае, когда первый FreeDrag в последовательности приходится на область текстуры. В противном случае вся последовательность жестов FreeDrag вплоть до DragComplete должна игнорироваться.

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

По теме:

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