Interações de toque no desenvolvimento de jogos para Windows Phone 7 Parte 4 Pinch

Página atualizada :
Data de criação de página :

Programação! - 4.Pinça, estique para escalar sprites

Sobre esta amostra

Smartphones modernos, como os espectadores de imagem, permitem que você amplie e reduza uma imagem usando dois dedos para aumentar ou diminuir a distância entre os dedos. Você pode fazer o mesmo com o Internet Explorer no Windows Phone 7. Esta ação é chamada de "beliscar, esticar" no Windows Phone 7.

Além de beliscar e alongar, você também pode usar ações como "tocar" para tocar brevemente (toque) um ponto na tela e "flick" para rastrear rapidamente a tela. Essas ações são coletivamente referidas como gestos.

Neste programa, gostaria de ampliar e reduzir o sprite exibido na tela por esta operação de pinça e estiramento. Além disso, até a última vez, eu obtive diretamente as informações do painel de toque e processei-o, mas desta vez eu gostaria de lidar com operações de toque usando métodos dedicados a gestos.

Metas deste programa amostral

Aperte e estique as operações para ampliar e encolher o sprite.

図 1 :ストレッチでスプライトを拡大
Figura 1: Alongamento para ampliar o sprite

Programa - Campos Declarando

Não há nova classe na declaração de campo, mas tem "a coordenada central da textura", "a ampliação do sprite" e "a distância entre as duas últimas posições de toque ao beliscar".

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

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

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

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

Programa - Habilitação de Gestos

Desta vez, realizaremos um processo somente por gestos, mas no estado padrão, nenhum dos gestos pode ser usado. Para recuperar cada informação de gesto, você deve definir o gesto a ser usado para a propriedade TouchPanel.EnabledGestures.

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

Ativar todos os gestos afeta o desempenho, por isso certifique-se de definir apenas os gestos que deseja usar. Aqui, "GestureType.Pinch" está definido para obter informações de operação de pinch e "GestureType.PinchComplete" está definido para indicar que o processo de pinch está completo. O local de configuração está definido no construtor do jogo.

Programa - Texturas de carregamento

Carregar texturas é o mesmo de antes, mas desta vez estamos calculando a "coordenada central da textura". Isso porque ao escalar um sprite, ele escala com a coordenada central como a origem.

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

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

Programa - Obter informações sobre gestos

Temos informações de gestos (beliscar aqui) no método Game.Update. O processamento de gestos é na forma de repetir tantos gestos quanto você habilitou. A estrutura "TouchCollection" que foi usada até a última vez não é utilizada.

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

Verifique o estado da propriedade TouchPanel.IsGesture Disponível no loop while para obter informações sobre gestos e verifique se as seguintes informações de gestos estão presentes: Se você tiver as seguintes informações de gestos, use o método "TouchPanel.ReadGesture" para obter as informações do gesto.

"GestureSample.GestureType" armazena informações sobre qual tipo de gesto está incluído, então dobre o processo com uma instrução de switch com base nele. Nesta amostra, o construtor define os enumes "GestureType.Pinch" e "GestureType.PinchComplete" para a propriedade "TouchPanel.EnabledGestures", para que sejam ramificadas, respectivamente.

Programa - Manipulação de gestos de pinça

É mais rápido olhar para os comentários no código para o que estamos fazendo, mas para resumir o que estamos fazendo, encontramos a diferença entre a distância entre os dois pontos de toque anteriores e a distância do ponto de contato entre os dois pontos desta vez, e usamos essa diferença para aumentar ou diminuir o valor da escala.

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;

As duas posições de toque podem ser obtidas com "GestureSample.Position" e "GestureSample.Position2", respectivamente. Você pode subtrair a diferença entre os dois vetores obtidos e encontrar a distância entre os dois pontos chamando o método "Vector2.Length".

A propósito, aqui definimos a distância anterior como 0 quando o beliscão não é realizado, de modo que o processo é ramificado quando a beliscão é iniciada e no segundo e subsequente loops. Isso porque na primeira vez de beliscar, não há distância prévia, então não há necessidade de escalar.

Além disso, desta vez usamos apenas duas propriedades, "GestureSample.Position" e "GestureSample.Position2", mas também existem propriedades "GestureSample.Delta" e "GestureSample.Delta2", que podem obter as informações de diferença da posição de toque anterior. Existem duas propriedades cada, mas esta é para multi-toque, e para gestos que usam apenas um toque único, você usará propriedades sem um "2".

