Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Outrun Revisited

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Outrun Revisited
Thomas Harte
Member #33
April 2000
avatar

A long time ago in a series of related threads (one, two, three), a discussion was held about Outrun style games. I came up with a brief engine demo that is still available on 23yrold3yrold's webpage. General criticism was that the corners were slightly unconvincing and at first it didn't support hills.

I've now taken the opportunity to revisit my ideas from back then and have produced a severely improved version. It properly cues its corners and supports different heights of terrain (although in a straight edged fashion familiar to anyone who knows what a polygon is), but remains a smoke and mirrors pseudo-3d "fake" extension of a 2d world.

What I still haven't been able to figure out are the rolling hills common to the older games. In some, such as Outrun itself, it is obvious that the trick is something simple like a sinal distortion (with scaling) of scanlines to produce something the player can see is meant to be a hill but with terribly unconvincing perspective. In others, such as Road Rash, the perspective seems to be quite good. I am wondering if anybody else has figured hills out?

I know it would be perfectly possible to ray cast onto a parabola or something, but I can't think of a way of avoiding possibly hundreds of square roots per frame with that, so am persuaded this is not the true path of racing games gone by. I am hoping some other people have some other smart suggestions.

Anyway, onto what I have managed so far. You'll see that source + a single .pcx (recycled from last time, a 23yrold3yrold original) is attached. It's a .cpp file but only so that I can not worry about where I'm declaring my variables and because new is a tiny bit neater than malloc. Anyone who knows C should have no problem with any of the syntax. It's all still a bit "first hack"y, filled with stupid variable names, direct calls to math.h functions where speed concerns would normally stop such free abandon and probably even a few variables that I don't even use. Keys are cursors + Q, A, W, S. Although Q/A are possibly confusing. They rotate the view around the x axis, a control that would almost certainly not be present in a finished product due to the hassle of adding objects to the scene.

It also doesn't properly check its return results. Particularly if it can't find its texture, it'll crash and if it can't get a 32bpp mode it'll irrationally refuse to run.

The algorithm is based on connected patchs of floor. Each patch has a curvature coefficient, used to fake the corners, a slope and a length. The improvements from the previous version come in each patch being allowed a unique gradient (in ordinary road user jargon) and curvature, and the use of that information to produce corners that properly approach and properly tail off.

The principle is simply that the patches are used for ray casting sequentially from front to back. If they have a curvature, then their scanlines are skewed by a function of sine, their position on their patch and the curvature coefficient for the patch. When the viewer enters the patch, the function is adjusted to start from the camera rather than the start of the patch.

Offsets in space and "forward direction" are accumulated as patches are walked. So, for example, a curve with a straight attached to the end causes the straight to "rotate" into view as best the pseudo-rotation in these games allows.

If there is any interest, I will continue posting to this thread, hopefully clearing up the code as I go. In the meantime, if anyone has some smart ideas for non-flat edged hills, I'd love to hear them.

EDIT: A screenshot for the interested (camera up high, rotated quite a way forwards):
http://img146.imageshack.us/img146/2068/picture29er.th.png
(click for a larger version)

EDIT2: demo with an actual bump in it attached!

KaBlammyman
Member #455
June 2000
avatar

nice work! 8-)

I also sent a PM.

->Insert clever quote here<-
http:my website

nonnus29
Member #2,606
August 2002
avatar

I'm interested in this too, so please keeping post updates....

Dennis
Member #1,090
July 2003
avatar

This thread inspires me to play some LotusTurboChallenge2(Amiga Emulator).:) (also downloading the demo, will report my impressions later...)

Thomas Harte
Member #33
April 2000
avatar

"Interestingly" my return to this sort of stuff is partly inspired by playing the Mega Drive Lotus Turbo Challenge (albeit on a real machine), which I believe is a straight port of no. 2 from the 16bits. Certainly it includes other cars as obstacles rather than competitors and no 2 on the Mega Drive includes RECS, which I think only came to the Amiga in no 3?

Anyway, enough of that and lets talk curved surfaces. I still cannot come up with a solution that doesn't involve either a square root or subdivision. Although a square root can be approximated on a 6800 in something like 2-300 cycles, and the machines will likely have had more than 1000 cycles to complete each scanline of the floor I note that the SNES has a piddly little CPU that almost certainly couldn't sqrt. Similarly, ports of Lotus Turbo Challenge (which has pretty decent hills) exist for the Amstrad CPC and ZX Spectrum, both of which have mildly slower CPUs than the SNES but also must do all their own pixel work. Even the Master System and NES can cheat by essentially having a pre-drawn perspective road and then just tweaking the scrolling registers on a scanline by scanline basis.

