ROWS=3
COLS=3
rem rigid body amount = ROWS * COLS
sync on
sync rate 0
cls
set display mode 1024,768,32
autocam off
position camera 0,0,-100
set camera range 50,150
rotate camera 0,0,0
color backdrop 0
 
global max_body_amount=100
global max_vertex_amount=20
global max_collision_data_amount=100
global max_material_amount=20
 
 
type xy
   x as float
   y as float
endtype
type xyw
   x as float
   y as float
   w as float
endtype
type body_type
   p as xyw
   avgv as xyw
   v as xyw
   force as xyw
   avgforce as xyw
   impulse as xyw
   mass as float
   moi as float
   vertex_amount
   push as xyw
   exist as boolean
   gravity as boolean
   active as boolean
   autofreeze as boolean
   object
   lin_damp as float
   ang_damp as float
   collision_radius as float
   material
endtype
type collision_data_type
   vertex_amount
   exist as boolean
endtype
type world_type
   min as xy
   max as xy
   onexit
   standard_gravity as xy
endtype
type collision_type
   pt as xy
   n as xy
   distance as float
   edge1
   edge2
   edge_length1 as float
   edge_length2 as float
   exist1 as boolean
   exist2 as boolean
endtype
type rbd_type
   world as world_type
   last_time
   collision as collision_type
endtype
type material_type
   sfriction as float
   kfriction as float
   elasticity as float
   collidable as boolean
endtype
 
dim body(max_body_amount) as body_type
dim bodycontact(max_body_amount,max_body_amount)
dim body_shape(max_body_amount,max_vertex_amount) as xy
dim collision_data(max_collision_data_amount+2) as collision_data_type
dim collision_data_v(max_collision_data_amount,max_vertex_amount) as xy
dim material(max_material_amount,max_material_amount) as material_type
dim groupid(max_material_amount)
global RBD as rbd_type
global RBD_V1=1
global RBD_V2=2
global RBD_V3=3
global RBD_V4=4
global RBD_V5=5
global RBD_V6=6
type debug_type
   torque as boolean
   force as boolean
   collision as boolean
   velocity as boolean
