MOBILE

XNA Game Studio 4.0 : Multitouch Input For Windows Phones (part 1)

8/6/2012 5:48:58 PM
The final type of input device supported by XNA Game Studio APIs are multitouch displays available on all Windows Phone devices. The multitouch APIs are supported on all Windows Phones.

Multitouch devices are unique in that the user can directly touch the display screen and seem to be actually touching and interacting with the images on the screen. This provides an intimate level of interaction that is common on hand-held devices.

Note

XNA Game Studio 4 is not the first version of XNA Game Studio to support multitouch. The Microsoft XNA Game Studio 3.1 Zune Extensions provides similar APIs for Zune HD devices.


Multitouch devices are represented in XNA Game Studio using the TouchPanel class type. There are two ways you can read multitouch data from the TouchPanel.

The first is to poll the current state of the TouchPanel using the GetState method. This returns a number of touch locations where the user has made contact with the multitouch display. All Windows Phone devices support at least four touch locations at a minimum. After you determine the current touch locations, you can use that information to move, rotate, or scale graphics on the display.

The second way to read multitouch data is to utilize gestures. A gesture is an action that is performed by the user that can occur over time and must be processed to determine which gesture the user intended to use. For example, the user can drag his finger across the screen.

Reading the TouchPanel Device State

Just like the previous input device APIs, the TouchPanel provides a state-based API that allows the current state of the multitouch device to be polled at regular intervals. This state can then be used to perform in game actions. Use the TouchPanel class to read the current state of a multitouch device. The GetState method returns a TouchCollection that contains all of the current touch locations. Table 1 and 2 contain a list of methods and properties for the TouchPanel object.

Table 1. Methods of TouchPanel
MethodDescription
GetStateReturns collection of current touch locations
GetCapabilitiesReturns the current touch panel capabilities
ReadGestureReturns the next available gesture

Table 2. Properties of TouchPanel
PropertyTypeDescription
DisplayWidthintThe width of the touch panel
DisplayHeightintThe height of the touch panel
DisplayOrientationDisplayOrientationOrientation of the touch panel
EnabledGesturesGestureTypeGestures enabled on the touch panel
IsGestureAvailableboolTrue if a gesture can be read
WindowHandleIntPtrWindow to receive touch input

To return the current collection of touch locations, add the following line of code to your game’s Update method:

TouchCollection currentTouchState = TouchPanel.GetState();

The TouchCollection contains all of the touch locations that are currently pressed or were released since the last frame. To read each TouchLocation, you can loop over the TouchCollection and read each of the locations properties:

// Loop each of the touch locations in the collection
foreach (TouchLocation touchLocation in currentTouchState)
{
    // The uniquie ID of this locaiton
    int touchID = touchLocation.Id;
    Vector2 touchPosition = touchLocation.Position;
    TouchLocationState touchState = touchLocation.State;
}

The Position and State can then be used by your game to make interactive game play decisions. Table 3 contains a list of the properties exposed by the TouchLocation structure.

Table 3. Properties of TouchLocation
PropertyTypeDescription
PositionVector2The position of the touch location
StateTouchLocationStateThe current state of the touch location
IdintThe unique ID of the touch location

Each touch location contains three properties. Use the Position property to determine where on the screen the TouchLocation is located. Each TouchLocation can be in any of four states. Pressed means this specific TouchLocation was just pressed by the user. Moved means that this specific TouchLocation was already tracked and that it has moved. Released mean that the TouchLocation that was being tracked is no longer pressed by the user, and he or she released his or her finger. Invalid means the TouchLocation is invalid and should not be used. Use the TouchLocation.State property to determine the current state of a returned location. The final property Id is used to give each TouchLocation a unique ID that can be used to determine whether two locations across GetState calls are the same point. The index of the touch location in the TouchCollection should not be used as the identifier because the user can pick up a finger but leave others pressed.

Note

If a user touches the screen and then his or her finger slides off the screen, the TouchLocation for that finger changes state to Released.


Determine Number of Touch Points

The TouchPanel class contains the TouchPanel.GetCapabilities method and returns TouchPanelCapabilities a structure. Table 4 contains the properties exposed by the TouchPanelCapabilities structure.

