Сенсорна взаємодія в розробці ігор для Windows Phone 7 Частина 4 Pinch

Сторінка оновлюється :
Дата створення сторінки :

Програмування! - 4.Щипати, розтягувати до масштабу спрайтів

Про цей зразок

Сучасні смартфони, такі як переглядачі зображень, дозволяють збільшувати і зменшувати зображення, використовуючи два пальці, щоб збільшити або зменшити відстань між пальцями. Те ж саме можна зробити з браузером Internet Explorer на телефоні Windows Phone 7. Ця дія називається «защемити, розтягнути» в Windows Phone 7.

Окрім защемлення та розтягування, ви також можете використовувати такі дії, як "дотик", щоб ненадовго торкнутися (торкнутися) однієї точки на екрані та "прогорнути", щоб швидко відстежити екран. Ці дії в сукупності називаються жестами.

У цій програмі я хотів би збільшити і зменшити спрайт, що відображається на екрані за допомогою цієї операції защемлення і розтягування. Також до минулого разу я безпосередньо отримував інформацію сенсорної панелі і обробляв її, але на цей раз хотілося б впоратися з сенсорними операціями методами, присвяченими жестам.

Цілі даного зразка програми

Операції защемлення та розтягування, щоб збільшити та зменшити спрайт.

図 1 :ストレッチでスプライトを拡大
Рисунок 1: Розтягніться, щоб збільшити спрайт

Програма - оголошення полів

У декларації поля немає нового класу, але він має "центральну координату текстури", "збільшення спрайту" та "відстань між двома останніми позиціями дотику при защемленні".

/// <summary>
/// テクスチャー
/// </summary>
Texture2D texture;

/// <summary>
/// テクスチャーの中心座標
/// </summary>
Vector2 textureCenterPos;

/// <summary>
/// スプライトのスケール
/// </summary>
float scale = 1;

/// <summary>
/// 前回の 2 点間の距離
/// </summary>
float previousLength = 0;

Програма - включення жестів

Цього разу ми виконаємо процес лише для жестів, але в стані за замовчуванням жоден з жестів не може бути використаний. Щоб отримати інформацію про кожен жест, необхідно встановити жест, який буде використовуватися для властивості TouchPanel.EnabledGestures.

// タッチパネルでピンチのジェスチャーを有効にする
TouchPanel.EnabledGestures = GestureType.Pinch | GestureType.PinchComplete;

Увімкнення всіх жестів впливає на продуктивність, тому переконайтеся, що ви встановлюєте лише ті жести, які потрібно використовувати. Тут для отримання інформації про операцію зведення встановлено "GestureType.Pinch", а "GestureType.PinchComplete" встановлено, щоб вказати, що процес зведення завершено. Місце налаштування встановлюється в конструкторі Гри.

Програма - Завантаження текстур

Завантаження текстур така ж, як і раніше, але на цей раз розраховуємо «центральну координату текстури». Це пояснюється тим, що при масштабуванні спрайту він масштабується з координатою центру як початком координат.

// テクスチャーをコンテンツパイプラインから読み込む
texture = Content.Load<Texture2D>("Texture");

// テクスチャーの中心座標を求める
textureCenterPos = new Vector2(texture.Width / 2, texture.Height / 2);

Програма - Отримання інформації про жести

Отримуємо інформацію про жести (затисніть тут) в методі Game.Update. Обробка жестів відбувається у вигляді повторення такої кількості жестів, скільки ви включили. Структура "TouchCollection", яка використовувалася до останнього разу, не використовується.

// 次のジェスチャー情報が取得できる場合は true を返し続けます
while (TouchPanel.IsGestureAvailable)
{
  // 次のジェスチャー情報を読み込みます
  GestureSample gs = TouchPanel.ReadGesture();
  
  switch (gs.GestureType)
  {
    case GestureType.Pinch:
      // ここにピンチ処理を記述します
      break;
    case GestureType.PinchComplete:
      // ここにピンチ完了処理を記述します
      break;
  }
}

Перевірте стан властивості TouchPanel.IsGestureAvailable в циклі while для отримання інформації про жести і перевірте, чи присутні такі відомості про жести: Якщо у вас є наступна інформація про жести, скористайтеся методом "TouchPanel.ReadGesture", щоб отримати інформацію про жест.

