' Taito Space Invaders ' ллл ' ллллллл ' ллллллллллл ' л ллл л ' ллллллл ллллллл ' лл лл ' лл лл лл лл ' лл лл лл лл ' v1 ' anarky - anarky.tk, 2005 DEFINT A-Z DECLARE FUNCTION ArrayBytes (x, y) DECLARE SUB DefineGraphics () DECLARE SUB SetColour (colour, r, g, b) DECLARE SUB Display (x, y, a$) DECLARE SUB DisplayLife (life, visible) DECLARE SUB DisplayScore () DECLARE SUB DrawPlanet (visible) DECLARE SUB DrawShelters (visible) DECLARE SUB Delay (seconds!) DECLARE SUB ClearScreen () DECLARE SUB ClearScreenToCRT () DECLARE SUB IncScore (scoregain) DECLARE SUB ErodeShelter (x, y) DECLARE FUNCTION sbvoicetoreg (voice) DECLARE SUB sbwritereg (register, byte) DECLARE SUB sbresetcard () DECLARE SUB sbsetupvoice (voice) DECLARE SUB sbvoiceoff (voice) DECLARE SUB sbplaynote (voice, octave, note) DECLARE SUB sbvolume (voice, volume) DECLARE SUB sbmodulate (voice, volume) DEF SEG = 0 RANDOMIZE TIMER SCREEN 13 true = -1 false = NOT true screenwidth = 256 screenorgx = 32 shipwidth = 15 shipheight = 8 shipminx = 50 shipmaxx = 270 - shipwidth bulletheight = 3 bulletd = 3 invwidth = 12 invheight = 8 invbombheight = 5 invdiry = 7 invzaptime = 15 saucerwidth = 16 saucerheight = 7 saucery = 28 sheltery = 156 shelterwidth = 24 shelterheight = 16 shipcolour = 255 bulletcolour = 254 bombcolour = 253 shipexplodecolour = 252 sheltercolour = 251 textcolour = 250 invexplodewhitecolour = 249 invexplodegreencolour = 248 planetcolour = 247 saucercolour = 246 crtcolour = 245 SetColour shipcolour, 0, 63, 0 SetColour bulletcolour, 63, 63, 63 SetColour bombcolour, 63, 63, 63 SetColour shipexplodecolour, 0, 63, 0 SetColour sheltercolour, 0, 63, 0 SetColour textcolour, 63, 63, 63 SetColour invexplodewhitecolour, 63, 63, 63 SetColour invexplodegreencolour, 0, 63, 0 SetColour planetcolour, 0, 63, 0 SetColour saucercolour, 63, 0, 0 SetColour crtcolour, 14, 14, 14 shipgsize = ArrayBytes(shipwidth - 4, shipheight - 4) DIM shipg(shipgsize) DIM shipexpg(2 * shipgsize) invgsize = ArrayBytes(invwidth - 3, invheight - 3) DIM invg(4 * 55 * invgsize) DIM invg2(4 * 55 * invgsize) invbombgsize = ArrayBytes(1, 3) DIM invbombg(2 * invbombgsize) DIM invexpg(3 * invgsize) DIM saucerg(ArrayBytes(saucerwidth - 3, saucerheight - 3)) DIM shelterg(ArrayBytes(shelterwidth - 6, shelterheight - 6)) chargsize = ArrayBytes(2, 5) DIM charset(chargsize * 39) DIM damagex(255), damagey(255) FOR i = 0 TO 255 damagex(i) = RND * 4 damagey(i) = RND * 6 NEXT invvoice = 1 bulletvoice = 2 invzapvoice = 3 saucervoice = 4 shipexpvoice = 5 DIM invnote(3) FOR i = 0 TO 3 READ invnote(i) NEXT DATA &H2AE,&H287,&H263,&H241 sbresetcard FOR i = 1 TO 5 sbsetupvoice i NEXT sbmodulate invvoice, 40 sbmodulate bulletvoice, 45 sbvolume bulletvoice, 45 sbmodulate invzapvoice, 20 sbvolume invzapvoice, 53 sbvolume saucervoice, 55 sbmodulate shipexpvoice, 63 DefineGraphics DIM invx(55), invy(55), invs(55) DIM bombx(20), bomby(20), bombs(20), bombtype(20) speedtest = false score = 0 WHILE NOT switchoff ClearScreen WHILE INKEY$ > "" WEND Display 0, 0, "SCORE" DisplayScore a$ = "" WHILE a$ = "" WAIT &H3DA, 8 WAIT &H3DA, 8, 8 Display 11 * 8, 10 * 9, "GAME OVER" FOR i = 1 TO 2 WAIT &H3DA, 8 WAIT &H3DA, 8, 8 NEXT Display 11 * 8, 10 * 9, " " a$ = INKEY$ switchoff = (a$ = CHR$(27)) WEND '------------------ Next Game --------------- IF NOT switchoff THEN score = 0 lives = 3 level = 1 damagecounter = RND * 200 maxbombs = 12 bombchance = 95 gameover = false ClearScreen Display 0, 0, "SCORE" DisplayScore Display 16 * 8, 0, "LIVES" FOR i = 1 TO lives DisplayLife i, true NEXT END IF '------------------ Next Level -------------- WHILE NOT gameover AND NOT switchoff DrawPlanet true IF level < 5 THEN DrawShelters true END IF maxbombs = maxbombs - (maxbombs < 20) bombchance = bombchance + (bombchance > 80) shipx = shipminx shipy = 199 - shipheight * 2 canfire = false saucers = false inv = 1 FOR y = 0 TO 4 FOR x = 0 TO 10 invx(inv) = shipminx + shipwidth + x * 16 invy(inv) = shipy - 2 - invheight - (6 - level) * 14 - y * 14 invs(inv) = true inv = inv + 1 NEXT NEXT invleft = 55 inv = 0 invanim = 0 invnote = 0 invnotelength = 12 invnoted = 1 invnotes = true invdirx = 2 changedir = 0 numbombs = 0 FOR i = 1 TO maxbombs bombs(i) = false NEXT endinglevel = false Delay .6 saucercycles = 0 shots = 0 saucercount = 0 '------------------ Next Cycle -------------- WHILE NOT endlevel AND NOT gameover AND NOT switchoff WAIT &H3DA, 8 WAIT &H3DA, 8, 8 IF speedtest THEN SetColour 0, 32, 16, 16 END IF 'move invaders IF (NOT dying) AND (NOT endinglevel) AND (invzapticks = 0) THEN inv = inv + 1 oldinvanim = invanim IF inv = 56 THEN inv = 1 invanim = invanim XOR 1 SELECT CASE changedir CASE 1 changedir = 2 CASE 2 invdirx = -invdirx changedir = 0 END SELECT END IF WHILE invs(inv) = false inv = inv + 1 IF inv = 56 THEN inv = 1 invanim = invanim XOR 1 SELECT CASE changedir CASE 1 changedir = 2 CASE 2 invdirx = -invdirx changedir = 0 END SELECT END IF WEND LINE (invx(inv), invy(inv))-STEP(invwidth - 1, invheight - 1), crtcolour, BF IF changedir = 2 THEN invy(inv) = invy(inv) + invdiry IF invy(inv) > shipy - invheight THEN lives = 1 LINE (shipx, shipy)-STEP(shipwidth - 1, shipheight - 1), crtcolour, BF dying = true deathroes = 0 END IF ELSE invx(inv) = invx(inv) + invdirx IF invx(inv) <= shipminx - invwidth OR invx(inv) >= shipmaxx + shipwidth THEN changedir = 1 END IF END IF IF invy(inv) < sheltery - invheight THEN PUT (invx(inv), invy(inv)), invg((inv - 1) * invgsize * 4 + invanim * 2 * invgsize), PSET ELSEIF invy(inv) < sheltery THEN PUT (invx(inv), invy(inv)), invg((inv - 1) * invgsize * 4 + invanim * 2 * invgsize + invgsize), PSET ELSE PUT (invx(inv), invy(inv)), invg2((inv - 1) * invgsize * 4 + invanim * 2 * invgsize), PSET END IF END IF 'invader move sound invnoted = invnoted - 1 IF invnoted = 0 THEN IF invnotes THEN IF invleft > 11 THEN sbvoiceoff invvoice END IF invnoted = invleft - invnotelength IF invnoted < 1 THEN invnoted = 1 END IF ELSE IF invleft > 0 AND NOT dying AND NOT endinglevel THEN sbplaynote invvoice, 1, invnote(invnote) invnote = (invnote + 1) AND 3 END IF invnoted = invnotelength END IF invnotes = NOT invnotes END IF 'drop bomb IF NOT dying AND NOT endinglevel THEN IF numbombs < maxbombs AND RND * 100 > bombchance THEN obstructed = false FOR i = inv - 11 TO 1 STEP -11 IF invs(i) THEN obstructed = true i = 1 END IF NEXT IF NOT obstructed THEN i = 1 WHILE bombs(i) i = i + 1 WEND bombx(i) = invx(inv) + 5 bomby(i) = invy(inv) + 8 bombs(i) = true IF RND * 100 > 85 THEN bombtype(i) = 1 ELSE bombtype(i) = 0 END IF numbombs = numbombs + 1 END IF END IF END IF 'move bombs FOR i = 1 TO maxbombs IF bombs(i) THEN LINE (bombx(i), bomby(i))-STEP(2, 4), crtcolour, BF IF bombtype(i) = 0 THEN bomby(i) = bomby(i) + 1 ELSE bomby(i) = bomby(i) + 2 END IF a = POINT(bombx(i), bomby(i) + 5) b = POINT(bombx(i) + 2, bomby(i) + 5) IF bomby(i) > 194 THEN bombs(i) = false numbombs = numbombs - 1 ELSEIF a = sheltercolour OR b = sheltercolour THEN ErodeShelter bombx(i), bomby(i) + 7 bombs(i) = false numbombs = numbombs - 1 ELSEIF a = shipcolour OR b = shipcolour THEN bombs(i) = false numbombs = numbombs - 1 DisplayLife lives, false LINE (shipx, shipy)-STEP(shipwidth - 1, shipheight - 1), crtcolour, BF sbvoiceoff invvoice dying = true deathroes = 0 ELSE PUT (bombx(i), bomby(i)), invbombg(bombtype(i) * invbombgsize), PSET END IF END IF NEXT 'launch saucer IF NOT saucers AND NOT saucerdying THEN IF saucercycles = 25 * 70 AND invleft > 9 THEN IF RND > .5 THEN saucerx = screenorgx saucerdx = 1 ELSE saucerx = screenorgx + screenwidth - saucerwidth saucerdx = -1 END IF saucernote = &H202 saucerd = 1 saucers = true saucercount = saucercount + 1 END IF END IF 'move saucer IF saucers THEN saucerd = saucerd - 1 IF saucerd = 0 THEN LINE (saucerx, saucery)-STEP(saucerwidth - 1, saucerheight - 1), crtcolour, BF saucerx = saucerx + saucerdx IF saucerx > screenorgx + screenwidth - saucerwidth OR saucerx < screenorgx THEN sbvoiceoff saucervoice saucers = false saucercycles = 0 ELSE PUT (saucerx, saucery), saucerg(0), PSET saucernote = saucernote - 15 IF saucernote < &H1B0 THEN saucernote = &H202 END IF sbplaynote saucervoice, 5, saucernote saucerd = 2 END IF END IF END IF 'explode saucer IF saucerdying THEN saucerdeathroes = saucerdeathroes - 1 IF saucerdeathroes = 0 THEN LINE (saucerx, saucery)-STEP(3 * 8, 1 * 9), crtcolour, BF sbvoiceoff saucervoice saucercycles = 0 saucerdying = false ELSE saucernote = saucernote + 4 IF saucernote > &H202 THEN saucernote = &H1B0 END IF sbplaynote saucervoice, 4, saucernote END IF END IF 'move player and fire bullet IF NOT dying THEN k = PEEK(&H417) LINE (shipx, shipy)-STEP(14, 7), crtcolour, BF IF (k AND 4) AND shipx > shipminx THEN shipx = shipx - 1 IF (k AND 8) AND shipx < shipmaxx THEN shipx = shipx + 1 PUT (shipx, shipy), shipg, PSET IF canfire AND (k AND 1) AND (bullets = false) AND (invzapticks = 0) THEN bulletx = shipx + 7 bullety = shipy - bulletheight bulletsound = true bulletsoundd = 10 bullets = true shots = shots + 1 END IF canfire = (bullets = false) AND (invzapticks = 0) AND (k AND 1) = 0 END IF 'move bullet IF bullets THEN LINE (bulletx, bullety)-STEP(0, bulletheight), crtcolour bullety = bullety - bulletd IF bulletsound THEN bulletsoundd = bulletsoundd - 1 IF bulletsoundd = 0 THEN sbvoiceoff bulletvoice bulletsound = false ELSE sbplaynote bulletvoice, 5, RND * 255 + 256 END IF END IF IF bullety < saucery THEN bullets = false ELSE a = POINT(bulletx, bullety) b = POINT(bulletx, bullety + 2) IF (a > 0 AND a < 111) OR (b > 0 AND b < 111) THEN bulletsound = false sbvoiceoff bulletvoice IF a = crtcolour THEN a = b a = (a - 1) \ 2 + 1 invs(a) = false invleft = invleft - 1 invzapx = invx(a) invzapy = invy(a) LINE (invzapx, invzapy)-STEP(invwidth - 1, invheight - 1), crtcolour, BF IF invzapy < sheltery - invheight THEN PUT (invzapx, invzapy), invexpg(0), PSET ELSEIF invzapy < sheltery THEN PUT (invzapx, invzapy), invexpg(invgsize), PSET ELSE PUT (invzapx, invzapy), invexpg(2 * invgsize), PSET END IF invzapticks = invzaptime IF invleft > 11 THEN invnotelength = 12 ELSEIF invleft > 0 THEN invnotelength = VAL("&H" + MID$("6778899AABB", invleft, 1)) ELSE sbvoiceoff invvoice END IF SELECT CASE a CASE 1 TO 22 IncScore 10 CASE 23 TO 44 IncScore 20 CASE ELSE IncScore 30 END SELECT bullets = false ELSEIF a = sheltercolour THEN ErodeShelter bulletx, bullety bulletsound = false sbvoiceoff bulletvoice bullets = false ELSEIF a = saucercolour OR b = saucercolour THEN LINE (saucerx, saucery)-STEP(saucerwidth - 1, saucerheight - 1), crtcolour, BF IF (shots = 23 AND saucercount = 1) OR (shots = 15 AND saucercount >= 2) THEN saucerscore = 300 ELSE saucerscore = INT(RND * 3 + 1) * 50 END IF Display saucerx - screenorgx, saucery, MID$(STR$(saucerscore), 2) IncScore saucerscore saucers = false saucerdying = true saucerdeathroes = 120 saucernote = &H1B0 bullets = false shots = 0 ELSE LINE (bulletx, bullety)-STEP(0, bulletheight), bulletcolour END IF END IF END IF 'explode ship IF dying THEN deathroes = deathroes + 1 IF deathroes < 130 OR numbombs > 0 THEN LINE (shipx, shipy)-STEP(shipwidth - 1, shipheight - 1), crtcolour, BF PUT (shipx, shipy), shipexpg((deathroes AND 4) / 4 * shipgsize), PSET sbplaynote shipexpvoice, 1, RND * 255 + &H100 ELSE sbvoiceoff shipexpvoice sbvoiceoff saucervoice LINE (shipx, shipy)-STEP(shipwidth - 1, shipheight - 1), crtcolour, BF dying = false lives = lives - 1 IF lives = 0 THEN sbvoiceoff invvoice gameover = true ELSE shipx = shipminx shipy = 199 - shipheight * 2 Delay 1 END IF END IF END IF 'count down exploding invader IF invzapticks THEN invzapticks = invzapticks - 1 sbplaynote invzapvoice, 6, &H280 + invzapticks * 40 IF invzapticks = 0 THEN sbvoiceoff invzapvoice LINE (invzapx, invzapy)-STEP(invwidth - 1, invheight - 1), crtcolour, BF IF invleft = 0 THEN endinglevel = true endingleveld = 0 END IF END IF END IF 'counting down at end of level IF endinglevel THEN endingleveld = endingleveld + 1 IF endingleveld > 200 AND numbombs = 0 AND NOT bullets AND dying = false THEN LINE (shipx, shipy)-STEP(shipwidth - 1, shipheight - 1), crtcolour, BF endinglevel = false endlevel = true END IF END IF IF speedtest THEN SetColour 0, 0, 0, 0 END IF key$ = INKEY$ switchoff = (key$ = CHR$(27)) IF key$ = "=" THEN speedtest = NOT speedtest END IF saucercycles = saucercycles + 1 WEND '(cycle) IF gameover THEN a$ = "GAME OVER" FOR i = 1 TO LEN(a$) Display 10 * 8 + i * 8, 4 * 9, MID$(a$, i, 1) Delay .15 NEXT Delay 3 END IF IF endlevel THEN DrawPlanet true DrawShelters false Delay .9 level = level + 1 IF level > 6 THEN level = 6 END IF endlevel = false END IF WEND '(level) WEND '(game/attract) FOR i = 1 TO 5 sbvoiceoff i NEXT sbresetcard SYSTEM DATA " # " DATA " ### " DATA " ### " DATA " ############# " DATA "###############" DATA "###############" DATA "###############" DATA "###############" DATA " # " DATA " # # # " DATA " # # # " DATA " # # # " DATA " # ## # " DATA "# ######## " DATA " ########## " DATA " ############ " DATA " # # # " DATA " # " DATA " # # # " DATA " # # " DATA " # ## # #" DATA " ###### # " DATA " ######## " DATA " ############ " DATA " #### " DATA " ########## " DATA "############" DATA "### ## ###" DATA "############" DATA " ## ## " DATA " ## ## ## " DATA "## ##" DATA " #### " DATA " ########## " DATA "############" DATA "### ## ###" DATA "############" DATA " ### ### " DATA " ## ## ## " DATA " ## ## " DATA " # # " DATA "# # # # " DATA "# ####### # " DATA "### ### ### " DATA "########### " DATA " ######### " DATA " # # " DATA " # # " DATA " # # " DATA " # # " DATA " ####### " DATA " ## ### ## " DATA "########### " DATA "# ####### # " DATA "# # # # " DATA " ## ## " DATA " ## " DATA " #### " DATA " ###### " DATA " ## ## ## " DATA " ######## " DATA " # # " DATA " # ## # " DATA " # # # # " DATA " ## " DATA " #### " DATA " ###### " DATA " ## ## ## " DATA " ######## " DATA " # ## # " DATA " # # " DATA " # # " DATA " # # " DATA " # # # #" DATA " # # # " DATA "### " DATA " # ##" DATA " ## # " DATA " # # # " DATA " # # " DATA " # " DATA " # " DATA " # " DATA "###" DATA " # " DATA " # " DATA "# " DATA " # " DATA " #" DATA " # " DATA " ###### " DATA " ########## " DATA " ############ " DATA " ## ## ## ## ## " DATA "################" DATA " ### ## ### " DATA " # # " DATA " ################ " DATA " ################## " DATA " #################### " DATA " ###################### " DATA "########################" DATA "########################" DATA "########################" DATA "########################" DATA "########################" DATA "########################" DATA "########################" DATA "########################" DATA "####### #######" DATA "###### ######" DATA "##### #####" DATA "##### #####" DATA A DATA " # " DATA " # # " DATA "# #" DATA "#####" DATA "# #" DATA "# #" DATA "# #" DATA C DATA " ### " DATA "# #" DATA "# " DATA "# " DATA "# " DATA "# #" DATA " ### " DATA E DATA "#####" DATA "# " DATA "# " DATA "#### " DATA "# " DATA "# " DATA "#####" DATA G DATA " ### " DATA "# #" DATA "# " DATA "# ###" DATA "# #" DATA "# #" DATA " ### " DATA I DATA " ### " DATA " # " DATA " # " DATA " # " DATA " # " DATA " # " DATA " ### " DATA L DATA "# " DATA "# " DATA "# " DATA "# " DATA "# " DATA "# " DATA "#####" DATA M DATA "# #" DATA "## ##" DATA "# # #" DATA "# # #" DATA "# #" DATA "# #" DATA "# #" DATA O DATA " ### " DATA "# #" DATA "# #" DATA "# #" DATA "# #" DATA "# #" DATA " ### " DATA R DATA "#### " DATA "# #" DATA "# #" DATA "#### " DATA "# # " DATA "# # " DATA "# #" DATA S DATA " ### " DATA "# #" DATA "# " DATA " ### " DATA " #" DATA "# #" DATA " ### " DATA V DATA "# #" DATA "# #" DATA "# #" DATA "# #" DATA "# #" DATA " # # " DATA " # " DATA 0 DATA " ### " DATA "# #" DATA "# ##" DATA "# # #" DATA "## #" DATA "# #" DATA " ### " DATA 1 DATA " # " DATA " ## " DATA " # " DATA " # " DATA " # " DATA " # " DATA " ### " DATA 2 DATA " ### " DATA "# #" DATA " #" DATA " ### " DATA "# " DATA "# " DATA "#####" DATA 3 DATA " ### " DATA "# #" DATA " #" DATA " ## " DATA " #" DATA "# #" DATA " ### " DATA 4 DATA "# " DATA "# " DATA "# # " DATA "#####" DATA " # " DATA " # " DATA " # " DATA 5 DATA "#####" DATA "# " DATA "#### " DATA " #" DATA " #" DATA "# #" DATA " ### " DATA 6 DATA " ### " DATA "# #" DATA "# " DATA "#### " DATA "# #" DATA "# #" DATA " ### " DATA 7 DATA "#####" DATA " #" DATA " # " DATA " # " DATA " # " DATA " # " DATA " # " DATA 8 DATA " ### " DATA "# #" DATA "# #" DATA " ### " DATA "# #" DATA "# #" DATA " ### " DATA 9 DATA " ### " DATA "# #" DATA "# #" DATA " ####" DATA " #" DATA "# #" DATA " ### " FUNCTION ArrayBytes (x, y) ArrayBytes = 4 + INT(((PMAP(x, 0) - PMAP(0, 0) + 1) * 8 + 7) / 8) * (PMAP(y, 1) - PMAP(0, 1) + 1) END FUNCTION SUB ClearScreen SHARED screenwidth, screenorgx, crtcolour LINE (0, 0)-(319, 199), 0, BF LINE (screenorgx, 0)-STEP(screenwidth, 199), crtcolour, BF END SUB SUB ClearScreenToCRT SHARED crtcolour LINE (0, 0)-(319, 199), crtcolour, BF END SUB SUB DefineGraphics SHARED shipwidth, shipheight, shipgsize, shipg(), shipexpg() SHARED invwidth, invheight, invgsize, invg(), invg2() SHARED invexpg(), invbombheight, invbombgsize, invbombg() SHARED saucerwidth, saucerheight, saucerg() SHARED shelterwidth, shelterheight, shelterg() SHARED chargsize, charset() SHARED shipcolour, bulletcolour, bombcolour, shipexplodecolour SHARED sheltercolour, textcolour, invexplodewhitecolour SHARED invexplodegreencolour, saucercolour, crtcolour 'define ship ClearScreenToCRT FOR y = 1 TO shipheight READ a$ FOR x = 1 TO shipwidth IF MID$(a$, x, 1) = "#" THEN PSET (x, y), shipcolour NEXT NEXT GET (1, 1)-STEP(shipwidth - 1, shipheight - 1), shipg(0) 'define ship explosion FOR i = 1 TO 2 LINE (1, 1)-STEP(shipwidth - 1, shipheight - 1), crtcolour, BF FOR y = 1 TO shipheight READ a$ FOR x = 1 TO shipwidth IF MID$(a$, x, 1) = "#" THEN PSET (x, y), shipexplodecolour NEXT NEXT GET (1, 1)-STEP(shipwidth - 1, shipheight - 1), shipexpg((i - 1) * shipgsize) NEXT 'define invaders ClearScreenToCRT FOR invtype = 0 TO 2 FOR anim = 0 TO 1 LINE (1, 1)-STEP(invwidth - 1, invheight - 1), crtcolour, BF FOR y = 1 TO invheight READ a$ FOR x = 1 TO invwidth IF MID$(a$, x, 1) = "#" THEN PSET (x, y), 255 NEXT NEXT IF invtype = 2 THEN rows = 1 ELSE rows = 2 FOR inv = invtype * 22 TO invtype * 22 + rows * 11 - 1 arraypointer = inv * invgsize * 4 + anim * invgsize * 2 invcolour = inv * 2 + 1 SetColour invcolour, 63, 63, 63 SetColour invcolour + 1, 0, 63, 0 FOR y = 1 TO invheight FOR x = 1 TO invwidth IF POINT(x, y) <> crtcolour THEN PSET (x, y), invcolour NEXT NEXT GET (1, 1)-STEP(invwidth - 1, invheight - 1), invg(arraypointer) FOR y = 5 TO invheight FOR x = 1 TO invwidth IF POINT(x, y) <> crtcolour THEN PSET (x, y), invcolour + 1 NEXT NEXT GET (1, 1)-STEP(invwidth - 1, invheight - 1), invg(arraypointer + invgsize) FOR y = 1 TO 4 FOR x = 1 TO invwidth IF POINT(x, y) <> crtcolour THEN PSET (x, y), invcolour + 1 NEXT NEXT GET (1, 1)-STEP(invwidth - 1, invheight - 1), invg2(arraypointer) NEXT NEXT NEXT 'define invader explosion ClearScreenToCRT FOR y = 1 TO invheight READ a$ FOR x = 1 TO invwidth IF MID$(a$, x, 1) = "#" THEN PSET (x, y), invexplodewhitecolour NEXT NEXT GET (1, 1)-STEP(invwidth - 1, invheight - 1), invexpg(0) FOR y = 5 TO invheight FOR x = 1 TO invwidth IF POINT(x, y) <> crtcolour THEN PSET (x, y), invexplodegreencolour NEXT NEXT GET (1, 1)-STEP(invwidth - 1, invheight - 1), invexpg(invgsize) FOR y = 1 TO 4 FOR x = 1 TO invwidth IF POINT(x, y) <> crtcolour THEN PSET (x, y), invexplodegreencolour NEXT NEXT GET (1, 1)-STEP(invwidth - 1, invheight - 1), invexpg(2 * invgsize) 'define bombs ClearScreenToCRT FOR i = 1 TO 2 FOR y = 1 TO invbombheight READ a$ FOR x = 1 TO 3 IF MID$(a$, x, 1) = "#" THEN PSET (x, y), bombcolour NEXT NEXT GET (1, 1)-STEP(2, invbombheight - 1), invbombg((i - 1) * invbombgsize) ClearScreenToCRT NEXT 'define saucer ClearScreenToCRT FOR y = 1 TO saucerheight READ a$ FOR x = 1 TO saucerwidth IF MID$(a$, x, 1) = "#" THEN PSET (x, y), saucercolour NEXT NEXT GET (1, 1)-STEP(saucerwidth, saucerheight), saucerg(0) 'define shelter ClearScreenToCRT FOR y = 1 TO shelterheight READ a$ FOR x = 1 TO shelterwidth IF MID$(a$, x, 1) = "#" THEN PSET (x, y), sheltercolour NEXT NEXT GET (1, 1)-STEP(shelterwidth - 1, shelterheight - 1), shelterg(0) 'define character set ClearScreenToCRT FOR i = 1 TO 21 READ a$ a = ASC(a$) FOR y = 1 TO 7 READ a$ FOR x = 1 TO 5 IF MID$(a$, x, 1) = "#" THEN PSET (x, y), textcolour NEXT NEXT GET (1, 1)-STEP(4, 7), charset((a - 48) * chargsize) LINE (1, 1)-STEP(4, 7), crtcolour, BF NEXT ClearScreenToCRT END SUB SUB Delay (seconds!) SHARED true, switchoff t# = TIMER DO IF INKEY$ = CHR$(27) THEN switchoff = true END IF LOOP UNTIL TIMER > t# + seconds! OR switchoff END SUB SUB Display (x, y, a$) SHARED screenorgx, chargsize, charset(), crtcolour FOR i = 1 TO LEN(a$) LINE (screenorgx + x + (i - 1) * 8, y)-STEP(5, 7), crtcolour, BF a = ASC(MID$(a$, i)) IF a <> 32 THEN PUT (screenorgx + x + (i - 1) * 8, y), charset((a - 48) * chargsize), PSET END IF NEXT END SUB SUB DisplayLife (life, visible) SHARED screenorgx, shipwidth, shipheight, shipg(), crtcolour IF visible THEN PUT (screenorgx + 16 * 8 + (life - 1) * shipwidth * 1.5, 1.5 * 8), shipg(0), PSET ELSE LINE (screenorgx + 16 * 8 + (life - 1) * shipwidth * 1.5, 1.5 * 8)-STEP(shipwidth, shipheight), crtcolour, BF END IF END SUB SUB DisplayScore SHARED score Display 0, 1 * 9, RIGHT$("000" + MID$(STR$(score), 2), 4) END SUB SUB DrawPlanet (visible) SHARED screenwidth, screenorgx, planetcolour, crtcolour IF visible THEN LINE (screenorgx, 199)-STEP(screenwidth - 1, 0), planetcolour ELSE LINE (screenorgx, 199)-STEP(screenwidth - 1, 0), crtcolour END IF END SUB SUB DrawShelters (visible) SHARED shipwidth, sheltery, shelterwidth, shelterheight, shelterg() SHARED shipminx, shipmaxx, crtcolour shelterspace = (shipmaxx + shipwidth - shipwidth * .9) - (shipminx + shipwidth * .9) xstep = (shelterspace - 4 * shelterwidth) / 3 + shelterwidth FOR i = 0 TO 3 x = shipminx + shipwidth * .9 + i * xstep IF visible THEN PUT (x, sheltery), shelterg(0), PSET ELSE LINE (x, sheltery)-STEP(shelterwidth - 1, shelterheight - 1), crtcolour, BF END IF NEXT END SUB SUB ErodeShelter (x, y) SHARED damagex(), damagey(), damagecounter, crtcolour FOR i = 1 TO 35 PSET (x + damagex(damagecounter + i) - 2, y + damagey(damagecounter + i + 1) - 4), crtcolour NEXT damagecounter = damagecounter + 20 IF damagecounter > 255 - i THEN damagecounter = 0 END IF END SUB SUB IncScore (scoregain) SHARED true, score, lives score = score + scoregain IF score >= 1000 AND score < 1000 + scoregain THEN lives = lives + 1 DisplayLife lives, true END IF DisplayScore END SUB SUB sbmodulate (voice, volume) sbwritereg &H40 + sbvoicetoreg(voice), &H3F - volume END SUB SUB sbplaynote (voice, octave, note) sbwritereg &HA0 - 1 + voice, note AND 255 sbwritereg &HB0 - 1 + voice, &H20 OR (octave * 4) OR ((note AND &H300) / 256) END SUB SUB sbresetcard FOR i = 1 TO &HF5 sbwritereg i, 0 NEXT END SUB SUB sbsetupvoice (voice) 'Sets up one voice. 'Modulator volume = silent 'Modulator attack = fastest 'Modulator decay = slowest 'Modulator sustain = medium 'Modulator release = medium 'Tone volume = loudest 'Tone attack = fastest 'Tone decay = slowest 'Tone sustain = medium 'Tone release = medium sbwritereg &H20 + sbvoicetoreg(voice), &H1 sbwritereg &H40 + sbvoicetoreg(voice), &H3F sbwritereg &H60 + sbvoicetoreg(voice), &HF0 sbwritereg &H80 + sbvoicetoreg(voice), &H77 sbwritereg &H23 + sbvoicetoreg(voice), &H1 sbwritereg &H43 + sbvoicetoreg(voice), &H0 sbwritereg &H63 + sbvoicetoreg(voice), &HF0 sbwritereg &H83 + sbvoicetoreg(voice), &H77 END SUB SUB sbvoiceoff (voice) sbwritereg &HB0 - 1 + voice, 0 END SUB FUNCTION sbvoicetoreg (voice) IF voice <= 3 THEN offset = -1 ELSEIF voice <= 6 THEN offset = 4 ELSE offset = 9 END IF sbvoicetoreg = voice + offset END FUNCTION SUB sbvolume (voice, volume) sbwritereg &H43 + sbvoicetoreg(voice), &H3F - volume END SUB SUB sbwritereg (register, byte) OUT &H388, register FOR i = 1 TO 6 a = INP(&H388) NEXT OUT &H389, byte FOR i = 1 TO 35 a = INP(&H388) NEXT END SUB SUB SetColour (colour, r, g, b) OUT &H3C6, &HFF OUT &H3C8, colour OUT &H3C9, r OUT &H3C9, g OUT &H3C9, b END SUB