Touchinteraktioner i spelutveckling för Windows Phone 7 Part 4 Pinch

Sidan uppdaterad :
Datum för skapande av sida :

Programmering! - 4.Nypa, sträck för att skala sprites

Om det här exemplet

Moderna smartphones, som bildvisare, låter dig förstora och krympa en bild genom att använda två fingrar för att öka eller krympa avståndet mellan fingrarna. Du kan göra samma sak med Internet Explorer på Windows Phone 7. Den här åtgärden kallas "nypa, sträck" i Windows Phone 7.

Förutom att klämma och sträcka kan du också använda åtgärder som "tryck" för att kort röra (trycka) en punkt på skärmen och "bläddra" för att snabbt spåra skärmen. Dessa åtgärder kallas kollektivt gester.

I det här programmet skulle jag vilja förstora och minska sprite som visas på skärmen genom denna nypa och sträckning. Fram till förra gången fick jag också direkt informationen på pekskärmen och bearbetade den, men den här gången skulle jag vilja hantera beröringsoperationer med metoder som är dedikerade till gester.

Mål för detta exempelprogram

Nyp och sträck operationer för att förstora och krympa sprite.

図 1 :ストレッチでスプライトを拡大
Bild 1: Sträck för att förstora spriten

Program - Deklarera fält

Det finns ingen ny klass i fältdeklarationen, men den har "texturens mittkoordinat", "spritens förstoring" och "avståndet mellan de två sista beröringspositionerna vid klämning".

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

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

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

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

Program - Aktivera gester

Den här gången kommer vi att utföra en process endast för gester, men i standardläget kan ingen av gesterna användas. Om du vill hämta varje gestinformation måste du ange vilken gest som ska användas för egenskapen TouchPanel.EnabledGestures.

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

Om du aktiverar alla gester påverkas prestanda, så se till att du bara ställer in de gester som du vill använda. Här är "GestureType.Pinch" inställd för att få information om nypoperation och "GestureType.PinchComplete" är inställd för att indikera att nypprocessen är klar. Inställningsplatsen ställs in i spelkonstruktorn.

Program - Läsa in texturer

Att ladda texturer är detsamma som tidigare, men den här gången beräknar vi "texturens mittkoordinat". Detta beror på att när du skalar en sprite skalas den med mittkoordinaten som ursprung.

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

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

Program - Hämta gestinformation

Vi får gestinformation (nypa här) i Game.Update-metoden. Gestbehandling är i form av att upprepa så många gester som du har aktiverat. Strukturen "TouchCollection" som användes fram till förra gången används inte.

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

Kontrollera tillståndet för egenskapen TouchPanel.IsGestureAvailable i while-loopen för gestinformation och kontrollera om följande gestinformation finns: Om du har följande gestinformation använder du metoden "TouchPanel.ReadGesture" för att hämta gestinformationen.

"GestureSample.GestureType" lagrar information om vilken gesttyp som ingår, så förgrena processen med en switch-sats baserad på den. I det här exemplet anger konstruktorn uppräkningarna "GestureType.Pinch" och "GestureType.PinchComplete" till egenskapen "TouchPanel.EnabledGestures", så att de är förgrenade.

Program - Nyp gesthantering

Det går snabbare att titta på kommentarerna i koden för vad vi gör, men för att sammanfatta vad vi gör hittar vi skillnaden mellan avståndet mellan de två föregående beröringspunkterna och beröringspunktsavståndet mellan de två punkterna den här gången och använder den skillnaden för att öka eller minska skalvärdet.

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;

De två pekpositionerna kan erhållas med "GestureSample.Position" respektive "GestureSample.Position2". Du kan subtrahera skillnaden mellan de två erhållna vektorerna och hitta avståndet mellan de två punkterna genom att ringa metoden "Vector2.Length".

Förresten, här definierar vi det tidigare avståndet som 0 när klämning inte utförs, så processen är grenad när klämning startas och i den andra och efterföljande slingor. Detta beror på att första gången klämma fast, det finns inget tidigare avstånd, så det finns inget behov av att skala.

Den här gången använder vi bara två egenskaper, "GestureSample.Position" och "GestureSample.Position2", men det finns också "GestureSample.Delta" och "GestureSample.Delta2" -egenskaper, som kan få skillnadsinformation från föregående pekposition. Det finns två egenskaper vardera, men det här är för multi-touch, och för gester som bara använder en enda beröring använder du egenskaper utan "2".

