XNA Game-Themed CS1 Examples ( XGC1 ) Release 2.0 (XNA V3.1) 2/8/2010
Topic: Topic.3.ModulesAndFunctions
Example: Ex_6.ParabolicFreeFall

# Functions And Algorithms: Parabolic Free Fall

References:

• Pre-requisite: it is assumed that you have read through the prior tutorials, and are familiar with the concepts covered in those tutorials.

Goals:

• In this tutorial, we will:
• Examine how help make it easier to quickly and correctly change our game

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:

As you can see, there is a single soccer ball on the screen.  While you can alter the soccer ball's movement using the right thumbstick, you can clearly see that the soccer ball is following the path of a parabola across the screen, in a simple simulation of gravity's pull on a soccer ball that's been thrown upwards .  The message at the top of the screen has been updated, as well.

2. Moving The Ball Along a Parabolic Arc.

Since the source code to this program is nearly identical to the program uses in the previous tutorial, we will only examine the code that's new, or different.

In order to know how to move the ball, we will need to track the velocity of the ball.  Velocity is defined as the speed and direction in which the ball is moving.  We will also define the initial velocity using named constants, as well as the amount to decrease the Y speed by at each update.
In a nutshell, we will set the starting speed for the ball, and at each update, we will decrease the ball's speed in the Y direction (to simulate gravity's downward pull), then move the ball. Across numerous updates, the ball will follow a parabolic arc across the screen.

• Declaring the instance variables and named constants  public class Game1 : XNACS1Base {     private XNACS1Circle m_TheSoccer; // a soccer ball     private float m_XSpeed;     private float m_YSpeed;     // Constants for circle/ball definition     private const float BALL_INIT_X = 5.0f;     private const float BALL_INIT_Y = 2.0f;     private const float BALL_INIT_RADIUS = 3.0f;         private const float INIT_SPEED_X = 0.53f;     private const float INIT_SPEED_Y = 0.9f;     private const float Y_SPEED_DECREASE_BY = 0.011f;
• As we can see from the picture above, we need to add in some variables to track the current velocity (since this changes over time), and we need to add in some named constants, to make it easy to define how the game works.
• We will track the speed in the X direction separately from the speed in the Y direction, using one variable for each:
private float m_XSpeed;

private float m_YSpeed;

(Later on, we'll look at using a Vector2 struct to track both parts of the velocity in a single, "compound" variable)

• We will declare several named constants.  The first two serve to define the starting speed (in the X and Y direction, respectively) for the ball:
private const float INIT_SPEED_X = 0.53f;

private const float INIT_SPEED_Y = 0.9f;

Lastly, we will define the amount by which we will decrease the ball's speed (but only in the Y direction!):
private const float Y_SPEED_DECREASE_BY = 0.011f;

• You've seen everything else in previous tutorials
• InitializeWorld():  protected override void InitializeWorld() {     World.SetWorldCoordinate( new Vector2(0,0), 100.0f);     // initialize the soccer ball     InitializeSoccer();     // Initialize the X and Y speed     m_XSpeed = INIT_SPEED_X;     m_YSpeed = INIT_SPEED_Y;     PlayACue( "Launch" ); }
• In order to make sure that everything is properly initialized, we'll need to add some code to the InitializeWorld method.  The first two (new) lines of code simply copy the values of the appropriate named constants into the appropriate instance variables:
m_XSpeed = INIT_SPEED_X;

m_YSpeed = INIT_SPEED_Y;

• After that, the program then plays a sound, in order to provide audio feedback to the user that the game is starting.
• You'll notice that playing a sound isn't really an "initialization" activity - it doesn't set things up for the game.  By putting the 'play sound' command here anyways, we're taking advantage of the fact that InitializeWorld is run once, and only once, and it's run prior to the start of the ' Draw and Update Cycle '.
• It's probably best to put any such 'start of game' actions at the end of InitializeWorld, like we've done here. That way, InitializeWorld first initializes the game, then it goes on to do any 'start of game' actions, then the ' Draw and Update Cycle ' runs until the game exits.
• UpdateWorld():  protected override void UpdateWorld() {     if (GamePad.ButtonBackClicked())         this .Exit();     // Step 1: move the soccer     MoveSoccerByThumbStick();     // Step 2: Update soccer y-speed, by fake gravitational pull     UpdateSoccerYSpeed();     // Step 3: Compute new soccer position     ComputeSoccerPosition();     // Step 4: Compute soccer size     ComputeSoccerSize();     // Step 5: Print message for the user     PrintMessageForUser(); }
• The check for exiting the game, the first step, and the last two steps are unchanged.
• In the new Step 2, we will update the ball's speed in the Y direction, as detailed below.
• In the new Step 3, we will update the ball's position, based on the ball's current speed, as detailed below.
• You'll notice that the actions are undertaken in a very particular order here:
1. Does the player want to exit the program?  If so, exit.  Otherwise, keep going.
2. Do everything that involves processing input, and/or updating things like the ball's speed, in steps #1 and #2
3. Once we've gotten the new speed, we do everything that involves changing the position and size of the ball, in steps #3 and #4.
4. Finally, print out the status messages to the player, in step #5
• UpdateSoccerYSpeed():  /// /// Update soccer y-speed, by fake gravitational pull /// private void UpdateSoccerYSpeed() {     m_YSpeed -= Y_SPEED_DECREASE_BY; }
• This function adjusts the Y speed of the ball by subtracting Y_SPEED_DECREASE_BY from m_YSpeed (and then assigning that new value back to m_YSpeed ).
• ComputeSoccerPosition():
 /// /// Compute soccer ball's new position according to the X and Y speeds /// private void ComputeSoccerPosition() {     m_TheSoccer.CenterX += m_XSpeed;     m_TheSoccer.CenterY += m_YSpeed; }
• Once the current speed has been calculated, then the ball should be moved along by that speed.  We do that by adding the current value of the X speed, and the Y speed, to the current X and Y part of the circle's center's location.
• You'll notice that the PrintMessageForUser has also been (trivially) modified, so that it prints out a slightly different message to the top of the screen.

FURTHER EXERCISES::

1. Start from a blank starter project (1000.201, if you need it), and re-do the code from memory as much as possible.  On your first try, do what you can, and keep the above code open so that when you get stuck, you can quickly look up what you forgot (and that after you finish a line, so that you can compare your line to the 'correct' line).  On the next try, do the same thing, but try to use the finished code less.  Repeat this until you can type everything, without refering the tutorial's code.
• Repeat this exercise daily for several days, so that you really get the hang of this.  As you go on, periodically review this by re-doing this exercise.
2. Initializing the Velocity In A Separate Function
For this exercise, you should use the same project that was explained in the above tutorial.
In the example code provided with this tutorial, the velocity of the ball was initialized in the InitializeWorld method, while the ball itself was initialized in the InitializeSoccer method.  For this exercise, you should take the code that initializes the ball's velocity, and put it into a new, separate function.  Make sure that you call that from InitializeSoccer.