Interakcje dotykowe w tworzeniu gier dla systemu Windows Phone 7, część 4 Szczypanie

Strona zaktualizowana :
Data utworzenia strony :

Programowanie! - 4.Uszczypnij, rozciągnij do skali duszków

Informacje o tej próbce

Nowoczesne smartfony, takie jak przeglądarki obrazów, umożliwiają powiększanie i zmniejszanie obrazu za pomocą dwóch palców w celu zwiększenia lub zmniejszenia odległości między palcami. To samo można zrobić z programem Internet Explorer w systemie Windows Phone 7. Ta czynność nosi nazwę "szczypanie, rozciąganie" w systemie Windows Phone 7.

Oprócz szczypania i rozciągania można również użyć takich działań, jak "stuknięcie", aby krótko dotknąć (stuknąć) jeden punkt na ekranie i "przesunąć", aby szybko prześledzić ekran. Działania te są zbiorczo określane jako gesty.

W tym programie chciałbym powiększyć i zmniejszyć duszka wyświetlanego na ekranie przez tę operację szczypania i rozciągania. Również do ostatniego razu bezpośrednio pozyskiwałem informacje z panelu dotykowego i przetwarzałem je, ale tym razem chciałbym obsługiwać operacje dotykowe za pomocą metod dedykowanych gestom.

Cele tego przykładowego programu

Operacje ściskania i rozciągania, aby powiększyć i zmniejszyć sprite'a.

図 1 :ストレッチでスプライトを拡大
Rysunek 1: Rozciągnij, aby powiększyć duszka

Program - Deklarowanie pól

W deklaracji pola nie ma nowej klasy, ale ma ona "środkową współrzędną tekstury", "powiększenie sprite'a" i "odległość między dwiema ostatnimi pozycjami dotyku podczas szczypania".

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

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

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

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

Program - Włączanie gestów

Tym razem wykonamy proces tylko gestów, ale w stanie domyślnym nie można użyć żadnego z gestów. Aby pobrać informacje o każdym geście, należy ustawić gest, który ma być używany dla właściwości TouchPanel.EnabledGestures.

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

Włączenie wszystkich gestów wpływa na wydajność, dlatego upewnij się, że ustawiasz tylko te gesty, których chcesz używać. W tym przypadku "GestureType.Pinch" jest ustawiony na uzyskiwanie informacji o operacji szczypania, a "GestureType.PinchComplete" jest ustawiony na wskazanie, że proces szczypania został zakończony. Lokalizacja ustawień jest ustawiana w konstruktorze Game.

Program - Ładowanie tekstur

Ładowanie tekstur jest takie samo jak poprzednio, ale tym razem obliczamy "współrzędną środkową tekstury". Dzieje się tak dlatego, że podczas skalowania duszka skaluje się ze współrzędną środkową jako początkiem.

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

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

Program - Pobierz informacje o gestach

Informacje o gestach (uszczypnij tutaj) otrzymujemy w metodzie Game.Update. Przetwarzanie gestów polega na powtarzaniu tylu gestów, ile zostało włączonych. Struktura "TouchCollection", która była używana do ostatniego razu, nie jest używana.

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

Sprawdź stan właściwości TouchPanel.IsGestureAvailable w pętli while, aby uzyskać informacje o gestach, i sprawdź, czy są obecne następujące informacje o gestach: Jeśli masz następujące informacje o gestach, użyj metody "TouchPanel.ReadGesture", aby uzyskać informacje o gestach.

"GestureSample.GestureType" przechowuje informacje o tym, który typ gestu jest uwzględniony, więc rozgałęzij proces za pomocą instrukcji switch na jej podstawie. W tym przykładzie konstruktor ustawia wyliczenia "GestureType.Pinch" i "GestureType.PinchComplete" na właściwość "TouchPanel.EnabledGestures", dzięki czemu są one odpowiednio rozgałęzione.

Program - Obsługa gestów szczypania

Szybciej jest spojrzeć na komentarze w kodzie do tego, co robimy, ale podsumowując to, co robimy, tym razem znajdujemy różnicę między odległością między dwoma poprzednimi punktami kontaktu a odległością punktu kontaktu między dwoma punktami i wykorzystujemy tę różnicę, aby zwiększyć lub zmniejszyć wartość skali.

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;

Dwie pozycje dotykowe można uzyskać odpowiednio za pomocą "GestureSample.Position" i "GestureSample.Position2". Możesz odjąć różnicę między dwoma otrzymanymi wektorami i znaleźć odległość między dwoma punktami, wywołując metodę "Vector2.Length".

Nawiasem mówiąc, tutaj definiujemy poprzednią odległość jako 0, gdy szczypanie nie jest wykonywane, więc proces jest rozgałęziony po rozpoczęciu szczypania oraz w drugiej i kolejnych pętlach. Dzieje się tak dlatego, że przy pierwszym uszczypnięciu nie ma wcześniejszej odległości, więc nie ma potrzeby skalowania.

Tym razem używamy tylko dwóch właściwości, "GestureSample.Position" i "GestureSample.Position2", ale są też właściwości "GestureSample.Delta" i "GestureSample.Delta2", które mogą uzyskać informacje o różnicy z poprzedniej pozycji dotykowej. Każda z nich ma dwie właściwości, ale dotyczy to wielodotyku, a w przypadku gestów, które używają tylko jednego dotknięcia, użyjesz właściwości bez "2".