Disregarding a heightmap, I'm therefore stuck at the conclusion that subdivision is the answer. There is no need for this to be expensive because it can be precalculated quite efficiently due to the limited depth of field and the fact that the hill will only ever be approached from one direction.

That said, I think possibly a heightmap is in use in the older games. My guess is that the camera remains a constant height from the floor and a number of hill positions are pre-cast, i.e. approaching a crest, levelling off from a crest, approaching a dip, levelling off in a dip. It's perfectly possible that some sort of tweening is used to transform between key frames, as this can be done in two multiplies and one add per scanline if things are set up correctly beforehand. I don't want to use this approach because I want the camera to be moveable and to properly "rotate" across the landscape, even if it can only ever do so subtley to prevent the various sprite objects from looking stupid. That means that as you cross the crest of a hill, the valley comes into view as you would expect.

In the meantime, I've discovered some sort of error that causes a slight jump in the scenery where patches with curvature of a different tilt meet. My guess is that I've used the distance along the patch synonymously with distance along the z axis somewhere without really thinking about it, or else that I'm clipping curves in a slightly incorrect fashion. That said, my clipping is the two lines that read:

if(PlayerZ > 0) BaseOffset = -PlayerZ;
else BaseOffset = 0;

So if the error is related to that, it probably isn't huge!

The aim is to fix that, then see what can be done concerning subdivision. I'm guessing that it'll be as simple as branching between sections of the patch list depending on distance.

It'd be really cool to make a game based on this stuff (although probably in OpenGL in order to use hardware scaling & translucency) but I just don't think I can source the art - that was certainly a problem last time.

Richard Phipps
Member #1,632
November 2001
avatar

What if they precalulated the height lines for a approaching hill for each frame while the hill was at it's highest height. Then all they had to do was dampen the height depending on the size of the hill. Shouldn't have taken too much memory I don't think..

Thomas Harte
Member #33
April 2000
avatar

Quote:

What if they precalulated the height lines for a approaching hill for each frame while the hill was at it's highest height. Then all they had to do was dampen the height depending on the size of the hill.

I have to admit I'm not 100% following what you mean by height lines. Are you talking about something slightly voxely (i.e. the program knows or calculates what z on the floor should come at each scanline if the floor were flat, then draws something in the shape of a rectangle to produce floor, albeit from front to back with clipping for zero overdraw)?

Quote:

My guess is that I've used the distance along the patch synonymously with distance along the z axis somewhere

The problem is in the main function, where I determine "StartPlane" by z-depth rather than plane relative depth. It is therefore only a problem when the player is high above the floor, because when they are close the correct moment of moving on a StartPlane more or less synchronises with when the player crosses the depth threshold. In pure drawing terms either way would do but because of the way curves are accumulated using pseudo math the main way needs to be changed or else the game can just keep the player "close" to the floor so that the problem doesn't occur.

I've also added a coloured sky and "side bars" to the road, i.e. those two tone stripes that are common to these games covering the untextured area. I suppose if I will insist on 32bpp, I could use a proper gradient! The camera "rotates" and moves/up down with the floor automatically and is shifted to the left/right when on a curve increasing the illusion of real 3d movement. I've come up with an ingenious little modification that allows real time subdivision effectively via lookup, although it's only two extra members to the Plane struct and one extra if statement to the caster. I have no doubt that a real 8/16bit racing game could use the algorithms I am implementing.

Richard Phipps
Member #1,632
November 2001
avatar

Quote:

I have to admit I'm not 100% following what you mean by height lines. Are you talking about something slightly voxely (i.e. the program knows or calculates what z on the floor should come at each scanline if the floor were flat, then draws something in the shape of a rectangle to produce floor, albeit from front to back with clipping for zero overdraw)?

Yes, something pretty much like that. :)

Thomas Harte
Member #33
April 2000
avatar

That would make sense. You could also create small hills (more like bumps, I guess) by adding pre-stored alterations to the correctly scanned floor in a fashion analogous to 1d sprite drawing, allowing several to be added in sequence.

