Outrun style Racing code ^.^

Miscellaneous Forums/Blitz Showcase/Outrun style Racing code ^.^

After a couple of weeks of fighting max, i finally got some code to run (by avoiding the Maxness of it all????) Well, anyway, heres my first bit of nice looking (when run anyway) code... Free for all to enjoy of course!!!


http://www.blitzbasic.com/codearcs/codearcs.php?code=1258

Would be nice seeing a Max Outrun or Pole Position remake with this code.

I'm doing pole position :) deeee dededededededede deee dededededededede deeee!

*remembers playing Pole Position on his 5th Birthday*


......


*goes in search of an Atari Emu*

Really on bmax?

Can I be beta tester?
Will u implement a pit stop as well? :)

Ace! Keep us posted please. :)

Just tried that code and it's super sweet.

Pit stop in Pole Position!? o.O wasnt in the original but i might add one, if i can find a way to do it!

Ive played with the code and got it to draw from back to front now so Z-ordering will work :D problem with that is i have to do all the track maths twice, once forward and once backwards, but it works real nice :)

Hey, I like this - I did something similar on the Spectrum (based on Outrun) - but I never implemented the bumps (didn't know how to do it at the time).

you did something like this.... on the SPECTRUM? oh my. ^.^

was it fast? I always wondered, cuz on my BBC Master 128, i could only get 1-2 fps doing this.

Did those computers have any special hardware tricks? i knew how to overclock the BBC but not enough. if youre doing it by lines (in which case its slow) its pretty easy just to do a y=y+d to it.

Yeh, was fast - I think I used an array to do the track - wasn't anything special though - I perfectly copied the outrun car from the Spectrum conversion - A Spectrum magazine did a close up of the car - big enough for me to see the individual pixels - so I did an exact copy into mine - gave it working brake lights and indicators too.

cool!. but how did you make it so fast on teh spectrum? i couldnt do anything with the ol speccy. did all my stuff with BBCs.

I also didnt realise there was a spectrum version of outrun ^.^

You are doing your track mathmatically - I did mine with sheer logic. Logic>maths.

I also didnt realise there was a spectrum version of outrun ^.^

Of course there was, there was a spectrum version of EVERYTHING!

I'd like to see the source. ^.^ hehe.

@Perturbatio, Okay i should have known that then. *wishes he had seen said game* man i missed alot.

Heres an updated bit of code... the basics of the game are there now.

framework brl.glmax2d
Import brl.random

Global scx=1024,scy=768
Graphics scx,scy,16,60
bglSetSwapInterval(1)

Global pathsize=1024	 	'This is the paths TRUE length
Global multiplier#=50		'This is how much this path is interpolated. (pathsize is multiplied by this)
Global pathlength#=pathsize*multiplier
						'This is the virtual paths length.

Global pathc2#[pathsize+1]
Global pathd2#[pathsize+1]
Global pathflag2[pathsize+1]	'Set flags for what is on the track:
							'1=streetlamps,2=left wall,3=right wall,4=tunnel
Global drawamt=200		'Amount of track to draw in one go
Global drawbit[drawamt+1]	'Buffer used to store which bits of track need to be drawn
Global maxcars=50		'500 cars at one time on the track!?!?! lower this for less ;)
Global carx#[maxcars+1]	'Where on the track the car is (left-right. Values -1 to +1)
Global cary#[maxcars+1]	'Not used yet- Maybe add jumping?
Global carpos#[maxcars+1]	' where along the path each car is stored
Global drawcar[maxcars+1] 	'Flag for each car- does it get drawn?
Global drawx[maxcars+1]	'X coordinate for drawing car. Set when you set Drawcar[car]=1
Global drawy[maxcars+1]	'y coordinate for drawing car. Set when you set Drawcar[car]=1
Global drawsz#[maxcars+1]	'size for drawing car. Set when you set Drawcar[car]=1
Global carspeed#[maxcars+1]  'Speed of car. Best results are between 1 and 2. values 0-2 work good.
Global player=1			'Player's car number

'Position the cars randomly
For n=2 To maxcars
carx#(n)=Rnd(-.8,.8)
carspeed(n)=rnd(.6,1.1)
carpos(n)=Rand(pathlength)
Next

'Generate the level data using random info
c#=0
d#=0

targd#=Rand(-5,5)
targc#=Rand(-5,5)
For n=multiplier*10 To pathlength
If Rand(0,multiplier)>multiplier-(multiplier/100) Then pathflag2(n/multiplier)=Rand(1,4)

If Rand(0,100)>99 Or cnt>multiplier*10 Then cnt=0;tc#=targc;targc#=Rand(-3,3);If Rand(0,10)>8 Or tc<>0 Then targc=0;cnt=-1
If cnt>-1 Then cnt=cnt+1
If Rand(0,100)>90 Then targd#=Rand(-3,4);If Rand(0,10)>2 Then targd=0
If n=0 Or n>pathlength-100 Then targd=0;targc=0

mc#=(c#-targc#)/10.0;If Abs(mc)>.1 Then mc=Sgn(mc)*.1
c#=c#-mc

md#=(d#-targd#)/10.0;If Abs(md)>.1 Then md=Sgn(md)*.1
d#=d#-md
d=d*.9
c=c*.9
pathc2[n/multiplier]=C
pathd2[n/multiplier]=d*.01
Next

dmult#=0.985
ymult#=1
pathpos#=0
Repeat

For n=1 To maxcars
carpos(n)=carpos(n)+carspeed(n)
carpos(n)=carpos(n) Mod pathlength
If carpos(n)<0 Then carpos(n)=carpos(n)+pathlength
carpos(n)=carpos(n)
drawcar(n)=0
Next


pathpos=(pathpos+1) Mod pathlength
pathpos2#=pathpos
Cls
pos#=pathpos
y#=scy
x#=scx/2.0
z#=scx/2.0

d#=10
D2#=10*120
oy#=y
miny#=scy
x=(scx/2.0)-carx(player)*scx
mv#=((pathc(pathpos)-pathc(opathpos))/10.0)
carx(player)=carx(player)+(KeyDown(key_right)-KeyDown(key_left))*.02
carspeed(player)=carspeed(player)+(KeyDown(key_up)-KeyDown(key_down))*.01
cnt=0
dc#=0
xc#=0
Repeat
ok=0
d#=d#/(1.03*1.03*dmult)
D2=D2/(1.029*1.03*dmult)
d4#=d#;If d4<1 Then d4=1
drawbit(cnt)=0
If y<=miny Then miny=y;drawbit(cnt)=1

'Change X value to make the tracks corners work properly

x=x+Float(pathc(pos)*(10.0-d)/5.0)*d4*2
x=x-Float(pathc(pathpos2)*(10.0-d)/5.0)*d4*2



'Change y value to make the tracks corners work properly and give perspective
dc#=dc#+pathd(pos)
y=y+dc
y=y-d*1.5*ymult

cnt=cnt+1;If cnt>drawamt Then ok=1	'set the OK flag if weve gone through enough track.
pos=(pos+1) Mod pathlength
Until ok=1 Or KeyDown(key_escape)

SetColor 70,50,200;DrawRect 0,0,scx,miny-1 'draw sky


'Okay, now lets do it all again backwards and draw stuff at the same time.
od3#=0
Repeat
cnt=cnt-1
	pos=(pos-1);If pos<0 Then pos=pos+pathlength
	ok=0
	d#=d#*(1.03*1.03*dmult)
	D2=D2*(1.029*1.03*dmult)
	d4#=d#;If d4<1 Then d4=1
	x1=x-(pathc(pos))-d2
	x2=x+(pathc(pos))+d2
	dq=0
	If Abs(y-oy)>.01 Then dq=1
	y2#=Abs(y-oy)
	If drawbit(cnt)=1 Then

		'grass colouring
			If (Int(pos/8) Mod 2)=0 Then SetColor 0,180,0 Else SetColor 0,200,0
		'draw the grass
		If dq=1 Then
			Drawquad 0,y,x1,y,ox1,oy,0,oy
			Drawquad scx,y,x2,y,ox2,oy,scx,oy
		EndIf

		'Draw track "edges"
		If (Int(pos/2) Mod 2)=0 Then SetColor 255,0,0 Else SetColor 255,255,255
		drawquad x1-d*16,y,x1,y,ox1,oy,ox1-d*16,oy
		drawquad x2,y,x2+d*16,y,ox2+d*16,oy,ox2,oy
'		drawquad x1-d*16,y,x1,y,ox1+od#*16,oy,ox1,oy
'		drawquad x2+d*16,y,x2,y,ox2+od*16,oy,ox2,oy

		
		'tarmac colouring
		If (Int(pos/7) Mod 2)=0 Then SetColor 120,120,120 Else SetColor 80,80,80
		
		'draw tarmac
		If dq=1 Then
			drawquad x1-1,y,x2+1,y,ox2+1,oy,ox1-1,oy
		EndIf
		'Draw white strip
		If (Int(pos/9) Mod 2)=0 And dq=1 Then 
			SetColor 255,255,255
			Drawquad x-d,y,x+d,y,ox+od#,oy,ox-od#,oy
		EndIf


		SetColor 255,255,255
		For n=1 To maxcars
			If Int(carpos[n])=Int(pos) Then 'Draw car
				drawcar(n)=1;drawx(n)=x+carx(n)*(d2);drawy(n)=y;drawsz#(n)=d*10	'set flag and store where to draw the cars!?
				DrawRect drawx(n)-drawsz(n)/2.0,drawy(n)-drawsz(n)/2.0,drawsz(n),drawsz(n)/2.0
			EndIf
		Next

	EndIf

	'Draw tunnels and stuff outside of the "should i draw" check above
	d3#=d
	If pathflag(pos)=1 then
		SetColor 255,255,255
		If Int(pos Mod 20)=10 Then DrawRect x2+(d3*40),y-(d3*100),d3*10,d3*100
		If Int(pos Mod 20)=0 Then DrawRect x1-(d3*40),y-(d3*100),d3*10,d3*100'DrawLine x1,y-(d*100),x1,y
	endif
	
	drawtunnel=pathflag(pos)-1;If drawtunnel<0 Then drawtunnel=0
	If drawtunnel>0 Then 
		SetColor 10,100,20
		If drawtunnel=1 Or drawtunnel=3 Then
			 Drawquad x2+(d3*25),y-(d3*100),ox2+(od3#*25),oy-(od3*100),ox2+(od3*25),oy,x2+(d3*25),y
		EndIf
		If drawtunnel=2 Or drawtunnel=3 Then 
			 Drawquad x1-(d3*25),y-(d3*100),ox1-(od3#*25),oy-(od3*100),ox1-(od3*25),oy,x1-(d3*25),y
		EndIf
		If drawtunnel=3 Then
			DY1=y-(d3*100)+2
			DY2=Oy-(Od3*100)+2
			SetColor 0,60,0
			DRAWQUAD X1-(D3*25),DY1,X2+(D3*25),DY1,oX2+(oD3*25),DY2,ox1-(od3*25),dy2
		EndIf
	EndIf
	
	
	
	'Store old values. 
	od3#=d3#
	ox1=x1
	ox2=x2
	ox=x
	oy=y
	od#=d#
	
	
	
	'Change X value to make the tracks corners work properly
	x=x-Float(pathc(pos)*(10.0-d)/5.0)*d4*2
	x=x+Float(pathc(pathpos2)*(10.0-d)/5.0)*d4*2


	
	'Change y value to make the tracks corners work properly and give perspective
	dc#=dc#-pathd(pos)
	y=y-dc
	y=y+d*1.5*ymult

	
	If cnt<1 Then ok=1  'set the OK flag if weve drawn enough track.
Until ok=1 Or KeyDown(key_escape)

opathpos=pathpos
DrawText pathpos,10,10
pathpos=carpos(player)-10
If pathpos<0 Then pathpos=pathpos+pathlength
bglSwapBuffers()
FlushMem
Until KeyDown(key_escape)
End


Function drawquad(x1#,y1#,x2#,y2#,x3#,y3#,x4#,y4#)
Local poly#[]=[Float(x1),Float(y1),Float(x2),Float(y2),Float(x3),Float(y3),Float(x4),Float(y4)]
DrawPoly poly
End Function

Function pathc#(pos#)
pos=pos/multiplier
pos=pos Mod pathsize
Local pos2=(pos+1) Mod pathsize
val1#=pathc2#(Floor(pos))
val2#=pathc2#(Floor(pos2))
val3#=pos#-Floor(pos#)
Return interpolate#(val1#,val2#,val3#)
End Function

Function pathd#(pos#)
pos=pos/multiplier
pos=pos Mod pathsize
Local pos2=(pos+1) Mod pathsize
val1#=pathd2#(Floor(pos))
val2#=pathd2#(Floor(pos2))
val3#=pos#-Floor(pos#)
Return interpolate#(val1#,val2#,val3#)
End Function

Function pathflag(pos)
Return Floor(pathflag2((pos/multiplier) Mod pathsize))
End function

Function interpolate#(val1#,val2#,decimal#)
Return Float(val1)+Float(Float(val2)-Float(val1))*decimal
End Function



I dont realy have time to do much with this but im trying to get to grips with max so i can get on with a larger project. If you see any ways to improve the efficiency, let us know :)

That is so cool. Would make a nice retro screensaver too.

Really amazing. :)
Reminds me of the good old days...hehe.

cheers lads :D

Did anyone played "Powerdrift"?

Also very nice old rusty racing game.... :D

Nice, loved Power Drift by the way ... wanted to make something like it not too long ago ... could probably do it with Max.

Great stuff Cygnus.

I used to play Outrun at the arcade so much that I ended up being able to get to each of the 5 goals using any path to get there.

Another awesome game that used this type of track was Lotus Esprite Challenge on the Amiga.. loved that one too.

You could also use it do a version Space Harrier which was another game I could complete all 18 levels on with my starting credits.

Ah the memories... ") (hey I just invented the Picaso smilie :D )

^.^ by chance ive come across loads of games using this style the last few days in our local retrocomputer shop ^>^

http://www.ysrnry.co.uk/articles/outrun.htm

Cygnus what have you done now? Those screenshots supplied by Perturbatio would certainly help in your updated version of Outrun, which you are now obligated to complete. ;)

I recently got to play outrun on the xbox. Feels a lot like the original only seems harder. Not a big fan of 2D racers anymore unless its something top down like the old MP supersprint games. But then you need the crazy wheel you spin fast to drift around the corners :)

