PowerBuilder Tips, Tricks, and Techniques

Berndt Hamboeck

Subscribe to Berndt Hamboeck: eMailAlertsEmail Alerts
Get Berndt Hamboeck: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

Related Topics: Game Developer

Game Developer: Article

XNA or Game Development for Everyone - Part 2

Restructuring the game

Implementing the Collision Check
Let’s open the solution from last month (or download it from my blog at http://hamboeck.blogspot.com/) and create a new instance variable in the Game class, which will soon hold the newly created track texture:

Texture2D trackCollision;

Next we have to add the gray and white track file to the content folder and load it in the LoadContent function below the line. Last month this was where we loaded the track image by using the line:

trackCollision = Content.Load<Texture2D>(“TrackC”);

Finally we need to check if the predicted position is still on the track. If it’s not, we will stop the car. There is room for improvement here, as it’s not very natural that a car suddenly stops or that a racing car is not able to drive on the green (even a Formula One car can do this), but for simplicity’s sake (to keep the article short) we’ll keep it this way. One way to enhance this is to use another color where the car can drive, but only slower. Just make the change to the collision image. Let’s say we use this new color where the users see green on the screen, but we move on and implement the check on our simplified background image. The correct place to enhance our application is the update method, where we have already calculated the amount of the movement based on the elapsed time last month:

float toMove = (int)(player.carSpeed *

Last month we simply moved the cars ahead, based on the current rotation:

player.carPosition.X += (float)
(toMove * Math.Cos(player.carRotation));
player.carPosition.Y += (float)
(toMove * Math.Sin(player.carRotation));

This piece of code needs to be changed so we can first check for a background collision. If there is a collision, we simply won’t move anymore; if there isn’t a collision, we move ahead.

float newX = player.carPosition.X +
(float)(toMove * Math.Cos(player.carRotation));
float newY = player.carPosition.Y +
(float)(toMove * Math.Sin(player.carRotation));

if (!BackgroundCollisionDetection(player, (int)toMove) &&
!PlayersCollisionDetection(player, newX, newY))
player.carPosition.X = newX;
player.carPosition.Y = newY;
player.carLastGoodPosition = player.carPosition;

As you can see, we introduced two new functions. The first one checks if the car is about to leave the track, which is definitely not allowed. We implement a simple check by getting the background color of the predicted position. For the background color we get a few expected values:

  • Gray means we’re on the track.
  • White means we’re leaving the track; this should be handled as a collision and the car should not continue to drive.
  • Black means the car is on the start/finish line.
  • Red means we are a little bit away from the start/finish line and a waypoint should be passed before we cross the start/finish line again.
  • Green tells us that the player passed a waypoint and driving through the start/finish line is fine.

The only tricky part is to get the background color. This is done by calling the generic GetData function, which expects a rectangle – created by using the passed X and Y coordinates plus 1 pixel each – on our newly created track image texture and returns exactly what we need for the background color. A more sophisticated algorithm would be to get all the underlying pixels of the car, not only a pixel on one specific point, but the simpler algorithm shows you the idea behind it pretty well – see Listing 1 for the implementation.

Car Crashes
The other new function we introduced in the last paragraph was the PlayersCollisionDetection function, which expects the current player and the predicted new location as arguments. There we will implement the most simple collision detection algorithm, one where all the needed functions are built into XNA. We create two boundingboxes: one for the current player and another one for the player we want to check for a collision. The boundingbox is half the size of our cars. With the boundingboxes in hand, we simply intersect them. The nice thing is that this would also work in a 3D game, but our game world is just 2D, so we don’t need the third axis, so the parameter is 0. If the two boundingboxes overlap, we have a collision and the player can not move ahead – see Listing 2 for the source code.

Game States
Our game gets better and better, but we should look at the game states, because this will have a major impact and we will have to shuffle around our existing code a bit. At the moment, we run the project and the cars immediately start to drive around. For a real game this is not the way it would be. The users expect an intro, at least some kind of menu to configure the game and to choose different options, such as the number of players and maps. Also at some point a race is over and the player wants to see the results, for example, the rankings for the finished race and the overall rankings if it’s a championship. This is more or less what game states are. The game needs to know the current state and provide the users the correct options. When we look at our game, I recommend implementing the following game states:

  • Intro: Our users should know who wrote this great game and this is definitely the place to do some marketing for ourselves.
  • MainMenu: From here the users choose what happens next.
  • NetworkGame: A multiplayer game where other human players will join the network game and compete in a single race or a whole championship.
  • LocalGame: A single player game where the other players will be handled by the computer.
  • HighScores: The fastest laps should be stored somewhere. This will make the game more attractive as users might play the game longer to beat a high score.
  • Options: Everything that can be configured, like the user’s name, the car color and so on.
  • LevelDesigner: As you might remember this was my main goal: to write this game myself as the existing tracks might get boring after a while and users might want to crate their own tracks.
  • Nothing: Not really game state, but something that we set, for example, per default.

This translates directly into a C# enumeration, which you can see in Listing 3.

More Stories By Berndt Hamboeck

Berndt Hamboeck is a senior consultant for BHITCON (www.bhitcon.net). He's a CSI, SCAPC8, EASAC, SCJP2, and started his Sybase development using PB5. You can reach him under [email protected]

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.