Programming4us
         
 
 
Windows Phone

Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 2) - Improving Programs Using Methods, Handling Collisions

6/21/2012 4:45:53 PM

3. Improving Programs Using Methods

The Great Programmer has just been around and has taken a look at your code. She purses her lips when she sees something she doesn’t like, and she’s doing that now. The bit of code she doesn’t like is the scaleSprites method where you set up the bread and cheese sprites:

void scaleSprites()
{
    cheese.TicksToCrossScreen = 200.0f;
    cheese.WidthFactor = 0.05f;

    cheese.SpriteRectangle.Width =
        (int)((displayWidth * cheese.WidthFactor) + 0.5f);
    float aspectRatio =
        (float)cheese.SpriteTexture.Width / cheese.SpriteTexture.Height;
    cheese.SpriteRectangle.Height =
        (int)((cheese.SpriteRectangle.Width / aspectRatio) + 0.5f);
    cheese.X = minDisplayX;
    cheese.Y = minDisplayY;
    cheese.XSpeed = displayWidth / cheese.TicksToCrossScreen;
    cheese.YSpeed = cheese.XSpeed;

    bread.WidthFactor = 0.15f;
    bread.TicksToCrossScreen = 120.0f;

    bread.SpriteRectangle.Width =
        (int)((displayWidth * bread.WidthFactor) + 0.5f);
    aspectRatio =
        (float)bread.SpriteTexture.Width / bread.SpriteTexture.Height;
    bread.SpriteRectangle.Height =
        (int)((bread.SpriteRectangle.Width / aspectRatio) + 0.5f);
    bread.X = displayWidth / 2;
    bread.Y = displayHeight / 2;
    bread.XSpeed = displayWidth / bread.TicksToCrossScreen;
    bread.YSpeed = bread.XSpeed;
}

					  

For a start, she reckons that the name is no longer correct. The method doesn’t only scale the sprites; it also sets their initial position on the screen and their speed of movement. So you promise to go through and change the name of the method. The next thing she doesn’t like to see is the same piece of code repeated. Rather than perform exactly the same sequence of statements for the bread as for the cheese, she suggests that you make a method called setupSprite that sets up a sprite. You then call this for every sprite you want to set up. You know that you’ll have tomato sprites later, so this seems like a sensible, time-saving plan. You can pass the setupSprite method parameters that give it all the information it needs to work on, so you begin to write the method:

void setupSprite(
    GameSpriteStruct sprite,
    float widthFactor,
    float ticksToCrossScreen,
    float initialX,
    float initialY)
{
    sprite.WidthFactor = widthFactor;
    sprite.TicksToCrossScreen = ticksToCrossScreen;
    sprite.SpriteRectangle.Width = (int)((displayWidth * widthFactor) + 0.5f);
    float aspectRatio =
        (float)sprite.SpriteTexture.Width / sprite.SpriteTexture.Height;
    sprite.SpriteRectangle.Height =
        (int)((sprite.SpriteRectangle.Width / aspectRatio) + 0.5f);
    sprite.X = initialX;
    sprite.Y = initialY;
    sprite.XSpeed = displayWidth / ticksToCrossScreen;
    sprite.YSpeed = sprite.XSpeed;
}

					  

The method is given the sprite to set up, along with the width factor, the time taken to cross the screen, and the initial start position of the sprite. You can then set up the cheese and bread by making two calls of the method:

void setupSprites()
{
    setupSprite(cheese, 0.05f, 200.0f, minDisplayX, minDisplayY);
    setupSprite(bread, 0.15f, 120.0f, displayWidth / 2, displayHeight / 2);
}

This looks much neater, and you’re really pleased with the code that you’ve written. You feed all your setup values into the method call, and it calculates the content of the gameSpriteStruct that needs to be set up. The only problem is that it doesn’t work. The method call doesn’t seem to have any effect on the bread or cheese sprite value.

3.1. Value and Reference Parameters

It turns out that your program doesn’t work because the parameters in your method are passed by value. A parameter is the means by which you can pass information into a method. When a method is called, the value given in the call is copied into the parameter. This means that when code in a method assigns a value to the parameter, the copy is changed, but not the original. In other words, the statement sprite.X = initialX; changes the value of a copy of the GameSpriteStruct that was supplied as a parameter. When a method ends, all the parameter copies are discarded, and the updated values are lost.