Top down racers? I liked micro machines myself.

btw I don't think the original outrun was ever easy - especially in that raised hydraulic version.


But then you need the crazy wheel you spin fast to drift around the corners :)


Yeah, very cool -- especially on this game, with the top cabinet pictured!

http://www.klov.com/game_detail.php?letter=H&game_id=8148

well, im still training myself in blitzmax and this is my learning code. ive not had much time to work on it though as my machine started acting wierd and now wont turn on. Building a new system as we speak. (this ones my sisters p3 350 o/c to 525 ^.^ (i wonder why my machines break so often?)

ive changed the perspective a bit but thats the only coding time ive had the last few days! il keep you all up to date though!

Nice bit of code, Cygnus!

Thanks again ^.^ i expect to get back at it soon. right now my GF is here so all im doing is responding to posts :)



Just a screenie to tide y'all over :)

Jinkies!

As you can tell, I'm not that good with graphics, so for now ive swiped 'em. To be sorted later on :)

Okay, i finally got an hour of coding in!!!!

Its no longer source only so heres a link to source+media (222k)

http://damientsturdy.pwp.blueyonder.co.uk/racer2.zip



framework brl.glmax2d
Import brl.random
Import brl.pngloader
'Import brl.ramstream
'Incbin "caranim.png"



'Import brl.blitz
Global scx#=800,scy#=600
Graphics scx,scy,0,60
bglSetSwapInterval(1)

