REM Project: CodeChallenges
REM Created: 13/12/2005 19:35:48
REM
REM ***** Main Source File *****
REM
 
`RACE
 
sync on : sync rate 80
 
`Create media
cls rgb(0,150,0)
for x = 1 to 200
   ink rgb(0,150+rnd(150),0),0
   dot 5 + rnd(90),5 + rnd(90)
next x
get image 1,0,0,100,100
 
`make basic object
make object box 1,5,3,7
position object 1,2500,2,2500
 
`make wheels
for w = 1 to 4
   make object cylinder 1 + w,2
   zrotate object 1 + w,90 : fix object pivot 1 + w
   scale object 1 + w,100,50,100
   set object rotation ZYX 1 + w
next w
 
make matrix 1,5000,5000,50,50
prepare matrix texture 1,1,1,1
 
`define pi
#constant pi = 3.141592654
 
`Make a car type
type CarData
   ForceX# as float
   ForceY# as float
   EngineForce# as float
   Xspeed# as float
   Zspeed# as float
   Speed# as float
   MaxSpeed# as float
   Mass# as float
   Traction# as float
   SteeringAng# as float
   CarAngle# as float
   WheelDist# as float
   SlipVal# as float
   Regrip# as float
   Slip# as float
endtype
 
dim Car(5) as CarData
 
