| XNA Game-Themed CS1 Examples (XGC1) | |
|
Release 2.0 (XNA V3.1) |
|
References:
Goals:
1. Obtain the example code
When the game starts, you'll see a screen that
looks similar to this:

This looks (and plays) identical to the prior tutorial - what's new for this tutorial is how we go about doing this, not what we see on the screen.
In this tutorial, we'll explore how to do inheritance from a class that you did not write yourself. This will simplify our code, and make it clear that you only need access to the compiled class, not the original source code, in order to do inheritance.
1. Paddle.cs:
This is effectively identical to what was presented in the prior tutorial.
The Block class is almost unmodified, as well. Since it was necessary to simplify it slightly (because of changes in the SoccerBall class), we'll look at that after the SoccerBall.cs file.
2. SoccerBall.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.
|
public
class SoccerBall
: XNACS1Circle
{ |
The most important change to the code in this tutorial is also the
smallest. We tell the C# compiler that we want the SoccerBall class to
inherit from the XNACS1Circle class by adding
:
XNACS1Circle
Because of this change, the SoccerBall class can be thought of as a more specialized type of XNACS1Circle. This means that any place that we could have used an XNACS1Circle, we can now also use the more specialized SoccerBall. For example, we can now use the SoccerBall object directly when checking to see if a SoccerBall has collided with a Block (instead of asking the SoccerBall for it's circle).
Because of this, we remove the m_TheBall instance variable from the SoccerBall class. We also remove the unneeded methods GetTheCircle, CurrentPosition, and RemoveFromDraw.
Throughout the remaining code, any place that we would have
written (for example)
m_TheBall.VelocityY = -m_TheBall.VelocityY;
we can now remove the m_TheBall part, and simply write:
VelocityY = -VelocityY;
Again, this works because the SoccerBall class is now a
(more specialized) XNACS1Circle class, and therefore it inherits
all the methods, instance variables, and properties of it's
XNACS1Circle base class.
We won't go over all of these details here, since you should be able to follow these small changes on your own.
|
///
<summary>
///
Constructs a SoccerBall object at the specified position
///
</summary>
///
<param name="centerPosition">position
to create the soccer object at.</param>
public SoccerBall(Vector2
centerPosition)
{
// Accessors from the base class
(from XNACS1Circle)
Center = centerPosition;
Radius = RADIUS;
Texture = "SoccerBall";
// set the soccer in motion!
ShouldTravel = true;
VelocityX = INIT_VELOCITY_X;
VelocityY = INIT_VELOCITY_Y; } |
As was mentioned above, you'll notice that the "m_TheBall." has been removed from everywhere in the constructor. Notice also that there isn't even a line that creates the new XNACS1Circle object anymore. This is because the SoccerBall itself is an XNACS1Circle object, and so by the time the constructor is run, the SoccerBall (including all the "XNACS1Circle parts" of the SoccerBall object) will have already been created.
You'll notice that in the previous tutorial we were able to set the
starting center point and radius of the circle object when we created it
(by using the XNACS1Circle's constructor method). Here, we're not
able to do that, so instead we'll need to set the Center and Radius
inside the constructor:
// Accessors from the base class
(from XNACS1Circle)
Center = centerPosition;
Radius = RADIUS;
|
public
void UpdateBall()
{
BoundCollideStatus status
= XNACS1Base.World.ClampAtWorldBound(this);
switch (status)
|
Note that we may need to refer to 'the current object', for example when passing to the Clamp method. We can do this using the 'this' reference, as demonstrated above.
2. Block.cs
This is almost unchanged. The only thing we need to adjust is that in the CollideWithSoccer method, instead of asking the SoccerBall object for it's XNACS1Circle object, we can instead
|
public
virtual bool
CollideWithSoccer(SoccerBall
theSoccer)
{
bool hit =
false;
if (m_IsActive)
{
hit = m_Rec.Collided(theSoccer);
if (hit)
{
// make sure the ball does not
"stick" to the block
if (theSoccer.VelocityX > 0)
{
// soccer travels towards the right
// collision should happen on the
left side
// move the soccer to just outside
of the block
theSoccer.CenterX = m_Rec.MinBound.X
-
theSoccer.Radius;
}
else
{
theSoccer.CenterX = m_Rec.MaxBound.X
+
theSoccer.Radius;
}
// Change soccer ball x-velocity
direction
theSoccer.VelocityX = -theSoccer.VelocityX;
m_HitCount++;
m_Rec.Label = "Hit=" +
m_HitCount;
}
}
return hit;
} }
|
As you can see from the bold-faced, larger font above, we no longer ask theSoccer for it's circle object, but instead, we treat it as a circle object directly.
3. Game1.cs:
This is almost identical to the prior tutorial
The only difference is that we no longer need that separate method for the SoccerBall's center, so we replace that with the XNACS1Circle's Center property, instead
FURTHER EXERCISES::