Global pathsize=1024	 	'This is the paths TRUE length
Global multiplier#=250		'This is how much this path is interpolated. (pathsize is multiplied by this)
Global pathlength#=pathsize*multiplier
						'This is the virtual paths length.

Global pathc2#[pathsize+1]
Global pathd2#[pathsize+1]
Global pathflag2[pathsize+1]	'Set flags for what is on the track:
Global iswater[pathsize+1]
Global cos2#[361]
Global Sin2#[361]
Global drawbuffer=1024
Global drawn[drawbuffer+1]
setupsincos
							'1=streetlamps,2=left wall,3=right wall,4=tunnel
Global drawamt=400		'Amount of track to draw in one go
Global drawbit[drawamt+1]	'Buffer used to store which bits of track need to be drawn
Global maxcars=50		'500 cars at one time on the track!?!?! lower this for less ;)
Global carx#[maxcars+1]	'Where on the track the car is (left-right. Values -1 to +1)
Global cary#[maxcars+1]	'Not used yet- Maybe add jumping?
Global carpos#[maxcars+1]	' where along the path each car is stored
Global drawcar[maxcars+1] 	'Flag for each car- does it get drawn?
Global drawx[maxcars+1]	'X coordinate for drawing car. Set when you set Drawcar[car]=1
Global drawy[maxcars+1]	'y coordinate for drawing car. Set when you set Drawcar[car]=1
Global drawsz#[maxcars+1]	'size for drawing car. Set when you set Drawcar[car]=1
Global carspeed#[maxcars+1]  'Speed of car. Best results are between 1 and 3.
Global maxspeed#[maxcars+1]  'max Speed of car. Best results are between 1 and 3.
Global player=1			'Player's car number
'Position the cars randomly
For n=1 To maxcars
carx#(n)=((n Mod 2)-.5)
carspeed(n)=0
maxspeed(n)=rnd(2,3)
carpos(n)=n*10
Next
maxspeed(1)=3.5
AutoMidHandle 1

Rem
	Graphics loading routine here
EndRem

SetMaskColor(10,20,255)
Global maxframes=49
Global carimage=LoadAnimImage("caranim.png",256,128,0,maxframes+1)
If carimage=Null Then RuntimeError "Car not found!"
'End

'Generate the level data using random info
c#=0
d#=0

targd#=Rand(-5,5)
targc#=Rand(-5,5)
For n=multiplier To pathlength
If Rand(0,1000)>999 And watercount=0 Then watercount=Rand(1,3)*1


If Rand(0,multiplier)>multiplier-(multiplier/100) Then pathflag2(n/multiplier)=Rand(1,4)
If Rand(0,100)>99 Or cnt>multiplier*10 Then	cnt=0;tc#=targc;targc#=Rand(-3,3);If Rand(0,10)>5 Or tc<>0 Then targc=0;cnt=-1
If cnt>-1 Then cnt=cnt+1
If Rand(0,100)>90 Then targd#=Rand(-3,4);If Rand(0,10)>5 Then targd=0
If n=0 Or n>pathlength-100 Then targd=0;targc=0

mc#=mc+(c#-targc#)/10.0;If Abs(mc)>.1 Then mc=Sgn(mc)*.1
c=c+mc
mc=mc*.9
c=targc
md#=(d#-targd#)/10.0;If Abs(md)>.1 Then md=Sgn(md)*.1
d#=d#-md
d=d*.9
c=c*.9
If watercount>0 Then iswater[n/multiplier]=1;watercount=watercount-1
pathc2[n/multiplier]=C*5
pathd2[n/multiplier]=d*.001
Next
patchmult=4
dmult#=1.02
ymult#=.5
pathpos#=0
Repeat
If KeyDown(key_tab) Then WaitKey;WaitKey

For n=1 To maxcars
carpos(n)=carpos(n)+carspeed(n)
carpos(n)=carpos(n) Mod pathlength
If carpos(n)<0 Then carpos(n)=carpos(n)+pathlength
carpos(n)=carpos(n)
drawcar(n)=0
carspeed(N)=carspeed(N)*.999
If carspeed(n)>maxspeed(n) Then carspeed(n)=maxspeed(N)
If n<>player Then carspeed(n)=carspeed(n)+.01
Next


pathpos=(pathpos+1) Mod pathlength
pathpos2#=pathpos
Cls
pos#=pathpos
y#=scy*1'.2
x#=scx/2.0
z#=scx/2.0

d#=10
D2#=10*120
oy#=y

xdir#=xdir#+(KeyDown(key_right)-KeyDown(key_left))
xdir=xdir*.8
carx(player)=carx(player)+xdir#*.01
carspeed(player)=carspeed(player)+(KeyDown(key_up)-KeyDown(key_down))*.01

