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)+16: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