Table 4. Properties of TouchPanelCapabilities
PropertyTypeDescription
IsConnectedVector2Returns true if a multitouch capable device is connected
MaximumTouchCountintReturns the maximum number of TouchLocations that can be tracked by the TouchPanel

To determine the number of touch points the device supports, use the following lines of code:

// Query the capabilities of the device
TouchPanelCapabilities touchCaps = TouchPanel.GetCapabilities();
// Check to see if a device is connected
if(touchCaps.IsConnected)
{
    // The max number of TouchLocation points that can be tracked
    int maxPoints = touchCaps.MaximumTouchCount;
}

After you have determined that a touch device is connected, use the MaximumTouchCount property to read how many TouchLocation points that the TouchPanel can track at a time.

Note

Windows Phone games should never require more than four touch points to play the game. More than four can be used if they are available, but they should not be required to play the game successfully.


TouchPanel Width, Height, and Orientation

By default, the width, height, and orientation are set for the TouchPanel. If your game supports autorotation, the orientation of the touch panel is automatically updated to match the graphics. TouchPanel does provide three properties to read their current values but also enables you to override their values. In most cases, this is not useful, but it can be useful if you require your input in a different scale than the display resolution. If your display is 480 wide and 800 tall but you want TouchLocation positions that range from 400 wide to 500 tall, you can use the following lines of code:

TouchPanel.DisplayWidth = 400;
TouchPanel.DisplayHeight = 500;

Moving Sprite Based on Multitouch Input

It is time to get the sprite moving around the screen again. This time, you use your newly learned multitouch APIs. Use the first touch location to move the sprite around the screen, and use the second touch location to rotate and scale the sprite. First, you need member variables to store the sprite texture, position, center, rotation, and scale. Add the following lines of code to your Game class:

Texture2D spriteTexture;
Vector2 spritePosition;
Vector2 spriteCenter;
float rotation = 0;
float scale = 1;

Next, load a texture to use as your sprite and set the sprite’s center based on the texture width and height. In the game’s LoadContent method, add the following lines of code:

spriteTexture = Content.Load<Texture2D>("XnaLogo");
spriteCenter.X = spriteTexture.Width / 2.0f;
spriteCenter.Y = spriteTexture.Height / 2.0f;

Now, read the current state of the TouchPanel and update your sprite. Add the following lines of code to your game’s Update method:

// Get current touch state
TouchCollection currentTouchState = TouchPanel.GetState();
// Loop over each touch point
for (int i = 0; i < currentTouchState.Count; i++)
{
    TouchLocation currentLocation = currentTouchState[i];

    // Only process points that were just pressed or are moving
    if (currentLocation.State == TouchLocationState.Pressed ||
        currentLocation.State == TouchLocationState.Moved)
    {
        // Use the 1st point for the sprite location
        if (i == 0)
        {
            spritePosition = currentLocation.Position;
        }
        // Use the 2nd point for rotation and scale
        if (i == 0)
        {
            // Check distance between the 1st and 2nd points
            Vector2 positionToSprite = currentLocation.Position - spritePosition;
            float distance = positionToSprite.Length();
            scale = distance / (spriteTexture.Width / 2);
            // Normalize to get direction vector
            positionToSprite.Normalize();
            // Use the direction between fingers to determine rotation angle
            float cosAngle = Vector2.Dot(positionToSprite, Vector2.UnitX);
            if (spritePosition.Y > currentLocation.Position.Y)
                rotation = 2 * MathHelper.Pi - (float)Math.Acos(cosAngle);
            else
                rotation = (float)Math.Acos(cosAngle);
        }
        else
            break;
    }
}

					  