miny#=scy*4
x=(scx/2.0)-carx(player)*scx*1.5
stx#=carx(player)
mv#=((pathc(pathpos)-pathc(opathpos))/10.0)
cnt=0
dc#=0
xc#=0
xdf#=((scx/2.0)-x)*.003*.7
DIV#=.05

Repeat
ok=0
d#=d#/dmult#
d2#=d2#/dmult

d4#=d#;If d4<1 Then d4=1
drawbit(cnt)=0
If y<=miny Then miny=y;drawbit(cnt)=1

'Change X value to make the tracks corners work properly
X=x+(Float(PATHC(POS)-PATHC(pathpos)))
x=x+xdf*d

'Change y value to make the tracks corners work properly and give perspective
dc#=dc#+pathd(pos)
y=y+dc
y=y-(d*ymult)
cnt=cnt+1;If cnt>drawamt Then ok=1	'set the OK flag if weve gone through enough track.
adiv#=div#;If adiv<1 Then adiv=1
pos=(pos+adiv) Mod pathlength;If pos<0 Then pos=pos+pathlength

DIV=DIV*1.02
Until ok=1 Or KeyDown(key_escape) 

SetColor 70,50,200;DrawRect 0,0,scx,miny-1 'draw sky


'Okay, now lets do it all again backwards and draw stuff at the same time.
od3#=0
For n=0 To drawbuffer
drawn[n]=0
Next