endtype
global debug as debug_type
n=make vector2(RBD_V1)
n=make vector2(RBD_V2)
n=make vector2(RBD_V3)
n=make vector2(RBD_V4)
n=make vector2(RBD_V5)
n=make vector2(RBD_V6)
RBD_Create()
n=0
for y=1 to ROWS
for x=1 to COLS
inc n
sx#=5*(rnd(2)+2)
sy#=5*(rnd(2)+2)
col=RBD_CreateBox(sx#,sy#)
make object box n,sx#,sy#,0.01
 
color object n,hsl(rnd(100.0)/100.0,1.0,0.5)
b=RBD_CreateBody(col)
mass#=sx#*sy#
moi#=RBD_CalculateMIBoxSolid(mass#,sx#,sy#)
RBD_BodySetMass(b,mass#,moi#)
RBD_BodySetDBProData(b, n)
body(b).p.y=30*(y-1)-55
body(b).p.x=30.0*(x-2.5)
next x
next y
n=n+1
col=RBD_CreateBox(200.0,5.0)
make object plain n,200.0,5.0
b=RBD_CreateBody(col)
RBD_BodySetDBProData(b, n)
body(b).mass=0
body(b).p.y=-60
body(b).p.w=0
body(b).p.x=0
inc n
make object plain n,200.0,5.0
b=RBD_CreateBody(col)
RBD_BodySetDBProData(b, n)
body(b).p.w=90
body(b).p.x=-80
body(b).p.y=0
body(b).mass=0
inc n
make object plain n,200.0,5.0
b=RBD_CreateBody(col)
RBD_BodySetDBProData(b, n)
body(b).p.w=0
body(b).p.x=0
body(b).p.y=60
body(b).mass=0
inc n
make object plain n,200.0,5.0
b=RBD_CreateBody(col)
RBD_BodySetDBProData(b, n)
body(b).p.w=90
body(b).p.x=80
body(b).p.y=0
body(b).mass=0
inc n
col=RBD_CreateBox(80.0,5.0)
make object plain n,80.0,5.0
bar=n
b=RBD_CreateBody(col)
body(b).autofreeze=0
RBD_BodySetDBProData(b, n)
body(b).mass=0
body(b).p.y=20
body(b).p.w=0
body(b).p.x=0
inc n
global time# as float
drag_body=-1
grabx#=0
graby#=0
global screen=10000
make object plain screen,10000,10000
position object screen,0,0,2
color object screen,0
set object light screen,0
ghost object on screen,1
`hide object screen
global dummy_obj=10001
make object cube dummy_obj,0
global last_body
backdrop off
make object plain 10002,5000,5000
`lock object on 10002
`move object 10002,52
position object 10002,0,0,10
color object 10002,0
set alpha mapping on 10002,20
set object ambient 10002,0
RBD_SetStandardGravity(0.0,-49)
go=1
`debug.collision=1
`debug.torque=1
`debug.force=1
do
   time#=RBD_GetElapsedTimeInSec()
   if go=1 then RBD_Update(time#)
   if spacekey()=1 and sp=0
   go=1-go
   endif
   sp=spacekey()
   set cursor 0,0
   print "FPS:",screen fps()
   set vector2 RBD_V1,0,1
   set vector2 RBD_V2,0,30*(upkey()-downkey())
   RBD_BodyAddForceLocal(body1)
`   set vector2 RBD_V1,-(rightkey()-leftkey())*200.0,0
`   RBD_BodyAddTorque(body1)
   body(RBD_GetBody(bar)).p.w=body(RBD_GetBody(bar)).p.w+(leftkey()-rightkey())
   if mouseclick()=1 and drag_body=-1
      obj=pick object(mousex(),mousey(),1,100)
      b=RBD_GetBody(obj)
      if b>=0
         if body(b).mass>0
            drag_body=b
            set vector2 RBD_V1,get pick vector x()+camera position x(),get pick vector y()+camera position y()
            set vector2 RBD_V1,x vector2(RBD_V1)-body(b).p.x,y vector2(RBD_V1)-body(b).p.y
            rotate_vector2(RBD_V1,-body(b).p.w)
            grabx#=x vector2(RBD_V1)
            graby#=y vector2(RBD_V1)
         endif
      endif
   endif
   print "Selected body:",last_body
   print "Velocity:",str$(body(last_body).v.x),",",str$(body(last_body).v.y)
   print "Angular Velocity:",str$(body(last_body).v.w)
   print "Mass:",str$(body(last_body).mass)
   print "Moment of Inertia:",str$(body(last_body).moi)
   if mouseclick()=0 then drag_body=-1
   if drag_body>=0
      obj=pick object(mousex(),mousey(),screen,screen)
      set vector2 RBD_V1,grabx#,graby#
      rotate_vector2(RBD_V1,body(drag_body).p.w)
      set vector2 RBD_V1,x vector2(RBD_V1)+body(drag_body).p.x,y vector2(RBD_V1)+body(drag_body).p.y
      dx#=get pick vector x()+camera position x()-x vector2(RBD_V1)
      dy#=get pick vector y()+camera position y()-y vector2(RBD_V1)
      d2#=dx#^2+dy#^2
      d#=sqrt(d2#)
      dx#=dx#/d#
      dy#=dy#/d#
      force#=body(drag_body).mass*(d2#)
      set vector2 RBD_V2,force#*dx#,force#*dy#
      RBD_BodyAddForceGlobal(drag_body)
      line mousex(),mousey(),screenx(x vector2(RBD_V1)),screeny(y vector2(RBD_V1))
      body(drag_body).v.x=body(drag_body).v.x*0.992
      body(drag_body).v.y=body(drag_body).v.y*0.992
      body(drag_body).v.w=body(drag_body).v.w*0.992
      last_body=drag_body
      body(last_body).active=1
   endif
   if shiftkey()=1
      body(last_body).v.x=0
      body(last_body).v.y=0
      if keystate(30)=1
         for b=0 to max_body_amount
            body(b).v.x=0
            body(b).v.y=0
            body(b).force.x=0
            body(b).force.y=0
         next b
      endif
   endif
   if controlkey()=1
      body(last_body).v.w=0
      if keystate(30)=1
         for b=0 to max_body_amount
            body(b).v.w=0
            body(b).force.w=0
         next b
      endif
   endif
   if keystate(34)=1 and key34=0
      key34=1
      body(last_body).gravity=1-body(last_body).gravity
   endif
   key34=keystate(34)
   sync
loop
 
function RBD_Create()
   RBD.world.min.x=-100.0
   RBD.world.max.x=100.0
   RBD.world.min.y=-100.0
   RBD.world.max.y=100.0
   RBD.world.standard_gravity.x=0
   RBD.world.standard_gravity.y=-9.8
   RBD.last_time=timer()
   RBD.world.onexit=0
   local b
   for b=0 to max_body_amount
      body(b).exist=0
   next b
   material(0,0).collidable=1
   material(0,0).elasticity=0.4
   material(0,0).sfriction=0.4
   material(0,0).kfriction=0.4
   groupid(0)=1
endfunction
 
function RBD_Update(time#)
   for b=0 to max_body_amount
      if body(b).exist=1
         if RBD.world.onexit=1
            if body(b).p.x<RBD.world.min.x or body(b).p.y<RBD.world.min.y or body(b).p.x>RBD.world.max.x or body(b).p.y>RBD.world.max.y then body(b).exist=0
         endif
         for l=1 to 2
            for b2=0 to max_body_amount
               if body(b2).exist=1
                  mat1=body(b).material
                  mat2=body(b2).material
                  if mat2<mat1
                     t=mat1
                     mat1=mat2
                     mat2=t
                  endif
                  if b<>b2 and material(mat1,mat2).collidable=1 and body(b).mass>0
                     d2#=(body(b).p.x-body(b2).p.x)^2+(body(b).p.y-body(b2).p.y)^2
                     if d2#<(body(b).collision_radius+body(b2).collision_radius)^2
                     ink rgb(0,255,0),0
                        col=BodyCollision(b,b2)
                        if col=1
                           body(b).active=1
                           body(b2).active=1
                           if l=1 and b<b2
                              `line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+RBD.collision.n.x*10.0),screeny(RBD.collision.pt.y+RBD.collision.n.y*10.0)
                              position object dummy_obj,RBD.collision.pt.x,RBD.collision.pt.y,0
                              cx=object screen x(dummy_obj)
                              cy=object screen y(dummy_obj)
                              position object dummy_obj,RBD.collision.pt.x+2.0*RBD.collision.n.x*RBD.collision.distance,RBD.collision.pt.y+2.0*RBD.collision.n.y*RBD.collision.distance,0
                              dx=object screen x(dummy_obj)
                              dy=object screen y(dummy_obj)
                              rem calculate normal impulse
                              nx#=RBD.collision.n.x
                              ny#=RBD.collision.n.y
                              rAPx#=RBD.collision.pt.x-body(b).p.x
                              rAPy#=RBD.collision.pt.y-body(b).p.y
                              rAP#=sqrt(rAPx#^2+rAPy#^2)
                              rBPx#=RBD.collision.pt.x-body(b2).p.x
                              rBPy#=RBD.collision.pt.y-body(b2).p.y
                              rBP#=sqrt(rBPx#^2+rBPy#^2)
                              rTAPx#=-rAPy#
                              rTAPy#=rAPx#
                              rTBPx#=-rBPy#
                              rTBPy#=rBPx#
                              if debug.collision=1
                                 ink rgb(100,25,255),0
                                 line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x-rAPx#),screeny(RBD.collision.pt.y-rAPy#)
                                 line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+rTAPx#),screeny(RBD.collision.pt.y+rTAPy#)
                                 ink rgb(255,25,100),0
                                 line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x-rBPx#),screeny(RBD.collision.pt.y-rBPy#)
                                 line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+rTBPx#),screeny(RBD.collision.pt.y+rTBPy#)
                                 ink rgb(255,0,0),0
                                 box screenx(RBD.collision.pt.x)-3,screeny(RBD.collision.pt.y)-3, screenx(RBD.collision.pt.x)+3,screeny(RBD.collision.pt.y)+3
 
                              endif
                              vA1x#=body(b).v.x
                              vA1y#=body(b).v.y
                              wA1#=body(b).v.w
                              vAP1x#=vA1x# +wA1#*rTAPx#
                              vAP1y#=vA1y# +wA1#*rTAPy#
                              vB1x#=body(b2).v.x
                              vB1y#=body(b2).v.y
                              wB1#=body(b2).v.w
                              vBP1x#=vB1x# +wB1#*rTBPx#
                              vBP1y#=vB1y# +wB1#*rTBPy#
                              vAB1x#=vBP1x#-vAP1x#
                              vAB1y#=vBP1y#-vAP1y#
                              vAB1#=vAB1x#*nx#+vAB1y#*ny#
                              e#=material(mat1,mat2).elasticity
                              if body(b).mass>0
                                 dma#=1.0/body(b).mass
                                 dmoia#=(rTAPx#*nx#+rTAPy#*ny#)^2/body(b).moi
                              else
                                 rem 0 mass = infinite mass.
                                 dma#=0
                                 dmoia#=0
                              endif
                              if body(b2).mass>0
                                 dmb#=1.0/body(b2).mass
                                 dmoib#=(rTBPx#*nx#+rTBPy#*ny#)^2/body(b2).moi
                              else
                                 rem 0 mass = infinite mass.
                                 dmb#=0
                                 dmoib#=0
                              endif
                              j#=(VAB1x#*nx#+VAB1y#*ny#)/(dma#+dmb#+dmoia#+dmoib#)
                              frictionj#=(VAB1x#*(-ny#)+VAB1y#*nx#)/(dma#+dmb#+dmoia#+dmoib#)
                              j#=j#*(1.0+e#)
                              if j#>0
                                 j#=0
                              endif
                              if abs(frictionj#)> abs(j#)*material(mat1,mat2).kfriction
                                 frictionj#=frictionj#/abs(frictionj#)*abs(j#)*material(mat1,mat2).kfriction
                              endif
                              ivA2x#=(j#)*nx#+frictionj#*(-ny#)
                              ivA2y#=(j#)*ny#+frictionj#*nx#
                              ivB2x#=-(j#)*nx#-frictionj#*(-ny#)
                              ivB2y#=-(j#)*ny#-frictionj#*nx#
                              `iwA2#=(rTAPx#*j#*nx#+rTAPy#*j#*ny#)/rAP#^2+(rTAPx#*frictionj#*(-ny#)+rTAPy#*frictionj#*nx#)/rAP#^2
                              `iwB2#=(rTBPx#*j#*nx#+rTBPy#*j#*ny#)/rBP#^2+(rTBPx#*frictionj#*(-ny#)+rTBPy#*frictionj#*nx#)/rBP#^2
                              k#=1.0
                              body(b).impulse.x=body(b).impulse.x+ivA2x#*k#
                              body(b).impulse.y=body(b).impulse.y+ivA2y#*k#
                              body(b).impulse.w=body(b).impulse.w+iwA2#*k#
                              body(b2).impulse.x=body(b2).impulse.x+ivB2x#*k#
                              body(b2).impulse.y=body(b2).impulse.y+ivB2y#*k#
                              body(b2).impulse.w=body(b2).impulse.w+iwB2#*k#
                             ` if j#>-0.1*(body(b).mass+body(b2).mass) or RBD.collision.distance>-2
                                 rem calculate normal force
                                 forcevA1x#=body(b).force.x
                                 forcevA1y#=body(b).force.y
                                 forcewA1#=body(b).avgforce.w*0.5
                                 forcevAP1x#=forcevA1x#+forcewA1#*rTAPx#/rAP#^2
                                 forcevAP1y#=forcevA1y#+forcewA1#*rTAPy#/rAP#^2
                                 forcevB1x#=body(b2).force.x
                                 forcevB1y#=body(b2).force.y
                                 forcewB1#=body(b2).avgforce.w*0.5
 `                                if body(b2).collision_radius>body(b).collision_radius
                                    forcevBP1x#=forcevB1x#+forcewB1#*rTBPx#/rBP#^2
                                    forcevBP1y#=forcevB1y#+forcewB1#*rTBPy#/rBP#^2
 `                                else
 `                                   forcevBP1x#=forcevB1x#+forcewB1#*rTBPx#/rBP#^2
 `                                   forcevBP1y#=forcevB1y#+forcewB1#*rTBPy#/rBP#^2
`                                 endif
                                 forcevAB1x#=forcevBP1x#-forcevAP1x#
                                 forcevAB1y#=forcevBP1y#-forcevAP1y#
                                 forcevAB1#=forcevAB1x#*nx#+forcevAB1y#*ny#
                                 forcej#=(forceVAB1x#*nx#+forceVAB1y#*ny#)
                                 if forcej#<0
`                                   line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+forcevAP1x#),screeny(RBD.collision.pt.y+forcevAP1y#)
                                    forceivA2x#=(forcej#)*nx#
                                    forceivA2y#=(forcej#)*ny#
                                    forceivB2x#=-(forcej#)*nx#
                                    forceivB2y#=-(forcej#)*ny#
                                    forceiwA2#=(rTAPx#*forcej#*nx#+rTAPy#*forcej#*ny#)
`                                    if body(b2).collision_radius>body(b).collision_radius
`                                       forceiwB2#=(rTBPx#*forcej#*nx#+rTBPy#*forcej#*ny#)
`                                    else
                                       forceiwB2#=-(rTBPx#*forcej#*nx#+rTBPy#*forcej#*ny#)
`                                    endif
                                    ` line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+forceiwA2#*rTAPx#/(rAP#*10000.0)),screeny(RBD.collision.pt.y+forceiwA2#*rTAPy#/(rAP#*10000.0))
                                    surfaceforce#=forcevAB1x#*(-ny#)+forcevAB1y#*nx#
                                    normalforce#=abs(forcej#)
                                    frictionforcej#=abs(normalforce#*material(mat1,mat2).kfriction)
                                    if abs(frictionforcej#)>abs(frictionj#/(2*time#)) then frictionforcej#=abs(frictionj#/(2*time#))
                                    frictionforcej#=-frictionforcej#*frictionj#/abs(frictionj#)
                                    if abs(vAB1x#*(-ny#)+vAB1y#*nx#)<3
                                       frictionforcej#=0
                                    endif
                                    frictionforcej#=0
 
         `                           line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+frictionforcej#*frictionnx#*10.0),screeny(RBD.collision.pt.y+frictionforcej#*frictionny#*10.0)
                                    `line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+frictionforcej#*(-ny#)/1000.0),screeny(RBD.collision.pt.y+frictionforcej#*nx#/1000.0)
                                    frictionforceivA2x#=(frictionforcej#)*(-ny#)
                                    frictionforceivA2y#=(frictionforcej#)*nx#
                                    frictionforceivB2x#=-(frictionforcej#)*(-ny#)
                                    frictionforceivB2y#=-(frictionforcej#)*(nx#)
                                    frictionforceiwA2#=(rTAPx#*frictionforcej#*(-ny#)+rTAPy#*frictionforcej#*nx#)
                                    frictionforceiwB2#=(rTBPx#*frictionforcej#*(-ny#)+rTBPy#*frictionforcej#*nx#)
                                    k#=1
                                    body(b).force.x=body(b).force.x+forceivA2x#*k# +frictionforceivA2x#*k#
                                    body(b).force.y=body(b).force.y+forceivA2y#*k# +frictionforceivA2y#*k#
                                    body(b).force.w=body(b).force.w+forceiwA2#*k# +frictionforceiwA2#*k#
                                    body(b2).force.x=body(b2).force.x+forceivB2x#*k# +frictionforceivB2x#*k#
                                    body(b2).force.y=body(b2).force.y+forceivB2y#*k# +frictionforceivB2y#*k#
                                    body(b2).force.w=body(b2).force.w+forceiwB2#*k# +frictionforceiwB2#*k#
 `                                   body(b).avgforce.x=(body(b).avgforce.x*1.0+body(b).force.x)/2.0
`                                    body(b).avgforce.y=(body(b).avgforce.y*1.0+body(b).force.y)/2.0
                                    body(b).avgforce.x=body(b).force.x
                                    body(b).avgforce.y=body(b).force.y
                                    body(b).avgforce.w=(body(b).avgforce.w*1.0+body(b).force.w)/2.0
 
                                 endif
                              `endif
                           endif
                           rem this alters the position of the bodies (encourages them to not overlap)
                           `if b<b2
                              if body(b2).mass=0
                                 body(b).p.x=body(b).p.x+RBD.collision.distance*(RBD.collision.n.x)*0.5
                                 body(b).p.y=body(b).p.y+RBD.collision.distance*(RBD.collision.n.y)*0.5
                                 body(b2).force.x=0
                                 body(b2).force.y=0
                                 body(b2).force.w=0
                              else
                                 body(b).p.x=body(b).p.x+RBD.collision.distance*(RBD.collision.n.x)*body(b).mass/(body(b).mass+body(b2).mass)*0.5
                                 body(b).p.y=body(b).p.y+RBD.collision.distance*(RBD.collision.n.y)*body(b).mass/(body(b).mass+body(b2).mass)*0.5
                                 body(b2).p.x=body(b2).p.x-RBD.collision.distance*(RBD.collision.n.x)*body(b).mass/(body(b).mass+body(b2).mass)*0.5
                                 body(b2).p.y=body(b2).p.y-RBD.collision.distance*(RBD.collision.n.y)*body(b).mass/(body(b).mass+body(b2).mass)*0.5
                              endif
                           `endif
                          ` endif
                        endif
                     endif
                  endif
               endif
            next b2
         next l
 
         body(b).force.x=body(b).force.x-body(b).lin_damp*body(b).v.x*abs(body(b).v.x)*time#
         body(b).force.y=body(b).force.y-body(b).lin_damp*body(b).v.y*abs(body(b).v.y)*time#
         body(b).force.w=body(b).force.w-body(b).ang_damp*body(b).v.w*abs(body(b).v.w)*time#
         if body(b).mass=0
            body(b).v.x=0
            body(b).v.y=0
            body(b).v.w=0
         endif
         if b=last_body
              ` print "Sum of all forces being applied to object:",str$(body(last_body).force.x,2),",",str$(body(last_body).force.y,2)
         endif
         if body(b).active=1 and body(b).mass>0
 
            if debug.torque=1
               for r=1 to 10
                  line screenx(body(b).p.x+(r*0.01+5)*cos(body(b).avgforce.w*r*0.001)),screeny(body(b).p.y+(r*0.01+5)*sin(body(b).avgforce.w*r*0.001)),screenx(body(b).p.x+((r+1)*0.01+5)*cos(body(b).avgforce.w*(r+1)*0.001)),screeny(body(b).p.y+((r+1)*0.01+5)*sin(body(b).avgforce.w*(r+1)*0.001))
               next r
            endif
            if debug.force=1
               line screenx(body(b).p.x),screeny(body(b).p.y),screenx(body(b).p.x+body(b).force.x*0.01),screeny(body(b).p.y+body(b).force.y*0.01)
            endif
 
            body(b).v.x=body(b).v.x+body(b).force.x/body(b).mass*time#+body(b).impulse.x/body(b).mass
            body(b).v.y=body(b).v.y+body(b).force.y/body(b).mass*time#+body(b).impulse.y/body(b).mass
            body(b).v.w=body(b).v.w+body(b).force.w/body(b).moi*time#+body(b).impulse.w/body(b).moi
            body(b).p.x=body(b).p.x+body(b).push.x
            body(b).p.y=body(b).p.y+body(b).push.y
            body(b).p.w=body(b).p.w+body(b).push.w
            body(b).avgforce.x=body(b).force.x
            body(b).avgforce.y=body(b).force.y
            body(b).avgforce.w=body(b).force.w
            body(b).force.x=RBD.world.standard_gravity.x*body(b).mass*body(b).gravity
            body(b).force.y=RBD.world.standard_gravity.y*body(b).mass*body(b).gravity
            body(b).force.w=0
            body(b).impulse.x=0
            body(b).impulse.y=0
            body(b).impulse.w=0
            body(b).push.x=0
            body(b).push.y=0
            body(b).push.w=0
            body(b).p.x=body(b).p.x+body(b).v.x*time#
            body(b).p.y=body(b).p.y+body(b).v.y*time#
            body(b).p.w=body(b).p.w+body(b).v.w*time#*180.0/3.14159
         else
            body(b).v.x=0
            body(b).v.y=0
            body(b).v.w=0
            body(b).force.x=0
            body(b).force.y=0
            body(b).force.w=0
            body(b).impulse.x=0
            body(b).impulse.y=0
            body(b).impulse.w=0
            body(b).push.x=0
            body(b).push.y=0
            body(b).push.w=0
         endif
         if body(b).active=1
            check=0
            if abs(body(b).force.x)<0.4
            `   body(b).force.x=0
               inc check
            endif
            if abs(body(b).v.x)<0.4
            `   body(b).v.x=0
               inc check
            endif
            if abs(body(b).force.y)<0.4
            `   body(b).force.y=0
               inc check
            endif
            if abs(body(b).v.y)<0.4
            `   body(b).v.y=0
               inc check
            endif
            if abs(body(b).force.w)<0.4
            `   body(b).force.w=0
               inc check
            endif
            if abs(body(b).v.w)<0.4
            `   body(b).v.w=0
               inc check
            endif
            if check=6 and body(b).autofreeze=1
               body(b).active=0
            endif
         else
            check=0
            if abs(body(b).force.x)>100 or abs(body(b).force.y)>100 or abs(body(b).force.w)>100 then body(b).active=1
         endif
         if body(b).object>0
            position object body(b).object,curvevalue(body(b).p.x,object position x(body(b).object),1.5),curvevalue(body(b).p.y,object position y(body(b).object),1.5),0
            rotate object body(b).object,0,0,curveangle(body(b).p.w,object angle z(body(b).object),1.5)
            `text screenx(body(b).p.x),screeny(body(b).p.y),str$(b)
         endif
 
         rem wrap objects around if they get out of the screen
         if body(b).p.y<-70 then body(b).p.y=70
         if body(b).p.y>70 then body(b).p.y=-70
         if body(b).p.x<-90 then body(b).p.x=90
         if body(b).p.x>90 then body(b).p.x=-90
      endif
   next b
   local c
   for c=0 to max_collision_data_amount
      collision_data(c).exist=0
   next c
endfunction
 
function RBD_GetElapsedTimeInSec()
   t#=(timer()-RBD.last_time)*0.001
   RBD.last_time=timer()
   if t#<0.001 then t#=0.001
endfunction t#
 
function RBD_SetWorldSize()
   RBD.world.min.x=x vector2(RBD_V1)
   RBD.world.min.y=y vector2(RBD_V1)
   RBD.world.max.x=x vector2(RBD_V2)
   RBD.world.max.y=y vector2(RBD_V2)
endfunction
 
function RBD_CreateBox(sx#,sy#)
   local c=0
   while collision_data(c).exist=1
      inc c
   endwhile
   collision_data(c).exist=1
   collision_data(c).vertex_amount=4
   collision_data_v(c,0).x=sx#*0.5
   collision_data_v(c,0).y=sy#*0.5
 
   collision_data_v(c,1).x=sx#*0.5
   collision_data_v(c,1).y=-sy#*0.5
 
   collision_data_v(c,2).x=-sx#*0.5
   collision_data_v(c,2).y=-sy#*0.5
 
   collision_data_v(c,3).x=-sx#*0.5
   collision_data_v(c,3).y=sy#*0.5
endfunction c
 
function RBD_CreateBody(col)
   local b=0
   while body(b).exist=1
      inc b
   endwhile
   body(b).exist=1
   body(b).gravity=1
   body(b).mass=1
   body(b).p.x=0
   body(b).p.y=0
   body(b).p.w=0
   body(b).v.x=0
   body(b).v.y=0
   body(b).v.w=0
   body(b).force.x=0
   body(b).force.y=0-98*body(b).mass*body(b).gravity
   body(b).force.w=0
   body(b).impulse.x=0
   body(b).impulse.y=0
   body(b).impulse.w=0
   body(b).moi=1
   body(b).active=1
   body(b).autofreeze=1
   body(b).lin_damp=0.1
   body(b).ang_damp=0.1
   body(b).vertex_amount=collision_data(col).vertex_amount
   body(b).material=0
   local v
   rad2#=0
   for v=0 to body(b).vertex_amount-1
      body_shape(b,v).x=collision_data_v(col,v).x
      body_shape(b,v).y=collision_data_v(col,v).y
      r#=collision_data_v(col,v).x^2+collision_data_v(col,v).y^2
      if r#>rad2#
         rad2#=r#
      endif
   next v
   body(b).collision_radius=sqrt(rad2#)
endfunction b
 
function RBD_DestroyBody(b)
   body(b).exist=0
endfunction
 
function RBD_BodyGetRotation(b)
   set vector2 RBD_V1,body(b).p.w,0
endfunction
 
function RBD_BodyGetPosition(b)
   set vector2 RBD_V1,body(b).p.x,body(b).p.y
endfunction
 
function RBD_DestroyAllBodies()
   local b
   for b=0 to max_body_amount
      RBD_DestroyBody(b)
   next b
endfunction
 
function RBD_SetBodyLeaveWorldEvent(flag)
   RBD.world.onexit=flag
endfunction
 
function RBD_BodySetDBProData(body, db_num)
   body(body).object=db_num
endfunction
 
function RBD_BodySetVelocity(body)
   body(body).v.x=x vector2(RBD_V1)
   body(body).v.y=y vector2(RBD_V1)
endfunction
 
function RBD_BodyGetVelocity(body)
   set vector2 RBD_V1,body(body).v.x,body(body).v.y
endfunction
 
function RBD_BodySetOmega(body)
   body(body).v.w=x vector2(RBD_V1)
endfunction
 
function RBD_BodyGetOmega(body)
   set vector2 RBD_V1,body(body).v.w,0
endfunction
 
function RBD_BodySetLinearDamping(body, lin_damp#)
   body(body).lin_damp=lin_damp#
endfunction
 
function RBD_BodyGetLinearDamping(body)
d#=body(body).lin_damp
endfunction d#
 
function RBD_BodySetAngularDamping(body, ang_damp#)
   body(body).ang_damp=ang_damp#
endfunction
 
function RBD_BodyGetAngularDamping(body)
d#=body(body).ang_damp
endfunction d#
 
 
function RBD_BodyAddTorque(body)
   body(body).force.w=body(body).force.w+x vector2(RBD_V1)
endfunction
 
function RBD_BodySetTorque(body)
   body(body).force.w=x vector2(RBD_V1)
endfunction
 
function RBD_BodyAddForceGlobal(b)
   RX#=x vector2(RBD_V1)-body(b).p.x
   RY#=y vector2(RBD_V1)-body(b).p.y
   FX#=x vector2(RBD_V2)
   FY#=y vector2(RBD_V2)
   torque#=(RX#*FY#-RY#*FX#)
   R#=sqrt(RX#^2+RY#^2)
   body(b).force.w=body(b).force.w+torque#
   body(b).force.x=body(b).force.x+FX#*abs(RX#/R#)
   body(b).force.y=body(b).force.y+FY#*abs(RY#/R#)
endfunction
 
function RBD_BodyAddForceLocal(b)
   rotate_vector2(RBD_V1,body(b).p.w)
   set vector2 RBD_V1,x vector2(RBD_V1)+body(b).p.x,y vector2(RBD_V1)+body(b).p.y
   rotate_vector2(RBD_V2,body(b).p.w)
   RBD_BodyAddForceGlobal(b)
endfunction
 
function RBD_BodySetForceGlobal(b)
   RX#=x vector2(RBD_V1)-body(b).p.x
   RY#=y vector2(RBD_V1)-body(b).p.y
   FX#=x vector2(RBD_V2)
   FY#=y vector2(RBD_V2)
   torque#=(RX#*FY#-RY#*FX#)
   body(b).force.w=torque#
   R#=sqrt(RX#^2+RY#^2)
   body(b).force.x=FX#*abs(RX#/R#)
   body(b).force.y=FY#*abs(RY#/R#)
endfunction
 
 
function RBD_BodySetForceLocal(b)
   rotate_vector2(RBD_V1,body(b).p.w)
   set vector2 RBD_V1,x vector2(RBD_V1)+body(b).p.x,y vector2(RBD_V1)+body(b).p.y
   rotate_vector2(RBD_V2,body(b).p.w)
   RBD_BodySetForceGlobal(b)
endfunction
 
function RBD_BodyAddImpulseGlobal(b)
   RX#=x vector2(RBD_V1)-body(b).p.x
   RY#=y vector2(RBD_V1)-body(b).p.y
   FX#=x vector2(RBD_V2)
   FY#=y vector2(RBD_V2)
   R#=sqrt(RX#^2+RY#^2)
   torque#=(RX#*FY#-RY#*FX#)
   body(b).impulse.w=body(b).impulse.w+torque#/R#^2
   body(b).impulse.x=body(b).impulse.x+FX#*abs(RX#/R#)
   body(b).impulse.y=body(b).impulse.y+FY#*abs(RY#/R#)
endfunction
 
function RBD_BodyAddImpulseLocal(b)
   rotate_vector2(RBD_V1,body(b).p.w)
   set vector2 RBD_V1,x vector2(RBD_V1)+body(b).p.x,y vector2(RBD_V1)+body(b).p.y
   rotate_vector2(RBD_V2,body(b).p.w)
   RBD_BodyAddImpulseGlobal(b)
endfunction
 
function rotate_vector2(v,r#)
   set vector2 RBD_V3,cos(r#),sin(r#)
   set vector2 RBD_V4,-y vector2(RBD_V3),x vector2(RBD_V3)
   set vector2 v,x vector2(v)*x vector2(RBD_V3)+y vector2(v)*x vector2(RBD_V4),x vector2(v)*y vector2(RBD_V3)+y vector2(v)*y vector2(RBD_V4)
endfunction
 
function BodyCollision(b1,b2)
   if body(b2).vertex_amount<body(b1).vertex_amount
      bt=b1
      b1=b2
      b2=bt
   endif
   va1=body(b1).vertex_amount
   va2=body(b2).vertex_amount
   RBD_collision_distance1#=100000
   RBD_collision_distance2#=100000
   RBD.collision.exist1=0
   RBD.collision.exist2=0
   RBD.collision.pt.x=0
   RBD.collision.pt.y=0
   RBD.collision.n.x=0
   RBD.collision.n.y=0
`   RBD.collision.point_amount=0
   for v=0 to va1-1
 
      px#=body_shape(b1,v).x
      py#=body_shape(b1,v).y
      set vector2 RBD_V1,px#,py#
      rotate_vector2(RBD_V1,body(b1).p.w)
      px#=x vector2(RBD_v1)+body(b1).p.x
      py#=y vector2(RBD_v1)+body(b1).p.y
 
      vx#=body_shape(b1,mod((v+1),(va1))).x-body_shape(b1,v).x
      vy#=body_shape(b1,mod((v+1),(va1))).y-body_shape(b1,v).y
      set vector2 RBD_V1,vx#,vy#
      length#=length vector2(RBD_V1)
      rotate_vector2(RBD_V1,body(b1).p.w+90)
      normalize vector2 RBD_V1,RBD_V1
      nx#=x vector2(RBD_V1)
      ny#=y vector2(RBD_V1)
      minv1#=100000
      minv1=0
      maxv1#=-100000
      maxv1=0
      minv2#=100000
      minv2=0
      maxv2#=-100000
      maxv2=0
      for v2=0 to va2-1
         set vector2 RBD_V2,body_shape(b2,v2).x,body_shape(b2,v2).y
         rotate_vector2(RBD_V2,body(b2).p.w)
         set vector2 RBD_V2,x vector2(RBD_V2)+body(b2).p.x-px#,y vector2(RBD_V2)+body(b2).p.y-py#
         v2#=x vector2(RBD_V2)*x vector2(RBD_V1)+y vector2(RBD_V2)*y vector2(RBD_V1)
         if v2#<minv2#
            minv2#=v2#
            minv2=v2
 
            vx#=body_shape(b2,mod((v2+1),(va2))).x-body_shape(b2,v2).x
            vy#=body_shape(b2,mod((v2+1),(va2))).y-body_shape(b2,v2).y
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b2).p.w)
            e1nx#=x vector2(RBD_V6)
            e1ny#=y vector2(RBD_V6)
 
 
            vx#=(body_shape(b2,mod((v2+1),(va2))).x+body_shape(b2,v2).x)/2.0
            vy#=(body_shape(b2,mod((v2+1),(va2))).y+body_shape(b2,v2).y)/2.0
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b2).p.w)
            e1ax#=x vector2(RBD_V6)+body(b2).p.x
            e1ay#=y vector2(RBD_V6)+body(b2).p.y
 
            vx#=body_shape(b2,mod((v2-1),(va2))).x-body_shape(b2,v2).x
            vy#=body_shape(b2,mod((v2-1),(va2))).y-body_shape(b2,v2).y
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b2).p.w)
            e2nx#=x vector2(RBD_V6)
            e2ny#=y vector2(RBD_V6)
 
 
            vx#=(body_shape(b2,mod((v2-1),(va2))).x+body_shape(b2,v2).x)/2.0
            vy#=(body_shape(b2,mod((v2-1),(va2))).y+body_shape(b2,v2).y)/2.0
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b2).p.w)
            e2ax#=x vector2(RBD_V6)+body(b2).p.x
            e2ay#=y vector2(RBD_V6)+body(b2).p.y
 
 
         endif
         if v2#>maxv2#
            maxv2#=v2#
            maxv2=v2
         endif
      next v2
      if minv2#>0
         exitfunction 0
      else
         d#=0-minv2#
         cv=minv2
         if d#>0
            if d#<=RBD_collision_distance1#
               RBD_collision_distance1#=d#
               RBD.collision.edge1=v
               RBD.collision.edge_length1=length#
               RBD.collision.exist1=1
                     `  line screenx(e1ax#),screeny(e1ay#),screenx(e1ax#+e1nx#*20.0),screeny(e1ay#+e1ny#*20.0)
                     `  line screenx(e2ax#),screeny(e2ay#),screenx(e2ax#+e2nx#*20.0),screeny(e2ay#+e2ny#*20.0)
               endif
            endif
      endif
   next v
   for v=0 to va2-1
      px#=body_shape(b2,v).x
      py#=body_shape(b2,v).y
      set vector2 RBD_V1,px#,py#
      rotate_vector2(RBD_V1,body(b2).p.w)
      px#=x vector2(RBD_v1)+body(b2).p.x
      py#=y vector2(RBD_v1)+body(b2).p.y
 
      vx#=body_shape(b2,mod((v+1),(va2))).x-body_shape(b2,v).x
      vy#=body_shape(b2,mod((v+1),(va2))).y-body_shape(b2,v).y
      set vector2 RBD_V1,vx#,vy#
      length#=length vector2(RBD_V1)
      rotate_vector2(RBD_V1,body(b2).p.w+90)
      normalize vector2 RBD_V1,RBD_V1
 
      nx#=x vector2(RBD_V1)
      ny#=y vector2(RBD_V1)
 
      minv1#=100000
      minv1=0
      maxv1#=-100000
      maxv1=0
      minv2#=100000
      minv2=0
      maxv2#=-100000
      maxv2=0
 
      for v1=0 to va1-1
         set vector2 RBD_V2,body_shape(b1,v1).x,body_shape(b1,v1).y
         rotate_vector2(RBD_V2,body(b1).p.w)
         set vector2 RBD_V2,x vector2(RBD_V2)+body(b1).p.x-px#,y vector2(RBD_V2)+body(b1).p.y-py#
         v1#=x vector2(RBD_V2)*x vector2(RBD_V1)+y vector2(RBD_V2)*y vector2(RBD_V1)
         if v1#<minv1#
            minv1#=v1#
            minv1=v1
 
            vx#=body_shape(b1,mod((v1+1),(va1))).x-body_shape(b1,v1).x
            vy#=body_shape(b1,mod((v1+1),(va1))).y-body_shape(b1,v1).y
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b1).p.w)
            e1nx#=x vector2(RBD_V6)
            e1ny#=y vector2(RBD_V6)
 
 
            vx#=(body_shape(b1,mod((v1+1),(va1))).x+body_shape(b1,v1).x)/2.0
            vy#=(body_shape(b1,mod((v1+1),(va1))).y+body_shape(b1,v1).y)/2.0
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b1).p.w)
            e1ax#=x vector2(RBD_V6)+body(b1).p.x
            e1ay#=y vector2(RBD_V6)+body(b1).p.y
 
            vx#=body_shape(b1,mod((v1-1),(va1))).x-body_shape(b1,v1).x
            vy#=body_shape(b1,mod((v1-1),(va1))).y-body_shape(b1,v1).y
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b1).p.w)
            e2nx#=x vector2(RBD_V6)
            e2ny#=y vector2(RBD_V6)
 
 
            vx#=(body_shape(b1,mod((v1-1),(va1))).x+body_shape(b1,v1).x)/2.0
            vy#=(body_shape(b1,mod((v1-1),(va1))).y+body_shape(b1,v1).y)/2.0
            set vector2 RBD_V6,vx#,vy#
            rotate_vector2(RBD_V6,body(b1).p.w)
            e2ax#=x vector2(RBD_V6)+body(b1).p.x
            e2ay#=y vector2(RBD_V6)+body(b1).p.y
 
 
 
         endif
         if v1#>maxv1#
            maxv1#=v1#
            maxv1=v1
         endif
      next v1
      if  minv1#>0
         exitfunction 0
      else
         d#=0-minv1#
         cv=minv1
         if d#>0
            if d#<=RBD_collision_distance2#
               RBD_collision_distance2#=d#
               RBD.collision.edge2=v
               RBD.collision.edge_length2=length#
               RBD.collision.exist2=1
                      ` line screenx(e1ax#),screeny(e1ay#),screenx(e1ax#+e1nx#*20.0),screeny(e1ay#+e1ny#*20.0)
                      ` line screenx(e2ax#),screeny(e2ay#),screenx(e2ax#+e2nx#*20.0),screeny(e2ay#+e2ny#*20.0)
               endif
            endif
      endif
   next v
   point_amount=0
   if RBD.collision.exist1=1
      maxd#=0
      v=RBD.collision.edge1
      vx#=body_shape(b1,mod((v+1),body(b1).vertex_amount)).x-body_shape(b1,v).x
      vy#=body_shape(b1,mod((v+1),body(b1).vertex_amount)).y-body_shape(b1,v).y
      set vector2 RBD_V1,vx#,vy#
      length#=length vector2(RBD_V1)
      normalize vector2 RBD_V1,RBD_V1
      rotate_vector2(RBD_V1,body(b1).p.w)
      tx#=x vector2(RBD_V1)
      ty#=y vector2(RBD_V1)
      rotate_vector2(RBD_V1,-90)
      nx#=x vector2(RBD_V1)
      ny#=y vector2(RBD_V1)
      set vector2 RBD_V5,body_shape(b1,v).x,body_shape(b1,v).y
      rotate_vector2(RBD_V5,body(b1).p.w)
      set vector2 RBD_V5,x vector2(RBD_V5)+body(b1).p.x,y vector2(RBD_V5)+body(b1).p.y
      set vector2 RBD_V1,body_shape(b1,v).x,body_shape(b1,v).y
      rotate_vector2(RBD_V1,body(b1).p.w)
      px#=body(b1).p.x+x vector2(RBD_V1)
      py#=body(b1).p.y+y vector2(RBD_V1)
      set vector2 RBD_V1,body_shape(b1,v).x,body_shape(b1,v).y
      rotate_vector2(RBD_V1,body(b1).p.w)
      set vector2 RBD_V6,x vector2(RBD_V1)+body(b1).p.x-px#,y vector2(RBD_V1)+body(b1).p.y-py#
      v2#=x vector2(RBD_V6)*nx#+y vector2(RBD_V6)*ny#
      for v2=0 to body(b2).vertex_amount-1
         set vector2 RBD_V1,body_shape(b2,v2).x,body_shape(b2,v2).y
         rotate_vector2(RBD_V1,body(b2).p.w)
         set vector2 RBD_V6,x vector2(RBD_V1)+body(b2).p.x-px#,y vector2(RBD_V1)+body(b2).p.y-py#
         v2#=x vector2(RBD_V6)*nx#+y vector2(RBD_V6)*ny#
         if v2#>-0.3
            cx#=x vector2(RBD_V6)*tx#+y vector2(RBD_V6)*ty#
            if cx#>-0.0001 and cx#<RBD.collision.edge_length1+0.0001
               x#=x#+cx#
               d#=v2#
               if d#>maxd#
                  maxd#=d#
               endif
               inc point_amount
            endif
         endif
      next v2
      if point_amount>0
         x#=x#/point_amount
         RBD_collision_distance1#=-maxd#
         RBD.collision.pt.x=RBD.collision.pt.x+x#*tx#+px#
         RBD.collision.pt.y=RBD.collision.pt.y+x#*ty#+py#
         RBD.collision.n.x=-nx#
         RBD.collision.n.y=-ny#
         if RBD.collision.exist2=0
            RBD.collision.distance=RBD_collision_distance1#
         else
            nx1#=-nx#
            ny1#=-ny#
         endif
      else
         RBD.collision.exist1=0
      endif
   endif
   point_amount=0
   if RBD.collision.exist2=1
      maxd#=0
      v=RBD.collision.edge2
      vx#=body_shape(b2,mod((v+1),body(b2).vertex_amount)).x-body_shape(b2,v).x
      vy#=body_shape(b2,mod((v+1),body(b2).vertex_amount)).y-body_shape(b2,v).y
      set vector2 RBD_V1,vx#,vy#
      length#=length vector2(RBD_V1)
      normalize vector2 RBD_V1,RBD_V1
      rotate_vector2(RBD_V1,body(b2).p.w)
      tx#=x vector2(RBD_V1)
      ty#=y vector2(RBD_V1)
      rotate_vector2(RBD_V1,-90)
      nx#=x vector2(RBD_V1)
      ny#=y vector2(RBD_V1)
      set vector2 RBD_V5,body_shape(b2,v).x,body_shape(b2,v).y
      rotate_vector2(RBD_V5,body(b2).p.w)
      set vector2 RBD_V5,x vector2(RBD_V5)+body(b2).p.x,y vector2(RBD_V5)+body(b2).p.y
      set vector2 RBD_V1,body_shape(b2,v).x,body_shape(b2,v).y
      rotate_vector2(RBD_V1,body(b2).p.w)
      px#=body(b2).p.x+x vector2(RBD_V1)
      py#=body(b2).p.y+y vector2(RBD_V1)
      set vector2 RBD_V1,body_shape(b2,v).x,body_shape(b2,v).y
      rotate_vector2(RBD_V1,body(b2).p.w)
      set vector2 RBD_V6,x vector2(RBD_V1)+body(b2).p.x-px#,y vector2(RBD_V1)+body(b2).p.y-py#
      v2#=x vector2(RBD_V6)*nx#+y vector2(RBD_V6)*ny#
      for v2=0 to body(b1).vertex_amount-1
         set vector2 RBD_V1,body_shape(b1,v2).x,body_shape(b1,v2).y
         rotate_vector2(RBD_V1,body(b1).p.w)
         set vector2 RBD_V6,x vector2(RBD_V1)+body(b1).p.x-px#,y vector2(RBD_V1)+body(b1).p.y-py#
         v2#=x vector2(RBD_V6)*nx#+y vector2(RBD_V6)*ny#
         if v2#>-0.3
            cx#=x vector2(RBD_V6)*tx#+y vector2(RBD_V6)*ty#
            if cx#>-0.0001 and cx#<RBD.collision.edge_length2+0.0001
               x#=x#+cx#
               d#=v2#
               if d#>maxd#
                  maxd#=d#
               endif
               inc point_amount
            endif
         endif
      next v2
      if point_amount>0
         x#=x#/point_amount
         RBD_collision_distance2#=-maxd#
         RBD.collision.pt.x=RBD.collision.pt.x+x#*tx#+px#
         RBD.collision.pt.y=RBD.collision.pt.y+x#*ty#+py#
         RBD.collision.n.x=nx#
         RBD.collision.n.y=ny#
         if RBD.collision.exist1=0
            RBD.collision.distance=RBD_collision_distance2#
         else
            nx2#=nx#
            ny2#=ny#
         endif
      else
         RBD.collision.exist2=0
      endif
   endif
   if RBD.collision.exist1 and RBD.collision.exist2
      RBD.collision.pt.x=RBD.collision.pt.x/2.0
      RBD.collision.pt.y=RBD.collision.pt.y/2.0
      if RBD_collision_distance1#<RBD_collision_distance2#
         RBD.collision.distance=RBD_collision_distance1#
         RBD.collision.n.x=nx1#
         RBD.collision.n.y=ny1#
      else
         RBD.collision.distance=RBD_collision_distance2#
         RBD.collision.n.x=nx2#
         RBD.collision.n.y=ny2#
      endif
   endif
  ` line screenx(RBD.collision.pt.x),screeny(RBD.collision.pt.y),screenx(RBD.collision.pt.x+RBD.collision.n.x*20.0),screeny(RBD.collision.pt.y+RBD.collision.n.y*20.0)
   x=screenx(RBD.collision.pt.x)
   y=screeny(RBD.collision.pt.y)
   if debug.collision=1 then box x-3,y-3,x+3,y+3
endfunction 1
 
function screenx(x#)
position object dummy_obj,x#,0,0
x#=object screen x(dummy_obj)
endfunction x#
function screeny(y#)
position object dummy_obj,0,y#,0
y#=object screen y(dummy_obj)
endfunction y#
 
 
function mod(a,b)
if a<0 then a=a+b
RV = int(a / b)
RV = RV * b
RV = a - RV
endfunction RV
 
function RBD_GetBody(obj)
   for b=0 to max_body_amount
      if body(b).exist=1
         if body(b).object=obj
            exitfunction b
         endif
      endif
   next b
endfunction -1
 
function RBD_GetDBPro(body)
   obj=body(body).object
endfunction obj
 
function RBD_MaterialGetDefaultGroupID()
endfunction 0
 
function RBD_MaterialCreateGroupID()
   i=0
   while groupid(i)=1
      inc i
   endwhile
   groupid(i)=1
   for n=0 to max_material_amount
      material(i,n).collidable=1
      material(i,n).elasticity=1.0
   next n
endfunction i
 
function RBD_MaterialSetDefaultCollidable(mat1,mat2,state)
   material(mat1,mat2).collidable=state
endfunction
 
function RBD_MaterialSetDefaultFriction(mat1,mat2,sfriction#,kfriction#)
   material(mat1,mat2).sfriction=sfriction#
   material(mat1,mat2).kfriction=kfriction#
endfunction
 
function RBD_MaterialSetDefaultElasticity(mat1,mat2,elasticity#)
   material(mat1,mat2).elasticity=elasticity#
endfunction
 
function RBD_CalculateMIBoxSolid(mass#,sx#,sy#)
moi#=(1.0/12.0)*mass#*(sx#^2+sy#^2)
endfunction moi#
 
function RBD_CalculateMICircleSolid(mass#,r#)
moi#=1.0/2*mass#*r#^2
endfunction moi#
 
function RBD_BodySetMass(b,mass#,moi#)
   body(b).mass=mass#
   if moi#<>0
      body(b).moi=moi#
   endif
endfunction
 
function RBD_SetStandardGravity(x#,y#)
   RBD.world.standard_gravity.x=x#
   RBD.world.standard_gravity.y=y#
endfunction
 
function RBD_GetStandardGravity()
   set vector2 RBD_V1,RBD.world.standard_gravity.x,RBD.world.standard_gravity.y
endfunction
 
function hsl(H#,S#,L#)
 
   if ( S# = 0 )                       `HSL values = 0 ÷ 1
 
      rR# = L# * 255                      `RGB results = 0 ÷ 255
      rG# = L# * 255
      rB# = L# * 255
 
   else
 
         if ( L# < 0.5 )
            var_2# = L# * ( 1 + S# )
         else
 
            var_2# = ( L# + S# ) - ( S# * L# )
         endif
 
         var_1# = (2 * L#) - var_2#
 
         R = 255.0 * Hue_2_RGB( var_1#, var_2#, H# + ( 1.0 / 3.0 ) )
         G = 255.0 * Hue_2_RGB( var_1#, var_2#, H# )
         B = 255.0 * Hue_2_RGB( var_1#, var_2#, H# - ( 1.0 / 3.0 ) )
 
   endif
color=rgb(r,g,b)
endfunction color
 
Function Hue_2_RGB( v1#, v2#, vH# )
 
   if ( vH# < 0 ) then vH# = vH# + 1
   if ( vH# > 1 ) then vH# = vH# - 1
   if ( ( 6 * vH# ) < 1 ) then res#=( v1# + ( v2# - v1# ) * 6.0 * vH# ): exitfunction ( res# )
   if ( ( 2 * vH# ) < 1 ) then exitfunction ( v2# )
   if ( ( 3 * vH# ) < 2 ) then res#=( v1# + ( v2# - v1# ) * ( ( 2.0 / 3.0 ) - vH# ) * 6.0 ):exitfunction ( res# )
 
Endfunction v1#