Sync On:Sync Rate 60:Autocam Off
Set Camera Range .01,100
Global GSize as Integer
GSize=100
Dim GlobalHeights(GSize,GSize)
Global Grav as Float
Grav=-.01
Global stearing as float
Global move# as float
Global acc# as float
Global Speed as float
Global friction# as float
Global heavy as float
Global Choing as Integer
 
Null=Make Vector3(1)
Null=Make Vector3(2)
Null=Make Vector3(3)
 
Type Vector
   Object as DWord
   x as float
   y as float
   z as float
Endtype
 
Dim ObjectPhysics(3) as Vector
 
 
 
Print "Drawing Grass..."
Sync
Grass()
Print "Global Heights..."
Sync
Establish_Globals()
 
Make_Terrain(64,64)
Print "Terrain Done..."
Sync
 
 
Position Camera 0,0,0
x#=Camera Position X()
z#=Camera Position Z()
y#=Get Terrain Ground Height(1,x#,z#)+150
Position Camera x#,y#,z#
 
Make_Vehicle()
 
 
lx=1:ly=1
Do
   turn#=(RightKey()-LeftKey())*1.0
   stearing = stearing + turn#-((stearing>0)-(stearing<0))*.3
   move#=(DownKey()-Upkey())*.002
   acc#=acc#+move#
   heavy=0
   If Choing=0
      If Lower$(Inkey$())="f"
         Move Object Up 21,.4
         Move Object Up 23,.4
         Choing=100
      Endif
      n#=0
      If SpaceKey()
         For i = 21 to 24
            Move Object Up i,.4+n#
            n#=n#+.02
         Next i
         Choing=100
      Endif
   Else
      Choing=Choing-1
   Endif
   For i = 21 to 22
      if stearing <-30 then stearing = -30
      if stearing >30 then stearing = 30
      gy#=Get Terrain Ground Height(1,Object Position X(i),Object Position Z(i))+Object Size Y(i)*.5
      if gy#>Object Position Y(i)
         Move Object i,acc#
         friction#=.35
      Else
         friction#=.999
         heavy=heavy-.0025
         if gy#<Object Position Y(i)-1.0 Then acc#=acc#-(.001*acc#)
      Endif
      Physics(i)
      Center Text Object Screen X(i),Object Screen Y(i)-20,Str$(i)
   Next i
   for i = 23 to 24
      gy#=Get Terrain Ground Height(1,Object Position X(i),Object Position Z(i))+Object Size Y(i)*.5
      if gy#>Object Position Y(i)
         Move Object i,acc#*.5
         friction#=.45
      Else
         friction#=.998
         heavy=heavy-.0025
         if gy#<Object Position Y(i)-1.0 Then acc#=acc#-(.001*acc#)
      Endif
      Physics(i)
      Center Text Object Screen X(i),Object Screen Y(i)-20,Str$(i)
   next i
   Space_Wheels(21,22,23,24,25,26,27)
   Rotate Camera 0,0,0
   Pitch Camera Down 6
   Move Camera -18
   Set Cursor 0,0
   Print "FPS: ";Screen FPS()
   Print "Speed: ";Int(-acc#*100)
   Sync
Loop
 
End
 
Function Make_Terrain(x,y)
   Print "Heightmap..."
   Sync
   Create_Heightmap(x,y)
   Print "Make Terrain..."
   Sync
   If Object Exist(1) then Delete Object 1
   Make Object Terrain 1
   Set Terrain Heightmap 1,"Heightmap.bmp"
   Set Terrain Texture 1,3,4
   Set Terrain Tiling 1,2
   Set Terrain Scale 1,5,.3,5
   Build Terrain 1
   Set Object Collision Off 1
Endfunction
 
 
Function Establish_Globals()
   GlobalHeights(1,1)=Rnd(50)+100
   For i=2 to GSize
      GlobalHeights(i,1)=rnd(50)+100
      adj=GlobalHeights(i-1,1)+rnd(13)-7
      GlobalHeights(i,1)=adj
   Next i
   For i=2 to GSize
      GlobalHeights(1,i)=rnd(50)+100
      adj=GlobalHeights(1,i-1)+rnd(13)-7
      GlobalHeights(1,i)=adj
   Next i
   For j = 2 to GSize
      For i= 2 to GSize
         adj=GlobalHeights(i-1,j-1)
         adj=adj+GlobalHeights(i,j-1)
         adj=adj+GlobalHeights(i-1,j)
         adj=adj/3
         nh=rnd(13)-7
         gh=adj+nh
         if gh<0 then gh=0
         if gh>200 then gh=200
         GlobalHeights(i,j)=gh
      Next i
   Next j
   Sleep 1000
Endfunction
 
Function Global_Position(n)
   Do
      if n>0 and n<GSize then Exit
      if n<1 then n=n+GSize
      if n>GSize then n=n-GSize
   Loop
Endfunction n
 
Function Splotch(h,s)
   Lock Pixels
   Ink 0,0
   Box 200,200,230+s,230+s
   c=rnd(7)+h-3
   Ink Rgb(c,c,c),0
   r=rnd(s/2)+s/4
   For i# = 0.0 to 360.0 step 2
      x=sin(i#)*r+215+s/2
      y=cos(i#)*r+215+s/2
      line 207+s/2,207+s/2,x,y
      r=r+(rnd(2)-1)
      if r>s+15 then r=s+15
      m=s-15:If m<2 then m=2
      if r<m then r=m
   Next i#
   Unlock Pixels
   Get Image 1,200,200,230+s,230+s
Endfunction
 
Function Create_Heightmap(x,y)
   Ink rgb(128,128,128),0
   Box 0,0,199,199
   For ny=0 to 5
      For nx=0 to 5
         Randomize Timer()
         TileHeight=10+rnd(6)+rnd(6)+rnd(6)
         ox=32+(nx*32):oy=32+(ny*32)
         mx=32+((nx+1)*32):my=32+((ny+1)*32)
         Splotch(TileHeight,32)
         Sprite 1,200,200,1
         Set Sprite 1,0,1
         Set Sprite Alpha 1,200
         Paste Sprite 1,ox+rnd(32)-16,oy+rnd(32)-16
         Box ox,oy,mx,my
      Next nx
   Next ny
   For ny=0 to 5
      For nx=0 to 5
         Randomize Timer()
         ox=32+(nx*32):oy=32+(ny*32)
         For i = 1 to rnd(3)+2
            sx=ox+rnd(32)-16:sy=oy+rnd(32)-16
            h=point(sx,sy)+Rnd(5)-Rnd(5)
            Splotch(h,15)
            Sprite 1,200,200,1
            Set Sprite 1,0,1
            Set Sprite Alpha 1,128
            Paste Sprite 1,sx,sy
         Next i
         Randomize Timer()
         ox=32+(nx*32):oy=32+(ny*32)
         for noise=1 to rnd(50)+rnd(50)+rnd(50)+50
            noisex=rnd(32)+ox
            noisey=rnd(32)+oy
            c=point(noisex,noisey)
            c=rgbr(c)+(rnd(5)-2)
            if c<0 then c=0
            if c>255 then c=255
            ink rgb(c,c,c),0
            dot noisex,noisey
         Next noise
      Next nx
   Next ny
   if file exist("Heightmap.bmp") Then Delete File "Heightmap.bmp"
   Get Image 2,32,32,32+x*5,32+y*5,0
   Save Image "Heightmap.bmp",2
   If Sprite Exist(1) Then Delete Sprite 1
   Ink Rgb(255,255,255),0
   Print "Heightmap Done"
   Sync
Endfunction
 
 
Function Grass()
   If Bitmap Exist(1) Then Delete Bitmap 1
   Create Bitmap 1,512,512
   Set Current Bitmap 1
   Ink Rgb(0,90,0),0
   Box 0,0,511,511
   g=0
   Do
      Splotch(180,15)
      Sprite 1,200,200,1
      Size Sprite 1,rnd(3)+1,Rnd(3)+1
      Set Sprite Alpha 1,128
      Set Sprite Diffuse 1,0,255,0
      Paste Sprite 1,rnd(67)-2,rnd(67)-2
      g=g+1
      If rnd(500)+500<g Then Exit
   Loop
   Get Image 3,1,1,64,64,0
   Ink Rgb(0,90,0),0
   Box 0,0,511,511
   g=0
   Do
      Splotch(rnd(80)+130,30)
      Sprite 1,200,200,1
      Size Sprite 1,rnd(10)+10,Rnd(10)+10
      Set Sprite Alpha 1,64
      Set Sprite Diffuse 1,0,255,0
      Paste Sprite 1,rnd(75)-10,rnd(75)-10
      g=g+1
      If rnd(1000)+200<g Then Exit
   Loop
   Get Image 4,1,1,64,64,0
   Set Current Bitmap 0
   Delete Bitmap 1
   Delete Sprite 1
Endfunction
 
 
Function Physics(ObjectID)
   Flag=0
   For i = 0 to Array Count(ObjectPhysics())
      if ObjectPhysics(i).Object=ObjectID
         Flag=1
         Exit
      Endif
   Next i
   If Flag = 0 Then ExitFunction
   x#=Object Position X(ObjectID):y#=Object Position Y(ObjectID):z#=Object Position Z(ObjectID)
   Position Object ObjectID,x#+X Vector3(ObjectID),y#+Y Vector3(ObjectID)+Grav+heavy,z#+Z Vector3(ObjectID)
   If Object Position X(ObjectID)>Object Size X(1)-1
      Position Object ObjectID,Object Size X(1)-1,Object Position Y(ObjectID),Object Position Z(ObjectID)
   Endif
   If Object Position X(ObjectID)<1
      Position Object ObjectID,1,Object Position Y(ObjectID),Object POsition Z(ObjectID)
   Endif
   If Object Position Z(ObjectID)>Object Size Z(1)-1
      Position Object ObjectID,Object Position X(ObjectID),Object Position Y(ObjectID),Object Size Z(1)-1
   Endif
   If Object Position Z(ObjectID)<1
      Position Object ObjectID,Object Position X(ObjectID),Object Position Y(ObjectID),1
   Endif
   gy#=Get Terrain Ground Height(1,Object Position X(ObjectID),Object Position Z(ObjectID))+Object Size Y(ObjectID)*.5
   dy#=gy#-Object Position Y(ObjectID)
   bounce=0
   if dy#>0
      Position Object ObjectID,Object Position X(ObjectID),Object Position Y(ObjectID)+dy#*.85,Object Position Z(ObjectID)
      bounce=1
   Endif
 
   Set Vector3 ObjectID,Object Position X(ObjectID)-ObjectPhysics(i).x,Object Position Y(ObjectID)-ObjectPhysics(i).y,Object Position Z(ObjectID)-ObjectPhysics(i).z
   Speed=Length Vector3(ObjectID)
   If Speed>1
      Multiply Vector3 ObjectID,1.0/Length Vector3(ObjectID)
   Endif
   If Bounce=1
      Set Vector3 ObjectID,X Vector3(ObjectID),Y Vector3(ObjectID)*.1,Z Vector3(ObjectID)
   Endif
   Set Vector3 ObjectID,X Vector3(ObjectID)*friction#,Y Vector3(ObjectID)*friction#,Z Vector3(ObjectID)*friction#
   ObjectPhysics(i).x=Object Position X(ObjectID)
   ObjectPhysics(i).y=Object Position Y(ObjectID)
   ObjectPhysics(i).z=Object Position Z(ObjectID)
Endfunction
 
Function Space_Wheels(Wheel1,Wheel2,Wheel3,Wheel4,Axel1,Axel2,Axel3)
   For run = 1 to 2
      ax#=(Object Position X(Wheel1)+Object Position X(Wheel2)+Object Position X(Wheel3)+Object Position X(Wheel4))/4.0
      ay#=(Object Position Y(Wheel1)+Object Position Y(Wheel2)+Object Position Y(Wheel3)+Object Position Y(Wheel4))/4.0
      az#=(Object Position Z(Wheel1)+Object Position Z(Wheel2)+Object Position Z(Wheel3)+Object Position Z(Wheel4))/4.0
 
      lay#=ay#:low=0
      If Object Position Y(Wheel1)<lay#
         lay#=Object Position Y(Wheel1)
         low=Wheel1
      Endif
      If Object Position Y(Wheel2)<lay#
         lay#=Object Position Y(Wheel2)
         low=Wheel2
      Endif
      If Object Position Y(Wheel3)<lay#
         lay#=Object Position Y(Wheel3)
         low=Wheel3
      Endif
      If Object Position Y(Wheel4)<lay#
         lay#=Object Position Y(Wheel4)
         low=Wheel4
      Endif
      If ay#-lay#>.5 and low<>0
         Set Vector3 1,Object Position X(low),lay#,Object Position Z(low)
         Normalize Vector3 1,1
         ax#=ax#+X Vector3(1)*.005:az#=az#+Z Vector3(1)*.005
      Endif
 
      fcx#=(Object Position X(Wheel1)+Object Position X(Wheel2))/2.0
      fcy#=(Object Position Y(Wheel1)+Object Position Y(Wheel2))/2.0
      fcz#=(Object Position Z(Wheel1)+Object Position Z(Wheel2))/2.0
 
      Set Vector3 1,Object Position X(Wheel2)-Object Position X(Wheel1),Object Position Y(Wheel2)-Object Position Y(Wheel1),Object Position Z(Wheel2)-Object Position Z(Wheel1)
      Position Object Axel1,fcx#,fcy#,fcz#
      Point Object Axel1,fcx#+X Vector3(1),fcy#+Y Vector3(1),fcz#+Z Vector3(1)
      Position Object Wheel1,Limb Position X(Axel1,2),Limb Position Y(Axel1,2),Limb Position Z(Axel1,2)
      Position Object Wheel2,Limb Position X(Axel1,1),Limb Position Y(Axel1,1),Limb Position Z(Axel1,1)
 
      rcx#=(Object Position X(Wheel3)+Object Position X(Wheel4))/2.0
      rcy#=(Object Position Y(Wheel3)+Object Position Y(Wheel4))/2.0
      rcz#=(Object Position Z(Wheel3)+Object Position Z(Wheel4))/2.0
 
      Set Vector3 1,Object Position X(Wheel4)-Object Position X(Wheel3),Object Position Y(Wheel4)-Object Position Y(Wheel3),Object Position Z(Wheel4)-Object Position Z(Wheel3)
      Position Object Axel1,rcx#,rcy#,rcz#
      Point Object Axel1,rcx#+X Vector3(1),rcy#+Y Vector3(1),rcz#+Z Vector3(1)
      Position Object Wheel3,Limb Position X(Axel1,2),Limb Position Y(Axel1,2),Limb Position Z(Axel1,2)
      Position Object Wheel4,Limb Position X(Axel1,1),Limb Position Y(Axel1,1),Limb Position Z(Axel1,1)
 
      Set Vector3 1,Object Position X(Wheel4)-Object Position X(Wheel1),Object Position Y(Wheel4)-Object Position Y(Wheel1),Object Position Z(Wheel4)-Object Position Z(Wheel1)
      Position Object Axel2,ax#,ay#,az#
      Point Object Axel2,ax#+X Vector3(1),ay#+Y Vector3(1),az#+Z Vector3(1)
      Position Object Wheel1,Limb Position X(Axel2,2),Limb Position Y(Axel2,2),Limb Position Z(Axel2,2)
      Position Object Wheel4,Limb Position X(Axel2,1),Limb Position Y(Axel2,1),Limb Position Z(Axel2,1)
 
      Set Vector3 1,Object Position X(Wheel3)-Object Position X(Wheel2),Object Position Y(Wheel3)-Object Position Y(Wheel2),Object Position Z(Wheel3)-Object Position Z(Wheel2)
      Position Object Axel3,ax#,ay#,az#
      Point Object Axel3,ax#+X Vector3(1),ay#+Y Vector3(1),az#+Z Vector3(1)
      Position Object Wheel2,Limb Position X(Axel3,2),Limb Position Y(Axel3,2),Limb Position Z(Axel3,2)
      Position Object Wheel3,Limb Position X(Axel3,1),Limb Position Y(Axel3,1),Limb Position Z(Axel3,1)
   Next run
 
   Point Object Wheel1,fcx#,fcy#,fcz#
   Turn Object Left Wheel1,90.0-stearing
 
   Point Object Wheel2,fcx#,fcy#,fcz#
   Turn Object Right Wheel2,90.0+stearing
 
 
   Point Object Wheel3,Object Position X(Wheel4),Object Position Y(Wheel4),Object Position Z(Wheel4)
   Turn Object Left Wheel3,90.0
   Point Object Wheel4,Object Position X(Wheel3),Object Position Y(Wheel3),Object Position Z(Wheel3)
   Turn Object Right Wheel4,90.0
 
   Position Camera ax#,ay#,az#
Endfunction
 
Function Make_Axel(ObjectID,length#)
   Make Object Triangle ObjectID, 0,0,0, 0,.01,0, 0,0,0
   Make Mesh From Object 1,ObjectID
   Delete Object ObjectID
   Make Object Cylinder ObjectID,.1
   Scale Object ObjectID,100,length#*1000.0,100
   Pitch Object Down ObjectID,90
   Fix Object Pivot ObjectID
   Make Mesh From Object 2,ObjectID
   Delete Object ObjectID
   Make Object ObjectID,2,0
   Add Limb ObjectID,1,1
   Offset Limb ObjectID,1,0,0,length#*.5
   Add Limb ObjectID,2,1
   Offset Limb ObjectID,2,0,0,length#*-.5
Endfunction
 
 
Function Make_Vehicle()
   For i = 21 to 24
      Make Object Cylinder i,1
      Roll Object Right i,90
      Fix Object Pivot i
      Set Object Cull i,0
      Null=Make Vector3(i)
      ObjectPhysics(i-21).Object = i
   Next i
   Position Object 21,5,20,5
   Position Object 22,2,20,5
   Position Object 23,5,20,1
   Position Object 24,2,20,1
   Make_Axel(25,3)
   Make_Axel(26,5)
   Make_Axel(27,5)
Endfunction