100 REM === BASIC Month 3: Cannonball 110 REM === http://reddit.com/r/RetroBattlestations 120 REM === written by FozzTexx 130 REM === A8 port by LaceySnr 200 REM === Clear screen, hide cursor and setup variables 210 PRINT CHR$(125) 215 POKE 752,1 220 CL = 39:RW = 23:REM Columns and Rows of screen 230 CA = 45:CN = 5:REM Angle and length of cannon 240 CX = 5:PX = CL-5:SC = 0:LV = 3 250 PI = 3.14159:K=0 260 DIM P$(30):DIM LIVES$(6):LIVES$ =" UUU" 300 REM === Play game 310 CV = INT(RND(1) * 15) + 10:GOSUB 4010:GOSUB 2010 320 GOSUB 2510 325 REM Using internal key-codes without conversion since they're not being printed, these are A, Z, Q and SPACE respectively 330 IF K = 63 THEN CA = CA + 5:IF CA > 85 THEN CA = 85 340 IF K = 23 THEN CA = CA - 5:IF CA < 15 THEN CA = 15 350 IF K = 47 THEN GOTO 5000 360 IF K = 33 THEN 410 370 GOSUB 1010 380 GOTO 320 400 REM === Fire! 410 LX = (CN + 1) * COS((360 - CA) * PI / 180):LY = (CN + 1) * SIN((360 - CA) * PI / 180) 420 BX = CX + LX:BY = RW + LY 430 GOSUB 1510 440 VX = CV * COS((360 - CA) * PI / 180):VY = CV * SIN((360 - CA) * PI / 180) 500 REM === Move player and animate ball - 134 & 135 are left and right 510 GOSUB 2510 520 IF K = 134 THEN PX = PX - 1:IF PX < CX+CN THEN PX = CX+CN 530 IF K = 135 THEN PX = PX + 1:IF PX > CL - 1 THEN PX = CL -1 540 GOSUB 2010 550 BX = BX + (VX / 10):BY = BY + (VY / 10):GOSUB 1510 560 VY = VY + 2 570 IF BY < RW THEN 510 580 P$=" ":X1I=BXI:Y1I=BYI:GOSUB 3510 600 REM === Score or die 610 LX = BX - INT(BXI):LY = BY - INT(BYI):L2 = RW - INT(BYI) 620 IX = BXI + LX * (L2 / LY) 630 IF IX >= PX - 1 AND IX <= PX + 1 THEN SC = SC + 10:GOTO 310 640 LV = LV - 1:GOSUB 4010 650 IF LV < 1 THEN P$="THY GAME IS OVER":X1I = (CL - LEN(P$)) / 2:Y1I = RW / 2:GOSUB 3510:END 660 GOTO 310 1000 REM === Draw cannon 1010 IF (CA = LA) THEN RETURN 1020 P$="ANGLE: ": P$(LEN(P$)+1)=STR$(CA):X1I=2:Y1I=1:GOSUB 3510 1030 LX = CN * COS((360 - LA) * PI / 180):LY = CN * SIN((360 - LA) * PI / 180) 1040 X1 = CX:Y1 = RW:X2 = X1 + LX:Y2 = Y1 + LY:P$ = " ":GOSUB 3010 1050 LX = CN * COS((360 - CA) * PI / 180):LY = CN * SIN((360 - CA) * PI / 180) 1060 X2 = X1 + LX:Y2 = Y1 + LY:P$= "%":GOSUB 3010 1070 LA=CA:RETURN 1500 REM === Draw ball 1510 X1I = INT(BX):Y1I = INT(BY):P$="o":GOSUB 3510 1520 IF BXI <> X1I OR BYI <> Y1I THEN X1I=BXI:Y1I=BYI:P$=" ":GOSUB 3510 1530 BXI = INT(BX):BYI = INT(BY) 1540 RETURN 2000 REM === Draw player 2010 P$="U":X1I = INT(PX):Y1I = INT(RW):GOSUB 3510 2020 IF PXI <> X1I THEN X1I=PXI:P$=" ":GOSUB 3510 2030 PXI = INT(PX) 2040 RETURN 2500 REM === Read the keyboard 2510 K = PEEK(764) 2520 POKE 764,255 2530 RETURN 3000 REM === Plot a line 3010 X1I = INT(X1):X2I = INT(X2):Y1I = INT(Y1):Y2I = INT(Y2) 3020 DXI = ABS(X2I - X1I):SXI = -1:IF X1I < X2I THEN SXI = 1 3030 DYI = ABS(Y2I - Y1I):SYI = -1:IF Y1I < Y2I THEN SYI = 1 3040 ERI = -DYI:IF DXI > DYI THEN ERI = DXI 3050 ERI = ERI / 2 3060 GOSUB 3510 3070 IF X1I = X2I AND Y1I = Y2I THEN RETURN 3080 E2I = ERI 3090 IF E2I > -DXI THEN ERI = ERI - DYI:X1I = X1I + SXI 3100 IF X1I = X2I AND Y1I = Y2I THEN RETURN 3110 IF E2I < DYI THEN ERI = ERI + DXI:Y1I = Y1I + SYI 3120 IF X1I = X2I AND Y1I = Y2I THEN RETURN 3130 GOTO 3060 3500 REM === Plot a point 3510 IF X1I < 0 OR X1I > CL OR Y1I < 0 OR Y1I > RW THEN RETURN 3520 POSITION X1I, Y1I 3530 PRINT P$; 3540 RETURN 4000 REM === Show score/lives/velocity 4010 P$="VELOCITY: " : P$(LEN(P$)+1)=STR$(CV) : X1I = CL / 3 : Y1I = 1 : GOSUB 3510 4020 P$="SCORE: " : P$(LEN(P$)+1)=STR$(SC) : X1I = CL * 2 / 3 : GOSUB 3510 4030 P$=LIVES$(LV+1,LV+3) : X1I=CL - 2:GOSUB 3510 4040 RETURN