Anyway, I'm going out for the night so I'm attaching my work to the end of today. One thing I especially like about the non-"voxel" approach is the way that a future slope can approach as at the start of this version. The camera jumps from one orientation to the next when you leave the slope, but that will be fixed if my little subdivision idea comes together. I think the main problem is going to be obtaining the data set, so I probably need to throw together a little track editor.

Dennis
Member #1,090
July 2003
avatar

Playing Lotus2 with a time cheat, i closely observed hills and valleys and here is how it "appears" to me what is going on:
I think of the ground as flexible neverending mattress, made of long horizontally aligned sticks that can change height and are connected at the sides.
The sticks can "scroll" along the mattress and when a stick "falls off" one end(of the neverending:P mattress), it is glued back to the other end.

One end of this mattress is conected to a line i would like to call the road horizon, which is just a thought horizontal line across the screen.(note the abrupt move from the abstract to the concrete in my sometimes strange writing style).
(However this road horizon, automagically changes its' y offset. More to that below.)
The other end is connected to an offset somewhere below the screen.(stick falling off here are put back to the road horizon)
The number of sticks in memory is constant, though the number of how many of them can be seen, changes, because sticks can change their height(even have a negative height, when driving uphill) and by that are overdrawn by other sticks.

Objects on the ground are off-set, between the middle of the relative heights of two connected sticks.
Actually i think the best way to implement it would be to just have one starting stick height(in terms of y offset starting at the screen bottom, counting upwards) and then only store relative change(signed integer) in height for each following stick.

This relative height stretches(preserving its sign) when the car is on a slope, proportional to the gradient angle.
(The gradient angle can directly be taken by comparing the absolute height of the stick the car just passed and the height of the next stick.)
Driving uphill, the positive different height lines will automagically move up, while the negative different height lines after the hill top will automagically move down(so drawing the sticks front to back, they won't be seen).
By this also the road horizon, as already mentioned above, changes its' y offset.
(The signs actually have to be switched, because of y offsets growing downwards on allegro bitmaps.)

To have some sort of road these so far only imaginary sticks must be textured of course, but this can probably be done by stretchblitting scanline by scanline.
The further the stick is away from the current front stick, the narrower the blit.

So much for the ground the car is moving on.

I also observed a few clever tricks to get the illusion of 3D going even more perfectly:
Driving a right curve the backdrop scrolls to the left and vice versa.
Depending on the current "absolute height" of the car (car height can be constantly changed by adding the height differences of the sticks, as the car passes over them(or subtracting, when driving backwards)) the backdrop is scrolled up and down.
Driving downhill the backdrop scrolls upwards.
Driving uphill the backdrop scrolls downwards.

Having all that said, i realize that curves can also be easily modeled in the same way. Have a starting x center road position and in every following stick just store the relative change of that x offset.
That way, the whole huge level ground data would consist of just a few things:
a starting height
a starting x offset
an array of height changes(signed integers)
an array of x changes(signed integers)
additional for each index of the "height changes array", some variables can be stored to be interpreted as what objects to show at the sides of the roads and at what relative offset to the road border

This was written in a hurry, i hope it somehow makes sense and that i did not accidantially mix up some terms or put wrong words in right places and vice versa.

Thomas Harte
Member #33
April 2000
avatar

Quote:

Playing Lotus2 with a time cheat, i closely observed hills and valleys and here is how it "appears" to me what is going on

Thanks for taking the time!

Quote:

I think of the ground as flexible neverending mattress, made of long horizontally aligned sticks that can change height and are connected at the sides.

So we are talking about a 1d heightfield? So in C you could reproduce it as a 1d array of height values which is indexed by depth into the screen?

Quote:

The number of sticks in memory is constant, though the number of how many of them can be seen, changes, because sticks can change their height(even have a negative height, when driving uphill) and by that are overdrawn by other sticks.

So you saw sticks modelled as "1 pixel deep"? It isn't that flat sections of terrain were constructed over the sticks as if they were a heightfield you'd communicate as vertices to OpenGL, for example?

Quote:

Having all that said, i realize that curves can also be easily modeled in the same way. Have a starting x center road position and in every following stick just store the relative change of that x offset.
That way, the whole huge level ground data would consist of just a few things:

This is how I did my last engine (give or take height changes), and the problem I had was that the approach and exit of corners looked wrong. I know plenty of games that are clearly doing just what you suggest, but it looked a little too fake for me.

What I've come up with is quite different, having taken Road Rash 2 as the thing from which I tried to determine behaviour rather than Lotus Turbo Challenge. Road Rash 2, by the way, has aged horribly and although I don't remember it having any such problem appears to have a framerate of 10-12fps. That's probably about half of Lotus Turbo Challenge, so it is believable that a more complicated algorithm is in use.

I've essentially stuck to what I had of a segmented track where each segment has a curvature and an orientation, but I've created a brief hill editor and thrown Bezier data into a file to generate track heights. I've implemented something a lot like adaptive meshing to save ray casting costs. The trick is to remember that in my engine the segments are a linked list. All I've done is added two variables to each node, a "too far" distance and a second "next segment" link. If the segment is further from the player than its "too far" distance then the engine immediately moves on to the thing linked by the new "next segment" link. By pre-merging segments and exploiting linked lists by having the off shoots reconverge onto the main list the processing cost for adaptive meshing is very very little.

You'll probably be able to see the Road Rash influence in this shot:

picture39ds.th.png

As versus a wikipedia shot of the original:

{"name":"MD_Road_Rash.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/2\/0259adaf64d33815da50bf1927928f6a.png","w":320,"h":225,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/2\/0259adaf64d33815da50bf1927928f6a"}MD_Road_Rash.png (click for article)

Note in particular that in mine a double peak is shown. The cool thing about the way I've settled on something that is pretty much "real maths" for the elevation is that the camera can genuinely rotate, no hacks. I've found a small bug in the code I already had while implementing this, which affects the SkewRatio value. That should be accumulated across segments and not reset (i.e. I wanted +=, not =).

Anyway, I want to make sure the adaptive stuff is actually working before I post source. I'll hopefully be back later!

EDIT: latest source attached. Note the new "track.dat" file, it's a list of depth and height references for the track, generated by a somewhat basic level editor I've thrown together. That editor doesn't know anything about or output curvature at present, so the code puts a fixed curvature on every single segment, producing one long leftward corner. I want to add curvature to the editor then I'll provide that too.

The number now in the top left of the screen is the number of patches/segments/planes (I should pick a name for them and stick with it!) considered for the current frame. It currently goes very high whenever a you approach a peak, which I believe is because it runs through all the downward faces realising they are facing away before finding something forward facing, casting a ray onto it and decidiing it is sufficiently far away that the casting can stop. I need to add a basic distance constraint in the ray caster when considering potentially visible faces.

There is one place where the adaptive meshing is visible, I'll leave the discovery of that as a treat! Note that I've switched to allocating Planes in blocks. Besides being better for the cache, this means that even with my adaptive meshing trick nothing gets deallocated twice.

The spirit of "getting things done" must, I think, now take a moment to give way to the spirit of "making readable code". I want to fix the problem described above, do a cleanup then have a look into the best way to add sprites. I'm imagining that on the forward pass, drawing the floor, a visible sprite list will be built along with correct clipping rectangles (since objects may be obscured by the floor), then it can be drawn from back to front. But we'll see.

Richard Phipps
Member #1,632
November 2001
avatar

Looks good! Are you going to be keeping the software rendering approach or switching to say OpenGL? :)

Thomas Harte
Member #33
April 2000
avatar

Quote:

Looks good! Are you going to be keeping the software rendering approach or switching to say OpenGL?

I'll probably do an OpenGL switch at some point, especially as here in the OS X world there isn't any other conduit to hardware acceleration and Allegro is a non-optimised pure-C implementation.

That said, it doesn't really make any odds while it remains as inevitably true as it does for almost every other project I attempt that I have no artist and correspondingly no way of obtaining art!

EDIT: does my somewhat overenthusiastic use of hills in my previous post's attachment make anyone else feel a little nauseous?

Dennis
Member #1,090
July 2003
avatar

(note this post was written offline, after your "Thanks for taking the time" post, and that i have not read any posts/edits inbetween yet, will do so after posting this)

Quote:

So we are talking about a 1d heightfield? So in C you could reproduce it as a 1d array of height values which is indexed by depth into the screen?

Yes, basically that would be an array that "drives" along the level height-differences-array.
Like this:
dm = number of sticks(==maximum into screen depth)

          current car position
          |
       <-[d0,d1,d2,d3,d4,...,dm]->                    <-(array "driving over" the level data)
[-1,-1,-2,-3,-4, 0, 0, 0,..., 0, 0,+1,+2,+4,+6, ... ] <-(height differences(level data)(for the sticks))
(driving down  , plateau          ,driving up , ...)

Quote:

So you saw sticks modelled as "1 pixel deep"?

No, i forgot to mention that there has to be some constant positive basic stick height.
(Note though, that the sticks are only imaginary lines so far, which are indeed just one pixel thick and ground has to be put in between two consecutive sticks later on.)
Starting with the first stick y offset as 0(bottom line on screen, counting upwards).
The derived stick y' offset for the following stick is that y offset of previous stick plus the basic stick height divided by the depth into the screen, that the following stick currently has.(depth into screen can be derived as index in that "moving array" above)
After that, the height difference multiplied by the gradient angle(derived from car position,car current height and height difference to next stick) also needs to be added to the y' offset.

Automagic illusions created by that:
That way if the car is driving on a down slope(->negative gradient angle) all following sticks y' offsets of sticks with a negative height difference will automagically move upwards, thus appearing to you, as if you are looking on them.
That way if the car is driving on an up slope(->positive gradient angle) all following sticky y' offsets of sticks with a negative height difference will automagically move downwards, thus having a lower y offset as the hill top stick, thus ,drawing front to back, are not shown, appearing as if you are indeed facing a hill top.
(and also if the will be a higher hill behind the hill you're driving upwards, the height lines of that heigher hill further back, will have positive height differences, which are automagically moving upwards, thus any higher hill will also automagically be visible)
This also applies to multiple hills in a row, which all should automagically appear correctly(drawing front to back).

Thinks to keep in mind(note to myself, if i should ever find the time to implement this):
It probably won't work right out of the box. Some experimenting with floating point "depth stretching" coefficient and different "basic stick heights" will be necessary to find a convincing perspective, as taking the integer indices of the "moving array" directly as depth will probably result in a rather "compressed" appearance.
But the basic algorithm, seems to be astonishingly simple.:)

That, plus the additional clever backdrop scrolling mentioned before, should create the illusion of hills and valleys nicely.

Quote:

I had was that the approach and exit of corners looked wrong. I know plenty of games that are clearly doing just what you suggest, but it looked a little too fake for me.

Now that you mention it, yes it will probably look odd.
Maybe that could be compensated by also adjusting the x' offset based on "into screen depth" in a similar way as with the y' offset with the heights, so several consecutive curves would also be shown correctly and all automagically?(provided that the number of sticks shown is large enough and that you're driving downhill, so the curves don't hide behind the current road horizon(==always the y' offset of the 'dm' stick in the moving array and not to be mixed up the backdrops own horizon))

Using a current highest y' offset so far, during rendering front to back, sticks whose y' offset computes to lower than that can be skipped, improving rendering performance.
By the way, i believe this method involves no ray-casting at all, also no polygon rendering, no square roots, no sines, no advanced math, just adding and multiplying.:)

Quote:

What I've come up with is quite different, having taken Road Rash 2 as the thing from which I tried to determine behaviour rather than Lotus Turbo Challenge.

Unfortunately i never played Road Rash2, so i can not say if you're screenshot looks like it or not.

Quote:

Note in particular that a double peak is shown. The cool thing about the way I've settled on something that is pretty much "real maths" for the elevation is that the camera can genuinely rotate, no hacks. I've found a small bug in the code I already had while implementing this, which affects the SkewRatio value. That should be accumulated across segments and not reset (i.e. I wanted +=, not =).

Double peaks should also be no problem for my "assumed Lotus2 method" but it would not support any camera rotation at all, because its all fake and no "real maths".

Quote:

Anyway, I want to make sure the adaptive stuff is actually working before I post source. I'll hopefully be back later!

I don't think i comprehend your method, but in the previous code attachment, the "hill" looked really odd, it was a very abrupt change of the road pointing upwards almost 70 degrees and "driving" over it resulted in some weird "jumpy" camera behaviour.

[EDIT]

Quote:

EDIT: does my somewhat overenthusiastic use of hills in my previous post's attachment make anyone else feel a little nauseous?

No, but the extra long, neverending curve held some strange sensation of weird fever dreaming. It goes on and on and on... it is really disturbing the peace of the mind, that it never turns the direction.(Now i can feel why a goldfish in a round bowl is driven mad.)

Thomas Harte
Member #33
April 2000
avatar

Quote:

Using a current highest y' offset so far, during rendering front to back, sticks whose y' offset computes to lower than that can be skipped, improving rendering performance.
By the way, i believe this method involves no ray-casting at all, also no polygon rendering, no square roots, no sines, no advanced math, just adding and multiplying.

With all due respect, you can only eliminate the polygon rendering/ray casting by doing the polygon rendering/ray casting in advance and prestoring the results! Otherwise you don't know where to map your sticks to on the screen. You can work it out with trigonometry, in which case you're reinventing the ray casting approach or with linear algebra meaning that you reinvent the polygon fill, but the result is the same!

I think the solution I implemented last time is very similar to what you suggest, except that the heights of sticks were not calculated but prestored. If you can run it, try the binary I posted in a previous thread. It may be DOS or it may be Windows, I don't recall and the source is long lost.

Quote:

I don't think i comprehend your method, but in the previous code attachment, the "hill" looked really odd, it was a very abrupt change of the road pointing upwards almost 70 degrees

Yes, look at the elevation view from the burgeoning editor (EDIT: uploaded correct shot!):

picture49ol.png

Given the shortness of the curve when mapped according to the scale applied, it must be at least the 70 you state! Luckily any degree of hill is possible. I think I have suffered a hill mania, having been impressed with the fact that I finally feel I have a grip on hills in the same way that recent C++ converts usually immediately try and do everything with classes.

Quote:

"driving" over it resulted in some weird "jumpy" camera behaviour.

If you mean up/down style jumping then the way the camera adapts to the hills needs work. It should be easy enough, I just need to do it.

If you mean the texture jumping left/right (which occurs if you look for it, but to my eye doesn't jump out), then it is a result of the adaptive meshing. I've essentially implemented depth cueing much as you suggest ("adjusting the x' offset based on "into screen depth" in a similar way as with the y' offset with the heights, so several consecutive curves would also be shown correctly and all automagically?"), which has the effect due to the way things are split by the (somewhat dense) adaptive meshing of switching between a true evaluation of cos and a Euler approximation reached by evaluation of -sin, the derivative of cos. Nowhere is this explicitly written or anything, it's just a natural effect that I hadn't otherwise given any thought to.

EDIT: I hope that the jumpiness is now entirely fixed. I've switched to maintaining camera position relative to the track surface, and am interpolating viewing angles from surface to surface. The adaptive meshing isn't quite so violent as it was before, but is still a little bit too simple for its own good. The code has now definitely crossed the threshold into ugliness. So my next task is to clean up what I have, and possibly remove whatever math.h references remain as I do. Even though the full source is still under 400 lines, I expect I'll break it into a few files purely for easy organisation. Once it is clean I will add curves to the level editor, removing the eternal left hand corner, and then sprite objects. Ideally I want to comment and document most of what I do because there aren't enough psuedo-3d games like this any more!

gnolam
Member #2,030
March 2002
avatar

Oooh, neat demo. Takes me back to the good old days!
I'll definitely have to stea^H^H^H^H^H take a closer look at this code. This could be the time to resurrect my software 2.5D racing project. :)

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Thomas Harte
Member #33
April 2000
avatar

Quote:

I'll definitely have to stea^H^H^H^H^H take a closer look at this code

You may want to wait for my tidy up - especially the bits concerning the camera movement are probably indecipherable at present.

In the meantime, I've made a first hack of curves into the level editor, and as a result have produced a level that features moderate hills and varied curves. It is attached, not because it significantly builds on code already posted but for the benefit of newcomers to the thread.

At present I have no idea why it does what it does when you approach the end of the level. Something somewhere obviously isn't terminated properly!

KaBlammyman
Member #455
June 2000
avatar

This "demo" is looking very professional! However, I feel that this is getting too complicated...were racing games on the NES (like rad racer) this complicated? I guess they had to be, otherwise it wouldnt look "real"

->Insert clever quote here<-
http:my website

Thomas Harte
Member #33
April 2000
avatar

Quote:

However, I feel that this is getting too complicated...were racing games on the NES (like rad racer) this complicated?

Admittedly I have been thinking more about the 16bit generation of titles than the 8bit. Although the algorithm I describe sounds complicated, it's does calculate the depths and texture offsets of around 90% of its scanlines with just 8 adds and 5 multiples each. And the others will normally be only around two or three times as expensive as that.

What the 8bit console racers probably do is load a single frame containing a single track slice scaled to 224 different possible widths. Through altering palette and scroll registers according to the hsync interrupt they can then display any combination of corner and slope they can calculate the correct values for virtually without drawing costs.

I would imagine that a fixed "width of road slice per scanline" table then produces a lookup for what scale of track slice should go where. Obviously with a display around 240 scanlines, this is a 240 byte table. Corners can be added quite cheaply in real time, probably using more tables with a few shifts and adds. This gives a flat display sufficiently cheaply for one of those consoles, and probably explains the proliferation of flat tracked racers.

To add hills, I'll bet they have a few precalculated hills. They can store these as how the 240 byte scaling table should look, say every 2 frames. For a 2 second hill animation, that's somewhere around 3,000 bytes of storage. You can further mix that up a bit by combining hill animations for small bumps.

Chances are, due to the resources available, that these hill animations were hand calculated by the programmers or else created by the artists rather than prebuilt by a computer so they should look pretty fake. If you still have access to Rad Racer, it's possibly worth booting it up and making a judgment on how realistic you think the hills appear and how similar they look to each other.

Pressing on with my implementation of an admittedly very 16bit type road racer, I've cleaned up what code I had and added a first stab at adding roadside objects - see the attachment for all of that. Predictably the editor doesn't do objects yet, so I've just hardcoded three in by hand. The final one seems to appear a pixel or so above the road when on the crest, but I'm not sure I can rule out Allegro's lack of subpixel accuracy as the culprit.

EDIT: I've also eliminated math.h functions from every per frame calculation. That costs less than 10kb in LUTs, so is probably worth it.

juvinious
Member #5,145
October 2004
avatar

You might want to include stdio.h in your Main.cpp or else it won't compile..(At least for me anyhow) :P
However, nice work so far it's look really good. Keep it up. :D

__________________________________________
Paintown

KaBlammyman
Member #455
June 2000
avatar

Hey, I'm not complaining at all ;D

So, let me get this straight...you are not using ray casting anymore? How much different is this demo as compared to your earlier work? Do they have anything in common? I thought i was getting somewhere with the coding and theory, then you went and got all "professional" on me >:(:'(:P

Anyway, I'll just PM you with specific questions.

<-- Doesnt understand how to do cool graphics programming and its pissing him off.

->Insert clever quote here<-
http:my website

Billybob
Member #3,136
January 2003

MinGW 3.4.2, allegro 4.2, all I get is a black screen with text at the top in your newest release. All the others worked fine.
And why do you have a src folder in the package? That's silly, cause you put everything in it :P

Anyway, the other demos looked cool!

Dennis
Member #1,090
July 2003
avatar

Quote:

all I get is a black screen with text at the top in your newest release

Same here, all pitch black and it just shows:
Visible segments:1 Base angle:-4129245.25
The value for the angle seems a little 'strange'.
(MSVC6, Allegro 4.20rc2)

Thomas Harte
Member #33
April 2000
avatar

Quote:

MinGW 3.4.2, allegro 4.2, all I get is a black screen with text at the top in your newest release. All the others worked fine.

Quote:

Same here, all pitch black and it just shows:
Visible segments:1 Base angle:-4129245.25

Hopefully for some reason it is not finding its track file. It may be worth trying the attachment to this post that will complain and exit if that is the case, but this is a knee jerk reaction to the problem and I haven't done any full analysis yet.

Quote:

And why do you have a src folder in the package? That's silly, cause you put everything in it

That's because I remain a UNIX thickie, and "tar cvzf NewRace.tgz src/" is just about my limit for now!

Quote:

So, let me get this straight...you are not using ray casting anymore?

No, I am!

Quote:

How much different is this demo as compared to your earlier work? Do they have anything in common?

Everything on this thread is very, very similar. Check out GetScanline in the first file I posted as compared to DrawFloor in FloorCaster.cpp in the latest. And its quite similar to my old code from years ago.

EDIT: I meant to say, here is a screenshot:

picture15gw.th.jpg

Dennis
Member #1,090
July 2003
avatar

Quote:

Hopefully for some reason it is not finding its track file. It may be worth trying the attachment to this post that will complain and exit if that is the case, but this is a knee jerk reaction to the problem and I haven't done any full analysis yet.

Nope, track file is found fine, still all black, same error message.
Maybe it is an ENDIAN issue with your track editor?!

Quote:

EDIT: I meant to say, here is a screenshot:

The tree grows through the asphalt. "Were you stoned, when you coded that?" (voice in the off: "No he was asphalted.":P doh!)

 1   2 


Go to: