Home > Games Programming, My Thoughts, Programming, XNA > Fuchs Navi Wheel – A Creative way of steering a car in a game

## Fuchs Navi Wheel – A Creative way of steering a car in a game

#### Introduction:

One day while I was studying for an exam then an idea came to my mind!
Wouldn’t it be cooler to use the touchpad to steer a moving car (instead of the boring Left\Right keys)?

I’m not a big fan of racing games but I liked the idea…
To simulate rotating a real steering wheel the player should create circles on the touchpad, counter-clockwise (ccw) to steer left, clockwise (cw) to steer right.

Moving the finger in such a way should continuously steer left

This might be harder than just using Left\Right buttons for steering, but I found the idea interesting :D.

#### Algorithm:

I used XNA to implement the idea, but all I needed is the last three mouse positions & some simple math, so it can be programmed easily anywhere…

The main idea is to calculate the angle between two vectors, assuming that the positions are p1, p2 and p3 (where p3 is the last position of the mouse):
The first vector v1 goes from p2 to p1

v1 = p1 – p2

The second vector v2 goes from p2 to p3

v2 = p3 – p2

We then normalize the two vectors to make there lengths equal to one.
The dot product of two vectors is :

u.v = |u|*|v|*Cos(a)

where u, v are the two vectors, |u|, |v| are the lengths of the two vectors, a is the smallest angle between the two vectors..

(dot product is commutative which means u.v = v.u )
Since we normalized the two vectors:

v1.v2 = |v1|*|v2|*Cos(a)

assuming that v1.v2 is equal to x (XNA has a method Vector2.Dot) :

x = 1*1*Cos(a)  = Cos(a)
a = ACos(x)

in other words 🙂  : the angle between two normalized vectors is equal to ACos(x) where x is the dot product of the two vectors..

After getting the angle we need to check its value to make sure that the mouse is moving in some sort of a circular path, to do so we check if the angle is near to something like 145 degrees (got the value by trying different values)

if |angle-145|<30 proceed with the operation

We now have to determine the sign of the angle (which dot product cannot provide).
The sign of the angle determines whether the mouse is moving clockwise or counter-clockwise.
To do so we use the cross product of two 3D vectors that we build from v1 & v2 by setting there Z component to zero, we now have two 3D vectors v3, v4 that exist in the xy plane of a 3D world where the xy plane is the screen.

The cross product of two vectors gives us a third vector that is perpendicular to both vectors, so the cross product of v3, v4 should be one of two:
1-pointing outside the screen (Z>0)
2-pointing inside the screen (Z<0)

Please note that cross(v3,v4) is in the opposite direction of cross(v4,v3), cross product is not commutative

so to get the final angle :

sign = cross(v3,v4).Z
angle *= sign

The angle is now ready 🙂 it might be positive or negative depending on how the mouse is being moved in this frame (cw/ccw).

We have to run this algorithm repeatedly, at most once per frame.

#### XNA Implementation:

I created a static class that impements the previous algorithm with some modifications & additional options, I didn’t know what to call it 🙂 so I named it after the Navi wheel found in some Nokia phones ( like my Nokia N78 )…

FuchsNaviWheel 😀 , I wont post the code here, you can view it from the source code below…

#### Sample:

I made a very simple sample to test the class, A tank with a road in yellow, try to follow the

In this video you can see the mouse movement & how it affects the tank.

#### Source Code & Excutable:

Here’s the source code (VS2010 + XNA4)

Three projects ( including the content project ):
1-FuchsNaviWheel: The project that produces the dll of the navi wheel, you might wanna change some values there since I didn’t test it for a racing game :).
2-FuchsNaviWheelLab: The project that tests the dll.
3-FuchsNaviWheelLabContent : just the content for the second project :|.

Here’s the dll of FuchsNaviWheel

& Here’s the demo from the video if you want to test your driving skills :).

Some notes :
1-The static class FuchsnaviWheel needs to be updated once per frame.
2-FuchsNaviWheel.Interval is the time ( measured in frames ) to capture a new position from the mouse.
3-FuchsNaviWheel.Steering is the steering that happened this frame.
4-FuchsNaviWheel.TotalSteering is total amount of steering since the start of the game.
5-FuchsNaviWheel.SmoothSteering similar to TotalSteering but its absolute value is reduced each frame to give a smooth steering ability.

#### Final words:

It was fun programming such a thing :), Especially when your touchpad doesn’t support such gestures :(… I might create an application for Windows & implement some other cool gestures , for example instead if steering a tank, the Right\Left keyboard button will be pressed to view the next\previous image in an image viewer :D.