Rem Project: top down racer
Rem Created: 14/03/2007 11:04:37
 
Rem ***** Main Source File *****
 
set display mode 1024,768,32
sync on
sync rate 60
hide light 0
color backdrop 0
 
make light 1
position light 1,0,50,100
set light range 1,500
 
 
`constants
matrixsizex=100
matrixsizez=100
xsegments=10
zsegments=10
tileimagesize=64
numberofcars=6
 
camx#=matrixsizex/2.0
camy#=80
camz#=matrixsizez/2.0
 
type tiletype
 
imagenumber as integer
tilenumber as integer
height as float
posx as float
posy as float
waypoint as integer
 
endtype
 
type cartype
 
objectnumber as integer
x as float
y as float
z as float
fi as float
fl as float
fd as float
fb as float
maxfd as float
maxfb as float
fx as float
fz as float
ax as float
az as float
vx as float
vz as float
ang as float
turnspeed as float
slow as integer
waypoint as integer
waypointset as integer
targetangle as float
lap as integer
 
endtype
 
type waypointtype
 
x as float
z as float
 
endtype
 
gosub make_track
gosub make_cars
 
 
position camera camx#,camy#,camz#
point camera camx#,0,camz#
 
 
ink -1,0
sync
sync
text 0,0,"Get ready ...."
sync
wait 2000
do
 
for n=1 to numberofcars
text 0,20*n,"Car"+str$(n)+" lap: "+str$(car(n).lap+1)+" of 3"
next n
`text 0,200,"Waypoints reached: "+str$(waypointsreached)
text 0,200,"Position: "+str$(position)
gosub move_player
gosub ai
gosub move_cars
gosub collision
 
sync
loop
 
 
 
 
collision:
 
for n=1 to numberofcars
 
for target=1 to numberofcars
  if n<>target
    if object collision(car(n).objectnumber,car(target).objectnumber)=1
      collision=1
      exit 
    else 
      collision=0
    endif
  endif
next target
 
tilex=int(car(n).x/(matrixsizex/xsegments))
tilez=int(car(n).z/(matrixsizez/zsegments))
if tilex>xsegments-1 then tilex=xsegments-1
if tilez>zsegments-1 then tilez=zsegments-1
if tile(tilex,tilez).imagenumber=5 then ongrass=1 else ongrass=0
 
if collision=1 or ongrass=1
   car(n).slow=1 
   set object emissive car(n).objectnumber,rgb(255,128,0)
else 
  car(n).slow=0
  set object emissive car(n).objectnumber,rgb(80,80,80)
endif
 
 
next n
 
return
 
ai:
 
for n=1 to numberofcars
  if n<>player
    car(n).fd=car(n).maxfd
    if car(n).slow=1 then car(n).fb=car(n).maxfb else car(n).fb=0
    if car(n).waypointset=0
      inc car(n).waypoint
      if car(n).waypoint>20 then car(n).waypoint=1: inc car(n).lap:if car(n).lap>2 then winner=n:goto gameover
      car(n).waypointset=1
      oldang#=car(n).ang 
    endif
    point object car(n).objectnumber,waypoint(car(n).waypoint).x,0,waypoint(car(n).waypoint).z
    car(n).targetangle=object angle y(car(n).objectnumber)
    rotate object car(n).objectnumber,0,oldang#,0
    rotate object car(n).objectnumber,0,curveangle(car(n).targetangle,car(n).ang,10),0
    car(n).ang=object angle y(car(n).objectnumber)
    tilex=int(car(n).x/(matrixsizex/xsegments))
    tilez=int(car(n).z/(matrixsizez/zsegments))
    if tile(tilex,tilez).waypoint=car(n).waypoint then car(n).waypointset=0
  endif
next n
 
return
 
 
move_player:
 
player=1
 
if upkey()=1 then car(player).fd=car(player).maxfd else car(player).fd=0
if downkey()=1 or car(player).slow=1 then car(player).fb=car(player).maxfb else car(player).fb=0
 
if leftkey()=1 then dec car(player).ang,car(player).turnspeed
if rightkey()=1 then inc car(player).ang,car(player).turnspeed
 
tilex=int(car(1).x/(matrixsizex/xsegments))
tilez=int(car(1).z/(matrixsizez/zsegments))
 
if tile(tilex,tilez).waypoint>0 and tile(tilex,tilez).waypoint<>car(1).waypoint then inc waypointsreached
if tile(tilex,tilez).waypoint<>0 then car(1).waypoint=tile(tilex,tilez).waypoint
 
 
 
