Here's a two car demo with simple AI controlling the second car.
The 'Force' variable is changed to an array, one for each car...
The 'Force' variable is changed to an array, one for each car...
; ################################################################################################### ; # JV-ODE Twin Car Demo # ; # Code by Jim Williams (VIP3R) # ; # Devious Codeworks - Copyright © 2007 # ; ################################################################################################### AppTitle "JV-ODE Twin Car Demo" Include "JV-ODE.bb" Graphics3D 800,600,0,2 Global CMass#=200 ; ### Car Mass Global WMass#=14 ; ### Wheel Mass Global WorldERP#=1 ; ### World Error Correction Global WorldFriction#=70 ; ### World Friction Global Torque#=24 ; ### Joint Torque Global SuspensionHS#=0.01 ; ### Suspension Hardness/Softness (Higher=Softer - Lower=Harder) Global CarAmount=2 Global ControlTimer=0 Global SteeringTimer=0 Dim Force#(CarAmount) Dim Steer#(CarAmount) Dim Car(CarAmount) Dim CGeom(CarAmount) Dim CMesh(CarAmount) Global CarStartY=20 Dim Wheel(CarAmount,4) Dim WGeom(CarAmount,4) Dim Joint(CarAmount,4) Type ODEGeom Field body Field geom Field mesh End Type ; ################################################################################################### ; ### Setup ODE Global World=dWorldCreate() Global Space=dHashSpaceCreate(0) Global ContactGroup=dJointGroupCreate(0) dWorldSetAutoDisableFlag(World,1) dWorldSetGravity(World,0,-0.98,0) dWorldSetERP(World,WorldERP) dContactSetMode(dContactSlip1) dContactSetMu(WorldFriction) For CarID=1 To 2 ; ### Create car body ode.ODEGeom=New ODEGeom ode\body=dBodyCreate(World) Car(CarID)=ode\body dBodySetRotation(ode\body,0,0,0) dBodySetPosition(ode\body,CarID*10,CarStartY,0) mass=dMassCreate() dMassSetBoxTotal(mass,CMass,3,1,4) dBodySetMass(ode\body,mass) dMassDestroy(mass) ode\geom=dCreateBox(Space,3,1,4) CGeom(CarID)=ode\geom dGeomSetBody(ode\geom,ode\body) ode\mesh=CreateCube() CMesh(CarID)=ode\mesh ScaleMesh ode\mesh,1.5,0.5,2 RotateMesh ode\mesh,0,0,0 PositionMesh ode\mesh,0,0,0 If CarID=1 EntityColor ode\mesh,40,80,255 Else EntityColor ode\mesh,180,40,180 End If EntityAlpha ode\mesh,1 ; ### Create wheels For count=1 To 4 ode.ODEGeom=New ODEGeom ode\body=dBodyCreate(World) Wheel(CarID,count)=ode\body dBodySetRotation(ode\body,0,0,0) dBodySetPosition(ode\body,0,0,0) mass=dMassCreate() dMassSetSphereTotal(mass,WMass,0.7) dBodySetMass(ode\body,mass) dMassDestroy(mass) ode\geom=dCreateSphere(Space,0.7) WGeom(CarID,count)=ode\geom dGeomSetBody(ode\geom,ode\body) ode\mesh=CreateCylinder(8) ScaleMesh ode\mesh,0.7,0.25,0.7 RotateMesh ode\mesh,0,0,90 PositionMesh ode\mesh,0,0,0 EntityColor ode\mesh,255,255,255 Next dBodySetPosition(Wheel(CarID,1),(CarID*10)-2,CarStartY-0.5,+2) dBodySetPosition(Wheel(CarID,2),(CarID*10)+2,CarStartY-0.5,+2) dBodySetPosition(Wheel(CarID,3),(CarID*10)-2,CarStartY-0.5,-2) dBodySetPosition(Wheel(CarID,4),(CarID*10)+2,CarStartY-0.5,-2) Next ; ### Create some objects SeedRnd MilliSecs() For spheres=1 To 20 ode.ODEGeom=New ODEGeom ode\body=dBodyCreate(World) dBodySetRotation(ode\body,0,0,0) dBodySetPosition(ode\body,Rnd(-100,100),30,Rnd(-100,100)) ode\geom=dCreateSphere(Space,4) dGeomSetBody(ode\geom,ode\body) ode\mesh=CreateSphere() ScaleMesh ode\mesh,4,4,4 RotateMesh ode\mesh,0,0,0 PositionMesh ode\mesh,0,0,0 EntityColor ode\mesh,Rnd(255),Rnd(255),Rnd(255) EntityAlpha ode\mesh,1 EntityShininess ode\mesh,0.7 Next For capsules=1 To 20 ode.ODEGeom=New ODEGeom ode\body=dBodyCreate(World) dBodySetRotation(ode\body,90,0,0) dBodySetPosition(ode\body,Rnd(-100,100),30,Rnd(-100,100)) ode\geom=dCreateCapsule(Space,1,8) dGeomSetBody(ode\geom,ode\body) ode\mesh=CreateCylinder(8) ScaleMesh ode\mesh,1,5,1 RotateMesh ode\mesh,90,0,0 ; <<< Mesh X-Axis must be rotated 90 degrees to fix cylinder alignment PositionMesh ode\mesh,0,0,0 EntityColor ode\mesh,Rnd(255),Rnd(255),Rnd(255) EntityAlpha ode\mesh,1 EntityShininess ode\mesh,0.7 Next ; ### Create light Global Light=CreateLight() RotateEntity Light,45,-90,0 LightColor Light,255,255,255 AmbientLight 130,130,130 ; ### Create camera Global CameraPivot=CreatePivot(CMesh(1)) PositionEntity CameraPivot,0,2,-7 Global Camera=CreateCamera() CameraClsColor Camera,0,0,0 CameraRange Camera,1,1000 ; ### Create plane dCreatePlane(Space,0,1,0,0) Plane=CreatePlane() EntityAlpha Plane,0.8 PlaneTexture=CreateTexture(128,128,9) ClsColor 0,200,80 Cls Color 255,255,255 Rect 0,0,64,64,1 Rect 64,64,64,64,1 CopyRect 0,0,128,128,0,0,BackBuffer(),TextureBuffer(PlaneTexture) ScaleTexture PlaneTexture,20,20 EntityTexture Plane,PlaneTexture,0,0 Mirror=CreateMirror() ; ################################################################################################### ; ### BLITZ STATIC OBJECT (White) blitzobject=CreateCube() ScaleMesh blitzobject,1,4,20 RotateMesh blitzobject,-10,8,4 PositionMesh blitzobject,10,5,40 EntityColor blitzobject,255,255,255 EntityAlpha blitzobject,1 ; ### ODE STATIC OBJECT (Blue) ode.ODEGeom=New ODEGeom ode\geom=dCreateBox(Space,2,8,40) dGeomSetRotation(ode\geom,-10,8,4) dGeomSetPosition(ode\geom,20,5,40) ode\mesh=CreateCube() ScaleMesh ode\mesh,1,4,20 RotateMesh ode\mesh,0,0,0 PositionMesh ode\mesh,0,0,0 EntityColor ode\mesh,0,100,200 EntityAlpha ode\mesh,1 ; ### ODE STATIC OBJECT (Red) ode.ODEGeom=New ODEGeom ode\geom=dCreateBox(Space,18,0.2,40) dGeomSetRotation(ode\geom,-14,0,0) dGeomSetPosition(ode\geom,-20,4.9,40) ode\mesh=CreateCube() ScaleMesh ode\mesh,9,0.1,20 RotateMesh ode\mesh,0,0,0 PositionMesh ode\mesh,0,0,0 EntityColor ode\mesh,200,0,100 EntityAlpha ode\mesh,1 ; ################################################################################################### SetupCar() While Not KeyHit(1) UpdateKeys() PTime=MilliSecs() UpdateCar() UpdateGeoms() dSpaceCollide(Space,World,ContactGroup) dWorldQuickStep(World,0.1) dJointGroupEmpty(ContactGroup) PhysicsTime#=MilliSecs()-PTime UpdateCam() UpdateWorld RenderWorld Text 0,0,"JV-ODE Version "+dGetVersion() Text 0,15,"Physics Time:"+PhysicsTime Text 0,50,"Force Car 1:"+Force(1) Text 0,65,"Force Car 2:"+Force(2) Text 0,80,"Torque:"+Torque Text 640,0,"A - Accelerate" Text 640,15,"Z - Brake/Reverse" Text 640,30,"Arrows - Steering" Text 640,45,"Space - Reset Car" Flip Wend dJointGroupDestroy(ContactGroup) dSpaceDestroy(Space) dWorldDestroy(World) dCloseODE() End ; ################################################################################################### Function SetupCar() For CarID=1 To 2 For count=1 To 4 Joint(CarID,count)=dJointCreateHinge2(World,0) dJointAttach(Joint(CarID,count),Car(CarID),Wheel(CarID,count)) dJointSetHinge2Anchor(Joint(CarID,count),dBodyGetPositionX(Wheel(CarID,count)),dBodyGetPositionY(Wheel(CarID,count)),dBodyGetPositionZ(Wheel(CarID,count))) dJointSetHinge2Axis1(Joint(CarID,count),0,1,0) dJointSetHinge2Axis2(Joint(CarID,count),-1,0,0) dJointSetHinge2Param(Joint(CarID,count),dParamSuspensionERP,0.8) dJointSetHinge2Param(Joint(CarID,count),dParamSuspensionCFM,SuspensionHS) If count>2 dJointSetHinge2Param(Joint(CarID,count),dParamLoStop,0) dJointSetHinge2Param(Joint(CarID,count),dParamHiStop,0) End If Next Force(CarID)=0 Next End Function ; ################################################################################################### Function UpdateKeys() ; ### Player Control For Car 1 If KeyDown(30)=1 Force(1)=Force(1)+0.08 If Force(1)>30 Then Force(1)=30 End If If KeyDown(44)=1 Force(1)=Force(1)-0.1 If Force(1)<-10 Then Force(1)=-10 If Force(1)>0 Then Force(1)=Force(1)*0.97 End If If KeyDown(30)=0 And KeyDown(44)=0 Then Force(1)=Force(1)*0.99 If KeyDown(203)=1 Or KeyDown(205)=1 If KeyDown(203)=1 Steer(1)=0.5 Else Steer(1)=-0.5 End If Else Steer(1)=0 End If If KeyHit(57)=1 Force(1)=0 dBodySetRotation(Car(1),dGeomGetPitch#(CGeom(1)),dGeomGetYaw#(CGeom(1)),0) End If ; ### Simple AI For Car 2 If ControlTimer>100 SeedRnd MilliSecs() AIKey=Rnd(100) If AIKey<40 Force(2)=Force(2)+0.8 If Force(2)>10 Then Force(2)=10 End If If AIKey=>40 Then Force(2)=Force(2)*0.99 ControlTimer=0 End If If SteeringTimer>100 SeedRnd MilliSecs() AIKey=Rnd(100) Steer(2)=0 If AIKey<30 Then Steer(2)=0.5 If AIKey>70 Then Steer(2)=-0.5 SteeringTimer=0 End If ControlTimer=ControlTimer+1 SteeringTimer=SteeringTimer+1 End Function ; ################################################################################################### Function UpdateCar() For CarID=1 To 2 For count=1 To 4 dBodyEnable(Wheel(CarID,count)) Next dBodyEnable(Car(CarID)) For count=1 To 4 dJointSetHinge2Param(Joint(CarID,count),dParamVel2,Force(CarID)) dJointSetHinge2Param(Joint(CarID,count),dParamFMax2,Torque) Next For count=1 To 2 angle#=Steer(CarID)-dJointGetHinge2Angle1(Joint(CarID,count)) dJointSetHinge2Param(Joint(CarID,count),dParamVel,angle) dJointSetHinge2Param(Joint(CarID,count),dParamFMax,400) Next Next End Function ; ################################################################################################### Function UpdateCam() PositionEntity CameraPivot,0,3,-12 camx#=EntityX(CameraPivot,1)-EntityX(Camera) camy#=EntityY(CameraPivot,1)-EntityY(Camera) camz#=EntityZ(CameraPivot,1)-EntityZ(Camera) TranslateEntity Camera,camx*0.5,camy*0.5,camz*0.5 PointEntity Camera,CMesh(1) End Function ; ################################################################################################### Function UpdateGeoms() For ode.ODEGeom=Each ODEGeom RotateEntity ode\mesh,dGeomGetPitch#(ode\geom),dGeomGetYaw#(ode\geom),dGeomGetRoll#(ode\geom) PositionEntity ode\mesh,dGeomGetPositionX#(ode\geom),dGeomGetPositionY#(ode\geom),dGeomGetPositionZ#(ode\geom) Next End Function ; ###################################################################################################