XNA Game-Themed CS1 Examples (XGC1)

Release 2.0 (XNA V3.1)
2/8/2010

Topic: Topic.7.ObjectsAndClasses
Example: Ex_9.BlockDeriveFromRec

OOP: Block derived from Rectangle; Overriding methods


References:

Goals:



1. Obtain the example code

Download and unzip the zip file and you will see an ExampleProgram folder. Open the ExampleProgram folder, the EXE folder contains the compiled program and you can double click on the .sln file to work with the source code.

When the game starts, you'll see a screen that looks similar to this:

This looks (and plays) almost identically to game presented in the prior tutorial. The only change that the user can observe is that when the soccer ball bounces off a Block of Paddle, a sound is played.

In this tutorial, we'll see another example of how to inheritance from a class that you did not create yourself - we will make the Block inherit from the XNACS1Rectangle class, much like the SoccerBall was made to inherit from the XNACS1Circle class in the prior tutorial.  We will also see that the Paddle class, which inherits from the Block class, now also (indirectly) inherits from teh XNACS1Rectangle class, as well.  In other words, we can have more than one level of inheritance - we can build up an inheritance hierarchy, if we want. 

We will also see method overriding, which is a way to replace a method in a derived class with a similar, but more specialized method.  (This should not to be confused with method overloading, which is something different)


1. SoccerBall.cs, Game1.cs

These are effectively identical to what was presented in the prior tutorial. 

2. Block.cs

In this tutorial, we're changing how the SoccerBall is set up, by having it inherit from the XNACS1Circle class.  Remember that XNACS1Circle is something that's provided to you, as part of the overall XNACS1Lib library.  You've never seen the source code for it, but your programs make use of it.  We'll make use of it here, by having the SoccerBall inherit from it.

3. Paddle

This is very similar to what was presented in the prior tutorial.  You'll notice that because Paddle is derived from Block, and Block is now derived from XNACS1Rectangle (and because Block no longer has an m_Rec instance variable), that we need to remove any occurrences of  m_Rec from the Paddle class, as well.  Additionally, we override the PlayCollisionCue method:

What's new is the PlayCollisionCue method, which now overrides the one in the base class

4. What happens when the soccer ball collides with a basic Block

Let's examine what happens when a soccer ball collides with the Block in the middle of the screen.

  1. The framework (XNA, and the XNACS1Lib library) call the UpdateWorld method in the Game1.cs file.

  2. The program executes all the statements sequentially, until it gets to:

    m_TheBlocker.CollideWithSoccer(m_TheBall); 


    At this point it calls the CollideWithSoccer method on the m_TheBlocker object, which is Block object.  I know this seems both obvious and trivial, but it'll be important later.

  3. The CollideWithSoccer method is executed sequentially from top to bottom, until it gets to:

    PlayCollisionCue();

  4. Instead of just calling the method, C# notices that the method is declared to be virtual on the Block class.  At that point, C# asks "Is there a more specialized version that could be used?  In particular, is there a more specialized version of the Block class?"  It examine the Block class because this method was called on m_TheBlocker back in UpdateWorld.  C# finds the one-and-only version of the PlayCollisionCue on the Block class, and calls that version (thus playing the "Block" sound)

5. What happens when the soccer ball collides with a Paddle

Let's examine what happens when a soccer ball collides with, say, the left Paddle

  1. The framework (XNA, and the XNACS1Lib library) call the UpdateWorld method in the Game1.cs file.

  2. The program executes all the statements sequentially, until it gets to:

    m_LeftPaddle.CollideWithSoccer(m_TheBall);


    At this point it calls the CollideWithSoccer method on the m_LeftPaddle object, which is Paddle object.  I know this seems both obvious and trivial, but it'll be important later.

  3. The CollideWithSoccer method (on the Block class) is executed sequentially from top to bottom, until it gets to:

    PlayCollisionCue();

  4. Instead of just calling the method, C# notices that the method is declared to be virtual on the Block class.  At that point, C# asks "Is there a more specialized version that could be used?  In particular, is there a more specialized version of the Paddle class?"  It examine the Paddle class because this method was called on m_LeftPaddle back in UpdateWorld.  C# finds the more specialized version of the PlayCollisionCue on the Paddle class, and calls that version (thus playing the "Paddle" sound)


FURTHER EXERCISES:: 

  1. Create a subclass of the Paddle, and make it play a different sound.  You will need to modify the Game1.cs file so that instead of creating the normal Paddle classes, you instead create instances of your new subclass of Paddle.
  2. Modify the SoccerBall class so that when it hits an edge of the screen, it plays a sound. 
    Next, create a subclass of the SoccerBall class, and make it play a different sound.
    In Game1.cs, make sure that you create an object of your new subclass, and confirm that the new sound is played when the on-screen soccer ball hits the wall.

Project home page: The Game-Themed Introductory Programming Project.
Kelvin Sung
Computing and Software Systems
University of Washington, Bothell
ksung@u.washington.edu
Michael Panitz
Business And Information Technology
Cascadia Community College
mpanitz@cascadia.eduu

Microsoft Logo This work is supported in part by a grant from Microsoft Research under the Computer Gaming Curriculum in Computer Science RFP, Award Number 15871 and 16531.
2/8/2010