I think this is as streamlined as I'm going to get it!
-=-=-
Been off-and-on working on this for the past few days. Little nips and tucks, and trying my best to keep it under control, but I can't find any more ways to get it any better.
The multiple balls colliding with multiple objects is quite a stress on the language.
Grrr.
More work necessary on the engine, methinks.
// A Boatload of Balls
// by Jayenkai
// Created 2021/8/23
// GotoJSE.com/t7sskpDg.BAS
Symbol 0,"1__0!22990_02.9.0/2?9?0?pp2.9?G0,p.2,9.G,00p?229,G.0p/299G!p@9G/i/bN@i!bbUN/0i.b,UUN?00i,b.U,N.0,ib?U.NN0?b?U?0/b.U.0_0bbUU";
Symbol 1,"1__0!:.0_0:@0/:/z,0?:!z.yy0,::;::;z.y.00:?z?y.0:,;:z;z,y?x:?z?y?x:.z?y!x:.z?y?xx0::z?y!x00::z.y!xx0,:z,y!xx0?zy/xx0/y?x,0_0x.";
Symbol 2,"2__0_0.;!0_0_0?;_;,0_0_;?4!;?0_0?;?44;!44;?0_00;.44;_;44;.0_;.4;_;?4;.0/;.4;_;/4;.0!;,4;!4!;!4;,0?;,4;?44;!44;?4;,0.;;4;?4;_;4;?4;;0,;,4;.4;_;,4;.4;,00;;4;.4;_;?4;.4;;00;;4;.4;?4.;?4;.4;;0;;4;.4;?4;.4;?4;.4;.4;.4;.4;;44;;4;.4;.4;.4;.4;.4;4.;4;.4;.4;.4;.4;.4;4.;4;.4;.4;.4;.4;.4;;44;;4;.4;.4;.4;.4;?4;.4;?4;.4;;0;;4;.4;?4.;?4;.4;;00;;4;.4;_;?4;.4;;00;,4;.4;_;,4;.4;,0,;;4;?4;_;4;?4;;0.;,4;?44;!44;?4;,0?;,4;!4!;!4;,0!;.4;_;/4;.0/;.4;_;?4;.0_;.44;_;44;.0_00;?44;!44;?0_0?;?4!;?0_0_;_;,0_0_0?;!";
Symbol 3,"2__0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0@;;40_0_0@4;.40_0_0@4;.40_0_0@4;.40_0_0@4;.40_0_0@4;.40_0_0@4;;0;;40_0_0!4;;00;;40_0_0!4;;00;,40_0_0.4;,0,;;40_0_0.4;;0.;,40_0_004;,0?;,40_0_4;,0!;.40_0/4;.0/;.40_0?4;.0_;.440_044;.0_00;?440!44;?0_0?;?4!;?0_0_;_;,0_0_0?;!";
Symbol 4,"0__0_40.40.II0?I00I0.I00I0?II0.40.4";
Symbol 5,"2__0_0_0_0_0_0_0_0_0_0_0_0_0AA0_0_0_0,AAH00HH0_0_0/AAH?0_0_0/AAH?0_0,VVO0_0AAH?0_OV.O0_0AAH?0_OV.O0_0AA0HH0_00OV.O0_0AA0_0?OV.O0_0AA0_0?OV.O0_0AA0_0?OVV0VVO0_AA0_0.OVV00VVO0_AA0_0.OVV00V,O0@AA0_0,OV,0,VVO0@AA0_0,OVV0.V,O0/AA0_00OV,0?V,O0!AA0_0OV,0!V.O0?AA0_OV.0/V.O0.AA0@OV.0_V.OO00AA0!OOV.0_00V?OOAA0.OOV?0_0?V?O!V?0_0_V_V,0_0_0?V!";
Symbol 6,"2__0_0_0_0_0_0_0_0_0_0_0_0_0AA0_0_0_0,AA00H,0_0_0/AAH?0_0_0/AAH?0_0,VVO0_0AAH?0_OV.O0_0AAH?0_OV.O0_0AAHH0_0,OV.O0_0AA0_0?OV.O0_0AA0_0?OV.O0_0AA0_0?OVV0VVO0_AA0_0.OVV00VVO0_AA0_0.OVV00V,O0@AA0_0,OV,0,VVO0@AA0_0,OVV0.V,O0/AA0_00OV,0?V,O0!AA0_0OV,0!V.O0?AA0_OV.0/V.O0.AA0@OV.0_V.OO00AA0!OOV.0_00V?OOAA0.OOV?0_0?V?O!V?0_0_V_V,0_0_0?V!";
Symbol 7,"2__0_0_0_0_0_0_0_0_0_0_0_0_0AA0_0_0_0,AA0H,0_0_0@AAH?0_0_0/AAH?0_0,VVO0_0AAH?0_OV.O0_0AAH?0_OV.O0_0AAH0,H0_OV.O0_0AA0_0?OV.O0_0AA0_0?OV.O0_0AA0_0?OVV0VVO0_AA0_0.OVV00VVO0_AA0_0.OVV00V,O0@AA0_0,OV,0,VVO0@AA0_0,OVV0.V,O0/AA0_00OV,0?V,O0!AA0_0OV,0!V.O0?AA0_OV.0/V.O0.AA0@OV.0_V.OO00AA0!OOV.0_00V?OOAA0.OOV?0_0?V?O!V?0_0_V_V,0_0_0?V!";
Symbol 8,"2__0_0_0_0_0_0_0_0_0_0_0_0_0AA0_0_0_0,AAH,0_0_0_AAH?0_0_0/AAH?0_0,VVO0_0AAH?0_OV.O0_0AAH?0_OV.O0_0AA0,HH0_OV.O0_0AA0_0?OV.O0_0AA0_0?OV.O0_0AA0_0?OVV0VVO0_AA0_0.OVV00VVO0_AA0_0.OVV00V,O0@AA0_0,OV,0,VVO0@AA0_0,OVV0.V,O0/AA0_00OV,0?V,O0!AA0_0OV,0!V.O0?AA0_OV.0/V.O0.AA0@OV.0_V.OO00AA0!OOV.0_00V?OOAA0.OOV?0_0?V?O!V?0_0_V_V,0_0_0?V!";
Symbol 9,"2__0_0_0_0_0_0_0_0_0_0_0_0_0AA0_0_0_0,AAHH00H0_0_0/AAH?0_0_0/AAH?0_0,VVO0_0AAH?0_OV.O0_0AAH?0_OV.O0_0AA00HH0_0OV.O0_0AA0_0?OV.O0_0AA0_0?OV.O0_0AA0_0?OVV0VVO0_AA0_0.OVV00VVO0_AA0_0.OVV00V,O0@AA0_0,OV,0,VVO0@AA0_0,OVV0.V,O0/AA0_00OV,0?V,O0!AA0_0OV,0!V.O0?AA0_OV.0/V.O0.AA0@OV.0_V.OO00AA0!OOV.0_00V?OOAA0.OOV?0_0?V?O!V?0_0_V_V,0_0_0?V!";
Symbol 10,"2__0_0@::0_0_0_00:.0_0_0_0:.0_0_0_00::0_0_00::0_0_0_00:.0_0.::0_0.:.0_0,:.0!ppU0.::0!::0?:.0,Up.U0_00:.0?::0.Up.U0_00:.0_00Up.U0_0,::0_0,Up.U0_0_0@Up.U0_0@::0/Upp0ppU0/::0!:.0?Upp00ppU0!:.0?:.0?Upp00p,U0?:.0!::0?Up,0,ppU0!::0_0?Upp0.p,U0_0_00Up,0?p,U0_0_Up,0!p.U0_0/Up.0/p.U0_0?Up.0_p.UU0_0UUp.0_00p?UU0!UUp?0_0?p?U!p?0_0_p_p,0_0_0?p!";
Symbol 11,"1__0_0_0_0_0_0_0_0_0?II0_0?II0_0?I0_0?B,0_0,B0B0BD_D_D_D?0D_D?0,D_D,0?D_D";
Symbol 12,"1__0?V0.V0_0Ve00eV0_0Ve.V0_0Ve.V0_0Ve.V0_0Ve.V0_0Ve.V0_0Ve.V0_0Ve.V0_0Ve.V";
Dim grid(50,10)
Dim pos(50)
Dim ball(10,10)
Graphics 1280,720,1
Border 30,30,80
GameHandler("A Boatload|of|Balls","Calendar")
.StartGame
SeedRnd ThisLevel*7
keydel=120
px=ScreenWidth()/2
px2=ScreenWidth()/2
ptilt=0
GotBalls=3
Sway=0
SwayAim=0
WaterCol=Rand(0,360)
// Floors
FloorCol=Rand(0,360)
For x=0 to 9
pos(x)=x
Next
For x=0 to 9
r=Rand(0,9)
t=pos(x)
pos(x)=pos(r)
pos(r)=t
next
For n=0 to 9
grid(n,0)=1
grid(n,1)=(120+(pos(n)*115))+Rand(-30,30)
grid(n,2)=96+n*52
m=(12-n)*0.1
grid(n,3)=Rnd(120,256)*m
grid(n,4)=Rnd(8,24)
grid(n,5)=0
grid(n,6)=0
m=n+10
grid(m,0)=1
grid(m,1)=grid(n,1)+Rnd(0-grid(n,3),grid(n,3))
grid(m,2)=grid(n,2)-24
Next
// Cups
For n=20 to 29
grid(n,0)=3
if n==20 or n==22 then grid(n,0)=5
if n==24 then grid(n,0)=10
grid(n,1)=(120+(pos(n-20)*115))+Rand(-50,50)
grid(n,2)=ScreenHeight()-96
grid(n,3)=Rnd(64,128)
grid(n,4)=Rnd(16,48)
grid(n,5)=0
grid(n,6)=0
Next
For n=0 to 9
ball(n,0)=0
next
gets=0
Return
.InGame
CLS
ResetDraw
fs=16
butt=0
if GamePad(ButtonA)>0.5 or (MouseDown() and MouseY()<ScreenHeight()/2) then butt=1
For b=0 to 2
if ball(b,0)<1 and butt==1 and keydel<1 and GotBalls>0
PlaySFX("Beeper_4tone_Up")
PlaySFX("Explode_High_5")
keydel=60
ball(b,0)=1
ball(b,1)=px
ball(b,2)=py
ball(b,3)=ptilt*0.5
ball(b,4)=-27
ball(b,5)=Rnd(0,360)
ball(b,8)=0
GotBalls=GotBalls-1
endif
if ball(b,0)>0
ball(b,1)=ball(b,1)+ball(b,3)
ball(b,5)=ball(b,5)+ball(b,3)*4
if ball(b,1)<8 then ball(b,1)=8:ball(b,3)=Abs(ball(b,3))
if ball(b,1)>ScreenWidth()-8 then ball(b,1)=ScreenWidth()-8:ball(b,3)=0-Abs(ball(b,3))
ball(b,2)=ball(b,2)+ball(b,4)
ball(b,3)=ball(b,3)*0.99
ball(b,4)=ball(b,4)+0.5
if ball(b,2)>ScreenHeight()+16 then ball(b,0)=0:PlaySFX("Beeper_Fall")
if ball(b,4)>fs then ball(b,4)=fs
endif
Next
SetThick 4
InkRot FloorCol,0.5,1
For n=0 to 29
if n<10
x1=(grid(n,1)-grid(n,3))+Sin(grid(n,5))*32
x2=(grid(n,1)+grid(n,3))+Sin(grid(n,5))*32
y1=(grid(n,2))+Sin(grid(n,5))*32
y2=(grid(n,2))+Sin(grid(n,5)+180)*32
Line x1,y1,x2,y2
grid(n,5)=SmoothTo(grid(n,5),grid(n,6),grid(n,4))
grid(n,6)=Sway
for b=0 to 2
if ball(b,4)>0 and ball(b,0)>0 and CollideLineToLine(x1,y1,x2,y2,ball(b,1),ball(b,2)-16,ball(b,1),ball(b,2)+8)
y=LineCollidePointY:l=y+3:r=y+3
if CollideLineToLine(x1,y1,x2,y2,ball(b,1)-4,ball(b,2)-16,ball(b,1)-4,ball(b,2)+8) then l=LineCollidePointY
if CollideLineToLine(x1,y1,x2,y2,ball(b,1)+4,ball(b,2)-16,ball(b,1)+4,ball(b,2)+8) then r=LineCollidePointY
ball(b,2)=y-8
if ball(b,4)>1.5 then PlaySFX("Noise_Thud_"+Rand(2,3))
ball(b,4)=0.5
ball(b,3)=ball(b,3)+(r-l)*0.05
endif
next
endif
if n>9 and n<20 and grid(n,0)==1
DrawImg grid(n,1),grid(n,2),2
for b=0 to 2
if ball(b,0)>0
if CollideCircleToCircle(grid(n,1),grid(n,2),32,ball(b,1),ball(b,2),30)
PlaySFX("Beeper_4tone_Up")
PlaySFX("Noise_Splash")
grid(n,0)=0
ball(b,8)=ball(b,8)+1:Gimme(ball(b,8)*20,grid(n,1),grid(n,2))
for e=0 to 15
ThrowParticle grid(n,1),grid(n,2),4,e*22.5,0.2,4,jRand(0,7)
next
endif
endif
next
endif
if n>19
s=grid(n,0)
if grid(n,0)==5 then s=5+(Floor(Mills()/40) Mod 5)
x=grid(n,1):y=grid(n,2)
SetSize 2,2
DrawImg x,y,s
for b=0 to 2
if ball(b,0)>0 and ball(b,4)>0
if CollideCircleToCircle(x,y,48,ball(b,1),ball(b,2),16)
for e=0 to 15
ThrowParticle x,y,4,e*22.5,0.2,4,jRand(0,7)
next
ball(b,8)=ball(b,8)+5:Gimme(ball(b,8)*25,grid(n,1),grid(n,2))
ball(b,0)=0
if grid(n,0)<5 then PlaySFX("Beeper_Fruit_Bonus")
if grid(n,0)==5 then ball(b,8)=ball(b,8)+5:Gimme(ball(b,8)*25,grid(n,1),grid(n,2)-32):GotBalls=GotBalls+1:PlaySFX("Beeper_Powerup")
if grid(n,0)==10 then
PlaySFX("Beeper_Collect")
PlaySFX("Explode_Low_6")
f=0
for p=0 to 10
if ball(p,0)==0 and f<7
f=f+1
ball(p,0)=1
ball(p,1)=x
ball(p,2)=y
ball(p,3)=Rnd(-6,6)
ball(p,4)=0-Rnd(26,28)
ball(p,8)=0
endif
next
endif
grid(n,0)=3
endif
endif
next
endif
Next
ResetDraw
keydel=keydel-1
if keydel<0 then keydel=0
if butt==0 then keydel=0
bz=0
SetSize 0.5
bon=0
For b=0 to 2
if ball(b,0)>0
bon=bon+1
bz=bz+1
SetAlpha 1
SetRot ball(b,5)
DrawImg ball(b,1),ball(b,2),0
SetAlpha 0.3
SetRot 0
DrawImg ball(b,1),ball(b,2),1
endif
Next
ResetDraw
SetThick 64
InkRot WaterCol,0.6,0.5
Line 0,ScreenHeight()+Sway,ScreenWidth(),ScreenHeight()-Sway
Sway=SmoothTo(Sway,SwayAim,32)
spd=(GamePad(ButtonLeft)-GamePad(ButtonRight))*2
if MouseDown() and MouseY()>ScreenHeight()/2 and MouseX()<ScreenWidth()/2 then spd=1.75
if MouseDown() and MouseY()>ScreenHeight()/2 and MouseX()>ScreenWidth()/2 then spd=-1.75
SwayAim=(SwayAim+spd)*0.98
if SwayAim<-32 then SwayAim=-32
if SwayAim>32 then SwayAim=32
ResetDraw
px2=px2-(spd*3)
ptilt=ptilt-spd*0.75
ptilt=Limit(ptilt,-30,30)
px2=Limit(px2,16,ScreenWidth()-16)
px=SmoothTo(px,px2,16)
py=ScreenHeight()-(32+(Sway*((px-(ScreenWidth()*0.5))/(ScreenWidth()*0.5))))
SetRot ptilt
DrawImg px,py,12
SetRot 0-Sway
DrawImg px,py,11
ResetDraw
SetFontSize 32
TextScore ScreenWidth()/2,32,1
For n=1 to GotBalls
if GotBalls>=n then DrawImg ScreenWidth()-((n-0.5)*34),16,1
Next
if Score>=500 and gets==0 then gets=1:PlaySFX("Beeper_Rise",0.5)
if Score>=1000 and gets==1 then gets=2:PlaySFX("Beeper_Rise",1)
if bon<1 and GotBalls<1
if gets==0 then EndGame "Out of Balls"
if gets==1 then EndGame "Beat 500!":WinLevel 1
if gets==2 then EndGame "Beat 1000!":WinLevel 2
endif
Return