Jump to content
IGNORED

Pole position like Road Algorithmes?


youki

Recommended Posts

Hi,

 

I'm looking for some documentation , explanation, algorithme to make road scrolling like we can see in game like poleposition or pitstop2 .

 

In fact i'm not interrested by the scrolling aspect, but more but how the curves are calculated (if they are...) .

 

I thought may be it is with "bezier" function , but i doubt it has been implemented in Poleposition on Atari 2600 for instance. There is surely something smarter to do.

 

May be the curve are not calculated, they are all predifined in memory and displayed when needed.

 

If somebody have input , it is welcome! :)

 

Thanks

Link to comment
Share on other sites

I'm not sure it even takes it to that level of sophistication.

 

There's a PPos + track editor, might be available on AtariMania. That might give some clues.

 

PolePos on the 8-bit adjusts the HScrol register on a by-scanline basis for the track. I suspect Pitstop actually does the track by rendering it without using scrolling tricks.

Link to comment
Share on other sites

Yes, i have idea about how it drawn on screen.

 

My question is more about the shape of the curves.

 

If for instance we consider the adjustement of the HScrol register , How the value for each scanline are choosed depending on the curvature of the turn.

 

Are they calculated from sinus table or kind of? If yes what would be the formula?

 

I'm going to look for the ppos editor to see if it can help. Thanks. :)

Link to comment
Share on other sites

  • 2 weeks later...

I don't know how it's done - but if I had to write it right now here's how I'd do it

 

*Each 'road section' would consist of 2 bytes - a distance and a signed curvature (keeps the definition size down)

 

*You then load the current curvature and put the distance into your timer variable. I'd then calculate the line offsets *once* and buffer them up (Not sure if you can get away with this on the VCS due to space constraints though)

 

*Each frame after that for every line I'd either move the offset left or right one step if it doesn't match the curvature position (to simulate entering/leaving a curve)

 

I'd also use the curvature amount to control the force placed on the car to throw it to the outside of the curve.

 

 

If I'm right then this scheme means you can represent each curve or straight in 2 bytes. an oval (2 big curves+2 straights) would be just 10 bytes (assuming one straight was defined in 2 halves at the beginning and end, and a dummy section definition to flag the lap point) so you could get quite a lot of track in a small amount of space.

Link to comment
Share on other sites

Yes, i had something like that in mind.

 

But what i look for is a formula or something to draw nice curvatures.

 

 

I think your best bet is to store the road edges as graphics tables. The entry for each line includes the HMxx shift from the line above, and the width of the stripe. The animation of the color stripes should be done with separate set of tables, or if your kernel has time you may be able to do the color stripes with some sort if parabolic function.

Link to comment
Share on other sites

  • 1 month later...

OK, I think I'll post my VB project here which I did a while back...

 

Here I tried to do some convincing pseudo 3D effects, which means that the graphics has to look believable and also be physically (nearly) correct.

 

If you start this program, you'll get a form showing the title screen of Pole Position (Arcade version). I did this in order to make sure that the sequence of curves really matches the real track geography (which isn't quite true in the arcade version).

 

On clicking on the form the first time, you'll notice a white line being drawn on the Pole Position track picture. This is the representation of the track data. The actual track data is defined in Form_Load procedure as an array of 300 numbers representing the track curvature. The numbers go from 0 to 9. 0 through 4 are left curves, 5 are straights and 6 to 9 are right curves. Each number represents a road segment of the same length.

Note that the numbers are not linear, but rather represent varying curve radiuses. These radiuses are represented as a "banking angle per segment", which is held in the array banking_angle. This basically holds the number of degrees the road bends left or right for each segment which has this number code for its radius. In my program, it gets initialized with the values -5.93, -4, -3, -2, -1.1, 0, 0.58, 0.66, 2.21, 2.9 and 4. But these numbers, actually, only get used to create the following lookup table:

 

The actual table the program works with the most is the table bend_lookup(i, j) where i is the number of the curvature, and j is the line number on screen. This works the following way:

 

It is assumed that on a straight segment, the road goes to the horizon in a straight line, so as long as the road doesn't bend, the vertical distance from one line to the next on screen stays the same. If the road bends, however, the vertical distance changes, but the amount it changes varies by the distance from the camera and the radius of the bend. Actually, the farther away a line is, the more bending per line is done because a line on screen represents a bigger distance in 3D.

 

