0 votes

Hey gang, so basically i was trying my hand on making a game kind of like "Mario Kart 64" (You know, with beautiful Sprite3D racers and stuff)

I got it working pretty much, fooled around for a while, had some fun, but then it hit me...

How do racing games code for vehicle positions? Pretty much every racing game in existence has something in the GUI showing your place, and this thing updates in real time.

I thought up a few methods but none sound like the best or most efficient way of doing it, the most convincing one was having some kind of pathfinding AI trying to "travel" from each car to the finish line and then "sorting" the cars from closest to furthest.

But anyways... how does it work?

Thanks in advance!

Godot version 3.2.2
in Engine by (309 points)

Are you trying to get the progress of the racers along the track?
If so you can use checkpoints, it's a common way to measure a player's progress.
You can also use a path to define the track for more flexibility and precision.

Im just trying to know how "most" (I figure not all games do it the same way) check for each car's position, i dont care about track progress %, just who's coming in first place, second place, third, and so on.

I figured checkpoints carefully placed along the track and a simply using "distance_to" (No pathfinding or fancy stuff) to the next checkpoint + the cumulative distances between the remaining checkpoints, and then the lowest number is first and so on.

But i want to know if there are better ways

I tried to calculate the ranking of players using the track progress because it doesn't need a lot of work.

I created a path and simply trace the track. Then made some PathFollow nodes to track down the players' progress. Then finally, sorted the players based on their progress.

So even though you don't need the players' progress, it's helpful for sorting the players.

One problem though is that I haven't figured out how to get the percentage of the path based on a given location.

So I used a proximity limit to make it simple, it's accurate and works well if you want to sort the players.

Sounds reasonable, if you can share a bit of code or pseudocode how-to i'd appreciate a lot!

Sure, but my implementation might be buggy if it's not tweaked properly. So be careful and you might help me to improve it as well.

There are several other reasons you may want to place checkpoints on each track anyway:

  • Preventing players from advancing a few meters, going backwards, then crossing the finish line to count as a lap.
  • Disallow cutting through the track's scenery.
  • Placing players who accidentally leave the track back on the track.

Actually, I used two checkpoints to prevent the players from reversing and count the laps but I didn't include this part of the script for simplicity.

I used a path in combination with checkpoints to add precision and make the progress look continuous.

My game also had barriers so the players cannot leave the track anyway.

Your game might be structured differently but this is how I made mine.

1 Answer

+1 vote

Here is the code I used for my game:

extends Control

var step = 1 #Largest distance allowed for approximation.
var path_step = 0.0001 #The smaller, the more accurate.
var p1_position = Vector3()
var p2_position = Vector3()
var p1_progress = 0
var p2_progress = 0
var p1_laps = 0
var p2_laps = 0

func _process(_delta):
#   Player 1 progress
    #Calculate the player's position based on the curve.
    p1_position = $Track/Path.get_curve().get_closest_point($Player1.translation)
    #Increment the PathFollow node until it's close to the player's position.
    while ($Track/Path/P1PathFollow.translation - p1_position).length() > step:
        $Track/Path/P1PathFollow.unit_offset += path_step
    #Get the progress from the PathFollow's Offset, include laps as well.
    p1_progress = p1_laps + $Track/Path/P1PathFollow.unit_offset
#   Player 2 progress
    p2_position = $Track/Path.get_curve().get_closest_point($Player2.translation)
    while ($Track/Path/P2PathFollow.translation - p2_position).length() > step:
        $Track/Path/P2PathFollow.unit_offset += path_step
    p2_progress = p2_laps + $Track/Path/P2PathFollow.unit_offset

    if p1_progress > p2_progress:
        $RankLabel.text = "1: Player 1\n2: Player 2"
    elif p2_progress > p1_progress:
        $RankLabel.text = "1: Player 2\n2: Player 1"

Check out this image.

by (298 points)
edited by
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.