0 ------------------------------------------ $ Pixel Fandango Space Fighter X 0 ------------------------------------------ ( images% 280 2workImage%=images% < 1 F Set colour palette... P 19,1,2,0,0,0 Z 19,2,6,0,0,0 d 19,3,3,0,0,0 nCOL_EXPLODE=3 &x Create alien flight path data...  pathData% 550 FLIGHT_PATH_SIZE=255 FLIGHT_PATH_IX=220 FLIGHT_PATH_IY=950 1endOfPathData%=_InitFlightPattern(pathData%) & Add graphic image definitions... rocketImage%=workImage% -workImage%=_AddRocketImage(rocketImage%) alien1Image%=workImage% -workImage%=_AddAlien1Image(alien1Image%) bulletImage%=workImage% -workImage%=_AddBulletImage(bulletImage%) explosionImage%=workImage% 3workImage%=_AddExplosionImage(explosionImage%) !bigExplosionImage%=workImage% 9workImage%=_AddBigExplosionImage(bigExplosionImage%) " Entity States... ,DEAD_ENTITY=0 6ALIEN_LIVE=20 @ALIEN_EXPLODE=ALIEN_LIVE-1 JPLAYER_LIVE=200 TPLAYER_EXPLODE=PLAYER_LIVE-1 "^ Base entity field offsets... heENTITY_SIZE=26 reTYPE=0 |eSIZE=1 eIMAGE=2 eSTATE=6 eCOLOUR=7 eXPOS=8 eYPOS=12 eHWIDTH=16 eHHEIGHT=17 eXCENTRE=18 eYCENTRE=22 & Special fields above base entity %eFLIGHT_PATH_INDEX=eENTITY_SIZE+0  Entity types ePLAYER=0 eBULLET=1 eBOMB=2 eALIEN=3 & Other global settings... 0BOMB_SPEED=12 :BULLET_SPEED=20 DPLAYER_START_X=600 NPLAYER_START_Y=40 X Add entities... bpNext%=0 l entities% 2500 v  Player's rocket... pRocket%=entities% )rX%=PLAYER_START_X:rY%=PLAYER_START_Y UpNext%=_InitEntity(ePLAYER, 0, pRocket%, rocketImage%, PLAYER_LIVE, 2, rX%, rY%)  Aliens... MaxAliens%=20 pAliens%=pNext%  A=0 MaxAliens% vpNext%=_InitAlien(eALIEN, pNext%, alien1Image%, DEAD_ENTITY, 3, FLIGHT_PATH_IX, FLIGHT_PATH_IY, FLIGHT_PATH_SIZE)  A  Bullets... MaxBullets%=10 pBullets%=pNext%  B=0 MaxBullets% E pNext%=_InitEntity(eBULLET, 0, pNext%, bulletImage%, 0, 2, 0, 0)  B  pNextBullet%=pBullets% *pEndBullets%=pNext% 4 Bombs... >MaxBombs%=50 HpBombs%=pNext% R B=0 MaxBombs% C\pNext%=_InitEntity(eBOMB, 0, pNext%, bulletImage%, 0, 3, 0, 0) f B ppNextBomb%=pBombs% zpEndBombs%=pNext% canFire%=0 : 5  0, 128  0,1 , "Used Image Space:" workImage%-images% + "Used Entity Space:" pNext%-entities% 2 "Used F-Path Data:" endOfPathData%-pathData%  410,650:"PIXEL FANDANGO"  395,600:"SPACE-FIGHTER-X"  Clear keyboard buffer... *FX 15  430,550:"PRESS ANY KEY" a%= : 5 score%=0 lastScore%=0 $lives%=3 .spawnSize%=4 8 Game loop... B 'L_NewPlayer(pRocket%, rocketImage%) &V_MoveEntityTo(pRocket%, rX%, rY%) `cycle%=0 jalienSpawn%=0 t ~cycle%=cycle%+1 S score%<>lastScore% 300,1000: 0,0: "SCORE:";lastScore%:lastScore%=score% & 300,1000: 0,3: "SCORE:";score% & 800,1000: 0,3: "LIVES:";lives% !pPlayerState%=pRocket%+eSTATE  draw aliens... workAlien%=pAliens% nLiveAliens%=0  A=0 MaxAliens% 4 Update explosion count (if in exploding state) "pAlienState%=workAlien%+eSTATE J ?(pAlienState%)=1 _DrawEntity(workAlien%, 0):?(workAlien%+eSTATE)=0 v ?(pAlienState%)>0 ?(pAlienState%)<20 ?(pAlienState%)=?(pAlienState%)-1:_DrawEntity(workAlien%, COL_EXPLODE) isAlive%=?(pAlienState%)>=20  isAlive% ?(pPlayerState%)=PLAYER_LIVE (1000)<15 pNextBomb%=_DropBomb(workAlien%, pNextBomb%): pNextBomb%>=pEndBombs% pNextBomb%=pBombs%  isAlive% workAlien%=_UpdateAlien(workAlien%, pBullets%, pathData%, explosionImage%) workAlien%=_NextEntity(workAlien%) , isAlive% nLiveAliens%=nLiveAliens%+1 ( A o2 nLiveAliens%=0 alienSpawn%=0 alienSpawn%=spawnSize%: spawnSize%0 _StartAlien(pAliens%):alienSpawn%=alienSpawn%-1 F draw bullets... PworkBullet%=pBullets% Z B=0 MaxBullets% 9dworkBullet%=_UpdateBullet(workBullet%, BULLET_SPEED) n B xworkBomb%=pBombs%  B=0 MaxBombs% 3workBomb%=_UpdateBullet(workBomb%, BOMB_SPEED)  B  handle user input... newX%=rX% 3 (-98) newX%=newX%-12: newX%<32 newX%=32 7 (-67) newX%=newX%+12: newX%>1150 newX%=1150 : (-74)=0 ?(pPlayerState%)=PLAYER_LIVE canFire%=1 ] canFire%=1 (-74) pNextBullet%=_SetBullet(pNextBullet%,1,rX%+50,rY%+90):canFire%=0 9 pNextBullet%>=pEndBullets% pNextBullet%=pBullets% % Wait for screen refresh sync... *FX19 ` newX%<>rX% ?(pPlayerState%)=PLAYER_LIVE _MoveEntityTo(pRocket%, newX%, rY%):rX%=newX% H ?(pPlayerState%)address%=_AddImagePartScaled(address%, 1, 80, 40, rScale) ?address%=_AddImagePartScaled(address%, 2, 100, 20, rScale) = address%=_AddImagePartScaled(address%, 2, 80, 0, rScale) =address%=_AddImagePartScaled(address%, 2, 60, 0, rScale) > address%=_AddImagePartScaled(address%, 2, 40, 20, rScale) >*address%=_AddImagePartScaled(address%, 2, 60, 40, rScale) >4address%=_AddImagePartScaled(address%, 2, 80, 40, rScale) >>address%=_AddImagePartScaled(address%, 2, 80, 80, rScale) ?Haddress%=_AddImagePartScaled(address%, 2, 100, 60, rScale) ?Raddress%=_AddImagePartScaled(address%, 2, 70, 120, rScale) >\address%=_AddImagePartScaled(address%, 2, 80, 80, rScale) >faddress%=_AddImagePartScaled(address%, 2, 60, 80, rScale) ?paddress%=_AddImagePartScaled(address%, 2, 70, 120, rScale) >zaddress%=_AddImagePartScaled(address%, 2, 40, 60, rScale) >address%=_AddImagePartScaled(address%, 2, 60, 80, rScale) >address%=_AddImagePartScaled(address%, 2, 60, 40, rScale)  left wing >address%=_AddImagePartScaled(address%, 1, 20, 60, rScale) =address%=_AddImagePartScaled(address%, 2, 0, 80, rScale) =address%=_AddImagePartScaled(address%, 2, 0, 40, rScale) >address%=_AddImagePartScaled(address%, 2, 20, 20, rScale) >address%=_AddImagePartScaled(address%, 2, 20, 60, rScale) >address%=_AddImagePartScaled(address%, 2, 40, 60, rScale) >address%=_AddImagePartScaled(address%, 2, 40, 20, rScale) >address%=_AddImagePartScaled(address%, 2, 20, 20, rScale)  right wing ?address%=_AddImagePartScaled(address%, 1, 120, 60, rScale) ? address%=_AddImagePartScaled(address%, 2, 140, 80, rScale) ? address%=_AddImagePartScaled(address%, 2, 140, 40, rScale) ? address%=_AddImagePartScaled(address%, 2, 120, 20, rScale) ?$ address%=_AddImagePartScaled(address%, 2, 120, 60, rScale) ?. address%=_AddImagePartScaled(address%, 2, 100, 60, rScale) ?8 address%=_AddImagePartScaled(address%, 2, 100, 20, rScale) ?B address%=_AddImagePartScaled(address%, 2, 120, 20, rScale) L ?(address%)=0 V =address%+1 ` _AddAlien1Image(address%) j aScale=1.4 Qt address%=_AddImageHeader(address%, (25*aScale), (20*aScale), (20*aScale)) >~ address%=_AddImagePartScaled(address%, 1, 40, 30, aScale) > address%=_AddImagePartScaled(address%, 2, 40, 10, aScale) = address%=_AddImagePartScaled(address%, 2, 50, 0, aScale) > address%=_AddImagePartScaled(address%, 2, 50, 20, aScale) > address%=_AddImagePartScaled(address%, 2, 30, 40, aScale) > address%=_AddImagePartScaled(address%, 2, 20, 40, aScale) = address%=_AddImagePartScaled(address%, 2, 0, 20, aScale) < address%=_AddImagePartScaled(address%, 2, 0, 0, aScale) > address%=_AddImagePartScaled(address%, 2, 10, 10, aScale) > address%=_AddImagePartScaled(address%, 2, 10, 30, aScale) > address%=_AddImagePartScaled(address%, 2, 10, 10, aScale) = address%=_AddImagePartScaled(address%, 2, 20, 0, aScale) = address%=_AddImagePartScaled(address%, 2, 30, 0, aScale) > address%=_AddImagePartScaled(address%, 2, 40, 10, aScale) > address%=_AddImagePartScaled(address%, 1, 15, 20, aScale) > address%=_AddImagePartScaled(address%, 2, 35, 20, aScale) > address%=_AddImagePartScaled(address%, 2, 35, 30, aScale) >( address%=_AddImagePartScaled(address%, 2, 25, 20, aScale) >2 address%=_AddImagePartScaled(address%, 2, 15, 30, aScale) >< address%=_AddImagePartScaled(address%, 2, 15, 20, aScale) F ?(address%)=0 P =address%+1 Z _AddBulletImage(address%) 0d address%=_AddImageHeader(address%, 3, 8, 5) .n address%=_AddImagePart(address%, 1, 0, 0) .x address%=_AddImagePart(address%, 2, 6, 0) / address%=_AddImagePart(address%, 2, 6, 16) / address%=_AddImagePart(address%, 2, 0, 16) . address%=_AddImagePart(address%, 2, 0, 0)  ?(address%)=0  =address%+1 # _AddExplosionImage(address%) 3 address%=_AddImageHeader(address%, 25, 25, 25) . address%=_AddImagePart(address%, 1, 0, 0) 0 address%=_AddImagePart(address%, 2, 10, 20) / address%=_AddImagePart(address%, 2, 0, 30) 0 address%=_AddImagePart(address%, 2, 15, 30) 0 address%=_AddImagePart(address%, 2, 20, 50) 0 address%=_AddImagePart(address%, 2, 30, 30) 0 address%=_AddImagePart(address%, 2, 50, 40) 0 address%=_AddImagePart(address%, 2, 40, 20) 0 address%=_AddImagePart(address%, 2, 50, 10) 0" address%=_AddImagePart(address%, 2, 35, 10) /, address%=_AddImagePart(address%, 2, 30, 0) 06 address%=_AddImagePart(address%, 2, 20, 10) .@ address%=_AddImagePart(address%, 2, 0, 0) J ?(address%)=0 T =address%+1 &^ _AddBigExplosionImage(address%) 3h address%=_AddImageHeader(address%, 50, 50, 50) .r address%=_AddImagePart(address%, 1, 0, 0) 0| address%=_AddImagePart(address%, 2, 20, 40) / address%=_AddImagePart(address%, 2, 0, 60) 0 address%=_AddImagePart(address%, 2, 30, 60) 1 address%=_AddImagePart(address%, 2, 40, 100) 0 address%=_AddImagePart(address%, 2, 60, 60) 1 address%=_AddImagePart(address%, 2, 100, 80) 0 address%=_AddImagePart(address%, 2, 80, 40) 1 address%=_AddImagePart(address%, 2, 100, 20) 0 address%=_AddImagePart(address%, 2, 70, 20) / address%=_AddImagePart(address%, 2, 60, 0) 0 address%=_AddImagePart(address%, 2, 40, 20) . address%=_AddImagePart(address%, 2, 0, 0)  ?(address%)=0  =address%+1   --------------------------  Proc to draw image from & data at address in pos x,y 0 -------------------------- ": _DrawImage(pImage%, x%, y%) $D Skip the header information... N pImage%=pImage%+3 X Draw each image part... b ,l pImage%=_DrawImagePart(pImage%, x%, y%) v pImage%=0   --------------------------  Function to draw single  part of an image defn  and return next address  or 0 if its the last part -------------------------- % _DrawImagePart(pPart%, x%, y%) , Return 0 if this item is an end marker  ?pPart%=0 =0 $ Either move or draw to a point 4 ?(pPart%)=1 ?(pPart%+1)+x%, ?(pPart%+2)+y% 4 ?(pPart%)=2 ?(pPart%+1)+x%, ?(pPart%+2)+y%  return next address  =pPart%+3  8* -------------------------------------------------- '4 Functions to handle game entities 8> -------------------------------------------------- H R -------------------------- \ Initialise a new entity f Return next address p -------------------------- Qz _InitEntity(typeId%, addSize%, pEntity%, pImage%, state%, colour%, x%, y%) $ Record basic entity parameters  ?pEntity%=typeId% + ?(pEntity%+eSIZE)=eENTITY_SIZE+addSize%  !(pEntity%+eIMAGE)=pImage%  ?(pEntity%+eSTATE)=state%  ?(pEntity%+eCOLOUR)=colour%  !(pEntity%+eXPOS)=x%  !(pEntity%+eYPOS)=y% - Calc offsets for collision detection... / ?(pEntity%+eHWIDTH)=?(!(pEntity%+eIMAGE)+0) 0 ?(pEntity%+eHHEIGHT)=?(!(pEntity%+eIMAGE)+1) + Reserve space for centreX and centreY + calcs on move for collision detection !(pEntity%+eXCENTRE)=0 !(pEntity%+eYCENTRE)=0 4 Anything after this is specific to entity type $=pEntity%+?(pEntity%+eSIZE) . -------------------------- 8 Draw an entity B Return next address L -------------------------- %V _DrawEntity(pEntity%, colour%) ` 0,colour% Ij_DrawImage(!(pEntity%+eIMAGE), !(pEntity%+eXPOS), !(pEntity%+eYPOS)) t ~  --------------------------  Calc collision range  based on position, width,  height and radius.  --------------------------  _SetCollnCentre(pEntity%) >!(pEntity%+eXCENTRE)=!(pEntity%+eXPOS)+?(pEntity%+eHWIDTH) ?!(pEntity%+eYCENTRE)=!(pEntity%+eYPOS)+?(pEntity%+eHHEIGHT)    --------------------------  Move an entity (relative)  -------------------------- $  _MoveEntity(pEntity%, dx, dy) ( Only move if state > 0 (is active) 8 ?(pEntity%+eSTATE)=0 =pEntity%+?(pEntity%+eSIZE) (_DrawEntity(pEntity%, 0) 2pX%=!(pEntity%+eXPOS)+dx <pY%=!(pEntity%+eYPOS)+dy F pX%>1280 pX%=pX%-1280 P pX%<0 pX%=pX%+1280 Z pY%>1024 pY%=pY%-1024 d pY%<0 pY%=pY%+1024 n!(pEntity%+eXPOS)=pX% x!(pEntity%+eYPOS)=pY% _SetCollnCentre(pEntity%) /_DrawEntity(pEntity%, ?(pEntity%+eCOLOUR)) =pEntity%+?(pEntity%+eSIZE)   --------------------------  Move an entity (absolute)  -------------------------- & _MoveEntityTo(pEntity%, x%, y%) ( Only move if state > 0 (is active) 7 ?(pEntity%+eSTATE)=0 =pEntity+?(pEntity%+eSIZE) _DrawEntity(pEntity%, 0) !(pEntity%+eXPOS)=x% !(pEntity%+eYPOS)=y% _SetCollnCentre(pEntity%) /_DrawEntity(pEntity%, ?(pEntity%+eCOLOUR))  " , -------------------------- 6 Get pointer to next entity @ -------------------------- J _NextEntity(pEntity%) T=pEntity%+?(pEntity%+eSIZE) ^ h -------------------------- r Collision Detection "| lhs, rhs, top, bot collision % range pre calc'd on entity move  -------------------------- 2 _IsCollision(pEntity1%, pEntity2%, radius%) , Only check if both entities are active 7 ?(pEntity1%+eSTATE)=0 ?(pEntity2%+eSTATE)=0 = 0 5dX=(!(pEntity1%+eXCENTRE)-!(pEntity2%+eXCENTRE)) 5dY=(!(pEntity1%+eYCENTRE)-!(pEntity2%+eYCENTRE))  dX1000 !(pBullet%+eYPOS)<24 ?(pState%)=3 N=pBullet%+?(pBullet%+eSIZE) 8X -------------------------------------------------- +b _SetBullet(pBullet%, state%, x%, y%) l?(pBullet%+eSTATE)=state% v!(pBullet%+eXPOS)=x% !(pBullet%+eYPOS)=y% _SetCollnCentre(pBullet%)  state%=1 1,-15,100,1 ' IF state%=2 THEN SOUND 1,-10,50,5 =pBullet%+?(pBullet%+eSIZE) 8 -------------------------------------------------- P _InitAlien(type%, pEntity%, pImage%, state%, colour%, x%, y%, pathIndex%) RendAddress%=_InitEntity(type%, 1, pEntity%, pImage%, state%, colour%, x%, y%) -?(pEntity%+eFLIGHT_PATH_INDEX)=pathIndex% =endAddress% 8 -------------------------------------------------- # _AlienHit(pAlien%, pBullet%) _DrawEntity(pAlien%, 0) #?(pAlien%+eSTATE)=ALIEN_EXPLODE & !(pAlien%+eIMAGE)=pExplosionImage% ?(pBullets%+eSTATE)=3   0,-15,150,1 *score%=score%+10 4 8> -------------------------------------------------- AH _CheckAlienCollision(pAlien%, pBullets%, pExplosionImage%) 1R If alien is exploding (or dead) then ignore #\cRadius%=?(!(pAlien%+eIMAGE)+2) f ?(pAlien%+eSTATE)<20 p B=0 MaxBullets% mz ?(pBullets%+eSTATE)>0 _IsCollision(workAlien%, pBullets%, cRadius%) _AlienHit(pAlien%, pBullets%): *pBullets%=pBullets%+?(pBullets%+eSIZE)  B  8 -------------------------------------------------- , _IsPlayerCollision(pRocket%, pBombs%) $cRadius%=?(!(pRocket%+eIMAGE)+2)  B=0 MaxBombs% ` ?(pBombs%+eSTATE)>0 _IsCollision(pRocket%, pBombs%, cRadius%) ?(pBombs%+eSTATE)=3: =1 $pBombs%=pBombs%+?(pBombs%+eSIZE)  B =0 8 -------------------------------------------------- G _UpdateAlien(pAlien%, pBullets%, pFlightPath%, pExplosionImage%) >_CheckAlienCollision(pAlien%, pBullets%, explosionImage%) &fpi%=?(pAlien%+eFLIGHT_PATH_INDEX) fpi%=fpi%+1 Z$ fpi%>=FLIGHT_PATH_SIZE fpi%=0:_MoveEntityTo(pAlien%,FLIGHT_PATH_IX, FLIGHT_PATH_IY) &.?(pAlien%+eFLIGHT_PATH_INDEX)=fpi% "8pLookUp%=pFlightPath%+(fpi%*2) 'BdX=?(pLookUp%): dX>128 dX=128-dX )LdY=?(pLookUp%+1): dY>128 dY=128-dY "V=_MoveEntity(pAlien%, dX, dY) 8` -------------------------------------------------- $j _DropBomb(pAlien%,pNextBomb%) Lt=_SetBullet(pNextBomb%,2,!(workAlien%+eXCENTRE),!(workAlien%+eYCENTRE)) 8~ -------------------------------------------------- . _KillPlayer(pPlayer%, pExplosionImage%) _DrawEntity(pPlayer%, 0) ( ?(pPlayer%+eSTATE)