Touch gestures on Windows Phone 7

Update: My gesture sample is also now available for download which shows an example of mixing awesome gestures with awesome cats. You can find that here: https://creators.xna.com/en-us/sample/gestures

In the Windows Phone Developer Tools Beta released today, there are a lot of little bug fixes, tweaks, and a few new things to play with. One of the biggest new features (in my opinion, anyway :)) is the inclusion of a high-level touch gesture system in the XNA Framework. These touch gestures allow you to program your games and applications using a built in gesture system, rather than reinventing the wheel on what it means to tap, drag, or flick. This should not only save you time as a developer, but ensure that all games on Windows Phone 7 have a consistent feel.

Here is a list of the gestures being provided along with brief descriptions of them:

GestureType Description
Tap A finger touches the screen and releases without much movement.
DoubleTap Two taps in succession.
Hold A finger touches the screen and holds it in place for a brief period of time.
FreeDrag A finger touches the screen and moves in any direction.
VerticalDrag A finger touches the screen and moves in an up/down direction.
HorizontalDrag A finger touches the screen and moves in a left/right direction.
DragComplete Marks the end of a FreeDrag, VerticalDrag, or HorizontalDrag gesture.
Flick A finger drags across the screen and is lifted up without stopping.
Pinch Two fingers press on the screen and move around.
PinchComplete Marks the end of a Pinch gesture.

As you can see, it’s a good list of gestures that most games will find suitable for use. One thing to note as you are designing your game is that all gestures, except for pinch, are single touch gestures. This means if you press two fingers down and move them around, you will not see two drag gestures occurring; you will see a single pinch gesture (if you have those enabled) or you will see one drag gesture based on the average of the two finger positions.

So, now that you know about gestures, how do you use them? The first step for any game or application to use gestures is to enable the gestures you want to read. You must enabled the gestures before using any of the other gesture APIs or you’ll get an exception. Setting the gestures is as easy as setting a static property with a bitflag enumeration:

 TouchPanel.EnabledGestures =
    GestureType.Tap |
    GestureType.DoubleTap |
    GestureType.FreeDrag;

You can enable any or all of the gestures, however for the best results you should always enable only the gestures you need. Enabling extra gestures does affect the gesture engine’s logic and performance. If you need them all, by all means enable them all, but if you only need tap and vertical drag (for example, on your level select screen), you should only enable those two in order to get better accuracy and performance.

Once you have gestures enabled, you just need to read them each frame. Gestures are queued up behind the scenes which means that unlike the TouchPanel.GetState() API, you can see multiple gestures each frame. This gives a higher resolution for gestures as well as ensuring no gestures are missed. In your game’s update loop, you will want to check if there are available gestures and read them all. Failing to read them all can cause the queue to back up and may result in your app or game seeing a lot of old gestures at a later point.

To read the gestures, you can use a simple while loop:

 while (TouchPanel.IsGestureAvailable)
{
    GestureSample gesture = TouchPanel.ReadGesture();

    switch (gesture.GestureType)
    {
        // TODO: handle the gestures
    }
}

Now you have the gestures and know what they are, how do you get data? The GestureSample type exposes five properties (besides GestureType) to give you information about the gesture. These properties are Timestamp, Position, Position2, Delta, and Delta2. Timestamp is a TimeSpan that indicates when the gesture occurred and the other four are Vector2 values related to position and direction of the gestures. Note that Timestamp is not based on GameTime and is available primarily to enable games to figure out the relationship between gestures in the timeline of game events (i.e. you can see that a tap came in exactly 3.14 seconds after a flick by doing subtraction on the Timestamps of the gestures).

Each gesture only uses some of the Vector2 values as needed, leaving the rest set to the default (0, 0). For each gesture type, here is the breakdown of the data available to you:

GestureType Valid Fields
Tap Position
DoubleTap Position
Hold Position
FreeDrag Position, Delta
VerticalDrag Position, Delta
HorizontalDrag Position, Delta
DragComplete None
Flick Delta
Pinch Position, Position2, Delta, Delta 2
PinchComplete None

Mostly what you would have expected. There a few notable points:

  • Flick uses the Delta field to expose the flick speed. This speed is reported in pixels per second which makes it quite nice to use for flinging around your game objects or adding velocity to scrolling lists.
  • VerticalDrag and HorizontalDrag give their actual position data (where the finger is on the screen), but their deltas are constrained to their respective axis. This means the Delta of a VerticalDrag will always have a 0 X component and a HorizontalDrag will always have a 0 Y component. This is very nice for things like menus where you only want to scroll on a certain axis because you don’t have to 0 out the axis yourself.
  • Pinch reports back two fingers of data where Position/Delta map to one finger and Position2/Delta2 map to the other. This allows games to easily reconstruct the previous positions and handle the gesture appropriately, whether using the gesture to scale an object or rotate a camera.

So those are the new gestures in the Windows Phone Developer Tools Beta. If you have any questions, I recommend asking them over on the Creator’s Club forum, or feel free to leave them in the comments below.