XNA GameStudio 2.0
Making The Ball Move

Game States

When we wrote the Ball class, we thought about the need for variables to store the position and speed of the ball so that we can change it in the game. There is a bit more to it than that though. The ball isn't normally moving until someone 'kicks off'. When a player scores a goal, it is usually the other player who gets to 'kick off'. Our game will always be in one of the following states,

  • 0 - Ball Moving
  • 1 - Waiting For Player 1
  • 2 - Waiting For Player 2

We are going to add a field to keep track of these game states. We will add this to the fields at the top of the Game1.cs class. We will write statements to change the value of this field at different times so that we know what the ball should be doing.

// 0 - Ball Moving
// 1 - Waiting For Player 1
// 2 - Waiting For Player 2
int gamestate = 1;

The first 3 lines are comments. They don't do anything when the program runs, they are there to remind us of what our numbers mean.

Start The Ball Moving

To start the ball moving, we need to change the game state to 0, and set it off away from the player who kicks off but with some random element.

Copy the following procedure into the Game1.cs class. The second line is a shocker, I know. Basically it sets the X movement each game loop to 5 and the Y movement to a random number between -3 and 3 (increase this range to make the kick off more angular). We multiply the X velocity by -1 if player 2 is kicking off, sending the ball in the opposite direction. Finally we change the game state so that our program knows that the ball is now moving.

public void StartBallMoving()
{
   Random randNum = new Random();
   ball.velocity = new Vector2(5.0f, MathHelper.Lerp(-3.0f, 3.0f, (float)randNum.NextDouble()));
   if (gamestate == 2)
   {
      ball.velocity.X *= -1.0f;
   }
   gamestate = 0;
}

The next thing we need to do is add some lines of code to the HandleInput() method that we wrote earlier.

if (gamestate == 1 && kbState.IsKeyDown(Keys.D))
   StartBallMoving();
if (gamestate == 2 && kbState.IsKeyDown(Keys.Left))
   StartBallMoving();

This connects the StartBallMoving() method to the program - the code is executed if, when the game is waiting for a particular player to kick off, that player presses their kick off key.

The last job for kicking off is to make sure that the ball moves. Go to the Update() method and below the line that says HandleInput() and add the following lines,

if (gamestate == 0)
{
   ball.Update();
}

You can test this feature now. The ball should shoot off to the right when player 1 kicks off. If you change the gamestate field declaration at the top of the class to, int gamestate = 2;

... the ball shoots off the other way.

Dealing With Off-Screen Behaviour

When the ball goes off the left of the screen (its X position is less than zero) player1 kicks off. When the ball goes off the right of the screen (its X position is greater than 800 or the height of the screen if you changed it) player 2 kicks off. We also have to return the ball to the centre spot ready for kick off.

Return to the Update() method and underneath the line ball.Update(); add the following,

if (ball.position.X < 0)
{
   gamestate = 1;
   ball.position = new Vector2(400.0f - ball.sprite.Width / 2, 300.0f - ball.sprite.Height / 2);
}
if (ball.position.X > 800.0f)
{
   gamestate = 2;
   ball.position = new Vector2(400.0f - ball.sprite.Width / 2, 300.0f - ball.sprite.Height / 2);
}

Test out all of the kick-off functionality.

Dealing With Off-Screen Behaviour #2

The ball can also leave the screen by going off the top or bottom. In this case the Y part of the ball's position will be less than 0 or greater than 600 (the height of the screen as we defined it). No lives are lost, no goals scored when this happens - the ball bounces off the top.

Directly beneath the last set of statements that you added to the Update() method, add the following,

if (ball.position.Y < 0 || ball.position.Y > 600.0f)
{
   ball.velocity.Y *= -1.0f;
}

By multiplying the Y part of the velocity by -1, we are sending the ball in the opposite direction. This works whether the ball goes off the top or bottom.