Aanraakinteracties in game-ontwikkeling voor Windows Phone 7 Part 4 Pinch

Pagina bijgewerkt :
Aanmaakdatum van pagina :

Programmeren! - 4.Pinch, stretch op schaal sprites

Over dit voorbeeld

Met moderne smartphones, zoals beeldviewers, kunt u een afbeelding vergroten en verkleinen door twee vingers te gebruiken om de afstand tussen uw vingers te vergroten of te verkleinen. U kunt hetzelfde doen met Internet Explorer op Windows Phone 7. Deze actie wordt 'knijpen, uitrekken' genoemd in Windows Phone 7.

Naast knijpen en uitrekken, kunt u ook acties zoals "tikken" gebruiken om kort een punt op het scherm aan te raken (erop te tikken) en "vegen" om het scherm snel te traceren. Deze acties worden gezamenlijk gebaren genoemd.

In dit programma wil ik de sprite die op het scherm wordt weergegeven vergroten en verkleinen door deze knijp- en rekbewerking. Tot de vorige keer heb ik ook direct de informatie van het aanraakpaneel verkregen en verwerkt, maar deze keer wil ik aanraakbewerkingen uitvoeren met behulp van methoden die zijn gewijd aan gebaren.

Doelen van dit voorbeeldprogramma

Knijp- en rekbewerkingen uit om de sprite te vergroten en te verkleinen.

図 1 :ストレッチでスプライトを拡大
Figuur 1: Uitrekken om de sprite te vergroten

Programma - Velden declareren

Er is geen nieuwe klasse in de velddeclaratie, maar het heeft "de middelste coördinaat van de textuur", "de vergroting van de sprite" en "de afstand tussen de laatste twee aanraakposities bij het knijpen".

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

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

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

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

Programma - Gebaren inschakelen

Deze keer voeren we een proces met alleen gebaren uit, maar in de standaardstatus kan geen van de gebaren worden gebruikt. Als u elke gebaarinformatie wilt ophalen, moet u de beweging instellen die moet worden gebruikt voor de eigenschap TouchPanel.EnabledGestures.

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

Het inschakelen van alle bewegingen heeft invloed op de prestaties, dus zorg ervoor dat u alleen de bewegingen instelt die u wilt gebruiken. Hier is "GestureType.Pinch" ingesteld om informatie over knijpbewerkingen te verkrijgen en "GestureType.PinchComplete" om aan te geven dat het knijpproces is voltooid. De instellingslocatie wordt ingesteld in de gameconstructor.

Programma - Texturen laden

Het laden van texturen is hetzelfde als voorheen, maar deze keer berekenen we de "middencoördinaat van de textuur". Dit komt omdat bij het schalen van een sprite deze schaalt met de middelste coördinaat als oorsprong.

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

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

Programma - Informatie over gebaren ophalen

We krijgen gebareninformatie (knijp hier) in de Game.Update-methode. Gebarenverwerking is in de vorm van het herhalen van zoveel gebaren als u hebt ingeschakeld. De "TouchCollection"-structuur die tot de vorige keer werd gebruikt, wordt niet gebruikt.

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

Controleer de status van de eigenschap TouchPanel.IsGestureAvailable in de lus while voor gebareninformatie en controleer of de volgende gebareninformatie aanwezig is: Als u de volgende gebareninformatie hebt, gebruikt u de methode "TouchPanel.ReadGesture" om de gebareninformatie op te halen.

"GestureSample.GestureType" slaat informatie op over welk gebarentype is opgenomen, dus vertak het proces met een switch-instructie op basis daarvan. In dit voorbeeld stelt de constructor de opsommingen 'GestureType.Pinch' en 'GestureType.PinchComplete' in op de eigenschap 'TouchPanel.EnabledGestures', zodat ze respectievelijk vertakt zijn.

Programma - Pinch gesture handling

Het is sneller om naar de opmerkingen in de code te kijken voor wat we doen, maar om samen te vatten wat we doen, vinden we het verschil tussen de afstand tussen de vorige twee aanraakpunten en de aanraakpuntafstand tussen de twee punten deze keer, en gebruiken we dat verschil om de schaalwaarde te verhogen of te verlagen.

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 twee aanraakposities kunnen worden verkregen met respectievelijk "GestureSample.Position" en "GestureSample.Position2". U kunt het verschil tussen de twee verkregen vectoren aftrekken en de afstand tussen de twee punten vinden door de methode "Vector2.Length" aan te roepen.

Trouwens, hier definiëren we de vorige afstand als 0 wanneer knijpen niet wordt uitgevoerd, dus het proces wordt vertakt wanneer het knijpen wordt gestart en in de tweede en volgende lussen. Dit komt omdat de eerste keer knijpen, er geen eerdere afstand is, dus het is niet nodig om te schalen.

Deze keer gebruiken we ook slechts twee eigenschappen, "GestureSample.Position" en "GestureSample.Position2", maar er zijn ook "GestureSample.Delta" en "GestureSample.Delta2" eigenschappen, die de verschilinformatie van de vorige aanraakpositie kunnen krijgen. Er zijn elk twee eigenschappen, maar dit is voor multi-touch, en voor gebaren die alleen single touch gebruiken, gebruikt u eigenschappen zonder een "2".

