Tuesday 15 May 2012

Generating smooth roads for top-down racing games on-the-fly

Prologue:

I am making a fake 3D racing game (like a lot of flash games you have seen). It looks like a first-person racing game, but doesn't use any 3D functions. Why not real 3D, you may ask and the answer is quite simple:
a. Not every game development tool has 3D support
b. It will be lot faster if designed correctly.

When I was creating the tracks, I was a lot bored and it was a tiring task to lay long tracks by hand just for testing. So, I decided to code for dynamic random road generation, so that I will never run out of road :D

The beginning:

At first, I thought it would be quite easy, you know like:

 Generate random points within a small distance and join them to make a road.

But the major flaw that surfaced quickly was that the road was not at all smooth, it was like throwing away some chunk of concrete at places.
My thought was like:
This is not how roads really look like :(
So, I decided to come up with a new approach to tackle this problem and
the next day, I came up with this solution.

Main concept


 The idea is pretty simple. You'll need to have a knowledge of how sine curves are drawn on graphs.
We won't need any transformation matrices for this.

Note: 
1. The co-ordinate system is same as traditional, but the origin is at the bottom-center of the page.
   So, Y is always positive and X can be both be positive and negative upto a certain extent.
2. Co_eff is a constant value which constrains the maximum X co-ordinate of the road in order to
    fit it within the view. It is used as the amplitude of the sine curve.

First of all, I decided that that only full sine curves (one total period) will be used to avoid complexity.

 This also gave me one added advantage of smoothness of the curves even when one sine curve ends and a new one is drawn.

This are the steps for generating the first curve … The rest will follow similarly...

Steps:

1. Generate a random value  (within a  suitable range) and store it as y1
    This y1 value is the (relative) height (distance in the y direction) at which one full sine curve
    terminates.

2. Now, as we know, sine curves have a period of 2⊼ radians.
   But, in our case, the sine curve should start exactly at the current point and terminate exactly at the next
  point (0,y1) [relative to the current point].
  So, we need to find a variable named "value" such that y1=2⊼*value
  We will use a factor of (1/value) with the independent variable [here y-coordinate]
  (as the curves are drawn along y-axis, so the x-coordinate of the initial and final
   point doesn’t change. So, we don’t care about the x-coordinate)

3. Now, draw the curve “ x=co_eff*sin(y/value) ” starting from the initial point.

It will look like this:

Last words...

When I was first thought of this whole dynamic road generation thing, I asked one my friend on Facebook for his view on this matter. From what I could make out, he had a better but not-so-simple approach in mind. So, we decided to make a shared  Google Doc about this and I wrote about this concept there.
As of now, he's working on his version of this solution and hopefully, he will soon be done with it, and we can have a better version in this blog...

2 comments:

  1. You can try to generate dynamic roads on unity3D as of it’s also one of the best platform to create 3D games.

    ReplyDelete