`2D Physics
sync on : sync rate 60
set display mode 1024,768,32 : `hide mouse
 
`types
type vec
   x as float
   y as float
   m as float
endtype
type force
   f1 as vec
   f2 as vec
   fb as vec
   fw as vec
   fd as vec
   f as vec
endtype
type tscene
   grav as float
   density as float
   wind as vec
endtype
scene as tscene
type tball
   pos as vec
   acc as vec
   vel as vec
   mom as vec
   ang as float
   frc as force
   mass as float
   weight as float
   size as float
   drag as float
   collision as boolean
   bmdist as float
endtype
type tliquid
   size as integer
   damping as float
   elasticity as float
   vsum as float
   fix as float
   fixed as integer
   hleft as float
   hright as float
endtype
liquid as tliquid
 
`setup scene
scene.grav=0.8
scene.density=0.01
scene.wind.x=0.0
scene.wind.y=0.0
 
`setup water
liquid.size=150
liquid.damping=0.333
liquid.elasticity=2.0
liquid.fixed=1
makeMatrix2D(1,screen width()+100,liquid.size)
dim lheight(liquid.size) as float
dim lacc(liquid.size) as float
dim lvel(liquid.size) as float
dim lfixed(liquid.size) as boolean
   lfixed(liquid.fixed)=1
for x=1 to liquid.size
    lheight(x)=rnd(300)-150
   for t=1 to 6
      lheight(x)=(lheight(x-1)+lheight(x))/2
   next t
next x
 
`create balls
balls=3
dim ball(balls) as tball
for b=1 to balls
   ball(b).pos.x=rnd(screen width())
   ball(b).pos.y=rnd(screen height())
   ball(b).size=rnd(20)+20
   ball(b).mass=rnd(50)+50
   ball(b).weight=ball(b).mass*scene.grav
   ball(b).drag=0.47
next b
 
 
 
`main loop
do
 
`control wind
if upkey() then scene.wind.y=scene.wind.y-1
if downkey() then scene.wind.y=scene.wind.y+1
if leftkey() then scene.wind.x=scene.wind.x-1
if rightkey() then scene.wind.x=scene.wind.x+1
 
`control balls
for b=1 to balls
   ball(b).bmdist=sqrt((mousex()-ball(b).pos.x)^2+(mousey()-ball(b).pos.y)^2)
   ball(b).frc.f1.x=sin(ball(b).ang)*(ball(b).bmdist/6)
   ball(b).frc.f1.y=cos(ball(b).ang)*(ball(b).bmdist/6)
   ball(b).ang=atanfull(mousex()-ball(b).pos.x,mousey()-ball(b).pos.y)
   ball(b).mom.x=ball(b).mass*ball(b).vel.x : ball(b).mom.y=ball(b).mass*ball(b).vel.y
   ball(b).frc.fd.x=-(ball(b).drag/2)*(ball(b).size*2)*scene.density*((ball(b).vel.x^2)*sign(ball(b).vel.x))
   ball(b).frc.fd.y=-(ball(b).drag/2)*(ball(b).size*2)*scene.density*((ball(b).vel.y^2)*sign(ball(b).vel.y))
   ball(b).frc.fw.y=ball(b).weight
   ball(b).frc.fb.x=scene.wind.x : ball(b).frc.fb.y=scene.wind.y
   if ball(b).pos.x<=0 or ball(b).pos.y<=0 or ball(b).pos.x>screen width() or ball(b).pos.y>screen height()
      ball(b).collision=1
   else
      ball(b).collision=0
   endif
   ball(b).frc.f.x=ball(b).frc.f1.x+ball(b).frc.f2.x+ball(b).frc.fb.x+ball(b).frc.fd.x+ball(b).frc.fw.x
   ball(b).frc.f.y=ball(b).frc.f1.y+ball(b).frc.f2.y+ball(b).frc.fb.y+ball(b).frc.fd.y+ball(b).frc.fw.y
   ball(b).acc.x=ball(b).frc.f.x/ball(b).mass
   ball(b).acc.y=ball(b).frc.f.y/ball(b).mass
   ball(b).vel.x=ball(b).vel.x+ball(b).acc.x
   ball(b).vel.y=ball(b).vel.y+ball(b).acc.y
      ball(b).vel.m=sqrt(ball(b).vel.x^2+ball(b).vel.y^2)
   ball(b).pos.x=ball(b).pos.x+ball(b).vel.x
   ball(b).pos.y=ball(b).pos.y+ball(b).vel.y
 
   `draw circles
   ink rgb(255,255,255),0
   circle ball(b).pos.x,ball(b).pos.y,ball(b).size
   box ball(b).pos.x+((sin(ball(b).ang)*ball(b).size)-2),ball(b).pos.y+((cos(ball(b).ang)*ball(b).size)-2),ball(b).pos.x+((sin(ball(b).ang)*ball(b).size)+2),ball(b).pos.y+((cos(ball(b).ang)*ball(b).size)+2)
 
   `draw force vectors
   amp#=1
   ink rgb(255,0,0),0
   if spacekey() and shold=0 then shold=1 : showvec=abs(showvec-1)
   if spacekey()=0 then shold=0
   if showvec=1
   line ball(b).pos.x,ball(b).pos.y,ball(b).pos.x+(ball(b).frc.f1.x*amp#),ball(b).pos.y+(ball(b).frc.f1.y*amp#)
   line ball(b).pos.x,ball(b).pos.y,ball(b).pos.x+(ball(b).frc.f2.x*amp#),ball(b).pos.y+(ball(b).frc.f2.y*amp#)
   line ball(b).pos.x,ball(b).pos.y,ball(b).pos.x+(ball(b).frc.fd.x*amp#),ball(b).pos.y+(ball(b).frc.fd.y*amp#)
   line ball(b).pos.x,ball(b).pos.y,ball(b).pos.x+(ball(b).frc.fw.x*amp#),ball(b).pos.y+(ball(b).frc.fw.y*amp#)
   line ball(b).pos.x,ball(b).pos.y,ball(b).pos.x+(ball(b).frc.fb.x*amp#),ball(b).pos.y+(ball(b).frc.fb.y*amp#)
   ink rgb(0,255,0),0
   line ball(b).pos.x,ball(b).pos.y,ball(b).pos.x+(ball(b).frc.f.x*amp#),ball(b).pos.y+(ball(b).frc.f.y*amp#)
   endif
next b
 
 
`control liquid
ink rgb(0,128,250),0
y#=rnd(300)-150
if lfixed(liquid.fixed)=1
   lheight(liquid.fixed)=y#