if waypointsreached>17 and car(1).waypoint=1
  inc car(1).lap
  if car(1).lap>2 then winner=1:goto gameover
  waypointsreached=0
endif
 
position=1
for n=2 to numberofcars
if car(n).waypoint-1>car(1).waypoint and car(n).lap>= car(1).lap then inc position
next n
 
 
 
return
 
move_cars:
 
for n=1 to numberofcars
 
 
 
`calculate resultant velocity size and direction of travel from previous loop
vresultant#=sqrt(car(n).vx^2+car(n).vz^2)
directionoftravel#=atanfull(car(n).vx,car(n).vz)
 
`calculate angle between car and direction of travel
angle#=differencebetweentwoangles(car(n).ang,directionoftravel#)
 
`calculate inline friction size
inlinefriction#=(car(n).fi+car(n).fb)*vresultant#*cos(angle#)
if inlinefriction#<0 then inlinefriction#=0
`calculate x and z components of inline friction
inlinefrictionx#=inlinefriction#*sin(directionoftravel#)
inlinefrictionz#=inlinefriction#*cos(directionoftravel#)
 
`calculate lateral friction size
lateralfriction#=car(n).fl*vresultant#*sin(angle#)
 
`calculate x and z components of lateral friction
lateralfrictionx#=lateralfriction#*sin(directionoftravel#)
lateralfrictionz#=lateralfriction#*cos(directionoftravel#)
 
`calculate total friction
totalfrictionx#=(inlinefrictionx#+lateralfrictionx#)
totalfrictionz#=(inlinefrictionz#+lateralfrictionz#)
 
`calculate x and z force components due to drive
car(n).fx=car(n).fd*sin(car(n).ang)
car(n).fz=car(n).fd*cos(car(n).ang)
 
`calculate new x and z velocity components due to driving and frictional forces
inc car(n).vx,car(n).fx-totalfrictionx#
inc car(n).vz,car(n).fz-totalfrictionz#
 
`update positions
inc car(n).x,car(n).vx
inc car(n).z,car(n).vz
car(n).y=get ground height(1,car(n).x,car(n).z)
 
rotate object car(n).objectnumber,0,car(n).ang,0
position object car(n).objectnumber,car(n).x,car(n).y,car(n).z
 
next n
 
 
return
 
 
make_cars:
 
dim car(numberofcars) as cartype
 
for n=1 to numberofcars
  car(n).objectnumber=free_object()
  make object box car(n).objectnumber,1,0.2,2
 
  if n=1 then color object car(n).objectnumber,rgb(255,0,0)
  if n=2 then color object car(n).objectnumber,rgb(255,255,0)
  if n=3 then color object car(n).objectnumber,rgb(255,0,255)
  if n=4 then color object car(n).objectnumber,rgb(0,255,0)
  if n=5 then color object car(n).objectnumber,rgb(0,255,255)
  if n=6 then color object car(n).objectnumber,rgb(0,0,255)
 
  disable object zdepth car(n).objectnumber
 
  wheel1=free_object()
  make object box wheel1,0.4,0.2,0.4
  position object wheel1,-0.5,0,0.7
  disable object zdepth wheel1
  color object wheel1,rgb(0,0,0)
  glue object to limb wheel1,car(n).objectnumber,0
  wheel2=free_object()
  make object box wheel2,0.4,0.2,0.4
  position object wheel2,0.5,0,0.7
  disable object zdepth wheel2
  color object wheel2,rgb(0,0,0)
  glue object to limb wheel2,car(n).objectnumber,0
  wheel3=free_object()
  make object box wheel3,0.6,0.2,0.5
  position object wheel3,-0.5,0,-0.7
  disable object zdepth wheel3
  color object wheel3,rgb(0,0,0)
  glue object to limb wheel3,car(n).objectnumber,0
  wheel4=free_object()
  make object box wheel4,0.6,0.2,0.5
  position object wheel4,0.5,0,-0.7
  disable object zdepth wheel4
  color object wheel4,rgb(0,0,0)
  glue object to limb wheel4,car(n).objectnumber,0
  body=free_object()
  make object box body,0.4,0.3,2.4
  glue object to limb body,car(n).objectnumber,0
  disable object zdepth body
  tail=free_object()
  make object box tail,1.2,0.3,0.4
  position object tail,0,0,-1.3
  glue object to limb tail,car(n).objectnumber,0
  disable object zdepth tail
 
 
 
 if xoffset=0 then xoffset=4 else xoffset=0
  car(n).x=13+xoffset
  car(n).y=0.5
  car(n).z=25-n*2
  car(n).fi=0.01 `force due to inline friction
  car(n).fl=0.04 `force due to lateral friction
  car(n).maxfd=0.01+n*0.003 `force due to drive
  car(n).maxfb=0.04 `force due to braking friction
  car(n).turnspeed=2
  position object car(n).objectnumber,car(n).x,car(n).y,car(n).z
