Sign in to follow this  
Jurgen

interesting problem, outrun type of game

Recommended Posts

I'm trying to make a game as a hobby project. It's a classic racing game clone, like outrun and the lotus series. So it has this 3rd-person pov from behind the car with the landscape moving under you. Like a conveyor belt. Everything works fine until i want to add hills. On a flat surface, it's easy to fake a 3d effect for the curves. When i want to add hills i keep on running into problems. The hills and curves distort when moving forward (and that's what you want in a racing game ;) ). I want to use a minimum of 3d math since i think it shouldn't be necesary for such a simple game (web based). I just want to 'fake' the effect. Of course some 3D math will be needed. I was struck by the elegance of bezier curves and i think somehow the solution is to be found there. Basicaly, the center of the track, or the two sides of the track can be bezier curves. I draw them and that works fine, but the problem is in animating this curve in such a way that it appears to give the desired semi-3D effect. Some considerations i made: -a bezier curve in 3d can be easily projected to the screen by only projecting the four control points. -I would like to define a track by just saying how much the gradient is or how much the curve rate is. So the track would be described by a kind of dx/dz and dy/dz functions (could just be arrays of course). -Distance (z)is also a problem. There is track distance and real distance. When a track is defined as a dx and dy for every, say, 50 meters of track, we have to do a lot of calculating(sqrt) to find the real distance, needed for example for scaling objects and for rendering the iterating colors on the floor (as typicaly seen in those kind of games). My questions are: -Can it be done in this way, without using full 3d calculations? -Is this approach the approach i should take? -Does anyone have hints on how to implement this? help is greatly appreciated, Jurgen

Share this post


Link to post
Share on other sites
I'm not going to comment on the hills/curves, since I'm not sure of the "best" method to do what you need. My suggestion would be simply if you can do it quickly, then go with Bezier Curves. If not, consider something like splines. If that doesn't work, linear approximation or polygonal representations are fast, and smooth enough for a good number of professionally designed games.

As for the computation of z, you don't need to compute the square root more than once. Like with sine, cosine, and tangent, you should create a table of information for the square roots. By hand, compute the largest square you'd ever really need, and pick the next largest integer for the "cap", call it n. Then make a table from between 0 and n, using some fraction you like and use linear approximation to find about the square root of some number:


float squareOf[n*4];

//...
for (int i=0;i<n*4;i++)
squareOf[i]=sqrt(i/4.0);

//...
float fastSqrt(float m)
{
// Binary search, O(log n) time
int currentPosition=n*2; // n*4 / 2 = n*2
int previousPosition=0;
int tempPosition;
float lowDistance;
float highDistance;
float delta;

if (m>squareOf[currentPosition]) previousPosition=n*4-1;

while (true) // Not essential to be an infinite loop
{
if (m==squareOf[currentPosition]) return currentPosition/4.0;
if (m>squareOf[currentPosition])
{
if (previousPosition==currentPosition+1)
{
// Linear approximation
delta=squareOf[previousPosition]-squareOf[currentPosition];
lowDistance=(m-squareOf[currentPosition])/delta;
highDistance=(squareOf[previousPosition]-m)/delta;
return (squareOf[currentPosition]*lowDistance +
squareOf[previousPosition]*highDistance)/4.0;
}
else
{
tempPosition=abs(previousPosition-currentPosition)/2;
previousPosition=currentPosition;
currentPosition+=tempPosition;
}
}
else // if (m<currentPosition)
{
if (previousPosition+1==currentPosition)
{
// Linear approximation
delta=squareOf[currentPosition]-squareOf[previousPosition];
lowDistance=(m-squareOf[previousPosition])/delta;
highDistance=(squareOf[currentPosition]-m)/delta;
return (squareOf[previousPosition]*lowDistance +
squareOf[currentPosition]*highDistance)/4.0;
}
else
{
tempPosition=abs(previousPosition-currentPosition)/2;
previousPosition=currentPosition;
currentPosition-=tempPosition;
}
}
}
return 0.0; // To avoid warnings.
}


I wouldn't recommend copy/pasting this code into your game, as I just wrote it and I don't know how well it work. Still, that's how I would do it. Or at least something like that.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Oh boy, I've always wondered how this was done too! I hope someone can shed some light on it for us!!!

[/may sound sarcastic, but I'd really like to know]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this