Program - Hantera när nypgesten slutförs

När nypgesten är klar (släpper något av fingrarna från pekskärmen) sätts avståndet mellan de två föregående punkterna tillbaka till 0. Ursprungligen kan det vara bättre att använda en separat flagga, men eftersom det är fysiskt omöjligt att röra samma position med två fingrar definieras avståndet 0 som att inte klämma fast. (Om upplösningen är låg kan det vara möjligt att röra vid samma position ...)

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

Program - Rita Sprites

Jag ska inte gå in för mycket i detalj här eftersom det bara handlar om att rita sprite, men jag placerade sprite i mitten av skärmen och ritade det beräknade skalvärdet genom att förstora och krympa det med mitten av sprite som ursprung.

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

Sammanfattning av detta exempel

Den här gången förklarade vi processen tillägnad gester. I exemplet skapar vi bara en nypprocess, men det finns också "flicks" och "holds". Om du vill ta reda på vilka gester som är tillgängliga kan du läsa XNA Game Studio 4.0-hjälpen för GestureType-uppräkningar.

Du kan implementera samma sak från beröringsinformationen som erhållits från TouchPanel.GetState-metoden utan att använda gestspecifika metoder eller strukturer, men i så fall måste du beräkna hastigheten på multi-touch ID-hantering, beröringstid, flicks etc. själv. Genom att använda gestspecifika metoder kan dessa implementeringar förenklas, och det finns också fördelen att alla spel och applikationer kan drivas på samma sätt.

När du själv skapar en pekskärmsprocess, om du kan ersätta en liknande process som en gest, rekommenderar vi att du använder den här.

Programmering! - 5.Nyp för att rotera sprites

Om det här exemplet

Klämning hänvisar vanligtvis till "klämning" och "stretching", men XNA Game Studio 4.0: s nypprocess begränsar inte specifikt processen till dessa två, så du kan också utföra operationer som cirklar en beröringspunkt runt en annan beröringspunkt.

Här skulle jag vilja rotera sprite med den operationsmetoden. Förresten uppträdde inga nya metoder eller klasser den här gången, och den är baserad på föregående skalning.

I beskrivningen av exempelkoden i den här artikeln utelämnas samma delar som det föregående skalningsexemplet.

Mål för detta exempelprogram

Genom att rotera de två beröringspunkterna roterar spriten. Den tidigare skalningsåtgärden fungerar också.

図 2 :タッチポイントを回してスプライトを回転させています
Bild 2: Rotera spriten genom att vrida kontaktpunkten

Program - Deklarera fält

"Sprite rotationsmängd" och "Senaste rotationsvinkel" läggs till i föregående skalningsprogram. Alla vinklar beräknas i radianer.

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

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

Program - Rotationsprocess

Rotationsprocessen utförs under nypgester på samma sätt som vid skalning.

Jag ska inte gå in för mycket i detalj på att beräkna rotationen eftersom det är en matematisk berättelse, men du kan få vinkelradianen med "Math.Atan2" -metoden genom att hitta skillnadsvektorn från beröringspunkt 1 till beröringspunkt 2. Hitta skillnaden mellan den erhållna vinkeln och den tidigare förvärvade vinkeln och lägg till den i spritens rotationsvinkel.

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 - Rita Sprites

Det finns inga större förändringar i att rita sprites. Det femte argumentet i metoden SpriteBacth.Draw är inställt på den beräknade rotationsvinkeln.

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

Sammanfattning av detta exempel

Den här gången försökte jag rotera spriten genom nypoperation. Vi använder inga nya klasser i synnerhet, men jag hoppas att du förstår att vi kan förverkliga tillämpad bearbetning baserat på de funktioner som tillhandahålls.

Till sist

Vi gick igenom exempel och demonstrerade implementeringen av touchinteraktioner med Windows Phone 7 och XNA Game Studio 4.0. Innehållet inkluderade förvärv av enstaka beröringar och multitouch och manipulering av beröringsinformation och bearbetning genom beröringsgestmanipulation med gestspecifika metoder.

Den här gången har jag fokuserat på pekskärmen, men det finns fortfarande några funktioner som jag inte har introducerat ännu. Windows Phone 7 innehåller även nya inmatningsfunktioner i XNA Game Studio 4.0, till exempel accelerometerinmatning och röstinmatning. Det finns några intressanta funktioner som jag inte kunde presentera den här gången, så njut av att utforska de funktioner du vill använda.