Main Site Links Resources Tutorials
News VB Gaming Code Downloads DirectX 7
Contact Webmaster VB Programming Product Reviews DirectX 8
  General Multimedia Articles DirectX 9
      Miscellaneous

Immediate Mode: Character Movement
By: Jack Hoxley
Written: August 2000
Download:
IM_CharMove.Zip (14kb)


Character movement is not technically a Direct3D topic - it's actually 2D. It comes in here as it's a perfect model of how 3D games and engines move the player around, and I'm getting lots of messages from people wanting to know how this works...

In this sample there will be no collision detection, and we will only be working in 2 dimensions (X and Y). The problem is - "If my character is facing 312 degrees, what is the vector to move it along a line of that angle?"

It basically involves some simple maths, commonly referred to as the "Unit Circle". We know that if that character is moving up the Y axis we have the vector [0,-1] and if it is going down [0,+1] Left and right are [-1,0] and [+1,0] respectively. But what if it's not going straight up/down/left/right?

If you look at this diagram I will explain:

Okay, so we want to find out the coordinates "X,Y" when we have the angle "A". We use these two formula's:

X = r * Cos(A)
Y= r * Sin(A)

But because the radius is always one (so we end up with normalized vectors) we can simplify this as:

X=Cos(A)
Y=Sin(A)

That's all very well, but when you're writing the code, you need to use radians rather than angles - otherwise you get some truly weird results. In Code this will look like:

Const Pi as single = 3.14159
Const Rad as single = Pi / 180
Dim X as single,Y as single,A as integer, Theta as single

Theta = A * Rad
X = Cos(Theta)
Y = Sin(Theta)

You can now get a correct vector based on the angle that the player is at...

BUT, using Cos( ) and Sin( ) in your game loop is not good for speed - and it's a little awkward to use. The easiest solution is to use a lookup table. On the first loop we calculate all the possible angles, then fill an array with the vectors for [easy] use later.

This code will generate a lookup table:

'## These parts go in the (declarations) section
Const Pi = 3.14159
Const Rad = Pi / 180
Dim VectorCircle(360) as D3DVECTOR

Sub GenerateVectors
Dim I as integer,Theta as Double

For I = 0 to 360
Theta = I * Rad
VectorCircle(I).X = Cos(Theta)
VectorCircle(I).Y = Sin(Theta)
'We dont need to use the .Z coordinate...
'You could use it if you want to move up and down slopes

Next I

End Sub

So we now have a table of all the vectors we need. Now we need something to use it with. We'll use a D3DMatrix to translate an object around. Assuming that the player can press Left/Right to alter the angle and Forward/Backward to move. In a first person shooter (half-life/Quake) the mouse would control the rotation (left/right). If you dont understand matrices read through the other tutorials on this page.

Dim matPlayer as D3DMATRIX,matTemp as D3DMATRIX
Dim vPlayer as D3DVECTOR 'Holds it's position
Const Rad = 3.14159 / 180
'I am assuming that "PlayerRotation" is a valid integer that represents a number 0 - 360

Dx.RotateYMatrix matPlayer, PlayerRotation * Rad
vPlayer.x = vPlayer.x + VectorCircle(PlayerRotation).x
vPlayer.z = vPlayer.z + VectorCircle(PlayerRotation).y
TranslateMatrix matTemp, vPlayer
Dx.MatrixMultiply matPlayer, matPlayer, matTemp

Done. Assuming that the user can alter the rotation and specify forward or backwards the player will move smoothly and precisly across the world. You will need to alter the "vPlayer.x = vPlayer.x +...." line so that it can have a "+" for moving forward and a "-" for moving backwards. Finally, you may well have noticed that I'm using the vPlayer.z value rather than the vPlayer.y value - this is because of the way the 3D world works - and Y is up/down. Change it and see what happens....

You can download a working example from the top of this page, or from the downloads page.

DirectX 4 VB 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster