Racing game: determining positions

I haven’t yet found a living post (that is, one that has non-dead links) that answers this, so I’ll ask it here: What kind of options do I have for giving a racing game a position system? It’d be nice to have a solution that doesn’t depend on specific parts of another game, so I’m not limited in implementing it.

On page 5, saluk gave me a perfect explanation of how it could be done. Its just a set of collision check points put around the track(basically a large plane which has been duplicated a few times in edit mode.), and then you use a simple mathmatical formula to calculate the place for each vehicle.

It took awhile to implement and to get working, but once it did, it worked perfectly.

You can see how I did it in the actual game blends which can be found in this thread… http://blenderartists.org/forum/showthread.php?t=70379

Hope this helps!

Hmm… The idea definately shows promise. However, I’m worried about what happens when two cars are close to each other. Because they both touched the same checkpoint last, wouldn’t they be considered “tied”, even if one is obviously ahead of the other?

When two cars are between the same pair of check points, you can do an additional calculation to determine which one is in front of the other.

A simple scheme is to calculate which car is closer to the next check point, although this might still sometimes fail.

A somewhat improved scheme calculates each car’s projection on the line segment between the two checkpoints, assuming on a curved track you place them close enough to each other.

Here is Python code to calculate the length (d) of the projection:

``````
u1 = checkpoint1.getPosition()  #previous check point
u0 =  checkpoint0.getPosition() #next check point
p1 = car.getPosition()

u = [u1[0] - u0[0], u1[1] - u0[1], u1[2] - u0[2]] #vector between check points
p = [p1[0] - u0[0], p1[1] - u0[1], p1[2] - u0[2]] #vector between car and previous checkpoint
d = (u[0]*p[0] + u[1]*p[1] + u[2]*p[2])/sqrt(u[0]*u[0] + u[1]*u[1] + u[2]*u[2])

``````

The last line will make sense only if you know a bit of vectors.
Form trig:
d = |p|cos alpha,
with alpha the angle between the two vectors u and p. But
cos alpha = u dot p / (|u||p|), so

d = |p|u dot p / (|u||p|)
= u dot p /|u|

The following is a very crude picture of this (I would upload a proper image, but we cannot FTP today…

``````
p1 (car
/|
/ |
p  /  |
/_d_|____________
u0          u          u1

``````

The angle between p and u is alpha, p1 is where the car is, and u0 and u1 are thwe two checkpoints.

So you calculate d for each car, and see which one is bigger - that car is in front.

well, its not perfect, but it does the job.

If you have alot of checkpoints(I had like 20 something for my egypt track), then it will be relatively reliable.

Just make sure to have the last checkpoint right at the finishing line…that way, the person who is really in front will actually win in the end.

Okay. How would I get the checkpoint objects? I know I can do getObjectList(), but I don’t know what to do so that I get a list of all the checkpoints (they’re all called Checkpoint.0##) and only the checkpoints. As of right now, I only know that you can get a single object by adding its name in square brackets after the round brakets.

I’d use a list and a for loop. like

``````
checkpoints = ["OBcheck.001","OBcheck.002"]
for name in checkpoints:
obj = scene.getObjectList()[name]
obj.doSomething()

``````

But personally, and i really don’t know much about this. It seems like you’d have the checkpoint get the collision object and then save it to a GameLogic list, or a scoreboard.

I used a collision sensor. Each time the car ran into one checkpoint, it added to a global property(ie, last checkpoint hit, this would be needed to do the calculation too.). For the next checkpoint, the “last checkpoint hit” property had to equal a certain value for that checkpoint to register as being hit.(ie, after hitting checkpoint#1 the “last checkpoint hit” property would = 1, and checkpoint#2 would only register if that property equaled 1…that way, the player can turn around and drive backwards without the placement or lap counting screwing up.)