Touch interactions in game development for Windows Phone 7, Part 3 Drag operations

Page update date :
Page creation date :

Programming! - 3.Try moving the card to the touch

About this sample

This time, I would like to create a progran that places four cards on the screen and places and drags the cards to the place where they are touched. This is a multi-touch version of the program that first dragged a sprite with the Mouse class. Until now, there have been many explanations, so this time I would like to explain mainly about the program.

Goals of this sample program

Drag multiple cards at the same time as you touch with multi-touch.

図 1 :マルチタッチによるドラッグ操作
Figure 1: Multi-touch drag operation

Program - Card Classes

When it comes to multi-touch, it becomes necessary to have multiple objects, so here I would like to create a "Card" class with the sprite to be moved as a "card".

/// <summary>
/// ドラッグできるカード
/// </summary>
public class Card
{
  /// <summary>
  /// タッチ ID
  /// </summary>
  public int Id { get; set; }

  /// <summary>
  /// カードの位置
  /// </summary>
  public Vector2 Position { get; set; }

  /// <summary>
  /// カードの色
  /// </summary>
  public Color Color { get; set; }
}

In order not to make the code too complicated, the card class has three properties: touch ID, position, and color. There is no particular item to go into detail, but "Touch ID" is used to check which touchpoint is linked.

Program - Declaring Fields

There's nothing new about it other than having an array of Card classes to hold card information. This time, it's like an application of the previous samples. I made four cards, each with a different color so you can see the difference when drawing.

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

/// <summary>
/// カードの一覧(4 枚分)
/// </summary>
Card[] cards = new Card[]
{
  new Card { Color = Color.White, },
  new Card { Color = Color.Yellow, },
  new Card { Color = Color.Fuchsia, },
  new Card { Color = Color.Aqua, },
};

Programmatic - Get Touch Information

Inside the Game.Update method. This area is formulaic, so there is nothing particularly new.

// タッチパネルの機能情報を取得
TouchPanelCapabilities capabilities = TouchPanel.GetCapabilities();

// タッチパネルが使用可能であるかチェック
if (capabilities.IsConnected)
{
  // 現在のタッチパネルの入力情報を取得
  TouchCollection touches = TouchPanel.GetState();

  //   :
  // ここに処理
  //   :
}

Program - Link a touch ID to a card when touched

In the sample program, the order is reversed from the viewpoint of processing cost, but it is easier to understand if you explain it from here, so I will explain this first.

First, loop through the acquired TouchCollection foreach to get each piece of information.

/// タッチ情報の処理を行う
foreach (TouchLocation tl in touches)
{
  // タッチ状態を調べる
  switch (tl.State)
  {
    case TouchLocationState.Pressed:
      // タッチされた瞬間は空いているカードを検索して紐づける
      Card card = cards.Where(c => c.Id == 0).FirstOrDefault();
      if (card != null)
      {
          card.Id = tl.Id;
          card.Position = tl.Position;
      }
      break;
  }
}

Check the "TouchLocation.State" property to indicate that "TouchLocationState.Pressed" is the moment you touched it.

In this sample, if the ID of the card is "0", it is defined as not being used, so "cards. Where(c => c.Id == 0). FirstOrDefault()" to search for a card with ID 0 from the list of cards and retrieve that card if found. If not found, null is returned. Here, extension methods are called by LINQ to simplify the code, but if you are concerned about processing costs, you can search for them one by one with a for loop.

When you find the card, set the touch ID and touch position on the card.

Program - handling cards during touch and when they are released

Keep the card in a drag state at all times while you touch it, and when you release it, it will be disconnected from the touchpoint to the card.

// 各カードの情報を調べる
foreach (Card card in cards)
{
  if (card.Id != 0)
  {
    // 紐づくタッチ情報がまだ存在するか ID で検索
    TouchLocation tl;
    if (touches.FindById(card.Id, out tl) == true)
    {
      // まだタッチされている場合は位置情報取得
      card.Position = tl.Position;
    }
    else
    {
      // すでにタッチ情報がなかったら紐付を外す
      card.Id = 0;
    }
  }
}

Loop the card list with foreach and process each card. If the ID is anything other than 0, it is linked to the touchpoint and the process continues.

The TouchCollection structure provides a "FindById" method that allows you to retrieve the touch information for the specified ID, if one exists. If the Card.Id property is not 0, we can assume that it is associated with some touch point, so we will try to get the touch information with the FindById method.

If the FindById method returns true, it is still in the touch state, so get the touch position from the TouchLocation.Position property and set it in the card class. If the FindById method returns false, the touch is released, so set Card.ID to 0 and set it as no one is touching it.

Program - Drawing Cards

The parameters needed for drawing should already be set to the Card class, so there's nothing new.

// スプライトの描画準備
spriteBatch.Begin();

// 各カードを描画
foreach (Card card in cards)
{
  spriteBatch.Draw(texture, card.Position, card.Color);
}

// スプライトの一括描画
spriteBatch.End();

Summary of this sample

This time, I tried to create an image program that uses multi-touch to actually move objects in the game. We also observed that when multiple cards were dragged at the same time using the ID of the touch information, the movement of the cards was consistent even if the other finger was lifted or touched again.

This sample is just a sample and only simple processing is performed. However, the basic part of the multi-touch operation by the touch panel should be covered by actual game programming, so please apply it to multi-touch processing that suits your game based on this.