"GestureSample.GestureType" зберігає інформацію про те, який тип жесту включений, тому розгалужуйте процес оператором перемикача на його основі. У цьому зразку конструктор встановлює енуми "GestureType.Pinch" і "GestureType.PinchComplete" на властивість "TouchPanel.EnabledGestures", тому вони відповідно розгалужені.

Програма - обробка жестів щипання

Швидше подивитися на коментарі в коді для того, що ми робимо, але щоб підсумувати те, що ми робимо, ми знаходимо різницю між відстанню між попередніми двома точками дотику та відстанню точки дотику між двома точками цього разу і використовуємо цю різницю для збільшення або зменшення значення шкали.

case GestureType.Pinch:
  // 現在の2点間の距離を求めます
  float nowLength = (gs.Position - gs.Position2).Length();

  if (previousLength == 0)
  {
    // 前回の2点間の距離が 0 の場合は
    // 現在の2点間の距離を設定します
    // 初回はスケール計算を行いません
    previousLength = nowLength;
  }
  else
  {
    // 前回の2点間の距離との差分を計算します
    float diffLength = nowLength - previousLength;
    
    // ピンチ、ストレッチした距離に応じて
    // スケールを変化させています
    // 補正値は適当に設定します
    scale = MathHelper.Max(scale + diffLength / 150, 0);
    
    // 今回の距離を次の計算のために保持します
    previousLength = nowLength;
  }
  break;

Дві сенсорні позиції можна отримати за допомогою «GestureSample.Position» і «GestureSample.Position2» відповідно. Відняти різницю між двома отриманими векторами і знайти відстань між двома точками можна, викликавши метод «Вектор2.Довжина».

До речі, тут ми визначаємо попереднє відстань як 0, коли прищипивание не виконується, тому процес розгалужується при запуску прищипування і в другій і наступних петлях. Це пояснюється тим, що при першому прийомі прищипування немає попередньої відстані, тому немає необхідності в масштабуванні.

Також на цей раз ми використовуємо тільки два властивості, "GestureSample.Position" і "GestureSample.Position2", але є і властивості "GestureSample.Delta" і "GestureSample.Delta2", які можуть отримати інформацію про різницю від попереднього положення дотику. Є по дві властивості, але це для мультитач, а для жестів, які використовують тільки один дотик, ви будете використовувати властивості без «2».

Програма - Обробка при завершенні жесту зведення

Коли жест щипка завершено (відпускання будь-якого пальця від сенсорної панелі), відстань між попередніми двома точками встановлюється назад до 0. Спочатку може бути краще використовувати окремий прапорець, але так як доторкнутися до одного і того ж положення двома пальцями фізично неможливо, то відстань 0 визначається як не защемлення. (Якщо роздільна здатність низька, можливо, вдасться торкнутися тієї ж позиції ...)

case GestureType.PinchComplete:
  // ピンチが終了した場合は保持している距離を 0 に戻して
  // 完了したことにします
  previousLength = 0;
  break;

Програма - Малювання спрайтів

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

// スプライトの描画準備
spriteBatch.Begin();

// スプライトを描画する
spriteBatch.Draw(texture,
                 new Vector2(graphics.PreferredBackBufferWidth / 2,
                             graphics.PreferredBackBufferHeight / 2),
                 null,
                 Color.White,
                 0.0f,
                 textureCenterPos,
                 scale,
                 SpriteEffects.None,
                 0.0f);

// スプライトの一括描画
spriteBatch.End();

Короткий зміст даного зразка

Цього разу ми пояснили процес, присвячений жестам. У зразку ми тільки створюємо щипковий процес, але є і «фліки» і «трюми». Щоб дізнатися, які жести доступні, перегляньте довідку XNA Game Studio 4.0 для енумів GestureType.

Те ж саме можна реалізувати і з сенсорної інформації, отриманої з TouchPanel.GetState методом без використання специфічних для жестів методів або структур, але в такому випадку вам потрібно буде самостійно розрахувати швидкість управління ідентифікатором мультитач, час дотику, фліків і т.д. Використовуючи специфічні для жестів методи, ці реалізації можна спростити, а також є перевага, що всіма іграми та програмами можна керувати однаково.

При самостійному створенні процесу сенсорної панелі, якщо можна підставити подібний процес в якості жесту, рекомендуємо скористатися цим.

Програмування! - 5.Защемлення для обертання спрайтів