Programma - Bediening wanneer knijpbeweging voltooid is

Wanneer het knijpgebaar is voltooid (waarbij een van beide vingers van het aanraakscherm wordt losgelaten), wordt de afstand tussen de vorige twee punten teruggezet naar 0. Oorspronkelijk is het misschien beter om een aparte vlag te gebruiken, maar omdat het fysiek onmogelijk is om dezelfde positie met twee vingers aan te raken, wordt de afstand van 0 gedefinieerd als niet knijpen. (Als de resolutie laag is, is het mogelijk om dezelfde positie aan te raken ...)

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

Programma - Sprites tekenen

Ik zal hier niet te veel in detail treden omdat het alleen gaat om het tekenen van de sprite, maar ik plaatste de sprite in het midden van het scherm en tekende de berekende schaalwaarde door deze te vergroten en te verkleinen met het midden van de sprite als de oorsprong.

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

Samenvatting van deze steekproef

Deze keer hebben we het proces uitgelegd dat gewijd is aan gebaren. In het monster creëren we alleen een knijpproces, maar er zijn ook "flicks" en "holds". Als u wilt weten welke gebaren beschikbaar zijn, raadpleegt u de XNA Game Studio 4.0 Help voor GestureType-opsommingen.

U kunt hetzelfde implementeren uit de aanraakinformatie die is verkregen van de TouchPanel.GetState-methode zonder gebarenspecifieke methoden of structuren te gebruiken, maar in dat geval moet u de snelheid van multi-touch ID-beheer, aanraaktijd, flicks, enz. Zelf berekenen. Door gebruik te maken van gebarenspecifieke methoden kunnen deze implementaties worden vereenvoudigd en is er ook het voordeel dat alle games en applicaties op dezelfde manier kunnen worden bediend.

Wanneer u zelf een aanraakpaneelproces maakt en u een soortgelijk proces kunt vervangen door een gebaar, raden we u aan dit te gebruiken.

Programmeren! - 5.Pinch om sprites te draaien

Over dit voorbeeld

Knijpen verwijst meestal naar "knijpen" en "uitrekken", maar het knijpproces van XNA Game Studio 4.0 beperkt het proces niet specifiek tot die twee, dus u kunt ook bewerkingen uitvoeren die het ene aanraakpunt rond een ander aanraakpunt cirkelen.

Hier wil ik de sprite draaien met die werkwijze. Overigens zijn er deze keer geen nieuwe methoden of klassen verschenen en is deze gebaseerd op de vorige schaling.

In de beschrijving van de voorbeeldcode in dit artikel worden dezelfde onderdelen als het vorige schaalvoorbeeld weggelaten.

Doelen van dit voorbeeldprogramma

Door de twee touchpoints te roteren, roteert de sprite. De vorige schaalbewerking werkt ook.

図 2 :タッチポイントを回してスプライトを回転させています
Figuur 2: De sprite draaien door het touchpoint te draaien

Programma - Velden declareren

"Sprite rotatiehoeveelheid" en "Laatste rotatiehoek" worden toegevoegd aan het vorige schaalprogramma. Alle hoeken worden berekend in radialen.

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

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

Programma - Rotatieproces

Het rotatieproces wordt tijdens knijpbewegingen op dezelfde manier uitgevoerd als bij het schalen.

Ik zal niet te veel in detail treden over het berekenen van de rotatie omdat het een wiskundig verhaal is, maar je kunt de hoekradiaan krijgen met de "Math.Atan2" -methode door de verschilvector van touchpoint 1 naar touchpoint 2 te vinden. Zoek het verschil tussen de verkregen hoek en de eerder verworven hoek en voeg deze toe aan de rotatiehoek van de sprite.

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

Programma - Sprites tekenen

Er zijn geen grote wijzigingen in het tekenen van sprites. Het vijfde argument van de methode SpriteBacth.Draw wordt ingesteld op de berekende rotatiehoek.

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

Samenvatting van deze steekproef

Deze keer probeerde ik de sprite te draaien door een knijpbewerking. We gebruiken geen nieuwe klassen in het bijzonder, maar ik hoop dat u begrijpt dat we toegepaste verwerking kunnen realiseren op basis van de geleverde functies.

Eindelijk

We hebben voorbeelden doorgenomen en de implementatie van aanraakinteracties gedemonstreerd met Windows Phone 7 en XNA Game Studio 4.0. De inhoud omvatte single-touch en multi-touch touch acquisitie en manipulatie van touch informatie, en verwerking door touch gesture manipulatie met behulp van gebaren-specifieke methoden.

Deze keer heb ik me gericht op het aanraakscherm, maar er zijn nog steeds enkele functies die ik nog niet heb geïntroduceerd. Windows Phone 7 bevat ook nieuwe invoerfuncties in XNA Game Studio 4.0, zoals versnellingsmeteringang en spraakinvoer. Er zijn een aantal interessante functies die ik deze keer niet kon introduceren, dus geniet van het verkennen van de functies die u wilt gebruiken.