Windows Phone 7 Bölüm 4 Pinch için oyun geliştirmede dokunmatik etkileşimler

Sayfa güncel :
Sayfa oluşturma tarihi :

Programlama! - 4. Sıkıştırma, sprite'ları ölçeklendirmek için germe

Bu örnek hakkında

Resim görüntüleyiciler gibi modern akıllı telefonlar, parmaklarınız arasındaki mesafeyi artırmak veya küçültmek için iki parmağınızı kullanarak bir görüntüyü büyütmenize ve küçültmenize olanak tanır. Aynı işlemi Windows Phone 7'deki Internet Explorer ile de yapabilirsiniz. Bu eyleme Windows Phone 7'de "çimdikleme, germe" adı verilir.

Sıkıştırma ve germeye ek olarak, ekrandaki bir noktaya kısaca dokunmak (dokunmak) için "dokunmak" ve ekranı hızlı bir şekilde izlemek için "hafifçe vurmak" gibi eylemleri de kullanabilirsiniz. Bu eylemler toplu olarak hareketler olarak adlandırılır.

Bu programda, bu sıkıştırma ve germe işlemi ile ekranda görüntülenen hareketli grafiği büyütmek ve azaltmak istiyorum. Ayrıca, geçen sefere kadar, dokunmatik panelin bilgilerini doğrudan aldım ve işledim, ancak bu sefer hareketlere adanmış yöntemleri kullanarak dokunma işlemlerini ele almak istiyorum.

Bu örnek programın hedefleri

Hareketli grafiği büyütmek ve küçültmek için işlemleri kıstırın ve gerin.

図 1 :ストレッチでスプライトを拡大
Resim 1: Hareketli grafiği büyütmek için germe

Program - Alanların Bildirilmesi

Alan bildiriminde yeni bir sınıf yoktur, ancak "dokunun merkez koordinatı", "hareketli grafiğin büyütülmesi" ve "sıkıştırma sırasında son iki dokunma konumu arasındaki mesafe" vardır.

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

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

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

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

Program - Hareketleri Etkinleştirme

Bu kez, yalnızca hareket eden bir işlem gerçekleştireceğiz, ancak varsayılan durumda, hareketlerin hiçbiri kullanılamaz. Her hareket bilgisini almak için, TouchPanel.EnabledGestures özelliği için kullanılacak hareketi ayarlamanız gerekir.

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

Tüm hareketleri etkinleştirmek performansı etkiler, bu nedenle yalnızca kullanmak istediğiniz hareketleri ayarladığınızdan emin olun. Burada, "GestureType.Pinch" sıkıştırma işlemi bilgilerini almak için ayarlanır ve "GestureType.PinchComplete" sıkıştırma işleminin tamamlandığını belirtmek için ayarlanır. Ayar konumu Oyun oluşturucuda ayarlanır.

Program - Dokuları yükleme

Dokuların yüklenmesi eskisi gibi aynıdır, ancak bu sefer "dokunun merkez koordinatını" hesaplıyoruz. Bunun nedeni, bir hareketli grafiği ölçeklendirirken, kaynak olarak merkez koordinatıyla ölçeklendirilmesidir.

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

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

Program - Hareket bilgilerini alın

Game.Update yönteminde hareket bilgileri alıyoruz (buraya sıkıştırın). Hareket işleme, etkinleştirdiğiniz kadar çok hareketi tekrarlama şeklindedir. Son zamana kadar kullanılan "TouchCollection" yapısı kullanılmaz.

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

Hareket bilgileri için while döngüsündeki TouchPanel.IsGestureAvailable özelliğinin durumunu kontrol edin ve aşağıdaki hareket bilgilerinin mevcut olup olmadığını kontrol edin: Aşağıdaki hareket bilgilerine sahipseniz, hareket bilgilerini almak için "TouchPanel.ReadGesture" yöntemini kullanın.

"GestureSample.GestureType", hangi hareket türünün dahil edildiğine ilişkin bilgileri depolar, bu nedenle işlemi buna dayalı bir anahtar deyimiyle dallandırın. Bu örnekte, oluşturucu "GestureType.Pinch" ve "GestureType.PinchComplete" enumlarını "TouchPanel.EnabledGestures" özelliğine ayarlar, böylece sırasıyla dallanırlar.

Program - Sıkıştırma hareketi işleme

Yaptığımız şey için koddaki yorumlara bakmak daha hızlıdır, ancak ne yaptığımızı özetlemek için, önceki iki temas noktası arasındaki mesafe ile iki nokta arasındaki temas noktası mesafesi arasındaki farkı bu sefer buluruz ve bu farkı ölçek değerini artırmak veya azaltmak için kullanırız.

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;

İki dokunma konumu sırasıyla "GestureSample.Position" ve "GestureSample.Position2" ile elde edilebilir. Elde edilen iki vektör arasındaki farkı çıkarabilir ve "Vector2.Length" yöntemini çağırarak iki nokta arasındaki mesafeyi bulabilirsiniz.

Bu arada, burada kıstırma işlemi yapılmadığında önceki mesafeyi 0 olarak tanımlıyoruz, bu nedenle sıkıştırma işlemi başlatıldığında ve ikinci ve sonraki döngülerde işlem dallanıyor. Bunun nedeni, ilk sıkma zamanında, önceki mesafenin olmamasıdır, bu nedenle ölçeklendirmeye gerek yoktur.

Ayrıca, bu sefer yalnızca iki özellik kullanıyoruz, "GestureSample.Position" ve "GestureSample.Position2", ancak önceki dokunma konumundan fark bilgilerini alabilen "GestureSample.Delta" ve "GestureSample.Delta2" özellikleri de var. Her biri iki özellik vardır, ancak bu çoklu dokunma içindir ve yalnızca tek dokunuş kullanan hareketler için özellikleri "2" olmadan kullanacaksınız.

