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#