There is also a table track_lookup calculated, which gives the distance of each line on screen related to the camera position, taking into account the fact that the farther you look into the distance, the more distance each line on screen represents. This is used at "run time" to look at the correct track segment for calculations.

 

Note that both tables, bend_lookup and track_lookup, are of data type integer, so their elements only take up 2 bytes each. In my approach, I would store these tables in ROM, or calculate them beforehand and place them in RAM if enough RAM is present. In this program, they get calculated at the first click on the form.

 

On the second click on the form, the loop gets entered where the track actually gets displayed. This is done in the Form_Click event. There is one variable called pixel_multiplikator which actually only cares for correctly scaling the pixels on the PC screen in order to fill the given form height and width. On a videogame system, this would probably be a fixed value. This is also the only variable (rather, nearly constant) that multiplications are done with. There is one division by 256 in the routine, but it only gets used in order to get the upper byte of integer values. In Assembler you probably wouldn't need that division... all other calculations here only consist of additions and subtractions.

 

The program now does the following:

It goes through positions on the road by looping the segment number from 1 to 300, and the position in segment number from 1 to 255 in steps of 2. In a video game, this looping of course would occur in variable speed, depending on the speed of the car.

 

The variable angle2 is first calculated. This gives the current angle you're looking at, which is used for giving the scrolling position of the background over the horizon. This background is only represented by a small black rectangle here.

 

The variable temp_track_bend holds the current bend, that is the vertical distance of the middle of the road on one line of the screen relative to the one below it. In total, I'm calculating this for 48 lines from bottom to top (horizon), accounting for a popular practice in 8-bit racing games to show the street at half resolution, that is, with only 48 horizontal lines where the actual screen resolution would be 96 scanlines in the area where the street gets drawn.

The variable temp_track_bend2 holds the absolute pixel position of the middle of the street for the current line. This is where temp_track_bend gets added to for each line.

The variable track_width is set according to the current line and says how wide the track should be at that line on screen.

 

Now for each loop and each line on screen, first track_width gets calculated, then track_bend_index gets calculated, which is the road segment representing that line on screen for the current camera position. This is done by using the track_lookup table telling how many road segments (and fractions of road segments) to look ahead for each line on screen.

 

Then temp_track_bend gets calculated by adding the information of bend_lookup, indexed with track_bend_index and current line number, to the current value of track_bend, which gives the new bend, which is the new vertical distance to the next line above.

Then temp_track_bend2 gets calculated by adding temp_track_bend to it.

 

Now temp_track_bend2 holds the information where the middle of the track for the current line should be. Now the linecolor of that line gets set by adding track_lookup(k) to j again and only use the lower byte of the result. The trick here is that one road segment equals two sequences of red and white on the side, so since those sequences are the same for each road segment, only the lower byte needs to be taken into account in order to determine if for the given line, the sides of the road are to be drawn red or white.

So then for each line, the grey road gets drawn, with red or white lines to the side of it, and green meadow to the left and right of those. Then another check gets done for the middle line which is one white line for two red and white lines on the side. This one only gets drawn if the lower byte of the sum of the current camera position in addition to the track index is greater than 128, so for each road segment it gets drawn for the half length of it.

 

And that's basically it... of course, the method to draw the road would differ depending on the system the code runs on. On the PC, which uses bitmapped graphics, the road just gets drawn the way I described. On the Atari 2600, instead, objects may be given for the middle and side lines and the horizontal move registers affected according to the values of temp_track_bend (caution, you have to set them top-down, while here they are calculated bottom-up!). On other systems with no easy hardware scrolling, like the C-64 and the TMS-99xx based systems, you probably have no other choice than just drawing the road on screen as calculated. On the Atari 8-bit and Amiga, however, things may come simpler, because on the Atari 8-bit and the Amiga you can basically adjust the horizontal fine scrolling and the address where the graphics gets picked from for each line. On the Amiga I would use the double-layer mode, where one layer gets used for the road graphics (with scroll registers adjusted accordingly - a Copper list might come handy here), and the other layer would be used for drawing bigger objects like oncoming cars and other obstacles. Similarly, on the 7800, you would use these values to "blit" the correct segment out of a pre-computed bitmap into a line, and then overlay that line with the obstacles and cars.

 

This was much information in one post. I hope it's clear enough, but if it isn't, feel free to ask questions!

Street_experiment.zip

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...