Program - Sıkıştırma hareketi tamamlandığında kullanım

Sıkıştırma hareketi tamamlandığında (dokunmatik panelden her iki parmağınızı da serbest bırakarak), önceki iki nokta arasındaki mesafe tekrar 0'a ayarlanır. Başlangıçta, ayrı bir bayrak kullanmak daha iyi olabilir, ancak aynı pozisyona iki parmakla dokunmak fiziksel olarak imkansız olduğundan, 0 mesafesi sıkıştırmama olarak tanımlanır. (Çözünürlük düşükse, aynı konuma dokunmak mümkün olabilir ...)

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

Program - Sprite Çizimi

Burada çok fazla ayrıntıya girmeyeceğim çünkü bu sadece hareketli grafiği çizmekle ilgili, ancak hareketli grafiği ekranın ortasına yerleştirdim ve hesaplanan ölçek değerini, orijin sprite merkezi ile büyüterek ve küçülterek çizdim.

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

Bu örneğin özeti

Bu kez, jestlere adanmış süreci açıkladık. Örnekte, yalnızca bir çimdik işlemi oluşturuyoruz, ancak "hareketler" ve "tutmalar" da var. Hangi hareketlerin kullanılabildiğini öğrenmek için GestureType enum'lar için XNA Game Studio 4.0 Yardımı'na göz atın.

Aynı şeyi, harekete özgü yöntemler veya yapılar kullanmadan TouchPanel.GetState yönteminden elde edilen dokunma bilgilerinden de uygulayabilirsiniz, ancak bu durumda, çoklu dokunmatik kimlik yönetiminin, dokunma süresinin, hareketlerin vb. Hızını kendiniz hesaplamanız gerekecektir. Harekete özel yöntemler kullanılarak bu uygulamalar basitleştirilebileceği gibi, tüm oyunların ve uygulamaların aynı şekilde çalıştırılabilmesi avantajı da vardır.

Kendiniz bir dokunmatik panel işlemi oluşturduğunuzda, benzer bir işlemi bir jest olarak değiştirebiliyorsanız, bunu kullanmanızı öneririz.

Programlama! - 5.Sprite'ları döndürmek için çimdikleyin

Bu örnek hakkında

Sıkıştırma genellikle "sıkıştırma" ve "germe" anlamına gelir, ancak XNA Game Studio 4.0'ın sıkıştırma işlemi işlemi özellikle bu ikisiyle sınırlamaz, bu nedenle bir temas noktasını başka bir temas noktasının etrafında daire içine alan işlemleri de gerçekleştirebilirsiniz.

Burada, sprite'ı bu işlem yöntemiyle döndürmek istiyorum. Bu arada, bu sefer yeni bir yöntem veya sınıf ortaya çıkmadı ve önceki ölçeklendirmeye dayanıyor.

Bu makaledeki örnek kodun açıklamasında, önceki ölçeklendirme örneğiyle aynı bölümler atlanmıştır.

Bu örnek programın hedefleri

İki temas noktasını döndürerek hareketli grafik döndürülür. Önceki ölçeklendirme işlemi de çalışır.

図 2 :タッチポイントを回してスプライトを回転させています
Resim 2: Temas noktasını çevirerek hareketli grafiği döndürme

Program - Alanların Bildirilmesi

"Hareketli grafik döndürme miktarı" ve "Son dönme açısı" önceki ölçeklendirme programına eklenir. Tüm açılar radyan cinsinden hesaplanır.

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

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

Program - Rotasyon Süreci

Döndürme işlemi, sıkıştırma hareketleri sırasında ölçekleme sırasında olduğu gibi gerçekleştirilir.

Rotasyonun hesaplanması konusunda çok fazla ayrıntıya girmeyeceğim çünkü bu bir matematik hikayesi, ancak temas noktası 1'den temas noktası 2'ye fark vektörünü bularak "Math.Atan2" yöntemiyle açı radyanını elde edebilirsiniz. Elde edilen açı ile daha önce elde edilen açı arasındaki farkı bulun ve hareketli grafiğin dönme açısına ekleyin.

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 - Sprite Çizimi

Sprite çiziminde önemli bir değişiklik yoktur. SpriteBacth.Draw yönteminin beşinci bağımsız değişkeni hesaplanan dönme açısına ayarlanır.

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

Bu örneğin özeti

Bu sefer sprite'ı çimdikleme işlemiyle döndürmeye çalıştım. Özellikle yeni sınıflar kullanmıyoruz, ancak umarım sağlanan işlevlere dayanarak uygulamalı işlemeyi gerçekleştirebileceğimizi anlarsınız.

Sonunda

Örnekleri inceledik ve Windows Phone 7 ve XNA Game Studio 4.0'ı kullanarak dokunmatik etkileşimlerin uygulanmasını gösterdik. İçerik, tek dokunuşlu ve çoklu dokunuşlu dokunma alımını ve dokunma bilgilerinin manipülasyonunu ve harekete özgü yöntemler kullanılarak dokunma hareketi manipülasyonu ile işlemeyi içeriyordu.

Bu sefer dokunmatik panele odaklandım ancak henüz tanıtmadığım bazı fonksiyonlar var. Windows Phone 7 ayrıca XNA Game Studio 4.0'da ivmeölçer girişi ve ses girişi gibi yeni giriş özellikleri içerir. Bu sefer tanıtamadığım bazı ilginç özellikler var, bu yüzden lütfen kullanmak istediğiniz işlevleri keşfetmenin tadını çıkarın.