| XNA Game-Themed CS1 Examples ( XGC1 ) | |
|
Release 2.0 (XNA V3.1)
|
|
Need (library reference):
Goals:
Before you begin
Let's start by examining the final, finished game that you will create throughout this chapter. Download and unzip the Example Code, and then open the solution for the 900 tutorials . In the Solution Explorer, you will see:
Once you've done that, you should proceed with this tutorial.
1. Obtain the example code
When the game starts, you'll see a screen that
looks similar to this:
The rectangle on the far left is a 'paddle'. You can move it up and down by pushing the left thumbstick up and down. The rectangle on the far right is also a 'paddle', which you can move up and down by pushing the right thumbstick up and down. The only other thing on the screen is a picture of a soccer ball. The soccer ball starts off in (roughly) the center of the screen, moving at a random speed in a random direction. Even at the end of this tutorial, the soccer ball will not interact with anything - it won't bounce off either paddle, nor the edges of the screen. Notice that the location of the paddles are displayed at the top of the screen, and the location of the soccer ball is displayed at the bottom.
Notice that since the soccer ball doesn't bounce of anything, it will just keep going. You can see this by observing that the position of the soccer ball continues to change, even after the soccer ball has left the screen.
| Summary of | |
| Controller Input: | Has this effect: |
| Left thumbstick | Moves the left paddle. Note that only the vertical input is used, because the paddle is only allowed to move up or down |
| Right thumbstick | Moves the right paddle. Note that only the vertical input is used, because the paddle is only allowed to move up or down |
| Back button | Exits the game |
Once you've seen what the final, finished game does ( the PongSoccer game ), and what you've seen what this tutorial's game does, you should open up the Game1.cs file for the 010.PaddlesAndBalls project, so that you can examine the source code. Keep in mind that the goal for this tutorial is to acquaint you with the source that we'll be building on, in future tutorials . Everything in the file should be familiar, with the possible exceptions of working with images ( aka textures) , creating your own regions , and generating random numbers using XNACS1Lib .
Let's examine the
C# source code that produces the behavior we see on-screen
|
public
class Game1 :
XNACS1Base
{ #region Constants for the paddle and ball// Paddle dimensions (both paddles are the same size) private const float PADDLE_WIDTH = 1.5f; // width of the paddle private const float PADDLE_HEIGHT = 10.0f; // Height of the paddle // paddle initial positions private const float LEFT_PADDLE_X = 3.0f; private const float RIGHT_PADDLE_X = 97.0f; private const float PADDLE_INIT_Y = 20.0f; // both start off at same height // Ball size, position, and velocity private const float BALL_INIT_X = 50.0f; // initial ball X and Y positions private const float BALL_INIT_Y = 25.0f; private const float BALL_RADIUS = 2.5f; // size of the ball // We want to specify a minimum and maximum speed for the ball. // Since we keep track of velocity by keeping track of the separate X and Y speeds, // we need to define a min & max speed for each of the X and Y directions private const float BALL_VELOCITY_MIN_X = 0.6f; private const float BALL_VELOCITY_MAX_X = 1.2f; private const float BALL_VELOCITY_MIN_Y = BALL_VELOCITY_MIN_X / 3.0f; private const float BALL_VELOCITY_MAX_Y = BALL_VELOCITY_MAX_X / 3.0f; #endregion private XNACS1Circle m_TheSoccer; // the soccer ball // The paddles: private XNACS1Rectangle m_LeftPaddle; private XNACS1Rectangle m_RightPaddle;
|
The soccer ball is represented using a circle that has a texture (image) put over it, so we declare m_TheSoccer as an XNACS1Circle . m_TheSoccer will keep track of it's current position and velocity . Essentially, each time UpdateWorld is called, the ball will be moved by a distance of m_TheSoccer.VelocityX in the horizontal direction, and m_TheSoccer.VelocityY in the vertical direction. Remember that a positive value for X means that the ball will be moving towards the right, while a negative value means that the ball will move towards the left. Remember that a positive value for Y means that the ball will be moving towards the top of the screen, while a negative value means that the ball will move downwards.
// The paddles:
private XNACS1Rectangle m_LeftPaddle;
private XNACS1Rectangle m_RightPaddle;
private const float PADDLE_WIDTH = 1.5f; // width of the paddle
private const float PADDLE_HEIGHT = 10.0f; // Height of the paddle
// paddle initial positions
private const float LEFT_PADDLE_X = 3.0f;
private const float RIGHT_PADDLE_X = 97.0f;
private const float PADDLE_INIT_Y = 20.0f; // both start off at same height
// Ball size, position, and velocity
private const float BALL_INIT_X = 50.0f; // initial ball X and Y positions
private const float BALL_INIT_Y = 25.0f;
private const float BALL_RADIUS = 2.5f; // size of the ball
Both paddles will be given a width of
PADDLE_WIDTH
,
and a height of
PADDLE_HEIGHT
.
By creating (and later, by using) these named constants, we ensure that both
paddles will have consistent dimensions.
Similarly, we position both paddles a distance of
PADDLE_INIT_Y
from the bottom of
the screen, so that they'll both start off at the same height.
However, the left paddle's X value needs to be different from the right
paddle's X value, so we define
LEFT_PADDLE_X
and
RIGHT_PADDLE_X
. The left
paddle will initially be placed at (
LEFT_PADDLE_X
,
PADDLE_INIT_Y
), while the right
paddle will initially be placed at (
RIGHT_PADDLE_X
,
PADDLE_INIT_Y
).
Lastly, the ball will initially be placed at (
BALL_INIT_X
,
BALL_INIT_Y
), and will have a
radius of
BALL_RADIUS
.
// We want to specify a minimum and maximum speed for the ball.
// Since we keep track of velocity by keeping track of the separate X and Y speeds,
// we need to define a min & max speed for each of the X and Y directions
private const float BALL_VELOCITY_MIN_X = 0.6f;
private const float BALL_VELOCITY_MAX_X = 1.2f;
private const float BALL_VELOCITY_MIN_Y = BALL_VELOCITY_MIN_X / 3.0f;
private const float BALL_VELOCITY_MAX_Y = BALL_VELOCITY_MAX_X / 3.0f;
|
protected
override
void
InitializeWorld()
World.SetWorldCoordinate(
new Vector2(0,0),
100.0f);
// initialize the left and right paddles m_LeftPaddle = InitializeRectangle(LEFT_PADDLE_X, PADDLE_INIT_Y, PADDLE_WIDTH, PADDLE_HEIGHT); m_RightPaddle = InitializeRectangle(RIGHT_PADDLE_X, PADDLE_INIT_Y, PADDLE_WIDTH, PADDLE_HEIGHT);
InitializeSoccer(); } |
|
///
<summary>
/// Allocate and initialize the soccer and the velocity for /// the soccer ball /// </summary> private void InitializeSoccer() { m_TheSoccer = new XNACS1Circle ();m_TheSoccer.Center = new Vector2 (BALL_INIT_X, BALL_INIT_Y);m_TheSoccer.Radius = BALL_RADIUS; m_TheSoccer.Texture = "SoccerBall" ;// initilize the soccer ball velocity m_TheSoccer.VelocityX = XNACS1Base .RandomFloat(BALL_VELOCITY_MIN_X, BALL_VELOCITY_MAX_X);m_TheSoccer.VelocityY = XNACS1Base .RandomFloat(BALL_VELOCITY_MIN_Y, BALL_VELOCITY_MAX_Y);m_TheSoccer.ShouldTravel = true ; // notice the soccer ball will travel by itself now (ShouldTravel is true). } |
UpdateWorld():
|
protected
override
void
UpdateWorld()
{ if (GamePad.ButtonBackClicked()) this .Exit(); // update the left and right paddles with thumbstick m_LeftPaddle.CenterY = m_LeftPaddle.Center.Y + GamePad.ThumbSticks.Left.Y; m_RightPaddle.CenterY = m_RightPaddle.Center.Y + GamePad.ThumbSticks.Right.Y; // the soccer center will be moved by velocity automatically because mTheSoccer.ShouldTravel is true EchoToTopStatus( "Left Paddle Center=" + m_LeftPaddle.Center + " Right Paddle Center=" + m_RightPaddle.Center); EchoToBottomStatus( "Soccer Ball position: " + m_TheSoccer.Center); } |
m_LeftPaddle.CenterY = m_LeftPaddle.Center.Y + GamePad.ThumbSticks.Left.Y;
m_RightPaddle.CenterY = m_RightPaddle.Center.Y + GamePad.ThumbSticks.Right.Y;
If the m_TheSoccer.ShouldTravel were false, we could update the center of
the soccer ball by:
// move the soccer
center by velocity
m_TheSoccer.Center = m_TheSoccer.Center + m_BallVelocity;
Much in the same way that we can assign one Vector2 object directly to another Vector2 object , we can also do addition on entire objects, as well (as we see here).
EchoToBottomStatus( "Soccer Ball position: " + m_TheSoccer.Center);
FURTHER EXERCISES::