Про цей зразок

Защемлення зазвичай відноситься до «защемлення» і «розтягування», але процес щипання XNA Game Studio 4.0 спеціально не обмежує процес цими двома, тому ви також можете виконувати операції, які обводять одну точку дотику навколо іншої точки дотику.

Тут я хотів би повернути спрайт за допомогою цього методу операції. До речі, ніяких нових методів або класів на цей раз не з'явилося, і засноване воно на попередньому масштабуванні.

В описі зразка коду в цій статті опущені ті ж частини, що і попередній зразок масштабування.

Цілі даного зразка програми

Обертаючи дві точки дотику, спрайт обертається. Також працює попередня операція масштабування.

図 2 :タッチポイントを回してスプライトを回転させています
Малюнок 2: Поворот спрайта поворотом точки дотику

Програма - оголошення полів

"Величина обертання спрайту" і "Останній кут повороту" додаються до попередньої програми масштабування. Всі кути обчислюються в радіанах.

/// <summary>
/// スプライトの回転量(radian)
/// </summary>
float rotate;

/// <summary>
/// 前回の回転角度(radian)
/// </summary>
float previousAngle;

Програма - процес ротації

Процес обертання виконується під час щипкових жестів так само, як і при масштабуванні.

Я не буду вдаватися в занадто детальну інформацію про обчислення обертання, тому що це математична історія, але ви можете отримати радіан кута за допомогою методу "Math.Atan2", знайшовши вектор різниці від точки дотику 1 до точки дотику 2. Знайдіть різницю між отриманим кутом і раніше придбаним кутом і додайте її до кута повороту спрайту.

switch (gs.GestureType)
{
  case GestureType.Pinch:
    //===== スケール計算 =====//
    // 前回と同じなので省略

    //===== 回転計算 =====//

    // 2点間のベクトルを求めます
    Vector2 pinchVector = gs.Position2 - gs.Position;

    // Atan2 で角度を求めます
    float nowAngle = (float)Math.Atan2(pinchVector.Y,
                                       pinchVector.X);

    if (previousAngle == 0)
    {
      // 前回の角度が 0 の場合は
      // 現在の角度を設定します
      // 初回は回転計算を行いません
      previousAngle = nowAngle;
    }
    else
    {
      // 前回の角度との差分をスプライトの回転角度に加算します
      rotate += nowAngle - previousAngle;

      // 今回の距離を次の計算のために保持します
      previousAngle = nowAngle;
    }
    break;
  case GestureType.PinchComplete:
    // ピンチが終了した場合は保持している距離、角度を 0 に戻して
    // 完了したことにします
    previousLength = 0;
    previousAngle = 0;
    break;
}

Програма - Малювання спрайтів

Серйозних змін в малюнку спрайтів немає. П'ятий аргумент методу SpriteBacth.Draw задається на розрахунковий кут повороту.

// スプライトの描画準備
spriteBatch.Begin();

// スプライトを描画する
spriteBatch.Draw(texture,
                 new Vector2(graphics.PreferredBackBufferWidth / 2,
                             graphics.PreferredBackBufferHeight / 2),
                 null,
                 Color.White,
                 rotate,
                 textureCenterPos,
                 scale,
                 SpriteEffects.None,
                 0.0f);

// スプライトの一括描画
spriteBatch.End();

Короткий зміст даного зразка

Цього разу я спробував обертати спрайт за допомогою операції щипка. Ми не використовуємо жодних нових класів зокрема, але я сподіваюся, що ви розумієте, що ми можемо реалізувати прикладну обробку на основі наданих функцій.

Нарешті

Ми переглянули зразки і продемонстрували реалізацію сенсорних взаємодій за допомогою Windows Phone 7 і XNA Game Studio 4.0. Вміст включав в себе придбання дотиків одним дотиком і мультидотиком, а також маніпулювання сенсорною інформацією, а також обробку за допомогою маніпулювання сенсорними жестами за допомогою специфічних для жестів методів.

На цей раз я зосередився на сенсорній панелі, але є ще деякі функції, які я ще не вводив. Windows Phone 7 також містить нові функції вводу в XNA Game Studio 4.0, такі як введення акселерометра та голосовий вхід. Є кілька цікавих функцій, які я не зміг представити цього разу, тому, будь ласка, насолоджуйтесь вивченням функцій, які ви хочете використовувати.