endif
for x=2 to liquid.size-1
   if x>1 then liquid.hleft=lheight(x-1)-lheight(x)
   if x<liquid.size then liquid.hright=lheight(x+1)-lheight(x)
   liquid.vsum=liquid.hleft+liquid.hright
   lacc(x)=liquid.vsum*liquid.elasticity
   lvel(x)=lvel(x)+lacc(x)
   lvel(x)=lvel(x)*liquid.damping
   if lfixed(x)=0
      lheight(x)=lheight(x)+lvel(x)
   endif
      setmatrixHeight2D(1,x,lheight(x))
next x
drawMatrix2D(1,-20,screen height()/2)
 
`show stuff
ink rgb(255,255,255),0
text 10,10,"Press Space to toggle Force Vectors"
text 10,30,"Use the Arrow Keys to Change Wind"
text 10,80,"Wind X: "+str$(scene.wind.x)
text 10,110,"Wind Y: "+str$(scene.wind.y)
 
 
sync
cls
loop
 
 
function sign(n as float)
if n>=0 then exitfunction 1
endfunction -1
 
Function MakeMatrix2D(mat,width,Tiles)
   Dim Mat2DTiles(Mat) : Mat2DTiles(Mat)=Tiles
   Dim Mat2DScroll(Mat)
   Dim Mat2DUp(Mat)
   Dim Mat2DW(Mat) : Mat2DW(mat)=width
   Dim Mat2DTileW(Mat) as float : Mat2DTileW(Mat)=Width/Tiles
   Dim Mat2DX(Mat,Tiles) as float
   Dim Mat2DY(Mat,Tiles) as float
   Dim Mat2dL(Mat,Tiles) as boolean
For T=0 to Tiles
   Mat2DX(Mat,T)=T*Mat2DTileW(Mat)
   Mat2DY(Mat,T)=Screen Height()/2
Next T
Endfunction
 
Function DrawMatrix2D(mat,along,up)
Mat2DScroll(Mat)=along
Mat2DUp(Mat)=up
For T=1 to Mat2DTiles(mat)
   Line Mat2DX(Mat,T-1)+along,Mat2DY(Mat,T-1)+up,Mat2DX(Mat,T)+along,Mat2DY(Mat,T)+up
Next T
Line Mat2DX(Mat,0)+along,Mat2DY(Mat,0)+up,Mat2DX(Mat,0)+along,Screen Height()
Line Mat2DX(Mat,Mat2DTiles(Mat))+along,Mat2DY(Mat,Mat2DTiles(Mat))+up,Mat2DX(Mat,Mat2DTiles(Mat))+along,Screen Height()
Endfunction
 
Function RandomizeMatrix2D(mat,value)
For T=0 to Mat2DTiles(mat)
if Mat2DL(mat,t)=0
   Mat2DY(mat,T)=(Screen Height()/2)+Rnd(value)
endif
Next T
Endfunction
 
Function SmoothMatrix2D(mat,amount)
For A=1 to Amount
Dim TH1(Mat2DTiles(mat)-1) : Dim TH2(Mat2DTiles(mat)-1)
For T=1 to Mat2DTiles(mat)-1
if Mat2DL(mat,t)=0
   TH1(T)=Mat2DY(Mat,T-1)
   TH2(T)=Mat2DY(Mat,T+1)
   Mat2DY(Mat,T)=((TH1(T)+TH2(T))/2)
endif
next t
Undim TH1() : Undim TH2()
next A
Endfunction
 
Function SetMatrixHeight2D(mat,x,height)
if Mat2DL(mat,x)=0
Mat2DY(mat,x)=height
endif
Endfunction
 
Function LockTile2D(mat,x)
Mat2DL(mat,x)=1
Endfunction
Function UnlockTile2D(mat,x)
Mat2DL(mat,x)=0
Endfunction
 
Function GetGroundHeight2D(mat,x)
local MT : local Y as float
local YC : local XD
Local Grad as float
For T=1 to Mat2DTiles(Mat)
If X>Mat2DX(Mat,T-1)+Mat2DScroll(Mat) and X<Mat2DX(Mat,T)+Mat2DScroll(Mat)
   on=1
else
   on=0
endif
if on=1
   MT=T : XD=X-(Mat2DX(Mat,MT-1)+Mat2DScroll(Mat))
   TH1=Mat2DY(Mat,MT-1) : TH2=Mat2DY(Mat,MT)
   YC=TH2-TH1
   Grad=YC/Mat2DTileW(Mat)
      Y=int((Grad*XD)+Mat2DY(Mat,MT-1))+Mat2DUp(Mat)
else
   If (X-1)>Mat2DX(Mat,T-1)+Mat2DScroll(Mat) and (X-1)<Mat2DX(Mat,T)+Mat2DScroll(Mat)
      non=1
   else
      non=0
   endif
Endif
if non=1
MT=T : XD=X-(Mat2DX(Mat,MT-1)+Mat2DScroll(Mat))
   TH1=Mat2DY(Mat,MT-1) : TH2=Mat2DY(Mat,MT)
   YC=TH2-TH1
   Grad=YC/Mat2DTileW(Mat)
      Y=(Grad*XD)+Mat2DY(Mat,MT-1)+Mat2DUp(Mat)
   endif
Next T
Endfunction Y
 
Function GetMatrixHeight2D(mat,x)
t=GetTileNumber2D(mat,x)
height=Mat2DY(mat,t)+Mat2DUp(Mat)
Endfunction height
 
Function GetTileNumber2D(mat,x)
For T=1 to Mat2DTiles(Mat)
   If X>Mat2DX(Mat,T-1)+Mat2DScroll(Mat) and X<Mat2DX(Mat,T)+Mat2DScroll(Mat)
      on=1
   else
      on=0
   Endif
   if on=1
      MT=T
   else
      If (X-1)>Mat2DX(Mat,T-1)+Mat2DScroll(Mat) and (X-1)<Mat2DX(Mat,T)+Mat2DScroll(Mat)
         MT=T
      Endif
   Endif
   Next T
Endfunction MT
 
Function GetTileAngle2D(mat,T)
y1=Mat2DY(Mat,T-1)
y2=Mat2DY(Mat,T)
ang#=atanfull(Mat2DTileW(mat),y1-y2)
endfunction ang#
 
Function GetTileNormalX2D(mat,T)
n#=sin(GetTileAngle2D(mat,T))
endfunction n#
Function GetTileNormalY2D(mat,T)
n#=cos(GetTileAngle2D(mat,T))
endfunction n#
 
function DrawMatrixNormals2D(mat)
for t=1 to Mat2DTiles(Mat)
x=Mat2DX(Mat,t)-(Mat2DTileW(Mat)/2)+Mat2DScroll(Mat)+(cos(GetTileAngle2D(mat,T))*10)
   line x,GetGroundHeight2D(Mat,x),x,GetGroundHeight2D(Mat,x)-(sin(GetTileAngle2D(mat,T))*10)
next t
endfunction
 
Function GetTileHardness2D(mat,x)
h=Mat2DL(mat,x)
Endfunction h