programming4us
         
 
 
Windows Phone

Windows Phone 7 : Using the Touch Screen (part 4) - Sprite Hit Testing - Elliptical Hit Tests, Building the Hit Tests into the Game Framework

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
7/17/2013 3:38:48 AM
3.3. Elliptical Hit Tests

Although rectangular hit tests are appropriate in some cases, in others it might be useful to test against a round sprite shape. To facilitate this, we can perform an elliptical hit test.

The ellipse that will be tested will completely fill the rectangular region occupied by the sprite, as shown in Figure 4.

Figure 4. The elliptical test region contained within a rectangular sprite

Of course, ellipses, unlike circles, are affected by rotation, so we need to take this into account when working out whether a test point falls inside the ellipse. In Figure 5(a), we can see a rotated ellipse whose scale is such that its width is twice its height. Also marked in the figure are two test points, the first of which is within the ellipse, whereas the second is not (though it is within the bounds of the sprite rectangle).

The approach that we take to determine whether the points are within the ellipse starts off the same as that used for the rectangle: performing the calculation to rotate the points and the ellipse back to an angle of zero. Once that has been done we can ignore the rotation and concentrate just on the elliptical shape. Again, we don't actually draw the sprite with the angle reset to zero or update the sprite's properties; we just perform the calculations that would be required for this rotation. If we were to draw the rotation, we would end up with the arrangement shown in Figure 5(b).

Figure 5. Elliptical hit tests against a rotated scaled sprite

Having obtained the coordinates relative to an unrotated ellipse, we can now determine whether the points are within the ellipse or not. For a circle this would be easy: we would find the radius of the circle and we would find the distance from the test point to the center of the circle. If the point distance is less than the radius, the point is inside the circle.

For an ellipse, this process is more complex, however. An ellipse doesn't have a radius because the distance from its center to its edge varies as the edge is traversed.

Fortunately, there is a very easy way to resolve this. We know how the sprite has been scaled, so we can divide the width of the ellipse by the scaled sprite width, and divide the height of the ellipse by the scaled sprite height. This will result in a new ellipse that is exactly one unit wide and one unit high. The size is less important than the fact that this resulting size is now that of a circle (with a radius of 0.5) rather than an ellipse, meaning that we can perform calculations against it very easily. Instead of scaling the sprite in this way, we can scale the test point and then see whether its distance from the circle center is less than 0.5. If so, the point is a hit; otherwise, it's a miss.

The steps required for the whole procedure are as follows; they are just like the steps for the rectangular hit test:

  • Move the touch point to be in object space rather than in screen space.

  • Rotate the point back by the sprite rotation angle.

  • Move the point to be relative to the center of the ellipse.

  • Divide the point's x position by the ellipse width and its y position by the ellipse height to scale down relative to a unit-width circle.

  • Test the point distance from the circle center to see whether it is within the circle's radius of 0.5.

Table 4-2 shows each of these calculations for each of the touch points shown in Figure 5. The sprite in question is 64 × 64 pixels and has been scaled to be double its normal width, resulting in an ellipse with a width of 128 pixels and a height of 64 pixels. Its center (and origin) is at the coordinate (200, 100).

Table 2. Calculation steps to determine whether a test point is within a rotated scaled ellipse
Test Point 1Test Point 2
Screen coordinate(224, 117)(248, 134)
Object-space coordinate(24, 17)(48, 34)
Rotated coordinate(27.6, 10.2)(55.2, 20.4)
Ellipse width/height128 pixels by 64 pixels
Rotated coordinate scaled by width and height(0.216, 0.159)(0.432, 0.318)
Distance from circle center at (0, 0)0.2680.536
Point contained within rectangle (distance <= 0.5)YesNo

As this table shows, the test point 1 coordinate is inside the ellipse (its calculated distance is less than 0.5), and the test point 2 coordinate is not.

The complete function to perform this calculation is shown in Listing 9. This code is taken from the SpriteObject class, so it has direct access to the sprite's properties.