`setup 1 car
Car(1).EngineForce# = 0.4
Car(1).MaxSpeed# = 5.0
Car(1).Mass# = 100.0
Car(1).Traction# = 0.97
Car(1).WheelDist# = 6
Car(1).SlipVal# = 40.0
Car(1).Regrip# = 10.0
Car(1).Slip# = Car(1).SlipVal#
 
do
 
   `gosub physics of car
   if upkey() = 1 then up = 1 else up = 0
   if downkey() = 1 then down = 1 else down = 0
   if leftkey() = 1 then left = 1 else left = 0
   if rightkey() = 1 then right = 1 else right = 0
   if spacekey() = 1 then brake = 1 else brake = 0
   gosub CarPhysics
   gosub UpdateCar
 
   `let the camera chase the car
   ChaseCam(1)
 
   sync
loop
 
`Carphysics
CarPhysics:
 
   `Controls on car
   if up = 1
      Car(1).Xspeed# = newxvalue(Car(1).Xspeed#, Car(1).CarAngle#, Car(1).EngineForce#)
      Car(1).Zspeed# = newzvalue(Car(1).Zspeed#, Car(1).CarAngle#, Car(1).EngineForce#)
   endif
   if left = 1
      if Car(1).SteeringAng# > -7.0 then dec Car(1).SteeringAng#
   endif
   if right = 1
      if Car(1).SteeringAng# < 7.0 then inc Car(1).SteeringAng#
   endif
   if brake = 1
      Car(1).Speed# = Car(1).Speed# * 0.5
   endif
 
   `*** Calculate continuous physics ***
   `Steering angle correction.
   if Car(1).SteeringAng# > 0.0 then dec Car(1).SteeringAng#, 0.2
   if Car(1).SteeringAng# < 0.0 then inc Car(1).SteeringAng#, 0.2
   if Car(1).SteeringAng# < 0.25 and Car(1).SteeringAng# > -0.25 then Car(1).SteeringAng# = 0.0
 
   `calculate speed
   Car(1).Speed# = sqrt( Car(1).Xspeed#^2 + Car(1).Zspeed#^2)
 
   `if lateral forces are too big, slip
   if abs(Car(1).ForceX#) < Car(1).Slip#
      Car(1).Slip# = Car(1).SlipVal#
 
      `Traction
      Car(1).Xspeed# = Car(1).Xspeed# * Car(1).Traction#
      Car(1).Zspeed# = Car(1).Zspeed# * Car(1).Traction#
 
      `If the car is below minimum speed, stop the car
      if Car(1).Speed# < 0.25 and Car(1).Speed# > -0.25 then Car(1).Speed# = 0.0
 
      `if the car is above maximum speed, keep max speed
      if Car(1).Speed# > Car(1).MaxSpeed# then Car(1).Speed# = Car(1).MaxSpeed#
      if Car(1).Speed# < Car(1).MaxSpeed# * -0.5 then Car(1).Speed# = Car(1).MaxSpeed# * -0.5
 
      `Adjust Car angle according to the current steering angle
      if Car(1).SteeringAng# <> 0.0
         trad# = tan(wrapvalue(90 - (Car(1).SteeringAng#*0.4))) * (Car(1).WheelDist#*0.5)
         TurnValue# = (180 * Car(1).Speed# / (pi * trad#))
 
         `Calculate Forces
         Car(1).ForceX# = sin(TurnValue#) * Car(1).Speed# * Car(1).Mass#
 
         `Turn car
         Car(1).CarAngle# = wrapvalue( Car(1).CarAngle# + TurnValue# )
 
      else
         `reset force when the steering angle is 0
         Car(1).ForceX# = 0.0
      endif
   else
      Car(1).Slip# = Car(1).Regrip#
      Car(1).Xspeed# = Car(1).Xspeed# * 0.94
      Car(1).Zspeed# = Car(1).Zspeed# * 0.94
      Car(1).CarAngle# = curveangle(wrapvalue(Car(1).CarAngle# + (Car(1).SteeringAng#*5)), Car(1).CarAngle#, 15)
      Car(1).ForceX# = ((sin(Car(1).CarAngle#) * Car(1).Zspeed#) + (sin(wrapvalue(90-Car(1).CarAngle#)) * Car(1).Xspeed#))*Car(1).Mass#
      if abs(Car(1).Slip#) < Car(1).Slip#
         Car(1).Zspeed# = tan(Car(1).CarAngle#) * Car(1).speed#
         Car(1).Xspeed# = tan(wrapvalue(90 - Car(1).CarAngle#)) * Car(1).speed#
      endif
   endif
 
   ink rgb(255,255,255),0
   text 5,5, "Lateral force: " + str$(Car(1).ForceX#)
   text 5,25,"Speed: " + str$(Car(1).Speed#)
   text 5,50,"Angle: " + str$(Car(1).CarAngle#)
 
return
 
UpdateCar:
 
   `get object's position
   posx# = object position x(1)
   posy# = object position y(1)
   posz# = object position z(1)
   Angy# = object angle y(1)
 
   `update positions
   if abs(Car(1).ForceX#) > Car(1).SlipVal#
      posx# = posx# + Car(1).Xspeed#
      posz# = posz# + Car(1).Zspeed#
   else
      posx# = newxvalue(posx#, Car(1).CarAngle#, Car(1).Speed#)
      posz# = newzvalue(posz#, Car(1).CarAngle#, Car(1).Speed#)
   endif
 
   `update object
   position object 1, posx#, posy#, posz#
   rotate object 1, 0, Car(1).CarAngle#, 0
 
   `position wheels
   WheelPivotFrontX# = newxvalue(posx#, Angy#, Car(1).WheelDist#*0.5)
   WheelPivotFrontZ# = newzvalue(posz#, Angy#, Car(1).WheelDist#*0.5)
   WheelPivotBackX# = newxvalue(posx#, Angy#, -Car(1).WheelDist#*0.5)
   WheelPivotBackZ# = newzvalue(posz#, Angy#, -Car(1).WheelDist#*0.5)
 
   `left front wheel
   position object 2, newxvalue(WheelPivotFrontX#, wrapvalue(Angy#-90),3),1,newzvalue(WheelPivotFrontZ#, wrapvalue(Angy#-90),3)
   rotate object 2,0,Angy# + (Car(1).SteeringAng#*3),0
   `right front wheel
   position object 3, newxvalue(WheelPivotFrontX#, wrapvalue(Angy#+90),3),1,newzvalue(WheelPivotFrontZ#, wrapvalue(Angy#+90),3)
   rotate object 3,0,Angy# + (Car(1).SteeringAng#*3),0
   `left back wheel
   position object 4, newxvalue(WheelPivotBackX#, wrapvalue(Angy#-90),3),1,newzvalue(WheelPivotBackZ#, wrapvalue(Angy#-90),3)
   rotate object 4,0,Angy#,0
   `right back wheel
   position object 5, newxvalue(WheelPivotBackX#, wrapvalue(Angy#+90),3),1,newzvalue(WheelPivotBackZ#, wrapvalue(Angy#+90),3)
   rotate object 5,0,Angy#,0
 
return
 
`****************
`Function
`****************
 
function ChaseCam(id)
   posx# = object position x(id)
   posy# = object position y(id)
   posz# = object position z(id)
   angy# = wrapvalue(object angle y(id) - 180)
 
   d# = 20.0
   h# = 15.0
   camx# = newxvalue(posx#, angy#, d#)
   camz# = newzvalue(posz#, angy#, d#)
   camy# = posy# + h#
 
   camx# = curvevalue(camx#, camera position x(), 7.5)
   camy# = curvevalue(camy#, camera position y(), 7.5)
   camz# = curvevalue(camz#, camera position z(), 7.5)
 
   position camera camx#,camy#,camz#
   point camera posx#, posy# + (h#/2), posz#
endfunction