## Introduction

This is the first instalment of a series of tutorials in which we aim to make a 3D Driving Simulation Game. With every successive tutorial, we will try to make the game cooler by adding new features in graphics, physics and gameplay. The aim of this first tutorial is to simulate a car over an infinitely large plane. I know this is not exactly what we have in the real world. But we will get more realistic in later tutorials. For now, imagine the world as a perfect plane with no obstacles.

## Background

This article is not for the absolute beginner. A basic understanding of XNA Game Studio 2.0 is necessary. But If you are a beginner, I would suggest the following:

- Download and Install Microsoft Visual C# 2005 Express Edition, its SP1 Update, and XNA Game Studio 2.0. All these can be downloaded free of cost from www.microsoft.com.
- Go through the 'XNA Game Studio Documentation', especially the articles 'Your First Game: Microsoft XNA Game Studio in 2D' and 'Going Beyond: XNA Game Studio in 3D'. These tutorials are fairly easy to comprehend.
- Go through the Riemer's XNA Tutorial. Reading all the 3 tutorials will give you a very good understanding of XNA. But for now, the first 2 tutorials are sufficient. The concept of Quaternions should be clearly understood.

Reasonable Knowledge of Newtonian Mechanics and Geometry is necessary to understand the formulas.

## Using the Code

The application has been divided into three classes `Game1`

, `Stuff`

, `Car`

. The class `Stuff`

represents any material body that can be rendered on the screen. The class `Car`

is a specialization of the Class `Stuff`

which represents a `Car`

. The class `Game1`

is the main application and uses objects of `Stuff `

and `Car`

.

Let us first understand the class `Stuff`

. If you go through the code, you will see that I have tried to encapsulate everything required to store information of any material body and render it on screen. I am only providing an overview of the member variable and function since the code is fairly straight forward.

- The members
`viewMatrix`

and `projectionMatrix`

are `static `

because they are the same for all renderable objects. - The members
`position`

and `rotation`

represent the position of the object and its orientation respectively in 3D Space. - The member
`cameraRotation`

represents the orientation of the camera. Storing this is necessary to achieve the effect of camera delay. - The member
`model`

represents the 3D Model of the body. - The function
`UpdateCamera`

updates the `viewMatrix`

according to the position and orientation of car. - The function
`Draw`

renders the 3D Model on the screen.

Now for the most difficult part - understanding the class `Car`

. There are two concepts at work. The first one is the effect of hitting the accelerator, releasing it, and braking on the cars motion. The second one is how the car turns when the steering is turned left or right.

The first concept. At any instant, the car is in some gear represented by the variable `gear`

. The speed of the vehicle determines the `gear`

. We have the top speed at each `gear `

stored in the variable `topSpeeds`

. The top speed at `gear x`

is also the minimum speed for `gear x+1`

. The acceleration is different at each `gear`

.

public void Accelerate()
{
free = false;
if ((gear<7)&&(speed > topSpeeds[gear]))
{
gear++;
}
if (gear == 0)
{
acceleration = accelerations[1];
}
else if (gear < 7)
acceleration = accelerations[gear];
else
{
gear = 6;
acceleration = 0;
speed = topSpeeds[6];
}
}

Now when the brake is applied, the effect is that a negative acceleration whose magnitude is the acceleration at that `gear `

added to a constant as shown. Here you also have to consider the reverse `gear `

and the maximum speed in reverse.

public void Brake()
{
free = false;
if((gear>0)&&speed<=topSpeeds[gear-1])
{
gear--;
}
if ((gear == 0) && (speed < -maxReverseSpeed))
{
acceleration = 0;
speed = -maxReverseSpeed;
}
else
{
acceleration = -accelerations[gear]-6.7f;
}
}

Also when the accelerator is released, even then a negative acceleration with magnitude same as acceleration at that `gear `

has to be applied. And eventually the `car `

comes at rest.

public void Free()
{
free = true;
if ((gear>0)&&(speed < topSpeeds[gear - 1]))
{
gear--;
}
acceleration = - accelerations[gear];
}

To determine the new position of car after every instant, the following code is placed in the `Update`

method.

float speed = speed + acceleration * time;
float dist = speed * time;
Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotation);
position += addVector * dist;

To make sure the car eventually comes to a stop when neither accelerator nor brake is pressed, this code is used:

float newSpeed = speed + acceleration * time;
if ((free == true) && (newSpeed * speed <= 0.0f))
{
gear = 1;
acceleration = accelerations[gear];
speed = 0.0f;
}
else
speed = newSpeed;

Now let us understand how a car turns. When the driver steers left or right, the plane surface makes an angle theta with the body of the car as shown in the figure. Theta should uniformly increase from to 0 to a Maximum Value. Also when the steering is left free theta should eventually become zero. The code for this is as follows:

if (turn == 0)
{
float newAngle = steerAngle;
if (steerAngle < 0.0f)
{
newAngle = steerAngle + time * steerSpeed;
}
else if (steerAngle > 0.0f)
{
newAngle = steerAngle - time * steerSpeed;
}
if (newAngle * steerAngle < 0.0f)
{
steerAngle = 0.0f;
}
else
steerAngle = newAngle;
}
else
{
if (turn == -1)
{
float newAngle = steerAngle - time * steerSpeed;
if (newAngle < -maxSteerAngle)
{
steerAngle = -maxSteerAngle;
}
else
{
steerAngle = newAngle;
}
}
else
{
float newAngle = steerAngle + time * steerSpeed;
if (newAngle > maxSteerAngle)
{
steerAngle = maxSteerAngle;
}
else
{
steerAngle = newAngle;
}
}
}

Now that we have understood how the tire turns, let us figure out how the `car `

turns. Look at the figure carefully:

You will at once understand what the constants `HD`

,`VD`

and `L`

represent. `O`

is the origin of the 3D Model. We assume that the `car `

will rotate about the point marked "Center Of Turning" with radius `r`

. The value of `r `

can be calculated using trignometry:

float x = (VD / Math.Abs((float)Math.Tan(steerAngle)) + HD / 2);
float r = (float)Math.Sqrt(x * x + L * L);

Now we have the radius. The angle by which the `car `

rotates can be found out and corresponding `Quaternion`

is created.

float theta = speed * time / r;
if (steerAngle < 0.0f)
theta = -theta;
rotation = rotation * Quaternion.CreateFromAxisAngle(new Vector3(0, -1, 0), theta);

New the `position `

of `car `

can be determined as follows:

speed = speed + acceleration * time;
float dist = speed * time;
Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotation);
position += addVector * dist;

The rest of the code is pretty much straight forward.

I would like to thank my friend, Tarang Bakshi, for his help with the game physics and ideas.

## History

- 14
^{th} September, 2008: Initial post