Passing value parameters into method calls is fine when you want to tell a method something, but it is less useful when you want the method to change the parameter. To make the method useful, you need to find a way of pointing the method at the variable you want it to change. It turns out that you have a way to do this, and you’ve seen it before. The device you’ll use is called a reference. If you give the method a reference to the thing you want it to change, it can follow the reference and make changes to your actual bread and cheese objects rather than to copies. C# structures are managed by value, which is why the values of the cheese and bread sprites get copied when the method is called. To tell C# to manage a particular parameter as a reference, you need to change the header of the method:

void setupSprite(
    ref GameSpriteStruct sprite,
    float widthFactor,
    float ticksToCrossScreen,
    float initialX,
    float initialY)
{
    // method goes here
}

The ref modifier before the GameSpriteStruct parameter in the method header tells the compiler to pass a reference to the parameter’s location in memory rather than copying a value stored in that memory location. You also need to use the ref modifier, as shown here in bold, when you make a call to the method:

setupSprite(ref cheese, 0.05f, 200.0f,
            minDisplayX, minDisplayY);
setupSprite(ref bread, 0.15f, 120.0f,
            displayWidth/2, displayHeight/2);

Now, when setupSprite runs, it is given the values of the rest of the parameters that it needs to work with and a reference to the GameSpriteStruct object that needs to be changed. You don’t need to change any code in the body of the method itself; the compiler makes sure that the instructions it produces follow the reference and update the correct values in memory rather than updating a copy of the values.


4. Handling Collisions

You have a bread bat and some cheese, and you can move the bread around the game and chase the cheese, but nothing happens when you hit the cheese with the bread. You now need to add the interaction between these two sprites. The first thing the game needs to do is detect when the bread and the cheese collide. The best way to do this is to use the rectangles that define the size and position of the two sprites on the screen. When these two rectangles intersect (that is, both of them cover the same part of the screen), it means that a collision has taken place. Figure 2 shows how this works.

Figure 2. A sprite collision


What you need is a method that you can use to detect when this happens. Fortunately, the designers of XNA have provided just such a method using the Rectangle type. The method, called Intersects, is used as follows:

if (cheese.SpriteRectangle.Intersects(bread.SpriteRectangle))
{
    // we have a collision
}

You call the Intersects method on one rectangle and feed it the other one to compare with it. It returns true if the two rectangles intersect. Note that in the previous code, it is necessary to get the rectangle value of the bread and cheese sprites.

Other -----------------
- 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
- Developing for Windows Phone and Xbox Live : Multiplayer Games (part 6) - Searching for an Available Network Session
- Developing for Windows Phone and Xbox Live : Multiplayer Games (part 5) - Searching for an Available Network Session
- Developing for Windows Phone and Xbox Live : Multiplayer Games (part 4) - Building a Game Lobby
- Developing for Windows Phone and Xbox Live : Multiplayer Games (part 3) - Creating a Network Session
- Developing for Windows Phone and Xbox Live : Multiplayer Games (part 2) - Main Menu and State Management
 
 
Most View
- Developing for Windows Phone and Xbox Live : Multiplayer Games (part 2) - Main Menu and State Management
- DotNetNuke Skinning : Package and Deploy
- Windows Server 2008: Installing a Read-Only Domain Controller (part 1)
- Troubleshooting Windows Home Server 2011 : Checking for Solutions to Problems
- Exchange Server 2010 : Troubleshooting Federated Delegation (part 3) - Troubleshooting Calendar and Contacts Sharing
- Microsoft Dynamics GP 2010 : Dynamics GP Utilities (part 1) - Completing the Dynamics GP installation
- Performing Administrative Tasks Using Central Administration (part 26) - External Service Connections
- Windows Azure : Programming Access Control Service (part 7) - Integrating ACS with a SAML Token Provider
- Microsoft Dynamics GP 2010 : Installing Microsoft SQL Server for Dynamics GP
- BizTalk 2010 Recipes : Business Rules Framework - Calling the Business Rules Engine from dot NET
Top 10
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 3) - Configuring Recipient Filtering
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 2)
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 1)
- Implementing Edge Services for an Exchange Server 2007 Environment : Installing and Configuring the Edge Transport Server Components
- What's New in SharePoint 2013 (part 7) - BCS
- What's New in SharePoint 2013 (part 6) - SEARCH
- What's New in SharePoint 2013 (part 6) - WEB CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 5) - ENTERPRISE CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 4) - WORKFLOWS
- What's New in SharePoint 2013 (part 3) - REMOTE EVENTS