10 REM Vader's Last Stand 20 REM By Jason H. Moore, Ph.D. 30 REM December 21, 2019 40 REM A mini-game programmed in BASIC XE 50 REM to illustrate and teach Atari graphics. 60 REM For educational and instructional purposes only. 70 REM This version has verbose comments. 100 REM *************************************** 101 REM *** EXECUTE INITIALIZATION ROUTINES *** 102 REM *************************************** 110 FAST:REM Precompiles the line numbers for speed 120 POKE 77,0:REM Turn off screen saver 130 GOSUB 4000:REM Setup graphics & title screen 140 GOSUB 5000:REM Move & redefine character set 150 GOSUB 6000:REM Set up game variables 160 GOSUB 7000:REM Draw playfield 170 GOSUB 8000:REM Setup PM graphics 500 REM ***************** 501 REM *** MAIN LOOP *** 502 REM ***************** 510 REM CHECK JOYSTICK, MOVE PLAYER & MISSILES 520 GOSUB 600:REM Update player & missile movement 530 GOSUB 700:REM Update missiles an difficulty 540 GOTO 520:REM Loop until game over 550 END:REM Never actually get here :) 600 REM PLAYER & MISSILE MOVEMENT 610 P0VS=VSTICK(0)*PSPEED:REM Read joystick (up/down) 620 P0HS=HSTICK(0)*PSPEED:REM Read joystick (left/right) 630 P0X=P0X+P0HS:REM Increment horizontal position 640 PMMOVE 0,P0X;P0VS:REM Move player 0 650 PMMOVE 6,M2X:REM Move missile 2 660 PMMOVE 7,M3X:REM Move missile 3 670 RETURN:REM Back to main loop 700 REM MISSILE MOVEMENT CALCULATIONS AND DIFFICULTY 710 IF MNEW=0 THEN GOTO 1600:REM New missiles needed? 720 PMCLR 4:REM Clear missiles 730 M2Y=INT(RND(1)*140+50):REM Random Y position 740 M3Y=INT(RND(1)*140+50):REM Random Y position 750 M2SIDE=RND(1):REM Random side 760 M3SIDE=RND(1):REM Random side 770 M2X=(M2SIDE<=0.5)*30+(M2SIDE>0.5)*220:REM Starting X position 780 M3X=(M3SIDE<=0.5)*30+(M3SIDE>0.5)*220:REM Starting X position 790 MISSILE 2,M2Y,4:MISSILE 3,M3Y,4:REM Draw missiles 2 & 3 800 SOUND 0,225,6,255:SOUND 0,150,6,255:REM Blip sound for missile fire 810 SOUND 0,75,6,255:SOUND 0,0,0,0 1000 REM INCREASE DIFFICULTY AS SCORE INCREASES 1010 SCORE=SCORE+1:REM Increment score 1020 POKE 87,1:REM Indicate text for GR1 1030 POSITION 6,0:PRINT #6;SCORE:REM Print the score at top 1040 MNEW=0:REM Missiles no longer new 1050 IF SCORE>5 THEN GOTO 1100:REM Speed=2 if score<6 1060 MSPEED=2:REM Set Speed=2 1070 GOTO 1600:REM Skip next difficulty checks 1100 IF SCORE>10 THEN GOTO 1200:REM Speed=3 if score>5 & <11 1110 MSPEED=3:REM Set Speed=3 1120 GOTO 1600:REM Skip next difficulty checks 1200 IF SCORE>15 THEN GOTO 1300:REM Speed=4 if score>10 & <16 1210 MSPEED=4:REM Set Speed=4 1220 POKE 87,2:REM Indicate text for GR2 1230 POSITION 10,7:PRINT #6; "*":REM Print a new mine 1240 GOTO 1600:REM Skip next difficulty checks 1300 IF SCORE>20 THEN GOTO 1400:REM Speed=4 if score>16 & <21 1310 MSPEED=4:REM Set Speed=4 1320 POKE 87,2:REM Indicate text for GR2 1330 POSITION 6,8:PRINT #6; "*":REM Print a new mine 1340 GOTO 1600:REM Skip next difficulty checks 1400 IF SCORE>30 THEN GOTO 1500:REM Speed=5 if score>20 & <31 1410 MSPEED=5:REM Set Speed=5 1420 POKE 87,2:REM Indicate text for GR2 1430 POSITION 8,3:PRINT #6; "*":REM Print a new mine 1440 GOTO 1600:REM Skip next difficulty checks 1500 MSPEED=6:REM Speed=6 if score>30 1510 POKE 87,2:REM Indicate text for GR2 1520 POSITION 12,5:PRINT #6; "*":REM Print a new mine 1600 REM SET NEW MISSILE X POSITIONS 1610 M2X=M2X+MSPEED*((M2SIDE<=0.5)-(M2SIDE>0.5)):REM New missile 2 X pos 1620 M3X=M3X+MSPEED*((M3SIDE<=0.5)-(M3SIDE>0.5)):REM New missile 3 X pos 1630 MNEW=((M2X<30)+(M2X>220)):REM New missiles needed? 1700 REM CHECK FOR COLLISIONS 1710 IF BUMP(6,0)=1 THEN GOTO 3000:REM Did missile 2 hit player 0? 1720 IF BUMP(7,0)=1 THEN GOTO 3000:REM Did missile 3 hit player 0? 1730 IF BUMP(0,8)=1 THEN GOTO 3000:REM Did player 0 hit playfield? 1740 RETURN:REM No collision, return to main loop 3000 REM COLLISION, END THE GAME 3010 PMCLR 4:REM Clear missile memory 3020 FOR I=1 TO 15:REM Explosion sounds loop 3030 SOUND 0,250,4,15/I+5:REM Explosion sounds 3040 POKE 704,64+I:REM Change color of player 0 from red to white 3050 FOR J=1 TO 100:REM Small delay so explosion lasts longer 3060 NEXT J:REM Increment delay loop 3070 NEXT I:REM Increment sound loop 3080 PMCLR 0:REM Clear the player memory 3090 SOUND 0,0,0,0:REM End the explosion sound 3100 FOR I=1 to 1000:REM Delay loop at end of explosion 3110 NEXT I:REM Increment delay loop 3120 PRINT #6;CHR$(125):REM Clear the screen 3130 SETCOLOR 0,4,10:REM Set text color to red 3140 POKE 87,2:REM Indicate text for GR2 3150 POSITION 2,4 3160 PRINT #6;"FINAL SCORE " 3170 POSITION 14,4 3180 PRINT #6;SCORE 3190 POSITION 2,6 3200 REM PEEK TO SEE IF START BUTTON PRESSED 3210 PRINT #6;"PRESS START" 3220 IF PEEK(53279)=6 THEN RUN 3230 GOTO 3220 4000 REM ************************************** 4001 REM *** SET UP GRAPHICS & TITLE SCREEN *** 4002 REM ************************************** 4010 GRAPHICS 2+16:POKE 752,1:REM Set GR2 and clear the cursor 4020 DL=PEEK(560)+PEEK(561)*256+4:REM Get address for display list 4030 POKE DL-1,70:REM Modify DL for one line of GR1 4040 SETCOLOR 0,12,8:REM Green text 4050 SETCOLOR 2,0,0:REM Black background 4100 POKE 87,2:REM Indicate GR2 text 4110 POSITION 2,2:PRINT #6; " VADER'S" 4120 POSITION 2,3:PRINT #6; " LAST STAND" 4130 POSITION 2,5:PRINT #6; " BY" 4140 POSITION 2,6:PRINT #6; " JASON H. MOORE" 4150 POSITION 2,9:PRINT #6; " GET READY!" 4200 RETURN:REM Return to initializations 5000 REM ************************************* 5001 REM *** MOVE & REDEFINE CHARACTER SET *** 5002 REM ************************************* 5010 MEMTOP=PEEK(106):REM Find the top of memory 5020 CHADDR=(MEMTOP-8)*256:REM Set character set address back 8 pages 5030 CHROM=PEEK(756)*256:REM Find address of character ROM 5040 MOVE CHROM,CHADDR,512:REM Move character set from ROM to RAM 5100 REM REDEFINE CHARS # (3) TO ) (9) 5110 REM THEN + (11) to / (15) AND : (26) to = (29) 5120 REM SKIPPING * AND NUMBERS SO WE CAN USE THEM 5130 CHRAM=CHADDR+24:REM Start with # 5140 FOR I=1 to 7:REM Loop to redefine 7 characters 5150 FOR ADDR=CHRAM TO CHRAM+7:REM Loop to redefine one character 5160 READ DAT:POKE ADDR,DAT:REM Read new char data & put in memory 5170 NEXT ADDR:REM Inner loop for single character 5180 CHRAM=CHRAM+8:REM Move ahead 8 bytes in RAM for next char 5190 NEXT I:REM Outer loop for the 7 characters 5200 CHRAM=CHRAM+8:REM Start with +, skip * 5210 FOR I=1 to 5 5220 FOR ADDR=CHRAM TO CHRAM+7 5230 READ DAT:POKE ADDR,DAT 5240 NEXT ADDR 5250 CHRAM=CHRAM+8 5260 NEXT I 5300 CHRAM=CHRAM+80:REM Now do : to @ 5310 FOR I=1 to 7 5320 FOR ADDR=CHRAM TO CHRAM+7 5330 READ DAT:POKE ADDR,DAT 5340 NEXT ADDR 5350 CHRAM=CHRAM+8 5360 NEXT I 5400 CHRAM=CHRAM+208:REM Now do [ to _ 5410 FOR I=1 to 5 5420 FOR ADDR=CHRAM TO CHRAM+7 5430 READ DAT:POKE ADDR,DAT 5440 NEXT ADDR 5450 CHRAM=CHRAM+8 5460 NEXT I 5500 RETURN:REM Return to initializations 6000 REM **************************** 6001 REM *** SETUP GAME VARIABLES *** 6002 REM **************************** 6010 P0X=120:P0Y=120:REM Initial player 0 position 6030 PSPEED=2:MSPEED=2:REM Initial player & missile speed 6040 MNEW=1:REM Indicate new missiles required 6050 SCORE=0:REM Variable to hold the score 6100 RETURN:REM Return to initializations 7000 REM ************************** 7001 REM *** DRAW THE PLAYFIELD *** 7002 REM ************************** 7010 PRINT #6;CHR$(125):REM Clear the screen 7020 POKE 756,CHADDR/256:REM Tell ANTIC where the character set is 7030 SETCOLOR 0,0,8:REM Playfield color grey 7040 POKE 87,1:REM Indicate text for GR1 7050 POSITION 0,0:REM Position the score at top left 7060 PRINT #6; "SCORE 0":REM Print the score 7100 REM Draw Death Star 7110 POKE 87,2:REM Indicate text for GR2 7120 POSITION 3,2:PRINT #6;"#',:":REM Draw top of death star 7130 POSITION 3,3:PRINT #6;"$(-;":REM Draw middle of death star 7140 POSITION 3,4:PRINT #6;"%).<":REM Draw middle of death star 7150 POSITION 3,5:PRINT #6;"&+/=":REM Draw bottom of death star 7200 REM Draw Mines 7210 POSITION 1,2:PRINT #6; "*":REM Position & draw a mine 7220 POSITION 12,2:PRINT #6; "*" 7230 POSITION 2,8:PRINT #6; "*" 7240 POSITION 14,9:PRINT #6; "*" 7250 POSITION 16,5:PRINT #6; "*" 7300 REM Draw Border 7310 POSITION 0,1:PRINT #6; "\":REM Draw upper left corner 7320 POSITION 19,1:PRINT #6; "]":REM Draw upper right corner 7330 POSITION 0,10:PRINT #6; "^":REM Draw lower left corner 7340 POSITION 19,10:PRINT #6; "_":REM Draw lower right corner 7350 POSITION 1,1:PRINT #6; ">>>>>>>>>>>>>>>>>>":REM Draw top border 7360 POSITION 1,10:PRINT #6; "??????????????????":REM Draw bottom border 7370 FOR I=2 TO 9:REM Loop to draw left & right 7380 POSITION 0,I:PRINT #6;"@":REM Draw left border 7390 POSITION 19,I:PRINT #6;"[":REM Draw right border 7400 NEXT I:REM Loop until border done 7500 RETURN 8000 REM ************************************* 8001 REM *** SETUP PLAYER MISSILE GRAPHICS *** 8002 REM ************************************* 8010 PMGRAPHICS 1:REM Single-line resolution PMG 8020 PMCLR 0:PMCLR 4:REM Clear player & missile memory 8030 PMWIDTH 0,2:PMWIDTH 1,1:REM Set width of player 0 8040 PMWIDTH 6,3:PMWIDTH 7,3:REM Set widths of missiles 2 & 3 8050 PMCOLOR 0,12,12:REM Set color of player 0 8060 PMCOLOR 2,2,12:REM Set color of player 2 for missile 2 8070 PMCOLOR 3,2,12:REM Set color of player 3 for missile 3 8080 P0ADR=PMADR(0):REM Find memory address for player 0 8100 REM Load player 0 shape data into memory 8110 FOR I=P0ADR+P0Y TO P0ADR+P0Y+13:REM Loop for loading 14 bytes 8120 READ DAT:POKE I,DAT:REM Read & write player shape data 8130 NEXT I:REM Loop until player 0 written 8500 RETURN 10000 REM ************************************** 10001 REM *** DATA FOR DEATH STAR CHARACTERS *** 10002 REM ************************************** 10010 DATA 0,0,3,7,15,15,31,31 10020 DATA 63,63,127,127,127,127,127,127 10030 DATA 0,127,127,127,127,127,63,63 10040 DATA 31,31,15,15,7,1,0,0 10050 DATA 0,63,255,255,255,255,255,207 10060 DATA 135,3,3,135,207,255,255,255 10070 DATA 0,255,255,255,255,255,255,255 10080 DATA 255,255,255,255,255,255,63,0 10090 DATA 0,252,255,255,255,255,255,255 10100 DATA 255,255,255,255,255,255,255,255 10110 DATA 0,255,255,255,255,255,255,255 10120 DATA 255,255,255,255,255,255,252,0 10130 DATA 0,0,128,224,240,240,248,248 10140 DATA 252,252,254,254,254,254,254,254 10150 DATA 0,254,254,254,254,254,252,252 10160 DATA 248,248,240,240,224,128,0,0 11000 REM *********************************** 11001 REM *** DATA FOR BORDER AND CORNERS *** 11002 REM *********************************** 11010 DATA 255,255,255,0,0,0,0,0 11020 DATA 0,0,0,0,0,255,255,255 11030 DATA 224,224,224,224,224,224,224,224 11040 DATA 7,7,7,7,7,7,7,7 11050 DATA 255,255,255,224,224,224,224,224 11060 DATA 255,255,255,7,7,7,7,7 11070 DATA 224,224,224,224,224,255,255,255 11080 DATA 7,7,7,7,7,255,255,255 12000 REM **************************** 12001 REM *** DATA FOR TIE FIGHTER *** 12002 REM **************************** 12010 DATA 66,129,129,153,153,255,255 12020 DATA 255,255,153,153,129,129,66