Repeat
	DIV=DIV/1.02
	adiv#=div#;If adiv<1 Then adiv=1
	opos#=pos#
	pos=(pos-adiv) Mod pathlength;If pos<0 Then pos=pos+pathlength
	cnt=cnt-1

	'Change y value to make the tracks corners work properly and give perspective
	y=y+(d*ymult)
	y=y-dc
	dc=dc-pathd(pos)
	

	'Change X value to make the tracks corners work properly
	X=x-(Float(PATHC(POS)-PATHC(pathpos)))
	x=x-xdf*d


	ok=0
	d=d*dmult
	d2=d2*dmult
	d4#=d#;If d4<1 Then d4=1
	x1=x-(pathc(pos))-d2
	x2=x+(pathc(pos))+d2
	dq=0
	If Abs(y-oy)>.01 Then dq=1
	y2#=Abs(y-oy)
	If drawbit(cnt)=1 Then

		'grass/water colouring
			If iswater(pos/multiplier)=0 Then
				If (Int(pos/(8*patchmult)) Mod 2)=0 Then SetColor 0,180,0 Else SetColor 0,200,0
			Else
				SetColor 0,0,255
			EndIf
		'draw the grass/water
		If dq=1 Then
			Drawquad 0,y,x1,y,ox1,oy,0,oy
			Drawquad scx,y,x2,y,ox2,oy,scx,oy
		EndIf

		'Draw track "edges"
		If (Int(pos/(2*patchmult)) Mod 2)=0 Then SetColor 255,0,0 Else SetColor 255,255,255
		drawquad x1-d*16,y,x1,y,ox1,oy,ox1-d*16,oy
		drawquad x2,y,x2+d*16,y,ox2+d*16,oy,ox2,oy
		
		'tarmac colouring
		If (Int(pos/(7*patchmult)) Mod 2)=0 Then SetColor 120,120,120 Else SetColor 80,80,80
		
		'draw tarmac
		If dq=1 Then
			drawquad x1-1,y,x2+1,y,ox2+1,oy,ox1-1,oy
		EndIf
		'Draw white strip
		If (Int(pos/(9*patchmult)) Mod 2)=0 And dq=1 Then 
			SetColor 255,255,255
			Drawquad x-d,y,x+d,y,ox+od#,oy,ox-od#,oy
		EndIf


	EndIf

	'Draw tunnels and stuff outside of the "should i draw" check above
	d3#=d
	apos#=pos
	ct=0
	div2=div;If div2<.2 Then div2=.2
	If pos>apos+div2 Then pos=apos+div2
	If d3<.02 Then d3=.02
	If pathflag(pos)=1 Then
		SetColor 255,255,255
		If Int(pos Mod 20)=10 Then DrawRect x2+(d3*40),y-(d3*100),d3*10,d3*100
		If Int(pos Mod 20)=0 Then DrawRect x1-(d3*40),y-(d3*100),d3*10,d3*100'DrawLine x1,y-(d*100),x1,y
	EndIf
	
	drawtunnel=pathflag(pos)-1;If drawtunnel<0 Then drawtunnel=0
	If drawtunnel>0 Then 
		SetColor 10,100,20
		If drawtunnel=1 Or drawtunnel=3 Then
			 Drawquad x2+(d3*25),y-(d3*100),ox2+(od3#*25),oy-(od3*100),ox2+(od3*25),oy,x2+(d3*25),y
		EndIf
		If drawtunnel=2 Or drawtunnel=3 Then 
			 Drawquad x1-(d3*25),y-(d3*100),ox1-(od3#*25),oy-(od3*100),ox1-(od3*25),oy,x1-(d3*25),y
		EndIf
		If drawtunnel=3 Then
			DY1=y-(d3*100)+2
			DY2=Oy-(Od3*100)+2
			SetColor 0,60,0
			DRAWQUAD X1-(D3*25),DY1,X2+(D3*25),DY1,oX2+(oD3*25),DY2,ox1-(od3*25),dy2
		EndIf
	EndIf

	If D>.1 Then
	SetColor 255,255,255
	For n=1 To maxcars
		If Int(carpos[n])=Int(pos) Then 'Draw car
			drawcar(n)=1;drawx(n)=x+carx(n)*(d2);drawy(n)=y;drawsz#(n)=d*10	'set flag and store where to draw the cars!?
			sc#=d/10
			sc=sc*2
			SetScale sc,sc
			fr=-(carx(n)-stx)*10
			If n=1 Then fr=fr+xdir
			fr=fr+(pathc(pos)-pathc(pathpos))*5
			If fr<-8 Then fr=-8
			If fr>8 Then fr=8
			fr=fr+8
			If fr>maxframes Then fr=maxframes
			If fr<0 Then fr=0
			DrawImage carimage,drawx(n),drawy(n)-(ImageHeight(carimage)/3)*sc,fr
		EndIf
	Next
	SetScale 1,1
	EndIf
	
	
	
	'Store old values. 
	od3#=d3#
	ox1=x1
	ox2=x2
	ox=x
	oy=y
	od#=d#
	
	
	
	If cnt<1 Then ok=1  'set the OK flag if weve drawn enough track.
Until ok=1 Or KeyDown(key_escape)

opathpos=pathpos
DrawText pathpos,10,10
pathpos=carpos(player)-10
If pathpos<0 Then pathpos=pathpos+pathlength
bglSwapBuffers()
FlushMem
Until KeyDown(key_escape)
End


Function drawquad(x1#,y1#,x2#,y2#,x3#,y3#,x4#,y4#)
Local poly#[]=[Float(x1),Float(y1),Float(x2),Float(y2),Float(x3),Float(y3),Float(x4),Float(y4)]
DrawPoly poly
End Function

Function pathc#(pos#)
pos=pos/multiplier
pos=pos Mod pathsize
Local pos2=(pos+1) Mod pathsize
val1#=pathc2#(Floor(pos))
val2#=pathc2#(Floor(pos2))
val3#=pos#-Floor(pos#)
Return interpolate#(val1#,val2#,val3#)
End Function

Function pathd#(pos#)
pos=pos/multiplier
pos=pos Mod pathsize
Local pos2=(pos+1) Mod pathsize
val1#=pathd2#(Floor(pos))
val2#=pathd2#(Floor(pos2))
val3#=pos#-Floor(pos#)
Return interpolate#(val1#,val2#,val3#)
End Function

Function pathflag(pos)
Return Floor(pathflag2((pos/multiplier) Mod pathsize))
End Function

Function interpolate#(val1#,val2#,decimal#)
Return Float(val1)+Float(Float(val2)-Float(val1))*decimal
End Function

Function setupsincos()
For n=0 To 360
Sin2(n)=Sin(n)
Cos2(n)=Cos(n)
Next
End Function

Function ssin#(val)
val=val Mod 360
If val<0 Then val:+360
Return sin2(val)
End Function

Function scos#(val)
val=val Mod 360
If val<0 Then val:+360
Return cos2#(val)
End Function


Line 167 should be:
For n=0 Until drawbuffer
Otherwise you are writing outside the array :)

ahh yes. twas the last thing i added
Hell, drawbuffer isnt even needed yet!

Nice work.

I used to play Lotus Esprit Turbo Challenge lots on the ST.

Lotus. ahh yes, we hacked our old school computer to play that. twas a good game.

Would it be possible to get the zip file back on line ? I would like to get the caranim.png file from it.

Thanks

redfox

yes, the zip file

I spent a while trying to make sense of the whole thing and did come cleaning/commenting.

Import BRL.Random
Import BRL.BMPLoader

Global scx#=800,scy#=600
Graphics scx,scy,0,60

Global pathsize=1024	 	'This is the paths TRUE length (integer?)
Global multiplier#=250		'This is how much this path is interpolated. (pathsize is multiplied by this)
Global pathlength#=pathsize*multiplier	'This is the virtual paths length.

Global pathc2#[pathsize+1]
Global pathd2#[pathsize+1]
Global pathflag2[pathsize+1]	'Set flags for what is on the track:'1=streetlamps,2=left wall,3=right wall,4=tunnel
Global iswater[pathsize+1]

Global drawamt=700		'Amount of track to draw in one go
Global drawbit[drawamt+1]	'Buffer used to store which bits of track need to be drawn
Global maxcars=50		'500 cars at one time on the track!?!?! lower this for less ;)
Global carx#[maxcars+1]	'Where on the track the car is (left-right. Values -1 to +1)
'Global cary#[maxcars+1]	'Not used yet- Maybe add jumping?
Global carpos#[maxcars+1]	' where along the path each car is stored

Global drawcar[maxcars+1] 	'Flag for each car- does it get drawn?

Global drawx[maxcars+1]	'X coordinate for drawing car. Set when you set Drawcar[car]=1
Global drawy[maxcars+1]	'y coordinate for drawing car. Set when you set Drawcar[car]=1
Global drawsz#[maxcars+1]	'size for drawing car. Set when you set Drawcar[car]=1

Global carspeed#[maxcars+1]  'Speed of car. Best results are between 1 and 3.
Global maxspeed#[maxcars+1]  'max Speed of car. Best results are between 1 and 3.

Global player=1			'Player's car number

'Position the cars randomly
For n=1 To maxcars
  carx#(n)=((n Mod 2)-.5)
  carspeed(n)=0
  maxspeed(n)=Rnd(2,3)
  carpos(n)=n*10
Next
maxspeed(1)=3.5


Rem
	Graphics loading routine here
EndRem

AutoMidHandle 1
SetMaskColor(10,20,255)
'Global maxframes=49
'Global carimage=LoadAnimImage("caranim.png",256,128,0,maxframes+1)
Global maxframes=5 ' was 49
Global carimage=LoadAnimImage("space1.bmp",256,128,0,maxframes+1)
If carimage=Null Then RuntimeError "Car not found!"

'##############################################################
'Generate the level data using random info
'##############################################################
c#=0    ' represents the change in X
d#=0    ' represents the change in slope

targd#=Rand(-3,4)
targc#=Rand(-3,3)

cnt=0

For n=multiplier To pathlength

  ' Handle water
  If Rand(0,1000)>999 And watercount=0 Then 
     watercount=Rand(1,3)*1
  EndIf

  If watercount>0 Then 
     iswater[n/multiplier]=1
     watercount=watercount-1
  EndIf


  ' Put stuff on the track
  If Rand(0,multiplier)>multiplier-(multiplier/100) Then 
     pathflag2(n/multiplier)=Rand(1,4)
  EndIf

 
  ' update the direction
  If Rand(0,100)>99 Or cnt>multiplier*10 Then	
      cnt=0
      tc#=targc
      targc#=Rand(-3,3)
      If Rand(0,10)>5 Or tc<>0 Then 
        targc=0
        cnt=-1
      EndIf
  EndIf

  If cnt>-1 Then
    cnt=cnt+1
  EndIf

  mc#=mc+(c#-targc#)/10.0

  If Abs(mc)>.1 Then 
     mc=Sgn(mc)*.1
  EndIf
  

  ' Update the slope
  If Rand(0,100)>90 Then 
      targd#=Rand(-3,4)
      If Rand(0,10)>5 Then 
          targd=0
      EndIf
  EndIf

  md#=(d#-targd#)/5.0 ' 10.0 5 is harder

  If Abs(md)>.1 Then 
     md=Sgn(md)*.1
  EndIf

  ' some fiddling... go figure
  If n=0 Or n>pathlength-100 Then 
     targd=0
     targc=0
  EndIf

  ' Update the parameters with the modifiers
  
  c=c+mc
  mc=mc*.9

  'c=targc  this is not needed

  d#=d#-md

  d=d*.9  'slowly diminish
  c=c*.9  'slowly diminish

  'c=0
  'd=0
  pathc2[n/multiplier]=c*2 'was 5 : intensity of the turn
  pathd2[n/multiplier]=d*.001

  'Print "mc="+mc+" md="+md

Next


'##############################################################
'  MAIN LOOP
'##############################################################
patchmult=4
dmult#=1.02  'very important parms but not that understandable now...
ymult#=1.0 '0.5    '.5    'very important parm to update y (.1 makes the track very flat, .8 more viewed from above)
pathpos#=0
cnt=0

Repeat
	If KeyDown(key_tab) Then WaitKey;WaitKey
	
	'##############################################################	
	' Update car positions
	'##############################################################
	For n=1 To maxcars
	  carpos(n)=carpos(n)+carspeed(n)
	  carpos(n)=carpos(n) Mod pathlength
	  If carpos(n)<0 Then carpos(n)=carpos(n)+pathlength
	  carpos(n)=carpos(n)
	  drawcar(n)=0
	  carspeed(N)=carspeed(N)*.999
	  If carspeed(n)>maxspeed(n) Then carspeed(n)=maxspeed(N)
	  If n<>player Then carspeed(n)=carspeed(n)+.01
	Next
	
	'##############################################################
	' Move 1 step further in the path
	'##############################################################
	pathpos=(pathpos+1) Mod pathlength

    ' Steer player's car.
	xdir#=xdir#-KeyDown(key_left)+KeyDown(key_right)
	' dampen movement
	xdir=xdir*.8
	' change X position on track by 1%
	' carx(player) is between -1 and +1 to stay on track. It can go further but this will be in the outside of the track.
	carx(player)=carx(player)+xdir#*.01
	
	' Manage speed: increase/decrease 1%
	carspeed(player)=carspeed(player)+(KeyDown(key_up)-KeyDown(key_down))*.01

	
	pathpos2#=pathpos
	pos#=pathpos
	
	x#=scx/2.0 ' Middle of screen / track
	y#=scy*1 '.2   BOTTOM OF SCREEN
	
	d#=10       ' d = ?
	d2#=10*120  'd2 = 120 x 10 (120=track width)
	
	oy#=y       'oldy ?
	
	miny#=scy*4   ' 4 times the screen height (just to be sure it is more than scy I guess)
	
	' remember that carx(player) is between -1.0 and +1.0
	' -1 means: scx/2 - (-1) * scx *1.5 : 400 - (-1)*1200 = +1600
	' +1 means: 400 - (+1) *1200 = 800
	
	x=(scx/2.0)-carx(player)*scx*1.5
	
	xdf#=((scx/2.0)-x)*.003*.7
	
	stx#=carx(player)
	
	mv#=((pathc(pathpos)-pathc(opathpos))/10.0)
	
	cnt=0
	dc#=0
	xc#=0
	
	' divide to advance on track : 5%
	div#=.05
	
	'##############################################################
	' DETERMINE WHAT HAS TO BE DRAWN
	'##############################################################
	Repeat
	
		ok=0

		drawbit(cnt)=0

		If y<=miny Then 
		  miny=y
		  drawbit(cnt)=1
		EndIf
		
		cnt=cnt+1
		If cnt>drawamt Then 
		  ok=1	'set the OK flag if we've gone through enough track.
		EndIf

		d#=d#/dmult#
		d2#=d2#/dmult
		
		d4#=d#
		If d4<1 Then 
		  d4=1
		EndIf
		
		'Change X value to make the tracks corners work properly
		x=x+(Float(pathc(pos)-pathc(pathpos)))
		x=x+xdf*d
		
		'Change y value to make the tracks corners work properly and give perspective
		'This is the key place !!!
		dc#=dc#+pathd(pos)
		y=y+dc
		y=y-(d*ymult)

        'adiv 	
		adiv#=div#
		If adiv<1 Then 
		  adiv=1
		EndIf
		
		'advance on track
		pos=(pos+adiv) Mod pathlength
		If pos<0 Then 
		  pos=pos+pathlength
		EndIf
		
		'increase div by 2%
		div=div*1.02
		
	
	Until ok=1 Or KeyDown(key_escape) 
	
	' Drawing starts here.	
	Cls
	SetColor 70,50,200
	DrawRect 0,0,scx,miny-1 'draw sky (using the damn miny)
		
		
	'Okay, now lets do it all again backwards and draw stuff at the same time.
		
	od3#=0
		
		
	Repeat
			DIV=DIV/1.02
			adiv#=div#
			If adiv<1 Then 
				adiv=1
			EndIf
			opos#=pos#
			pos=(pos-adiv) Mod pathlength
			
			If pos<0 Then 
			  pos=pos+pathlength
			EndIf
			cnt=cnt-1
		
			'Change y value to make the tracks corners work properly and give perspective
			y=y+(d*ymult)
			y=y-dc
			dc=dc-pathd(pos)
			
		
			'Change X value to make the tracks corners work properly
			X=x-(Float(PATHC(POS)-PATHC(pathpos)))
			x=x-xdf*d
		
		
			ok=0
			d=d*dmult
			d2=d2*dmult
			d4#=d#
			If d4<1 Then 
			  d4=1
			EndIf
			x1=x-(pathc(pos))-d2
			x2=x+(pathc(pos))+d2
			dq=0
			
			If Abs(y-oy)>.01 Then 
			  dq=1
			EndIf
			
			y2#=Abs(y-oy)
			
			' There is something to draw for the current position
			If drawbit(cnt)=1 Then
		
				'grass/water colouring
					If iswater(pos/multiplier)=0 Then
						If (Int(pos/(8*patchmult)) Mod 2)=0 Then SetColor 0,180,0 Else SetColor 0,200,0
					Else
						SetColor 0,0,255
					EndIf
				'draw the grass/water
				If dq=1 Then
					Drawquad 0,y,x1,y,ox1,oy,0,oy
					Drawquad scx,y,x2,y,ox2,oy,scx,oy
				EndIf
		
				'Draw track "edges"
				If (Int(pos/(2*patchmult)) Mod 2)=0 Then SetColor 255,0,0 Else SetColor 255,255,255
				drawquad x1-d*16,y,x1,y,ox1,oy,ox1-d*16,oy
				drawquad x2,y,x2+d*16,y,ox2+d*16,oy,ox2,oy
				
				'tarmac colouring
				If (Int(pos/(7*patchmult)) Mod 2)=0 Then SetColor 120,120,120 Else SetColor 80,80,80
				
				'draw tarmac
				If dq=1 Then
					drawquad x1-1,y,x2+1,y,ox2+1,oy,ox1-1,oy
				EndIf
				'Draw white strip
				If (Int(pos/(9*patchmult)) Mod 2)=0 And dq=1 Then 
					SetColor 255,255,255
					Drawquad x-d,y,x+d,y,ox+od#,oy,ox-od#,oy
				EndIf
		
		
			EndIf
		
			'Draw tunnels and stuff outside of the "should i draw" check above
			d3#=d
			apos#=pos
			ct=0
			div2=div
			If div2<.2 Then 
			  div2=.2
			EndIf
			
			If pos > apos+div2 Then 
			  pos=apos+div2
			EndIf
			
			If d3<.02 Then 
			  d3=.02
			EndIf
			
			' There is a lamp pole
			If pathflag(pos)=1 Then 
				SetColor 255,255,255
				If Int(pos Mod 20)=10 Then 
				   DrawRect x2+(d3*40),y-(d3*100),d3*10,d3*100
				EndIf
				If Int(pos Mod 20)=0 Then 
				   DrawRect x1-(d3*40),y-(d3*100),d3*10,d3*100
				   'DrawLine x1,y-(d*100),x1,y
			    EndIf
			EndIf
			
			drawtunnel=pathflag(pos)-1 ' since walls and tunnels are higher than 1, there will be something to do.
			If drawtunnel<0 Then 
			  drawtunnel=0
			EndIf
			' There is something to do
			If drawtunnel>0 Then 
				SetColor 10,100,20
				'Left wall or tunnel, draw left edge
				If drawtunnel=1 Or drawtunnel=3 Then
					 Drawquad x2+(d3*25),y-(d3*100),ox2+(od3#*25),oy-(od3*100),ox2+(od3*25),oy,x2+(d3*25),y
				EndIf
				'Right wall or tunnel, draw right edge
				If drawtunnel=2 Or drawtunnel=3 Then 
					 Drawquad x1-(d3*25),y-(d3*100),ox1-(od3#*25),oy-(od3*100),ox1-(od3*25),oy,x1-(d3*25),y
				EndIf
				'Tunnel, draw top
				If drawtunnel=3 Then
					DY1=y-(d3*100)+2
					DY2=Oy-(Od3*100)+2
					SetColor 0,60,0
					Drawquad X1-(D3*25),DY1,X2+(D3*25),DY1,oX2+(oD3*25),DY2,ox1-(od3*25),dy2
				EndIf
			EndIf
		
		    ' ??? what is D ?
		    ' Draw cars
			If d > 0.1 Then
				SetColor 255,255,255
				For n=1 To maxcars
					If Int(carpos[n])=Int(pos) Then 'Draw car
					    'set flag and store where to draw the cars!?
						drawcar(n)=1                ' draw it
						drawx(n)=x+carx(n)*(d2)		' x position
						drawy(n)=y					' y position
						drawsz#(n)=d*10				' size
						
						' compute scaling factor
						sc#=d/10
						sc=sc*2
						SetScale sc,sc
						
						' Which frame to draw (depend on the position of the car vs the position of the driver's car)
						fr=-(carx(n)-stx)*10
						If n=1 Then fr=fr+xdir
						fr=fr+(pathc(pos)-pathc(pathpos))*5
						If fr<-8 Then fr=-8
						If fr>8 Then fr=8
						fr=fr+8
						If fr>maxframes Then fr=maxframes
						If fr<0 Then fr=0
						
						DrawImage carimage,drawx(n),drawy(n)-(ImageHeight(carimage)/3)*sc,fr
					EndIf
				Next
				SetScale 1,1
			EndIf
			
			
			
			'Store old values. 
			od3#=d3#
			ox1=x1
			ox2=x2
			ox=x
			oy=y
			od#=d#
			
			If cnt<1 Then ok=1  'set the OK flag If weve drawn enough track.
			
	Until ok=1 Or KeyDown(key_escape)
		
	opathpos=pathpos
	DrawText pathpos,10,10
	DrawText carx(player),10,40
	pathpos=carpos(player)-10
	If pathpos<0 Then pathpos=pathpos+pathlength
	'bglSwapBuffers()
	Flip
	
	Until KeyDown(key_escape)
End


Function drawquad(x1#,y1#,x2#,y2#,x3#,y3#,x4#,y4#)
  Local poly#[]=[Float(x1),Float(y1),Float(x2),Float(y2),Float(x3),Float(y3),Float(x4),Float(y4)]
  DrawPoly poly
End Function

Function pathc#(pos#)
  pos=pos/multiplier
  pos=pos Mod pathsize
  Local pos2=(pos+1) Mod pathsize
  val1#=pathc2#(Floor(pos))
  val2#=pathc2#(Floor(pos2))
  val3#=pos#-Floor(pos#)
  Return interpolate#(val1#,val2#,val3#)
End Function

Function pathd#(pos#)
  pos=pos/multiplier
  pos=pos Mod pathsize
  Local pos2=(pos+1) Mod pathsize
  val1#=pathd2#(Floor(pos))
  val2#=pathd2#(Floor(pos2))
  val3#=pos#-Floor(pos#)
  Return interpolate#(val1#,val2#,val3#)
End Function

Function pathflag(pos)
  Return Floor(pathflag2((pos/multiplier) Mod pathsize))
End Function

Function interpolate#(val1#,val2#,decimal#)
  Return Float(val1)+Float(Float(val2)-Float(val1))*decimal
End Function


Of course, there are places where I have not clue on what this does. I googled for a while but wasn't able to find out any info on the algorithm.

Just found the source today so i'll pop the zip up shortly. same link!

Note this was the first real thing I wrote in BlitzMax. I'm glad you're enjoying this code hehe.

The original Zip does not contain source or the anim image, the one I upload will do.


[edit]
http://damientsturdy.pwp.blueyonder.co.uk/racer2.zip



Sorry I couldn't finish this guys- paid jobs took over from what I remember- this is the latest (messy haha) source I have.

Thanks!

For what it is worth, the sin/cos routines are not needed in the code as well as several other variables. The code I posted is somewhat cleaned on that front.

To get all the details right (with the functions of the parms) is going to take some time since this code is quite feature-packed !

If I remember correctly the Sin/Cos was a table lookup to speed things up a bit.

PathC(point)=turn value of this point of track- the function interpolates hence the extra code- it can accept floats.

PathD(point)=Hill value of this point of the track. As above.

Interpolate: Does the interpolation ;)


Also, i'm sorry the code wasn't written with Long variable names. I used to use the same variables in all my programs so I could go back to it any time, But it makes it hard for others to read.

X,Y/A,B = x/y axis. C/D = Amount the X/Yspeed changes by. in this example C (pathC)= turn amount and D=used to create the Y position to draw stuff, and also to decide the width of the track at that point.

Ok this helps. BTW d4 is not used at all in the algorithm.

This snippet also appears strange to me: why is d used as well as for y as for x ? what is xdf for ?

			'Change y value to make the tracks corners work properly and give perspective
			y=y+(d*ymult)
			y=y-dc
			dc=dc-pathd(pos)
			
		
			'Change X value to make the tracks corners work properly
			x=x-(Float(pathc(pos)-pathc(pathpos)))
			x=x-xdf*d


Thanks !

Yes, D4 used to be used for some older unoptimised stuff, but is no longer required. The code it pertains to was removed not long after it was added, I guess I left some old code in!

D and Y are used for X because of depth- the depth changes how much of the turn is added. this isn't really required and you can probably get it working by removing (or making some values static.)

XDF is again a value to determine how much "turn" should apply to the X axis. It could be static, i added it to make the effect easy to adjust. :)

OK, i have some pseudocode for you.

I wrote it in notepad haha- I'm at work right now, and can't test- it will need tweaking to get it to compile no doubt, but you can read the logic much better!

Any suggestions let me know, and i'll provide compiling source when I get home. I'm a little inundated with work at the mo so I can't spend alot of time here!

this is absolute basics- but it should be enough for you to do your own rather than try to convert old convoluted code :D

Implement the PathC/PathD/Interpolate funcs from above if you want to do that too :) It makes for memory savings.

'Basic Algo:
'This does NOT allow perspective filled polygon drawing.
'To enable the ability to fill polies correctly, you must do the loop twice, the first time as below but without drawing,
'The second time, follow it backwards- instead of *0.99, /0.99 instead, and instead of X=X+, do X=X-.... Do the drawing in this second loop.


Global turns:float[1000]	'contains a list of turns- 0=no turn <0 left, >0 right.
Global hills:float[1000]	'Contains a list of the hills etc. >0 = up, <0 = down.
Global PlayerPos:int=0		'Position the camera is at.
Global currentpos:int=0		'current track position. Used internally


repeat
	X:float=screenwidth/2
	Y:float=0
	Ydir:float=20
	done:int=false				'Flag to say this frame is complete.
	firstframe:int=true			'Flag to say this is the first piece of track to be rendered- Used to avoid drawing the wrong lines on first frame.
	currentpos=playerpos			'Set the current track position to be used by the algo.
	repeat
		trackwidth=Ydir*20		'Tweak this!!!
		'The followind two lines store the last frames track lines X coords.
		oldleftx=leftx
		oldrightx=rightx
		leftx=x-TrackWidth		'Point to draw the left of the track.
		rightX=x+trackwidth		'Point to draw the right of the track
		If firstframe=false then	'Not the first frame- draw!!!
			DrawLine (oldleftx,oldy,leftx,y)			
			DrawLine (oldrightx,oldy,rightx,y)
		Endif
		X=X+turns[currentpos]		'Add the turns!
		oldy=y				'Store the last frames Y position on screen		
		y=y-Ydir			'Bring the Y drawing coordinate up.
		Y=Y+hills[currentpos]]		'Add the hills!
		Currentpos=(Currentpos+1) mod 1000
		ydir=Ydir*0.99
		if ydir<.01 then done=true	'When the Y movement is almost 0, complete the frame. TWEAK THIS else it could either not draw much or be dog slow.
		
	until done=true
	Playerpos=(playerpos+1) mod 1000
	flip
	cls