Program - Obsługa po zakończeniu gestu szczypania

Po zakończeniu gestu uszczypnięcia (odsunięcie palca od panelu dotykowego) odległość między dwoma poprzednimi punktami zostanie ustawiona z powrotem na 0. Pierwotnie może być lepiej użyć oddzielnej flagi, ale ponieważ fizycznie niemożliwe jest dotknięcie tej samej pozycji dwoma palcami, odległość 0 jest definiowana jako brak szczypania. (Jeśli rozdzielczość jest niska, może być możliwe dotknięcie tej samej pozycji ...)

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

Program - Rysowanie sprite'ów

Nie będę tutaj wchodził w szczegóły, ponieważ chodzi tylko o narysowanie duszka, ale umieściłem duszka na środku ekranu i narysowałem obliczoną wartość skali, powiększając i zmniejszając ją ze środkiem duszka jako początkiem.

// スプライトの描画準備
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();

Podsumowanie tej próbki

Tym razem wyjaśniliśmy proces poświęcony gestom. W próbce tworzymy tylko proces szczypania, ale są też "ruchy" i "blokady". Aby dowiedzieć się, jakie gesty są dostępne, zapoznaj się z Pomocą programu XNA Game Studio 4.0 dotyczącą wyliczeń GestureType.

Możesz zaimplementować to samo z informacji dotykowych uzyskanych z metody TouchPanel.GetState bez użycia metod lub struktur specyficznych dla gestów, ale w takim przypadku musisz samodzielnie obliczyć szybkość zarządzania multi-touch ID, czas dotyku, szybkie ruchy itp. Korzystając z metod specyficznych dla gestów, implementacje te można uprościć, a zaletą jest to, że wszystkie gry i aplikacje mogą być obsługiwane w ten sam sposób.

Jeśli podczas samodzielnego tworzenia procesu panelu dotykowego można zastąpić podobny proces gestem, zalecamy użycie tego procesu.

Programowanie! - 5.Uszczypnij, aby obrócić sprite'y

Informacje o tej próbce

Szczypanie zwykle odnosi się do "szczypania" i "rozciągania", ale proces szczypania XNA Game Studio 4.0 nie ogranicza procesu do tych dwóch, więc możesz również wykonywać operacje, które okrążają jeden punkt kontaktu wokół innego punktu kontaktu.

Tutaj chciałbym obrócić duszka za pomocą tej metody działania. Nawiasem mówiąc, tym razem nie pojawiły się żadne nowe metody ani klasy i opiera się na poprzednim skalowaniu.

W opisie przykładowego kodu w tym artykule pominięto te same części, co poprzedni przykład skalowania.

Cele tego przykładowego programu

Obracając dwa punkty dotyku, duszek obraca się. Poprzednia operacja skalowania również działa.

図 2 :タッチポイントを回してスプライトを回転させています
Rysunek 2: Obracanie duszka poprzez obracanie punktu dotyku

Program - Deklarowanie pól

"Sprite rotation amount" i "Last rotation angle" są dodawane do poprzedniego programu skalowania. Wszystkie kąty są obliczane w radianach.

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

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

Program - Proces rotacji

Proces obrotu odbywa się podczas gestów szczypania w taki sam sposób, jak podczas skalowania.

Nie będę wchodził w szczegóły dotyczące obliczania obrotu, ponieważ jest to historia matematyczna, ale możesz uzyskać radian kąta za pomocą metody "Math.Atan2", znajdując wektor różnicy od punktu kontaktu 1 do punktu kontaktu 2. Znajdź różnicę między uzyskanym kątem a wcześniej uzyskanym kątem i dodaj go do kąta obrotu duszka.

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;
}

Program - Rysowanie sprite'ów

Nie ma większych zmian w rysowaniu duszków. Piąty argument metody SpriteBacth.Draw jest ustawiony na obliczony kąt obrotu.

// スプライトの描画準備
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();

Podsumowanie tej próbki

Tym razem próbowałem obrócić duszka przez operację szczypania. Nie używamy żadnych nowych klas w szczególności, ale mam nadzieję, że rozumiesz, że możemy realizować stosowane przetwarzanie w oparciu o dostarczone funkcje.

W końcu

Przeszliśmy przez przykłady i zademonstrowaliśmy implementację interakcji dotykowych przy użyciu Windows Phone 7 i XNA Game Studio 4.0. Treści obejmowały akwizycję dotyku i manipulację dotykiem za pomocą pojedynczych i wielodotykowych informacji dotykowych oraz przetwarzanie za pomocą gestów dotykowych przy użyciu metod specyficznych dla gestów.

Tym razem skupiłem się na panelu dotykowym, ale są jeszcze pewne funkcje, których jeszcze nie wprowadziłem. System Windows Phone 7 zawiera również nowe funkcje wprowadzania danych w XNA Game Studio 4.0, takie jak wejście akcelerometru i wprowadzanie głosowe. Jest kilka interesujących funkcji, których nie mogłem tym razem przedstawić, więc ciesz się odkrywaniem funkcji, których chcesz użyć.