In the previous code, notice that you loop over the first two touch locations. Each location is used only if its state is set to Pressed or Moved. Released and Invalid points are not used. The first touch point is used to set the sprite’s position on the screen. The second point is then used to determine the amount to scale and rotate the sprite. To determine the scale amount, create a vector from the second touch location to the first touch location. The distance of this vector is then calculated. The final scale divides this distance by the width of the texture to achieve the proper scale value. To determine the rotation of the sprite, find the angle of the line formed between the first and second finger and the unit X vector. You can then find the cosine of the angle between these two vectors by using the vector dot product. The vector dot product is equal to the cosine of the angle between them multiplied by the length of each vector. To simplify, make sure both vectors have a length of one also known as unit length. The Vector2.UnitX vector already has a length of one, so you don’t need to normalize it. The vector formed by the two touch locations is normalized. This sets the vector’s length to one and creates a direction vector. Now that both vectors have a length of one, the cosine of the angle between them can be found by just using the vector dot product. To get the final angle, take the arccosine of the dot product. This gives you the angle between the vector formed by the two touch locations and the unit X vector in radians.

Finally, draw the sprite to the screen using the values you determined. To draw the sprite to the screen, use the following lines of code in your game’s Draw method:

// Draw the sprite
spriteBatch.Begin();
spriteBatch.Draw(spriteTexture, spritePosition, null, Color.White,
                    rotation, spriteCenter, scale, SpriteEffects.None, 0);
spriteBatch.End();
Other  
  •  Motorola Motoluxe
  •  Apple's Undiscovered Country : The future of the iPhone
  •  Apple's Undiscovered Country : The Future Of The Ipad
  •  Programming the iPhone : Standard Control Types (part 6) - Segmented Controls
  •  Programming the iPhone : Standard Control Types (part 5) - Search Bars
  •  Programming the iPhone : Standard Control Types (part 4) - Tables and Pickers
  •  Programming the iPhone : Standard Control Types (part 3) - Sliders
  •  Programming the iPhone : Standard Control Types (part 2) - Modal Buttons
  •  Programming the iPhone : Standard Control Types (part 1) - Buttons
  •  Sony Introduced 3 New Phones In Xperia Series: Tipo, Miro And Ion
  •  Samsung Galaxy SIII And HTC One X: A Detailed And Thorough Comparison
  •  In Control
  •  BlackBerry Virtual Keyboard: The Development Through Each Appliance
  •  3D Phone – Why Is LG Optimus 3D Max P725 The Best Choice, Still?
  •  XNA Game Studio 4.0 : Xbox 360 Gamepad (part 2) - Moving Sprites Based on Gamepad Input
  •  XNA Game Studio 4.0 : Xbox 360 Gamepad (part 1) - Reading Gamepad State
  •  XNA Game Studio 4.0 : Adding Interactivity with User Input - Precision Control of a Mouse
  •  Asus Transformer Pad TF300
  •  Mobile Phone Game Programming : Using Sprite Animation - Building the UFO Example Program
  •  Mobile Phone Game Programming : Using Sprite Animation - Achieving Smooth Animation with the GameCanvas Class
  •  
    Top 10
    HP ElitePad 900 - A Well-Built Business Tablet
    Huawei MediaPad 7 Lite Android Tablet
    Best New App-Ons – August 2013
    How To See Through Website Lies
    17 Killer Mac Apps Under $20 (Part 5)
    17 Killer Mac Apps Under $20 (Part 4)
    17 Killer Mac Apps Under $20 (Part 3)
    17 Killer Mac Apps Under $20 (Part 2)
    17 Killer Mac Apps Under $20 (Part 1)
    PC Specialist Fusion Z11 - Black Midi Tower Window Gaming Case
    Most View
    Projectors Test - 300in Picture! Full HD! 3D And All For Under A Grand! (Part 3) : Optoma HD25, Optoma HD25 specs
    The Ideal Modern IT Department (Part 1)
    The Best Entry Level Phones – November 2012 (Part 4) - Motorola Motosmart
    Homeplug Problems In A Factory Setting (Part 1)
    Using Standard NT Security Features in Windows 7 : WORKING DIRECTLY WITH WINDOWS NT SECURITY (part 2) - Changing User Permissions
    Debugging and Deploying Mobile Games (part 2) - Choosing a Debugger, Deploying Mobile Games
    How To Tidy The Windows 8 UI (Part 2)
    Music And More To Go
    Home Cinema Amplifiers Awards – Q1 2013
    Best Photo Printers Revealed – Jan 2013 (Part 6)