next n
 
return
 
make_track:
 
 
make matrix 1,matrixsizex,matrixsizez,xsegments,zsegments
 
`grid
inc numberofimages
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
ink rgb(120,120,120),0
box 0,0,tileimagesize,tileimagesize
ink rgb(100,100,100),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
ink rgb(140,140,140),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
 
ink -1,0
for y=0 to tileimagesize step 8
for x=0 to tileimagesize step 8
if white=0 then white=1 else white=0
if white=1
box x,y,x+8,y+8
endif
next x
next y
 
for n=0 to 4
line 0,n,tileimagesize,n
next n
 
ink -1,0
for n=0 to 9 step 2
box 2,n*tileimagesize/10.0,6,(n+1)*tileimagesize/10.0
box tileimagesize-6,n*tileimagesize/10.0,tileimagesize-2,(n+1)*tileimagesize/10.0
next n
ink rgb(255,0,0),0
for n=1 to 10 step 2
box 2,n*tileimagesize/10.0,6,(n+1)*tileimagesize/10.0
box tileimagesize-6,n*tileimagesize/10.0,tileimagesize-2,(n+1)*tileimagesize/10.0
next n
 
grid=2
get image grid,0,0,tileimagesize,tileimagesize,1
set current bitmap 0
delete bitmap 1
 
`road vertical
inc numberofimages
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
ink rgb(120,120,120),0
box 0,0,tileimagesize,tileimagesize
ink rgb(100,100,100),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
ink rgb(140,140,140),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
 
ink -1,0
for n=0 to 9 step 2
box 2,n*tileimagesize/10.0,6,(n+1)*tileimagesize/10.0
box tileimagesize-6,n*tileimagesize/10.0,tileimagesize-2,(n+1)*tileimagesize/10.0
next n
ink rgb(255,0,0),0
for n=1 to 10 step 2
box 2,n*tileimagesize/10.0,6,(n+1)*tileimagesize/10.0
box tileimagesize-6,n*tileimagesize/10.0,tileimagesize-2,(n+1)*tileimagesize/10.0
next n
 
road1=8
get image road1,0,0,tileimagesize,tileimagesize,1
set current bitmap 0
delete bitmap 1
 
 
 
`road horizontal
inc numberofimages
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
 
ink rgb(120,120,120),0
box 0,0,tileimagesize,tileimagesize
ink rgb(100,100,100),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
ink rgb(140,140,140),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
 
ink -1,0
for n=0 to 9 step 2
box n*tileimagesize/10.0,2,(n+1)*tileimagesize/10.0,6
box n*tileimagesize/10.0,tileimagesize-6,(n+1)*tileimagesize/10.0,tileimagesize-2
next n
ink rgb(255,0,0),0
for n=1 to 10 step 2
box n*tileimagesize/10.0,2,(n+1)*tileimagesize/10.0,6
box n*tileimagesize/10.0,tileimagesize-6,(n+1)*tileimagesize/10.0,tileimagesize-2
next n
 
 
road2=6
get image road2,0,0,tileimagesize,tileimagesize,1
 
set current bitmap 0
delete bitmap 1
 
`road bend 7
inc numberofimages
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
 
ink rgb(120,120,120),0
box 0,0,tileimagesize,tileimagesize
ink rgb(100,100,100),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
ink rgb(140,140,140),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
 
ink -1,0
for n=0 to 9 step 2
box 2,n*tileimagesize/10.0,6,(n+1)*tileimagesize/10.0
box n*tileimagesize/10.0,2,(n+1)*tileimagesize/10.0,6
next n
ink rgb(255,0,0),0
for n=1 to 10 step 2
box 2,n*tileimagesize/10.0,6,(n+1)*tileimagesize/10.0
box n*tileimagesize/10.0,2,(n+1)*tileimagesize/10.0,6
next n
 
box tileimagesize-6,tileimagesize-6,tileimagesize-2,tileimagesize-2
 
 
road7=7
get image road7,0,0,tileimagesize,tileimagesize,1
 
set current bitmap 0
delete bitmap 1
 