Programa - Manuseio quando o gesto de beliscar é concluído

Quando o gesto de beliscão estiver completo (liberando qualquer dedo do painel de toque), a distância entre os dois pontos anteriores é fixada para 0. Originalmente, pode ser melhor usar uma bandeira separada, mas como é fisicamente impossível tocar na mesma posição com dois dedos, a distância de 0 é definida como não beliscar. (Se a resolução for baixa, pode ser possível tocar na mesma posição...)

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

Programa - Desenho de Sprites

Eu não vou entrar em muitos detalhes aqui porque é apenas sobre desenhar o sprite, mas eu coloquei o sprite no centro da tela e atraiu o valor de escala calculado ampliando e encolhendo-o com o centro do sprite como a origem.

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

Resumo desta amostra

Desta vez, explicamos o processo dedicado aos gestos. Na amostra, só criamos um processo de beliscão, mas também há "filmes" e "holds". Para descobrir quais gestos estão disponíveis, confira os enums do XNA Game Studio 4.0 Help for GestureType.

Você pode implementar a mesma coisa a partir das informações de toque obtidas do método TouchPanel.GetState sem usar métodos ou estruturas específicas de gestos, mas nesse caso, você precisará calcular a velocidade do gerenciamento de ID multi-toque, tempo de toque, movimentos, etc. você mesmo. Usando métodos específicos de gestos, essas implementações podem ser simplificadas, e há também a vantagem de que todos os jogos e aplicativos possam ser operados da mesma forma.

Quando você cria um processo de painel de toque você mesmo, se você pode substituir um processo semelhante como um gesto, recomendamos que você use isso.

Programação! - 5.Pinça para rodar sprites

Sobre esta amostra

Beliscar geralmente se refere a "beliscar" e "alongamento", mas o processo de pinça do XNA Game Studio 4.0 não limita especificamente o processo a esses dois, então você também pode executar operações que circundam um ponto de toque em torno de outro ponto de contato.

Aqui, eu gostaria de girar o sprite com esse método de operação. A propósito, não apareceram novos métodos ou classes desta vez, e é baseado no dimensionamento anterior.

Na descrição do código amostral neste artigo, as mesmas partes da amostra de escala anterior são omitidas.

Metas deste programa amostral

Ao girar os dois pontos de toque, o sprite gira. A operação de escala anterior também funciona.

図 2 :タッチポイントを回してスプライトを回転させています
Figura 2: Girando o sprite girando o ponto de toque

Programa - Campos Declarando

"Quantidade de rotação Sprite" e "Último ângulo de rotação" são adicionados ao programa de escala anterior. Todos os ângulos são calculados em radianos.

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

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

Programa - Processo de Rotação

O processo de rotação é realizado durante gestos de pinça da mesma forma que quando dimensionamento.

Eu não vou entrar em muitos detalhes sobre calcular a rotação porque é uma história de matemática, mas você pode obter o radian ângulo com o método "Math.Atan2" encontrando o vetor de diferença do ponto de toque 1 para o ponto de toque 2. Encontre a diferença entre o ângulo obtido e o ângulo adquirido anteriormente e adicione-o ao ângulo de rotação do 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;
}

Programa - Desenho de Sprites

Não há grandes mudanças no desenho de sprites. O quinto argumento do método SpriteBacth.Draw é definido para o ângulo de rotação calculado.

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

Resumo desta amostra

Desta vez, tentei rodar o sprite pela operação pinch. Não usamos nenhuma nova classe em particular, mas espero que entenda que podemos realizar o processamento aplicado com base nas funções fornecidas.

Enfim

Passamos por amostras e demonstramos a implementação de interações de toque usando o Windows Phone 7 e o XNA Game Studio 4.0. O conteúdo incluía aquisição de toque único e multi-toque e manipulação de informações de toque, e processamento por manipulação de gestos de toque usando métodos específicos de gestos.

Desta vez, eu me concentrei no painel de toque, mas ainda há algumas funções que ainda não apresentei. O Windows Phone 7 também inclui novos recursos de entrada no XNA Game Studio 4.0, como entrada do acelerômetro e entrada de voz. Existem algumas características interessantes que eu não poderia introduzir desta vez, então, por favor, aproveite para explorar as funções que você quer usar.