This is a wonderful collision and velocity routine that is easy to plug into an existing program. All you do is create a physics type for your entity, then call UpdatePhysics every loop instead of UpdateWorld.
The collision uses Blitz's collision, but manages to overcome a few of the weaknesses. Sliding, bouncing collisions will occur, depending on the elasticity you give the physics type.
This should be very useful as a base for more advanced physics.
The collision uses Blitz's collision, but manages to overcome a few of the weaknesses. Sliding, bouncing collisions will occur, depending on the elasticity you give the physics type.
This should be very useful as a base for more advanced physics.
Graphics3D 800,600,16,2 SetBuffer BackBuffer() cam=CreateCamera() MoveEntity cam,0,15,-20 TurnEntity cam,35,0,0 g=CreateCube() ScaleMesh g,10,10,10 FlipMesh g EntityType g,2 r=2 m=CreateSphere() EntityShininess m,1 EntityType m,1 EntityRadius m,r ScaleEntity m,r,r,r EntityColor m,255,0,0 Collisions 1,2,2,2 Collisions 1,1,2,2 RotateEntity CreateLight(),25,45,0 Type physics Field mesh Field velocity#[5] Field position#[5] Field elasticity# End Type balls=3 For n=1 To balls ph.physics=New physics ph\mesh=CopyEntity(m) ph\velocity[0]=Rnd(-.5,.5) ph\velocity[1]=Rnd(-1,1) ph\velocity[2]=Rnd(-.5,.5) ;PositionEntity ph\mesh,Rnd(-8,8),8,Rnd(-8,8) ResetEntity ph\mesh ph\elasticity#=0.95 EntityColor ph\mesh,Rand(255),Rand(255),Rand(255) Next HideEntity m period=1000/60 time=MilliSecs()-period While Not KeyHit(1) Repeat elapsed=MilliSecs()-time Until elapsed ticks=elapsed/period tween#=Float(elapsed Mod period)/Float(period) For k=1 To ticks time=time+period If KeyHit(28) ph.physics=New physics ph\mesh=CopyEntity(m) ph\velocity[0]=Rnd(-.5,.5) ph\velocity[1]=Rnd(-1,1) ph\velocity[2]=Rnd(-.5,.5) ;PositionEntity ph\mesh,Rnd(-8,8),8,Rnd(-8,8) ScaleEntity ph\mesh,r,r,r EntityRadius ph\mesh,r ResetEntity ph\mesh ph\elasticity#=0.95 EntityColor ph\mesh,Rand(255),Rand(255),Rand(255) balls=balls+1 EndIf If KeyHit(57) For ph.physics=Each physics ph\velocity[0]=Rnd(-.5,.5) ph\velocity[1]=Rnd(-2,2) ph\velocity[2]=Rnd(-.5,.5) Next EndIf UpdatePhysics Next RenderWorld Text 0,0,fps() Text 0,20,"Press space to reset balls." Text 0,40,"Press enter to add a ball." Text 0,60,balls+" balls exist." Flip Wend Function UpdatePhysics() friction#=0.99;sliding friction staticfriction#=0.0001;minimum velocity before an objects starts sticking For ph.physics=Each physics ph\position[0]=EntityX(ph\mesh,1) ph\position[1]=EntityY(ph\mesh,1) ph\position[2]=EntityZ(ph\mesh,1) ;gravity ph\velocity[1]=ph\velocity[1]-0.03 ;carry out velocity TranslateEntity ph\mesh,ph\velocity[0],ph\velocity[1],ph\velocity[2],1 ph\position[3]=EntityX(ph\mesh,1) ph\position[4]=EntityY(ph\mesh,1) ph\position[5]=EntityZ(ph\mesh,1) Next UpdateWorld ;correct velocity For ph.physics=Each physics ax#=(EntityX(ph\mesh,1)-ph\position[3]) ay#=(EntityY(ph\mesh,1)-ph\position[4]) az#=(EntityZ(ph\mesh,1)-ph\position[5]) PositionEntity ph\mesh,ph\position[3],ph\position[4],ph\position[5],1 ph\velocity[0]=(EntityX(ph\mesh,1)-ph\position[0]+ax*ph\elasticity) ph\velocity[1]=(EntityY(ph\mesh,1)-ph\position[1]+ay*ph\elasticity) ph\velocity[2]=(EntityZ(ph\mesh,1)-ph\position[2]+az*ph\elasticity) TranslateEntity ph\mesh,ax*(1.0-ph\elasticity),ay*(1.0-ph\elasticity),az*(1.0-ph\elasticity) Next ;transfer inertia For ph.physics=Each physics For c=1 To CountCollisions(ph\mesh) If GetEntityType(CollisionEntity(ph\mesh,c))=1 ;lose some energy as heat for each collision ph\velocity[0]=ph\velocity[0]*.98 ph\velocity[1]=ph\velocity[1]*.98 ph\velocity[2]=ph\velocity[2]*.98 ;hmmm...should the collision normals be absolute value or not? nx#=Abs(CollisionNX(ph\mesh,c)) ny#=Abs(CollisionNY(ph\mesh,c)) nz#=Abs(CollisionNZ(ph\mesh,c)) ph2.physics=findphysics(CollisionEntity(ph\mesh,c)) ph2\velocity[0]=ph2\velocity[0]+(nx)*ph\velocity[0]/2.0 ph2\velocity[1]=ph2\velocity[1]+(ny)*ph\velocity[1]/2.0 ph2\velocity[2]=ph2\velocity[2]+(nz)*ph\velocity[2]/2.0 ph\velocity[0]=ph\velocity[0]-(nx)*ph\velocity[0]/2.0 ph\velocity[1]=ph\velocity[1]-(ny)*ph\velocity[1]/2.0 ph\velocity[2]=ph\velocity[2]-(nz)*ph\velocity[2]/2.0 EndIf Next Next ;add friction For ph.physics=Each physics If EntityCollided(ph\mesh,2) ;sliding friction ph\velocity[0]=ph\velocity[0]*friction ph\velocity[1]=ph\velocity[1]*friction ph\velocity[2]=ph\velocity[2]*friction ;static friction If Abs(ph\velocity[0])<staticfriction# ph\velocity[0]=0.0 If Abs(ph\velocity[1])<staticfriction# ph\velocity[1]=0.0 If Abs(ph\velocity[2])<staticfriction# ph\velocity[2]=0.0 EndIf Next End Function Function FindPhysics.physics(e) For ph.physics=Each physics If ph\mesh=e Return ph Next Return Null End Function Global FPS_fpstime Function FPS() oldtime=FPS_fpstime FPS_fpstime=MilliSecs() elapsed=FPS_fpstime-oldtime If Not elapsed elapsed=1 FPS_fps=1000/elapsed Return FPS_FPS End Function