until keydown(key_escape)


Hey, thanks !

I think that I'll be able to understand it all now.

As for the when to draw cars test, it is now clear to me !

Rgds

'Basic Algo:
'This DOES allow perspective filled polygon drawing.
SuperStrict

Graphics 640,480
SetClsColor 100,100,255 'blue sky

Global turns:Float[1000]	'contains a list of turns- 0=no turn <0 left, >0 right.
Global hills:Float[1000]	'Contains a list of the hills etc. >0 = up, <0 = down.

'Fill the array above.
Global turn#=0
Global hill#=0
For Local x:Float=0 To 990 Step 100
	For Local x2:Int=x To x+99
		turns[x2]=turn*1000'Int(turn)
		If x2>0 Then hills[x2]=(hills[x2-1]+hill)*0.9'Int(turn)
		
	hill=hill*0.95
	Next
	hill=Rnd(-.2,.2)
	If turn<>0 Then turn=0 Else turn=Rnd(-.02,.02)
	turn=turn*0.95
Next

Global PlayerPos:Int=0		'Position the camera is at.
Global currentpos:Int=0		'current track position. Used internally
Global numberofits:Int=60	'Number if pieces of track to draw

Repeat
	Local x:Float=GraphicsWidth()/2
	Local y:Float=GraphicsHeight()
	Local Ydir:Float=100
	Local done:Int=False				'Flag to say this frame is complete.
	Local firstframe:Int=True			'Flag to say this is the first piece of track to be rendered- Used to avoid drawing the wrong lines on first frame.
	Local oldleftx:Int
	Local oldrightx:Int
	Local leftx:Int
	Local rightx:Int
	Local oldy:Int
	Local oldx:Int
	
	currentpos=PlayerPos				'Set the current track position to be used by the algo.
	
	'Right, to enable perspective drawing we are going to do the loop twice- once backwards, once forwards.
	
	'First: Forwards: NO need to do line calculation here, lets just do the math. The object of this is to find where to start drawing
	'backwards from in order to be able to draw polygins properly.
	'Note that the math here has to be mirrored exactly in the loop below. if any values are out, the drawing will bugger up.
	For Local Frameno:Int=0 To numberofits
		Local trackwidth:Int=Ydir*4		'Tweak this!!!
		x=x+turns[currentpos]			'Add the turns!
		y=y-Ydir*.2						'Bring the Y drawing coordinate up.
		y=y+hills[currentpos]*10		'Add the hills!
		Currentpos=(Currentpos+1) mod 1000
		ydir=Ydir*0.9
		firstframe=False
	Next

	'now backwards, and do the drawing.
		For Local Frameno:Int=0 To numberofits+10 '(draw a few extra to fill any hole at the bottom...) 
		Currentpos=(Currentpos-1);If currentpos<0 Then currentpos=currentpos+1000
		Local trackwidth:Int=Ydir*4		'Tweak this!!!
		'The followind two lines store the last frames track lines X coords.
		oldleftx=leftx
		oldrightx=rightx
		leftx=x-TrackWidth				'Point to draw the left of the track.
		rightX=x+trackwidth				'Point to draw the right of the track
		If frameno>0 Then				'Not the first frame- draw the track!!!
			If ((currentpos/4) mod 4)<2 Then SetColor 0,255,0 Else SetColor 0,200,0
			drawquad 0,oldy,0,y,leftx,y,oldleftx,oldy
			drawquad GraphicsWidth(),oldy,GraphicsWidth(),y,rightx,y,oldrightx,oldy
			
			If (((currentpos+2)/4) mod 4)<2 Then SetColor 128,128,128 Else SetColor 80,80,80
			'SetColor 0,0,0
			drawquad oldleftx,oldy,leftx,y,rightx,y,oldrightx,oldy
			SetColor 255,255,255
			DrawLine (oldleftx,oldy,leftx,y)			
			DrawLine (oldrightx,oldy,rightx,y)
			
			If ((currentpos/4) mod 4)<2 Then DrawLine (oldx,oldy,x,y)
		EndIf
		oldx=x
		x=x-turns[currentpos]			'Add the turns!
		oldy=y							'Store the last frames Y position on screen		
		y=y+Ydir*.2						'Bring the Y drawing coordinate up.
		y=y-hills[currentpos]*10	'Add the hills!
		ydir=Ydir/0.9
		firstframe=False
	Next


	
	
	Playerpos=(playerpos+1) mod 1000
	Flip
	Cls
Until KeyDown(KEY_ESCAPE)

Function drawquad(x1#,y1#,x2#,y2#,x3#,y3#,x4#,y4#)
  Local poly#[]=[Float(x1),Float(y1),Float(x2),Float(y2),Float(x3),Float(y3),Float(x4),Float(y4)]
  DrawPoly poly
End Function


This one is much more readable, and contains the code that enables you to draw filled polies. I hope it is of use.

Thats all from me!

Thanks for all the effort Cygnus, it goes appreciated !