$options +optimize ' degrees to radians coefficient D2R=0.3927 'use graphics 8 to clear out RAM and switch to graphics 1 for characters GR.8:GR.1 'make a display list DIM A$(96):A$="\70\70\70\46\60\BF\00\00\00\00\00\00\56\80\BD\70\56\A8\BD\70\56\D0\BD\70\56\F8\BD\70\56\20\BE\70\56\48\BE\70\56\70\BE\70\56\98\BE\70\70\70\70\70\70\70\41\50\A0" A=ADR(A$) MOVE A,$A050,53 DL=$A050 DPOKE 560,DL 'copy the Asteroids spaceships A$="\04\04\0E\0E\1F\01\03\07\0F\03\01\06\1E\0C\04\01\3E\1C\18\00\20\38\3F\38\20\18\1C\3E\01\00\04\0C\1E\06\01\03\0F\07\03\01\1F\0E\0E\04\04\0C\0F\0E\0C\08\04\06\0F\0C\10\06\0E\1F\20\00\01\07\3F\07\01\20\1F\0E\06\00\10\0C\0F\06\04\08\0C\0E\0F\0C" PM=$AC00 MOVE A,PM,80 POKE 54279,PM/256:REM Tell ANTIC where PM RAM is POKE 559,46:REM Enable PM DMA with 2-line res POKE 53277,3:REM Enable PM display POKE 704,15 'copy the space invaders characters into the a new character set CHSET=$A200 SCRN=$BD80 SCR2=SCRN+2 MOVE $E000,CHSET,$200:POKE 756,$A2 MOVE CHSET,CHSET+$200,$600 A$="\00\00\0F\0F\07\04\06\03\00\00\F0\F0\E0\20\30\18\30\0F\03\03\03\03\04\00\30\C0\00\00\00\00\80\00\06\02\01\01\01\06\04\00\10\30\C0\40\C0\20\30\00\00\0C\03\06\05\04\00\00\00\30\C0\60\A0\20\00\00\20\10\08\04\13\0D\03\04\04\08\10\20\C0\B0\C8\20\01\03\07\0C\1F\18\18\18\80\C0\E0\F0\F8\C0\C0\C0" MOVE A,CHSET+$108,96 A$="\00\01\0F\1F\07\04\06\06\00\80\F0\F8\E0\20\30\30\30\0C\03\03\03\03\04\08\30\D0\00\00\00\00\C0\00\03\01\01\01\07\04\00\00\00\10\F0\40\C0\40\60\00\00\0E\01\06\05\08\00\00\00\70\C0\60\A0\10\00\00\10\08\04\03\1D\03\04\08\08\10\20\C0\B8\C0\20\10\00\03\07\0E\1F\1B\18\00\00\C0\E0\70\F8\D8\C0\00" MOVE A,CHSET+$308,96 A$="\02\01\2F\1F\27\04\06\0C\40\80\F4\F8\E4\20\30\60\40\30\0F\03\03\04\08\10\00\30\D0\10\00\C0\00\00\01\01\0B\0E\03\01\03\00\80\00\80\E0\A0\00\00\00\08\06\01\06\05\08\10\00\10\60\80\60\A0\10\08\00\08\04\03\0D\13\04\08\10\10\20\C8\B0\C0\20\10\08\00\00\07\0F\1F\1B\03\00\00\00\E0\30\F8\D8\18\00" MOVE A,CHSET+$508,96 A$="\06\21\2F\1F\27\24\0C\18\60\84\F4\F8\E4\24\60\C0\00\00\3F\03\05\08\10\20\00\00\F0\10\10\E0\00\00\00\08\0F\02\03\02\06\00\C0\80\80\80\E0\40\00\00\0C\02\01\06\05\08\10\20\30\40\80\60\A0\10\08\04\04\03\0D\33\04\08\10\20\20\CC\B0\C0\20\10\08\04\00\00\07\0F\1F\03\03\03\00\00\E0\90\F8\18\18\18" MOVE A,CHSET+$708,96 FOR ROW=0TO5 FOR COL=0TO7 DP.SCR2+40*(ROW+2*(ROW>2))+COL*2,(2*RAND(6)+$21+RAND(4)*$40)*$101+$100 N. COL N. ROW NS=ROW*COL 'MIN X=48 $30 'MAX X=200 $C8 'MIN Y=16 $10 'MAX Y=100 $64 'make a look up table for direction sines and cosines DIM TRIGTABLE(1,15) FOR I=0TO15:TRIGTABLE(0,I)=SIN(D2R*I):TRIGTABLE(1,I)=COS(D2R*I):N.I REM ARMADA POSITION COARSE AND FIND, DIRECTION, OLD DIRECTION:APC=0:APF=0:AD=0:ADD=0 REM ARMADA VERTICAL AND DIRECTION: YA=0:YD=0 REM FRAME NUMBER AND DIRECTION: FP=0:FD=0 'ship position X=124:Y=52 'number of lives NL=3 'clear screen and print score and lives ?CHR$(125);SC,NL 'CLS:?SC,NL ' game loop REP. 'clear the collision register POKE 53278,1 ' read the fire button T0=T:T=STRIG(0) ' read the joystick S0=S:S=STICK(0) LR=(S&4=4)-(S&8=8):UP=S&1=0:DN=(S0&2=2)&(S&2=0) F=T0&(T=0) 'rotate the ship ANGLE=(ANGLE + 16 + LR + 8*DN) MOD 16 'thrust the ship IF UP SOUND 0,99,2,15 VANG=ANGLE 'V=V+VA-CD*V VX=VX+0.2*TRIGTABLE(0,VANG) VY=VY+0.2*TRIGTABLE(1,VANG) ENDIF IF (VX<>0)!(VY<>0) 'drag VX=VX-.02*VX VY=VY-.02*VY 'position update X=(X+VX -48 + 152) MOD 152 + 48 Y=(Y-VY -21 + 84) MOD 84 + 21 MOVE PM+$200,PM+$201,127 ENDIF 'update the player MOVE PM+ANGLE*5,PM+$200+(Y),5 'fire a missile IF F&(FC=0) FC=21:MA=ANGLE:MX=X+4+3*TRIGTABLE(0,MA):MY=Y+3-3*TRIGTABLE(1,MA) ENDIF 'animate missile IF FC SOUND 0,99-FC,10,FC DIV 2 FC=FC-1 'update missile location MX=(MX+2*TRIGTABLE(0,MA) -48 + 152) MOD 152 + 48 POKE 53252,MX POKE PM+$180+(MY),0 MY=(MY-2*TRIGTABLE(1,MA) -21 + 84) MOD 84 + 21 POKE PM+$180+(MY),FC>0 ENDIF 'move player horizontally POKE 53248,(X) 'vsync PAUSE1 'collision registers P0PF=PEEK(53252):M0PF=PEEK(53248) 'missile hit IF M0PF SOUND 0,20,0,15 MROW=(MY-21-3.5*YA)/8 MCOL=(MX-48-APF)/16 'clear invader DP.SCR2+40*TRUNC(MROW)+2*TRUNC(MCOL),0 'clear missile state FC=0 'decrement invader counter NS=NS-1 'increase score SC=SC+4 'update score ?CHR$(125);SC,NL 'CLS:?SC,NL 'clear missile POKE PM+$180+(MY),0 'if no more invaders, exit loop IF NS=0:EXIT:ENDIF ENDIF 'player hit IF P0PF SOUND 0,250,10,15 'lose a life NL=NL-1 'update scoreboard ?CHR$(125);SC,NL 'clear missile IF FC:FC=0: POKE PM+$180+(MY),0:END. 'start a new ship Y=50+YA*4 VX=0:VY=0 MOVE PM+$200,PM+$201,127:PAUSE 15 ENDIF 'rotate invader character sets FP=FP+2*((FD=0)-FD) FD=(FD&(FP>0))!(FP=6) 'FP FD '0 0 '2 0 '4 0 '6 1 '4 1 '2 1 '0 0 --- and so forth POKE 756,$A2+FP 'coarse and fine horizontal scrolling ADD=AD IF AD 'decrement fine counter APF=APF-1 'if roll counter, then coarse move IF APF=-1 M.SCR2,SCRN,358 APF=15 APC=APC-1 ENDIF 'update fine scroll register POKE $D404,APF 'switch directions if need to AD=(APC>0)!(APF>0) ELSE 'increment fine scroll counter APF=APF+1 'if roll counter, then coarse move IF APF=16:-M.SCRN,SCR2,358: APF=0: APC=APC+1: ENDIF 'update fine scroll register POKE $D404,APF 'switch directions if need to AD=(APC=1)&(APF=15) ENDIF 'make bump sound at edge and shift display list for vertical scroll IF AD-ADD SOUND 0,200-AD*30,10,15 'move blank screen parts around POKE DL+47+YA,$70*(YD=1) POKE DL+6+YA,$70*(YD=0) 'update Y position of armada YA=YA-YD+(YD=0) 'change direction at top or bottom YD=(YD&(YA>0))!(YA=5) ENDIF 'turn off beeps SOUND: rem 0,0,0,0 'end game when out of lives U.NL=0