`road bend 9
inc numberofimages
temp=free_sprite()
sprite temp,-100,-100,road7
mirror sprite temp
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
paste sprite temp,0,0
 
road9=9
get image road9,0,0,tileimagesize,tileimagesize,1
set current bitmap 0
delete bitmap 1
 
`road bend 3
inc numberofimages
flip sprite temp
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
paste sprite temp,0,0
 
road3=3
get image road3,0,0,tileimagesize,tileimagesize,1
set current bitmap 0
delete bitmap 1
 
`road bend 1
inc numberofimages
mirror sprite temp
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
paste sprite temp,0,0
 
road1=1
get image road1,0,0,tileimagesize,tileimagesize,1
set current bitmap 0
delete bitmap 1
 
 
 
 
 
 
 
`grass
inc numberofimages
create bitmap 1,tileimagesize,tileimagesize
set current bitmap 1
ink rgb(0,200,0),0
box 0,0,tileimagesize,tileimagesize
ink rgb(0,220,0),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
ink rgb(0,210,0),0
for n=1 to 600
dot rnd(tileimagesize),rnd(tileimagesize)
next n
blur bitmap 1,1
grass=5
get image grass,0,0,tileimagesize,tileimagesize,1
set current bitmap 0
delete bitmap 1
 
`create matrix texture
ink 0,0
dim tile(xsegments,zsegments) as tiletype
create bitmap 1,xsegments*tileimagesize,zsegments*tileimagesize
restore datastatements
 
create bitmap 1,9*tileimagesize,tileimagesize
for imagenumber=1 to 9
  if image exist(imagenumber)=1
    paste image imagenumber,(imagenumber-1)*tileimagesize,0
  endif
next imagenumber
matrixtexture=free_image()
get image matrixtexture,0,0,9*tileimagesize,tileimagesize
delete bitmap 1
 
prepare matrix texture 1,matrixtexture,9,1
set matrix trim 1,0.003,0.003
 
`read texture map
for z=zsegments-1 to 0 step -1
  for x=0 to xsegments-1
    read tile(x,z).imagenumber
  next x
next z
 
`read height map
for z=zsegments-1 to 0 step -1
  for x=0 to xsegments-1
    read tile(x,z).height
  next x
next z
 
dim waypoint(40) as waypointtype
`read waypoint map
for z=zsegments-1 to 0 step -1
  for x=0 to xsegments-1
    read tile(x,z).waypoint
    if tile(x,z).waypoint>0
      if tile(x,z).imagenumber=8 or tile(x,z).imagenumber=6 or tile(x,z).imagenumber=2 then offsetx#=0.5:offsetz#=0.5
      if tile(x,z).imagenumber=7 then offsetx#=0.8:offsetz#=0.2
      if tile(x,z).imagenumber=9 then offsetx#=0.2:offsetz#=0.2
      if tile(x,z).imagenumber=3 then offsetx#=0.2:offsetz#=0.8
      if tile(x,z).imagenumber=1 then offsetx#=0.8:offsetz#=0.8
      waypoint(tile(x,z).waypoint).x=(x+offsetx#)*matrixsizex/xsegments
      waypoint(tile(x,z).waypoint).z=(z+offsetz#)*matrixsizez/zsegments
    endif
  next x
next z
 
tile=0
for z=zsegments-1 to 0 step -1
  for x=0 to xsegments-1
    inc tile
    tile(x,z).tilenumber=tile
    set matrix tile 1,x,z,tile(x,z).imagenumber
    set matrix height 1,x,z,tile(x,z).height
  next x
next z
 
matnum=1
 
For Z = 1 To zsegments - 1
    For X = 1 To xsegments - 1
 
      rem Get matrix heights
      h8# = Get Matrix Height(MatNum,x,z-1)
      h4# = Get Matrix Height(MatNum,x-1,z)
      h#  = Get Matrix Height(MatNum,x,z)
      h2# = Get Matrix Height(MatNum,x,z)
 
      rem Calculate projected angle X using heights
      x1#=(x-1)*25.0 : y1#=h#
      x2#=(x+0)*25.0 : y2#=h4#
      dx#=x2#-x1#
      dy#=y2#-y1#
      ax# = AtanFull(dx#,dy#)
      ax# = WrapValue(90-ax#)
 
      rem Calculate projected angle Z using heights
      z1# = (z-1)*25.0 : y1#=h2#
      z2# = (z+0)*25.0 : y2#=h8#
      dz# = z2#-z1#
      dy# = y2#-y1#
      az# = AtanFull(dz#,dy#)
      az# = WrapValue(90-az#)
 
      rem Make normal from projected angle
      nx# = Sin(ax#)
      ny# = Cos(ax#)
      nz# = Sin(az#)
 
      rem Setting matrix normal for smoothness
      Set Matrix Normal MatNum,x,z,nx#,ny#,nz#
 
    Next X
  Next Z
 
`normal(1,xsegments,zsegments)
 
 
update matrix 1
 
return
 
 
function differencebetweentwoangles(angle2#,angle1#)
 
 
angle2#=wrapvalue(angle2#)
angle1#=wrapvalue(angle1#)
if angle1#>180 then dec angle1#,360
if angle2#>180 then dec angle2#,360
difference#=abs(angle2#-angle1#)
if difference#>180 then difference#=abs(difference#-360)
 
endfunction difference#
 
 
 
function normal(MatNum,MapSizeX,MapSizeZ)
 
for x=1 to MapSizeX-1
   for z=1 to MapSizeZ-1
      rem create regular normals for Terrain array
 
      rem  Vertices on the matrix
      rem    x-1,z-1    x,z-1
      rem    x-1,z      x,z
 
      rem Get stored heights
      h8#=tile(x,z-1).height
      h4#=tile(x-1,z).height
      h1#=tile(x,z).height
 
      rem Calculate projected angle X using heights
      y1#=h1#
      y2#=h4#
      rem X distance is a function of stepX#
      dx#=stepX#/10
      rem Y distance is the difference in height
      dy#=y2#-y1#
      ax#=atanfull(dx#,dy#)
      ax#=wrapvalue(90-ax#)
 
      rem Calculate projected angle Z using heights
      y1#=h1#
      y2#=h8#
      rem Z distance is a function of stepZ#
      dz#=stepZ#/10
      rem Y distance is the difference in height
      dy#=y2#-y1#
      az#=atanfull(dz#,dy#)
      az#=wrapvalue(90-az#)
 
      rem Make normal from projected angle
      nx# = Sin(ax#)
      ny# = Cos(ax#)
      nz# = Sin(az#)
 
      rem Setting matrix normal for smoothness
      Set Matrix Normal MatNum,x,z,nx#,ny#,nz#
 
   Next x
Next z
EndFunction
 
 
 
 
function free_image()
 
repeat
  inc n
until image exist(n)=0
 
endfunction n
 
function free_sprite()
 
repeat
  inc n
until sprite exist(n)=0
 
endfunction n
 
 
function free_object()
 
repeat
  inc n
until object exist(n)=0
 
endfunction n
 
datastatements:
 
`texturemap
data 5,5,5,5,5,5,5,5,5,5
data 5,7,6,6,6,6,6,9,5,5
data 5,8,5,5,5,5,5,1,9,5
data 5,1,6,6,6,9,5,5,8,5
data 5,5,5,5,5,1,9,5,8,5
data 5,7,6,9,5,5,8,5,8,5
data 5,8,5,1,6,6,3,5,8,5
data 5,2,5,5,5,5,5,5,8,5
data 5,1,6,6,6,6,6,6,3,5
data 5,5,5,5,5,5,5,5,5,5
 
`heightmap
data 0,0,0,0,0,4,4,4,4,4
data 0,0,0,0,0,4,4,4,4,4
data 0,0,0,0,0,4,4,4,4,4
data 0,0,0,0,0,0,4,9,9,9
data 0,0,0,0,0,0,4,9,9,9
data 0,0,0,3,3,3,0,9,9,9
data 0,0,0,3,3,3,0,4,4,4
data 0,0,0,5,5,5,0,0,0,0
data 0,0,0,5,5,5,0,0,0,0
data 0,0,0,5,5,5,0,0,0,0
 
`waypoints
data 00,00,00,00,00,00,00,00,00,00
data 00,11,00,00,12,00,00,13,00,00
data 00,00,00,00,00,00,00,00,14,00
data 00,10,09,00,00,08,00,00,00,00
data 00,00,00,00,00,00,07,00,00,00
data 00,02,00,03,00,00,00,00,15,00
data 00,01,00,00,04,05,06,00,00,00
data 00,00,00,00,00,00,00,00,16,00
data 00,20,19,00,00,18,00,00,17,00
data 00,00,00,00,00,00,00,00,00,00
 
gameover:
 
text 0,250,"Car "+str$(winner)+" wins!"
text 0,270,"You finished in position "+str$(position)
if winner=1 then text 0,290,"Congratulations!!!" else text 0,290,"Unlucky!!!"
sync
wait 2000
wait key
end