Example 9. Checking a test point to see if it is within a rotated and scaled sprite ellipse
protected bool IsPointInObject_EllipseTest(Microsoft.Xna.Framework.Vector2 point)
    {
        Rectangle bbox;
        Vector2 rotatedPoint = Vector2.Zero;

        // Retrieve the basic sprite bounding box
        bbox = BoundingBox;

        // Subtract the ellipse's top-left position from the test point so that the test
        // point is relative to the origin position rather than relative to the screen
        point -= Position;

        // Rotate the point by the negative angle of the sprite to cancel out the sprite
        // rotation
        rotatedPoint.X = (float)(Math.Cos(-Angle) * point.X - Math.Sin(-Angle) * point.Y);
        rotatedPoint.Y = (float)(Math.Sin(-Angle) * point.X + Math.Cos(-Angle) * point.Y);

        // Add back the origin point multiplied by the scale.
        // This will put us in the top-left corner of the bounding box.
        rotatedPoint += Origin * Scale;
        // Subtract the bounding box midpoint from each axis.
        // This will put us in the center of the ellipse.
        rotatedPoint -= new Vector2(bbox.Width / 2, bbox.Height / 2);

        // Divide the point by the width and height of the bounding box.
        // This will result in values between −0.5 and +0.5 on each axis for

					  


// positions within the bounding box. As both axes are then on the same
        // scale we can check the distance from the center point as a circle,
        // without having to worry about elliptical shapes.
        rotatedPoint /= new Vector2(bbox.Width, bbox.Height);

        // See if the distance from the origin to the point is <= 0.5
        // (the radius of a unit-size circle). If so, we are within the ellipse.
        return (rotatedPoint.Length() <= 0.5f);
    }

					  

3.4. Building the Hit Tests into the Game Framework

Checking touch points against game objects to see whether they have been selected is an operation that will be common to many games. To save each game from having to reimplement this logic, we will build these checks into the game framework.

This procedure starts off as an abstract function in GameObjectBase called IsPointInObject, as shown in Listing 10. It expects a Vector2 parameter to identify the position on the screen to test and returns a boolean value indicating whether that point is contained within the object.

Example 10. The abstract declaration for IsPointInObject contained inside GameObjectBase
/// <summary>
    /// Determine whether the specified position is contained within the object
    /// </summary>
    public abstract bool IsPointInObject(Vector2 point);

					  

To implement the IsPointInObject function for sprites, it is overridden within SpriteObject. We will enable our sprites to support testing against both the rectangular and elliptical tests that we have described, and to allow the game to specify which type of test to use a new property is added to the class, named AutoHitTestMode. The property is given the AutoHitTestModes enumeration as its type, allowing either Rectangle or Ellipse to be selected.

The SpriteObject implementation of IsPointInObject checks to see which of these hit modes is selected and then calls into either IsPointInObject_RectangleTest (as shown in Listing 8) or IsPointInObject_EllipseTest (as shown in Listing 9). Any game object can thus have its AutoHitTestMode property set at initialization and can then simply test points by calling the IsPointInObject function.

For sprites that need to perform some alternative or more complex processing when checking for hit points (perhaps just as simple as only allowing a hit to take place under certain conditions or perhaps implementing entirely new region calculations), the IsPointInObject can be further overridden in derived game object classes.

Other -----------------
- Windows Phone 8 : Phone Hardware - Using Motion (part 2) - Emulating Motion
- Windows Phone 8 : Phone Hardware - Using Motion (part 1)
- Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 3) - Strange Bounce Behavior, Strange Edge Behavior
- Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 2) - Improving Programs Using Methods, Handling Collisions
- Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 1) - Using a Structure to Hold Sprite Information, Using the Gamepad Thumbsticks to Control Movement
- Business Apps for Android & Windows Phone 7 : Handyscan, Outdoor Navigation, Pageonce Money& Bills, Glympse, Cool Tools
- Windows Phone 7 Game Development : Orthographic Projection (part 2) - Isometric Projection & Pixel-Aligned Projection
- Windows Phone 7 Game Development : Orthographic Projection (part 1) - The Viewing Frustum & Defining the Orthographic Viewing Frustum in XNA
- Windows Phone 7 Game Development : Lighting (part 3) - Adding Lighting to Games
- Windows Phone 7 Game Development : Lighting (part 2) - How XNA Calculates Light Reflections
- Windows Phone 7 Game Development : Lighting (part 1) - Types of Illumination
- Windows Phone 7 : User Interface - Using Panorama and Pivot Controls
- Windows Phone 7 : User Interface - Localizing Your Application
- User Interface : Using the Windows Phone 7 Predefined Styles
- Handling Input on Windows Phone 7 : Touch Input (part 3) - Multi-Point Touch
- Handling Input on Windows Phone 7 : Touch Input (part 2) - Raw Touch with Mouse Events
- Handling Input on Windows Phone 7 : Touch Input (part 1) - Single-Point Touch
- Handling Input on Windows Phone 7 : The Keyboard
- User Interface : Customizing the Soft Input Panel Keyboard to Accept Only Numbers
- User Interface : Detecting Changes in the Theme Template
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS