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