7
\$\begingroup\$

I am working a 2D racing game and I'm trying to figure out what is the best way to define the track.

At the very least, I need to be able to create a closed circuit with any amount of turns at any angle, and I need vehicles to collide with the edges of the track. I also want the following things to be true if possible (but they are optional):

  • The code is simple and free of funky workarounds and extras
  • I can define all of the parts of the track (such as turns) relative to the previous parts
  • I can predict the exact position of the road at a certain point (that way I can easily and cleanly make closed circuits)

Here are my options:

  1. Use a set of points. This is my current system. I have a set of turns and width changes that the track is supposed to make over time. I have a point which I transform according to these instructions, and I place a point every 5 steps or so, depending on how precise I want the track to be. These points make up the track. The main problem with this is the discrepancy between the collisions and the way the track is drawn. I won't get into too much detail, but the picture below shows what is happening (although it is exaggerated a bit). The blue lines are what is drawn, the red lines are what the vehicle collides with. I could work around this, but I'd rather avoid funky workaround code.

  2. Beizer curves. These seem cool, but my first impression of them is that they'll be a little daunting to learn and are probably too complicated for my needs.

  3. Some other kind of curve? I have heard of some other kinds of curves; maybe those are more applicable.

  4. Use Box2D or another physics engine. Instead of defining the center of the track, I could use a physics engine to define shapes that make up the road. The downside to this, however, is that I have to put in a little more work to place the checkpoints.

  5. Something completely different.

Basically, what is the simplest system for generating a race track that would allow me to create closed circuits cleanly, handle collisions, and not have a ton of weird code?

drawing and collisions

\$\endgroup\$
3
  • \$\begingroup\$ Related: Defining the track in a 2D racing game \$\endgroup\$
    – House
    Commented Sep 17, 2012 at 21:25
  • 1
    \$\begingroup\$ To be honest, it sounds like your collision detection code needs some work, rather than your track creation code. \$\endgroup\$
    – Cypher
    Commented Sep 17, 2012 at 22:12
  • 1
    \$\begingroup\$ There is never a best solution for any problem. \$\endgroup\$
    – Philipp
    Commented Apr 17, 2013 at 7:33

3 Answers 3

4
\$\begingroup\$

I would suggest something you haven't listed.

Don't "create" your track at all.

Rather, define it indirectly by placing a bunch of collide-able objects around where you want your track to be. Walls, old cars, wrecked buildings, semi-transparent-laser-beams... whatever you want. Heck, they don't even have to be visible. Then you can do your collision against those objects.

This has the benefit of being relatively fast, because each of those objects will end up just being a rectangle, and now you can just test for rectangle intersections.

In my opinion, this is the simplest way to go for any racing game, especially 2d.

\$\endgroup\$
8
  • 3
    \$\begingroup\$ Hmmm, that's actually a really cool idea. You gave me another idea: use Box2D to define shapes. Then I don't have to code my own collisions and I suddenly have a lot of freedom in track design. I will add that to the list. \$\endgroup\$
    – tesselode
    Commented Sep 17, 2012 at 22:28
  • 1
    \$\begingroup\$ This is a great suggestion, but it might still be useful to have some sort of representation of the track if you need to implement AI for opponent cars. I figure they will need to know where the track is to think of a route. \$\endgroup\$ Commented Sep 18, 2012 at 0:15
  • \$\begingroup\$ @DavidGouveia, it's not necessarily needed but agreed that it could be useful. \$\endgroup\$
    – Cypher
    Commented Sep 18, 2012 at 3:03
  • 1
    \$\begingroup\$ Maybe a simple list of points, creating a "spline" down the middle of the "track". Then we can apply some steering behaviors to the ai so that they follow those waypoints in a more realistic manner around turns. \$\endgroup\$
    – Cypher
    Commented Sep 18, 2012 at 3:14
  • 1
    \$\begingroup\$ @Cypher That's also what I had in mind, but instead of marking the middle of the track, it might be better to directly mark the best line instead (i.e. outside-inside-outside). \$\endgroup\$ Commented Sep 18, 2012 at 22:20
2
\$\begingroup\$

I am currently working on a 3D wipeout clone, and my tracks are constructed using a Catmull-Rom spline from a small number of points. Catmull-Rom is good because it goes through the points, unlike Bezier which uses the points as a hull.

In 3D it is more complicated because I use quaternions to control orientation at the points. But you can get away with using just positions if you construct the tangents from next and previous points.

Regarding collisions with the track surface and edges: Each vehicle has a world position, velocity, orientation and angular velocity, as usual, but I also store the parametric distance around the loop (s) and the horizontal distance across the track (x).

Then, every frame, I sample the curve at 'time' s to get a matrix and other info like track width. Using the inverse of the matrix I transform the vehicles position and velocity into track space and do track/wall collisions there (almost trivial), before transforming position and velocity back into world space.

Then a simple world-space euler update to find the next position.

Finally I have to update the parameter s to reflect the new position. Currently I do this with an iterative approach: take a few steps of s, calculating the track matrix until it is in front of the vehicle. Then a few more iterations using a binary search to get a more accurate sample. I am not overly happy about this step, but it works well and I use an adaptive stepsize to keep number of samples to a minimum.

\$\endgroup\$
0
\$\begingroup\$

To second a note made in comments: the notion of defining your track via a chain of points making up its spine should work just fine; if the red path in your question is what you're getting out of your procedure, then I would start by considering changes to that.

My recommendation for doing the 'chain of points' version of the track is essentially a linear version of a spline: at each point along the spine Pi, define the current tangent to the track Ti by Ti = Normalize(Pi+1-Pi-1) (this is the central difference approximation to the derivative). Once you have the tangent you can find a 'rib' vector at a right angle to the tangent: if the tangent is Ti = (Tx, Ty), then the rib vector is Ri = (Ty, -Tx). With the spine points and the rib vectors, you can define the outer boundaries of the track: the left boundary is BiL = Pi-w*Ri and the right boundary is BiR = Pi+w*Ri (this creates a track of width 2w — that is, w units out to either side of the central spine). Once you have that, you can think of the track as the union of the quadrilaterals ⟨B0L, B1L, B1R, B0R⟩, ⟨B1L, B2L, B2R, B1R⟩, etc. This approach will occasionally have problems around hairpin turns (particularly if the curvature gets to be tighter than the width of the track), and you may want enough manual control over the intermediate points that I would use this as just an autogenerated starting point rather than the final result of the process — but it should serve as a good starting point for building the track. This also means that the collision envelope for the track should be the same as the displayed envelope, which is important in its own right — the player should expect that what they see on the screen actually represents the functional bounds of the track.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .