﻿ rem -----------------------------------------------------------------------------------------------------------------------------------------
 rem --- Arkanoid Airhead finds Airhead - Bricks are trapped in space warped by someone, help AirHead find them all! :)                    ---
 rem --- A8 Display List technology on the Atari 2600 VCS!!                                                                                ---
 rem --- Download SuperCharger BASIC at RelationalFramework.com and write Atari 2600 games in BASIC with enhanced graphics and sound!      --- 
 rem -----------------------------------------------------------------------------------------------------------------------------------------

 rem 20200623 --- Ball should follow each Display List zone's physics as they are activated... with a few fun twists!
 rem              Player clears board to get to the next level with different colored bricks
 rem              Player only gets 1 life but the board resets with another AirHead ready to go again! 
 rem 20200626 --- bugfix - Inspiring new board tune was not playing! (chiptune index was off)
 rem 20200626 --- bugfix - Catching Power-ups sometimes caused the next power-up to automatically be caught (cleared reg)

 rem Clear board after enough bricks are hit (not all of them, tedious) 
 rem Power-up fun!!! :)
 rem       powerups fall down and are catchable 
 rem             Different power-ups       Scroll/No Scroll 
 rem                                       Laserbeams!      
 rem                                       Catch!           .....  todo ... dropped

 rem ---- Game controls:
 rem ---- BW swtich - expert setting (faster!)

 rem -------------------------------------------------
 rem ---init section, runs once: ---------------------
 rem -------------------------------------------------
grabinit rem 3,2,3
 data Arkanoid 1,4,2,3,2,5,0,4,1,4,1,5,2,2,3,1,5,1,4,3,1,4,5,1,1,2,2,5,0,3,4,1,5,2,3,1,3,1,1,4,1,5,1,2,1,1,4,1,5,2,1,4,5,0,1,1,3,3,4,1,2
 NUSIZ0=%00111111:rem super wide player2, wide missile 
 NUSIZ1=%00110000
 rem for j=0 to 7:player0(j)=pl(j):next j
 loadplayer0(56):player1x=0
 BYTErowoffset=120:COLUP1=$b4:bx=19:by=14:q=3  
 for j=20 to 71:k=j-20:k=Arkanoid(k)+10:for i=k to 14:vwpixel(j,i,on)
 if j<41 then n=j-20: vwpixel(n,i,on):n=52+j:vwpixel(n,i,on): rem handle mirrored section
 next i,j:player0y=88:player0x=94:COLUP1=$74:y=20:COLUBK=$0:AUDV0=0
 for j = 180 to 239:virtualworld(j)=0:next j: rem remove excess info...
 px=10:py=19:vwpixel(px,py,on):j=px+1:vwpixel(j,py,on)
 for j=10 to 14 step 2:for i = 0 to 91:vwpixel(i,j,on):next i,j 
 for j=0 to 7:player0colors(j)=player0colors(j)+17:next j
 COLUBK=$90:f=0:BITIndex=0:r=0:m=0:s=0:z=0:p=0:r=0:scrollvirtualworldtoggle=1:x=0:y=0:n=0
 rem COLUPF=100: gosub colorboard

 rem ---- VARIABLE MAP: ------------------------------------------------
 rem -- t,f             toggle,framecounter  frame 0 loops board via DLI's, frame 1 has it's own load in each gameloop [vertical blank]
 rem -- px,py   bx,by   paddlex, paddley, ballx/bally   (all virtual world tile coordinates)
 rem -- z,q             ball animaition index,ball direction; either DLI zone - 1 UL, 2 UR, 3 DL, 4 DR
 rem -- r               preserves entry point when entering top DLI zone
 rem -- s,u,m           toggle var,ball animiation delay, sprite animation fine increment
 rem -- j,e,i           loop vars
 rem    p,v,l,x,y,o     Arkanoid Powerup, Index and pointer, x,y coordinates,color/type; player driven randomizer index resets @60 d
 rem    n,g,h           Laser power for duration, laser x,y tile coordinates, 

 rem -------------------------------------------------
 rem --- gameloop subroutine, runs every frame:    ---
 rem -------------------------------------------------
 if f=0 then scrollvirtualworldtoggle=30:gosub DLI:scrollvirtualworldtoggle=0:return

 
 rem ------- Frame 1 top blank: Move Ball
 rem if joy0fire=0 then goto skipframe1_top_vertical_blank

 if f=3 and SWCHB|%11110111=247 then goto Frame1TopVerticalBlank:rem --- Frame 3 can just repeat frame1's load for a double speed ball!
 if f<>1 then goto skipframe1_top_vertical_blank

Frame1TopVerticalBlank 
 if MUSICINDEX>235 then return:rem -----------Wait while end tune plays before player is ready to try again, cue RelationalFramework Logo
 NUSIZ0=%00110000
 loadplayer0(z)
 u=u+1
 if u<5 then goto delayanimateball else u=0
 if z=48 then z=0 else z=z+8: fetch next animation frame for ball
delayanimateball
 rem handle reflection - top/bottom [paddle or miss]
 if q=3 and by=19 then q=1
 rem if q=1 and by=15 then q=3 ------------------add top DLI binding when<15
 rem if q=2 and by=15 then q=4
 if q=1 and by=10 then q=3:rem s=1:MUSICINDEX=10 ------------DEACTIVATING OVER THE TOP CAUSES SCROLLING, powerup will do it!
 if q=2 and by=10 then q=4:rem s=1:MUSICINDEX=10

 if q=4 and by=19 then q=2

 if q=4 and bx=19 then q=3:rem fix

 rem side angles
 if by<15 and s>0 and t>0 then gosub upperangles:goto skipangles: rem in upper scroll zone
 if bx=0 and q=1 then q=2:goto skipangles
 if bx=0 and q=3 then q=4:goto skipangles
 if bx=19 and q=2 then q=1:goto skipangles
 if bx=19 and q=4 then q=3
skipangles

 rem if by<15 then m=6
 if m=6 then goto tilebinder else m=m+2: rem incremental Ball movements
 if by<15 and t>0 then goto skipframe1_top_vertical_blank:rem --- no incrementals in upper DLI zone!
 if q=3 then player0y=player0y-2:player0x=player0x-2
 if q=4 then player0y=player0y-2:player0x=player0x+2
 if q=1 then player0y=player0y+2:player0x=player0x-2
 if q=2 then player0y=player0y+2:player0x=player0x+2
 goto skipframe1_top_vertical_blank

tilebinder m=0
 if q=3 then by=by+1:bx=bx-1
 if q=4 then by=by+1:bx=bx+1
 if q=1 then by=by-1:bx=bx-1
 if q=2 then by=by-1:bx=bx+1
 if bx=255 then bx=0

 rem tune this line below so the zone is entered perfectly and locked in, should turn off increments in the zone
 if by>=15 then e=bx+BITIndex:r=BITIndex:goto 100: rem in the bottom DLI zone! Ball follows the top zones physics when it enters it! with some special play physics added to keep it fun! :)
 e=bx+r:rem r preserves index mapping point at entry to new DLI zone! 
 if e>91 then e=91-e: rem debug check fix...
100 rem checkpoint
 if vwpixel(e,by,poll)<>0 then goto flip
 if by=19 and bx>=px and bx <=px+1 then goto flippaddlefix:rem why does above call fail when scrolling, off by 1??? --removing by condition shows y offset was off...hmmm...
 rem =------------------------------------------------- check for missed hit: change ball hues? no, only on clearing board...
 if by=19 then MUSICINDEX=240:score=0:gosub grabinit:return
 
 goto noflip

flip
 rem for paddle hits --------change dir based on where on the paddle the HIT occured:
 
 if by<> 19 then goto flippart2:rem --- flip off of paddle dir: - 1 UL, 2 UR, 3 DL, 4 DR
flippaddlefix
 if bx=px then q=1 else q=2:rem otherwise it's px+1... sending the ball to the right  
 goto noflip

flippart2 
 rem 20200626 bugfix - new board tune was not playing, index was off by 10 @190:
 if score< 64 then score=score+1 else MUSICINDEX=200:gosub colorboard:score=0:gosub grabinit:return:rem next board - add a call to change the board's dynamic color array!
 vwpixel(e,by,flip):rem remember to check the paddle!
 if e<20 then i=e+52:vwpixel(i,by,flip):rem handle mirrored
 if e>71 then i=e-52:vwpixel(i,by,flip):rem handle mirrored
110 AUDC0=4:AUDF0=by:AUDC1=6:AUDF1=by*2:SUSTAINFORFRAMES=8
 rem -- arkanoid powerups happen in any direction:
 if v<58 then v=v+1 else v=0:rem increment Arkanoid power-up 
 if Arkanoid(v)=5 and x=0 then p=0:x=e:y=by:rem queue powerup 
 if q=1 then q=3:goto noflip
 if q=2 then q=4:goto noflip
 rem -- Arkanoid powerups can only happen when the ball is comming down and hits something:-----------------------------------------
 if q=3 then q=1
 if q=4 then q=2
 rem if Arkanoid(v)=5 and x=0 then x=e:y=by:rem queue powerup 
noflip
 vwpixel(e,by,bindplayer0)

skipframe1_top_vertical_blank

 if f<>2 then goto skipframe2_top_vertical_blank: rem  --------------------------------------------FRAME II (power-ups!)
 rem 20200624 debug deactivng  ----- 
 rem if MUSICINDEX=5 then s=0:rem scrolling deactivated if active
 rem if joy0fire=1 then s=1-s:toggle with the button to test/deactivate

 rem --- check for akanoid item
 if x=0 then goto skipframe2_top_vertical_blank
 
 if p=0 then v=v+1:o=Arkanoid(v):p=o*32:p=p+64:l=p+32:COLUP1=powerupcolors(o):vwpixel(x,y,bindplayer1) else p=p+8
 if p=l then p=p-32:rem repeat 4 frames of animation on power-ups!
 loadplayer1(p):rem 2020626 powerup was triggering automatic catch of next powerup - clear reg before hand...bricks tripped it up ;)
 if player1y>20 then CXCLR=0:rem check impact of fix:...good!
 if player1y<16 then x=0:player1y=0:player1x=0:p=0:x=0:y=0 else goto notcaught:rem -- note, item won't be visible on the paddle and vanishes, only above it unless y=20... and -1 for the compare
 rem use collsion to catch power-ups:
 if CXP1FB >=126 then CXCLR=0:SUSTAINFORFRAMES=32:AUDC0=1:AUDF0=11:AUDC1=1:AUDF1=7 else return:rem ----activate powerup just caught! TODO
 rem --- now what powerup should be assigned?

 rem if o=0 or o=2 then s=1-s:rem green and blue S powerups both toggle scrolling on and off ---------------
 rem s=1-s:rem catching ANY powerup always toggles scrolling on/off :)
 if o<>0 and o<>2 then goto checklaser 
 if s=0 then s=255 else s=0
checklaser
 if o=1 then n=255:rem COLUBK=0:rem  catching laser... n=laser power-up duration
 return:rem --- done assigning powerups

notcaught 
 
 player1y=player1y-4

skipframe2_top_vertical_blank

 data powerupcolors $cc,$4a,$9e,$5e,$fe,$7e,$b4,$f0
 rem           green,yellow de replaced with 4a pink,cyan,light purple,fe offyellow,violet,dark green

 return:rem -------------------------------------------------------------------------------functions:
upperangles:rem  1 UL, 2 UR, 3 DL, 4 DR
 e=bx+r
 if e=0 and q=1 then q=2:goto skipupperangles
 if e=0 and q=3 then q=4:goto skipupperangles
 if e=91 and q=4 then q=3:goto skipupperangles
 if e=91 and q=2 then q=1
skipupperangles
 return

colorboard rem ---and paddle!
 for j=0 to 9:rowcolors(j)=rowcolors(j)+8:next j:return: rem -------------------------------------------color board routine
 rem --revised from 16 to 8 for 32 boards, intensity values should also flip (noticeably a different board!)

 rem -------------------------------------------------
 rem ---gameloop2 subroutine, runs every frame:   ---
 rem -------------------------------------------------
 if f>3 then f=0 else f=f+1:rem -------framecounter
 
 rem loop the board in the TOP section of the screen via simple Display Lists:
 if f=0 then scrollvirtualworldtoggle=3:gosub DLI:scrollvirtualworldtoggle=0:return


 rem ------- Frame 1 bottom blank: move paddle
 if f=3 and SWCHB|%11110111=247 then goto Frame1BottomVerticalBlank:rem --- Frame 3 can just repeat frame1's load for a double speed scroll!
 if f<>1 then goto skipframe1_bottom_vertical_blank
Frame1BottomVerticalBlank
 rem s=1:rem debug continuous scrolling
 if s>0 then s=s-1:t=1-t else t=0:rem ----toggle or not, driven by s (scroll duration) being active

 BITIndex=BITIndex+t
 if BITIndex>=71 then BITIndex=0
 
 e=px+BITIndex: rem debug scrollvirtualworldtoggle=1
 if joy0right=1 then vwpixel(e,py,flip):px=px+1:e=e+2:vwpixel(e,py,on):return
 if joy0left=1 then e=e+1:vwpixel(e,py,flip):px=px-1:e=e-2:vwpixel(e,py,on):return


skipframe1_bottom_vertical_blank 


 if f<>2 then goto skipframe2_bottom_vertial_blank

 rem -- launch missiles? -----------------------------------------------------                   PLAY LASER SONG for Launch Fx
 if n>0 then n=n-1 else missile0y=0:missile1y=0:missile1x=0:missile0x=0:return
 if joy0fire=1 and h=0 then g=px+1:h=19:MUSICINDEX=170:rem AUDC1=3:AUDF1=3:SUSTAINFORFRAMES=5
NoLaunchWindow  
 if h=0 then g=0:missile1x=0:missile1y=0:missile0x=0:missile0y=0:return
  
 e=BITIndex+g
 w=1-w: rem toggle delay!
 if h=19 then vwpixel(e,h,bindmissile1) 
 if w=1 then h=h-1:vwpixel(e,h,bindmissile1) else missile1y=missile1y+4
 missile0x=missile1x:missile0y=missile1y-2

 if h<16 and vwpixel(e,h,poll)<>0 then vwpixel(e,h,flip):score=score+1:h=0:AUDC0=4:AUDF0=h:AUDC1=6:AUDF1=h*2:SUSTAINFORFRAMES=8:goto NoLaunchWindow  
 if h=9 then h=0:goto NoLaunchWindow
skipframe2_bottom_vertial_blank


 rem byterowoffset is 120 for 1st DL
 rem AUDC0=4:AUDF0=h:AUDC1=6:AUDF1=h*2:SUSTAINFORFRAMES=8


 rem $b6 instead of 120?

rowcolors 36,52,68,76,100,76,68,52,182,40
player0colors $4e,$4c,$4a,$48,$46,$44,$42,$40
virtualworld
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................
............................................................................................


sprites
0
..XXXX..
.XXXXXX.
XXX..XXX
XxXXxXXX
XX..XXXX
XXXXX.XX
.....XX.
..XXXX..
8
..XXXX..
.XXXXXX.
X..XXXXX
XxXXxXXX
..XXXXXX
XXX.XXXX
...XXXX.
..XXXX..
16
..XXXX..
.XXXXXX.
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
.XXXXXX.
..XXXX..
24
..XXXX..
.XXXXXX.
XXXXX..X
XXXXXXXX
XXXXXX..
XXXXX.xX
.XxxX...
..XXXX..
32
..XXXX..
.XXXXXX.
XXXX..XX
XXXXXXXX
XXXXX..X
XXX.XXxX
.Xxx....
..XXXX..
40
..XXXX..
.XXXXXX.
X..XX..X
XXXXXXXX
XXX..XXX
X.XXXX.X
.X....X.
..XXXX..
48
..XXXX..
.XXXXXX.
X..XX..X
XXXXXXXX
XXX..XXX
X.XXXX.X
.X....X.
..XXXX..
56
.xx..xxx
x...x..x
xxx.x..x
..x.xx.x
xx...xx.
...x...x
...x....
...xxxxx
64
.xxxxxx.
Xx....xx
X.xxxxxx
XX...Xxx
XXXxx.XX
x.....XX
XXxxxxxx
.xxxxxx.
72
..xxxxx.
Xx....xx
Xxxxx.xx
X.....xx
XXXxxxXX
xxxxxxXX
XXxxxxxx
.xxxxxx.
80
.xxxxxx.
Xxxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
.xxxxxx.
88
.xxxxxx.
Xxxxxxxx
Xxxxxxxx
XXxxxXxx
Xx....XX
x.xxxxXX
XX...xxx
.xxxx.x.
96
.xxxxxx.
Xx..xxxx
XX..xxxx
XX..xxxx
XX..xxxx
XX.....x
XXxxxxxx
.xxxxxx.
104
.xxxxxx.
Xxxxxxxx
XXxxxxxx
XXxxxxxx
XX..xxxx
XX..xxxx
XX..xxxx
.x..xxx.
112
.xxxxxx.
Xxxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
.xxxxxx.
120
.x..xxx.
Xx..xxxx
XX.....x
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
.xxxxxx.
128
.xxxxxx.
Xx....xx
X.xxxxxx
XX...Xxx
XXXxx.XX
x.....XX
XXxxxxxx
.xxxxxx.
134
..xxxxx.
Xx....xx
Xxxxx.xx
X.....xx
XXXxxxXX
xxxxxxXX
XXxxxxxx
.xxxxxx.
140
.xxxxxx.
Xxxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
XXxxxxxx
.xxxxxx.
152
.xxxxxx.
Xxxxxxxx
Xxxxxxxx
XXxxxXxx
Xx....XX
x.xxxxXX
XX...xxx
.xxxx.x.




chiptunes
0,0,0,0,50
4,15,4,15,2
4,19,4,19,4
4,17,4,17,4
4,15,4,15,4
4,15,4,15,4
4,15,4,15,8
14,10,14,10,16
14,6,14,6,8
4,15,4,15,2
4,19,4,19,4
4,17,4,17,4
60:
14,10,14,10,16
4,15,4,15,2
4,19,4,19,4
4,17,4,17,4
14,6,14,6,8
4,15,4,15,2
4,19,4,19,4
4,17,4,17,4
14,10,14,10,16
12,9,12,9,8
12,8,12,8,8
4,15,4,15,2
4,19,4,19,4
4,17,4,17,4
12,7,12,9,8
12,9,12,9,8
12,8,12,8,8
12,7,12,9,8
4,15,4,15,2
4,19,4,19,4
11,7,11,9,16
4,17,4,17,0
170:
4,29,4,14,4
4,26,4,14,4
4,23,4,14,4
4,5,4,5,4
4,5,4,4,4
0,0,0,0,0
200:
4,9,14,5,16
4,8,14,5,16
4,7,14,5,16
4,5,14,5,48
0,0,0,0,0
225:
12,9,12,9,8
12,8,12,8,8
12,7,12,9,8
240:
14,20,14,24,15
14,22,14,27,15
14,24,14,30,45
0,0,0,0,0

