mode 2,8 cls load png "assets\title_8bit3.png",0,0 RotFix=-1 if mm.info(version)>5.0505 then RotFix=1 const SCREEN_BUFFER = 1 const SCREEN_GROUND_SPRITES_1 = 3 const SCREEN_PLAYER_SPRITES_1 = 4 const SCREEN_UI_ELEMENTS = 5 const SCREEN_EXPLOSIONS=6 const SCREEN_ENEMY_SPRITES=7 const SCREEN_BLUEPRINT=8 const SCREEN_BLAST=9 const SCREEN_HIGHSCORE=10 const GAME_STATE_START_SCREEN = 1 const GAME_STATE_RUNNING = 2 const GAME_STATE_GAME_OVER = 3 const GAME_STATE_PAUSED=4 const GAME_STATE_HIGHSCORE=5 dim float x,y, x2, y2, diffx,diffy dim float cl,sl ' Sin and Cosine cahce variables 'dim int t ' General looping and temporary variables dim float FPS_Timer, FPS_Scan_Count ' Used to track the frames per second 'dim int Game_State ' 1 = Title Page, 2= runn dim float Player_Angle_Degrees = 0 ' Angle in degrees of the players helicopter dim float Player_Angle_Radians = 0 ' Derived from Player_Angle_Degrees (read only) dim float Player_X = 150 ' Player X co-ordinate in 300 x 300 world dim float Player_Y = 150 ' Player Y co-ordinate in 300 x 300 world dim float Player_Inertia_X=0 dim float Player_Inertia_Y=0 dim float Player_Boost=0 dim float Player_Boost_Charge=0 dim float Player_Armour=100 dim float Player_Ammo=1000 dim float Player_Fuel=100 dim integer Player_Score=0 dim integer Player_Money=0 dim integer Player_Hover_Count=0 ' Used to detect if the player is hovering long enough to refuel dim integer index dim integer HighScore(100) dim integer GameState=1 dim Enemy_X(10) dim Enemy_Y(10) dim Enemy_Angle(10) dim Enemy_DX(10) dim Enemy_DY(10) dim Enemy_Health(10) dim Enemy_Speed(10) dim Enemy_OnRadar(10) dim Explosion_Step%(20) dim Explosion_X(20) dim Explosion_Y(20) dim Explosion_Type(20) ' 0-Missile, Non Zero-Building type (this allows us to change react ammo dumps) dim Explosion_DX(20,4) dim Explosion_DY(20,4) ' Used to optimise the number of sprites we need to show on the screen dim Grid_Min_X%(360) dim Grid_Max_X%(360) dim Grid_Min_Y%(360,20) dim Grid_Max_Y%(360,20) dim GrndSpriteX(50) dim GrndSpriteY(50) dim menuText$(8) dim float Bullet_X(40) dim float Bullet_Y(40) dim float Bullet_DX(40) dim float Bullet_DY(40) boomChannel=3 MasterVol=64 for grnd%=1 to 50 GrndSpriteX(grnd%)=int(grnd% mod 13) GrndSpriteY(grnd%)=int(grnd%/13) next grnd% page write SCREEN_HIGHSCORE load bmp "assets\scrHighScore.bmp" LoadHighScoreTable() LastHighScore=0 ' Build map dim integer Map_Ground(300,300) dim float Map_Health(300,300) page write SCREEN_BLUEPRINT load png "assets\Blueprint1.png",0,0 ' Setup initial enemies for e=1 to 10 Enemy_Health(e)=6 Enemy_X(e)=10+rnd*280 Enemy_Y(e)=10+rnd*100 Enemy_Angle(e)=rnd*6 Enemy_Speed(e)=0.05 next e page write SCREEN_PLAYER_SPRITES_1 load bmp "assets\scrPlayerSprites.bmp" page write SCREEN_EXPLOSIONS cls load png "assets\explosion.png",0,0 load png "assets\drone2.png",407,7 page write SCREEN_ENEMY_SPRITES ' Now produce all of the rotated sprites ' 640x400 - need 46x46 per sprite - 13 across x 8 down (104 sprites) ' so lets do 5 degree rotations on the enemy sprites. 360/5=72 load bmp "assets\scrEnemySprites.bmp" page write SCREEN_BLAST load bmp "assets\scrBlast.bmp" page write SCREEN_GROUND_SPRITES_1 ' Sprite source screen ' Each sprite has a blank area directly below it reserved for a temporary rotated version ' 32+7+7=46 width for each sprite ' Each 32x32 sprite is written to location 7,7 in the 46x46 area to give it space for rotation load bmp "assets\scrGroundSprites.bmp" dim Asset_Rotation%(50) for t=0 to 50:Asset_Rotation%(t)=-720:Next ' Make sure all rotations are invalid, so they get regenerated Game_State = GAME_STATE_RUNNING dim px%(8)=(100,640,640,500,300,200,500,400,450) dim py%(8)=(0,0,400,300,250,200,100,50,25) page write SCREEN_UI_ELEMENTS load bmp "assets\scrUIElements.bmp" ' Explaining Grin_Min/Max_X/Y arrays: ' Originally we displayed the grids that were -6 to +6 each side, and above and below the player. ' This is enough to keep the screen fully populated. It draws up to 169 sprites to fill the screen ' However if the player rotates 45 degrees, the corners of the screen will show sprites from further ' away (up to 8 squares). So they will appear blank unless we extend the player drawing field to ' -8 to +8 from the player location on the X and the y axis. This increaes the max sprite count to ' 289. This is 70% more sprites. Killing the frame rate ' Of course, if the player is at 45 degrees, a lot of those outer sprites are going to be off the ' screen. So we use an algorithm to calculate for each of the 360 possible angles what the min and max ' values for the X component are, and then for each of those X lines, what the min and max Y values ' would be for that X line. ' These are stored in Grid_Min_X%(angle), Grid_Max_X%(angle), Grid_Min_Y%(angle,x value) and ' Grid_Max_Y%(angle, x value) ' The values for these arrays are calculated in subroutine CalculateScreenAreaBasedOnAngle() ' It takes a while to run, so once it had finished I saved it to a file and now I just load ' the file from SD card to keep the program load time fast. ' I have left the subroutine intact though in case anyone wants to use it themselves. ' At the time of writing, this algorithm caused an increase in fram rate from 22 fps to 28 fps on ' average. So definitely worth doing. open "gridarray.dat" for input as #1 for k=0 to 360 input #1, Grid_Min_X%(k) input #1, Grid_Max_X%(k) for j=0 to 20 input #1, Grid_Min_Y%(k,j) input #1, Grid_Max_Y%(k,j) next j next k close #1 'CalculateScreenAreaBasedOnAngle() dim integer Radar_Line=0 map(32)=RGB(0,0,0) map(68)=RGB(32,32,32) Page Write SCREEN_BUFFER ' Main loop Fire_Toggle=1 Colour_Cycle%=0 Enemy_Step=1 High_Score_Cursor=100 GameState=GAME_STATE_HIGHSCORE EndOfGameCounter=100 'lt=timer 'framecount=0 LongFlash=0 ResetGameVariables() play modfile "assets\stranger_-_run.mod",8000 do FPS_Timer=timer LongFlash=LongFlash+1 if LongFlash>20 then LongFlash=0 if GameState=GAME_STATE_GAME_OVER then EndOFGameCounter=EndOfGameCounter+1 if EndOfGameCounter>=100 then LastHighScore=Player_Score ResetGameVariables() GameState=GAME_STATE_HIGHSCORE endif endif if GameState=GAME_STATE_HIGHSCORE then DrawHighScoreScreen() goto EndOfGameLoop endif if GameState=GAME_STATE_PAUSED or GameState=GAME_STATE_START_SCREEN then DrawMenuScreen() goto EndOfGameLoop endif cls rgb(128,128,128) ' Colours are 3 bytes for Red, 3 Bytes for Green, 2 bytes for blue. ' So 001 011 00 is RGB(32,96,0) because the colours jump up in 32s ' i.e. 001*32, 3*32, 0*32 Map(4)=RGB(0,0,0): Map(8)=RGB(0,0,0): Map(12)=RGB(0,0,0): Map(16)=RGB(0,0,0) Map(36)=RGB(0,0,0): Map(40)=RGB(0,0,0): Map(44)=RGB(0,0,0):Map(48)=RGB(0,0,0) Colour_Cycle%=Colour_Cycle%+1 if Colour_Cycle%>7 then Colour_Cycle%=0 if Colour_Cycle%=0 then Map(4)=RGB(0,148,255) if Colour_Cycle%=1 then Map(8)=RGB(0,148,255) if Colour_Cycle%=2 then Map(12)=RGB(0,148,255) if Colour_Cycle%=3 then Map(16)=RGB(0,148,255) if Colour_Cycle%=4 then Map(36)=RGB(0,148,255) if Colour_Cycle%=5 then Map(40)=RGB(0,148,255) if Colour_Cycle%=6 then Map(44)=RGB(0,148,255) if Colour_Cycle%=7 then Map(48)=RGB(0,148,255) Map Set Fire_Toggle=Fire_Toggle*-1 ' Check and see if the player is hovering (i.e. no key press) if keydown(0)=0 then Player_Hover_Count=Player_Hover_Count+1 else Player_Hover_Count=0 endif player_base_sprite=0 ' speed=0.2 Player_Boost_Charge=Player_Boost_Charge+0.1 '+0.1 ' Slow recharge if Player_Boost_Charge>100 then Player_Boost_Charge=100 Player_Fire=0 Player_Slide_Left=0 Player_Slide_Right=0 'Process key strokes ScanKeyboard() if GameState=GAME_STATE_RUNNING then if kbd_left then Player_Angle_Degrees=Player_Angle_Degrees-4: player_base_sprite=4 if kbd_right then Player_Angle_Degrees=Player_Angle_Degrees+4: player_base_sprite=8 if kbd_up then Player_Inertia_Y1=-cl*Player_Speed:Player_Inertia_X1=sl*Player_Speed ' Up cursor if kbd_down then Player_Inertia_Y1=cl*Player_Speed:Player_Inertia_X1=-sl*Player_Speed ' Down cursor if Fire_Toggle=1 and kbd_w then Player_Fire=Player_Gun_Count 'W = Fire if Player_Boost_Charge> 3 and kbd_s then Player_Boost=Player_Boost+1:Player_Boost_Charge=Player_Boost_Charge-1 if kbd_a then Player_Slide_Left=1 ' A - Strafe left if kbd_d then Player_Slide_Right=1 ' D - Strafe right if kbd_f1 then GameState=GAME_STATE_PAUSED endif ' There are 3 possible source of inertia on the chopper ' 1 is from the up/down (Forward-back) cursor keys ' 2 is from strafing left or right (A/D keys) ' 3 is from the boost (S key) if Player_Slide_Right=1 then Player_Inertia_Y2=sl*Player_Speed Player_Inertia_X2=cl*Player_Speed if Player_Base_Sprite=0 then Player_Base_Sprite=8 ' Use the right leaning sprite endif if Player_Slide_Left=1 then Player_Inertia_Y2=-sl*Player_Speed Player_Inertia_X2=-cl*Player_Speed if Player_Base_Sprite=0 then Player_Base_Sprite=4 ' Use the left leaning sprite end if Player_Inertia_X3=0 ' Boost inertia Player_Inertia_Y3=0 if Player_Boost_Charge<=0 then Player_Boost_Charge=0 if Player_Boost>=0 then if Player_Boost>20 then Player_Boost=20 ' Max Boost Player_Inertia_Y3=-cl*Player_Boost/20 Player_Inertia_X3=sl*Player_Boost/20 Player_Boost=Player_Boost-0.5 else Player_Boost=0 endif Player_X=Player_X+Player_Inertia_X1+Player_Inertia_X2+Player_Inertia_X3 Player_Y=Player_Y+Player_Inertia_Y1+Player_Inertia_Y2+Player_Inertia_Y3 ' Reduce the inertia's to slow the chopper down ' Note: The boost inertia will naturally fade away if abs(Player_Inertia_X1)>0.01 then Player_Inertia_X1=Player_Inertia_X1-(Player_Inertia_X1*0.1) else Player_Inertia_X1=0 endif if abs(Player_Inertia_Y1)>0.01 then Player_Inertia_Y1=Player_Inertia_Y1-(Player_Inertia_Y1*0.1) else Player_Inertia_Y1=0 endif if abs(Player_Inertia_X2)>0.01 then Player_Inertia_X2=Player_Inertia_X2-(Player_Inertia_X2*0.1) ' Left right straff inertia else Player_Inertia_X2=0 endif if abs(Player_Inertia_Y2)>0.01 then Player_Inertia_Y2=Player_Inertia_Y2-(Player_Inertia_Y2*0.1) ' Left right straff inertia else Player_Inertia_Y2=0 endif Player_Fuel=Player_Fuel-0.01 ' Make sure player doesn't fly off the edge of the map if Player_X<10 then Player_X=10 if Player_X>290 then Player_X=290 if Player_Y<10 then Player_Y=10 if Player_Y>290 then Player_Y=290 ' See if the player has been hovering long enough near a fuel or ammo dump to resupply if Player_Hover_count>Player_Hover_Limit then Refuel_Count=0 Rearm_Count=0 for refx=Player_X-1 to Player_X+1 for refy=Player_Y-1 to Player_Y+1 if Map_Ground(refx,refy)=6 then Rearm_Count=Rearm_Count+1 if Map_Ground(refx,refy)=3 then Refuel_Count=Refuel_Count+1 next refy next refx Player_Ammo=Player_Ammo+Rearm_Count*4 if Player_Ammo>Player_Max_Ammo then Player_Ammo=Player_Max_Ammo Player_Fuel=Player_Fuel+Refuel_Count/10 if Player_Fuel>Player_Max_Fuel then Player_Fuel=Player_Max_Fuel endif if Player_Angle_Degrees >= 360 then Player_Angle_Degrees = Player_Angle_Degrees - 360 if Player_Angle_Degrees <0 then Player_Angle_Degrees = Player_Angle_Degrees + 360 Player_Angle_Radians = (Player_Angle_Degrees/180) * 3.1415 blade_rotation=blade_rotation+1 if blade_rotation>=4 then blade_rotation=0 player_spriteX=Player_Base_Sprite+blade_rotation blitFlag = &B100 cl =cos(Player_Angle_Radians) sl =sin(Player_Angle_Radians) 'Rotate the sprites required for this screen 'Then draw them DrawRotatedMapSprites() 'Do Enemy AI - Just do one enemy AI per turn (as deifned by Enemy_Step) if Enemy_Health(Enemy_Step)>0 then ' work out desired heading diffx=Enemy_X(Enemy_Step)-Player_X diffy=Enemy_Y(Enemy_Step)-Player_Y newangle=atan2(diffy,diffx)-1.57 if newangle<0 then newangle=newangle+6.283 newangledeg=(newangle*180)/3.1415 diffangle=Enemy_Angle(Enemy_Step)-newangle+rnd*0.3-0.15 ' Do we turn left or right if diffangle<-3.1415 then diffangle=diffangle+6.283 if diffangle>3.1415 then diffangle=diffangle-6.283 ' Note angles are in radians. Where 180 degrees = pi if Enemy_Speed(Enemy_Step)>0.2 then Fast_Turn=0.25 Slow_Turn=0.1 else Fast_Turn=Enemy_Step/10 ' Give each missile a different speed when homing in on the player Slow_Turn=0.25 endif if abs(diffangle)<1 then 'small turn Enemy_Angle(Enemy_Step)=Enemy_Angle(Enemy_Step)-sgn(diffangle)*Slow_Turn else Enemy_Angle(Enemy_Step)=Enemy_Angle(Enemy_Step)-sgn(diffangle)*Fast_Turn endif if Enemy_Angle(Enemy_Step)<0 then Enemy_Angle(Enemy_Step)=Enemy_Angle(Enemy_Step)+6.283 if Enemy_Angle(Enemy_Step)>6.283 then Enemy_Angle(Enemy_Step)=Enemy_Angle(Enemy_Step)-6.283 Enemy_DX(Enemy_Step)=sin(Enemy_Angle(Enemy_Step)) Enemy_DY(Enemy_Step)=-cos(Enemy_Angle(Enemy_Step)) ' Speed is fast if far away dist=sqr(diffx*diffx+diffy*diffy) if dist>12 then Enemy_Speed(Enemy_Step)=0.5 Enemy_OnRadar(Enemy_Step)=0 else Enemy_OnRadar(Enemy_Step)=1 Enemy_Speed(Enemy_Step)=(Enemy_Step/100) +0.1 ' A bit of randomness to stop them all bunching up end if if dist<1 then ' hit Player_Armour=Player_Armour-10 if Player_Armour<0 then Player_Armour=0 StartExplosion(Enemy_X(Enemy_Step),Enemy_Y(Enemy_Step)) Enemy_X(Enemy_Step)=10+rnd*230 Enemy_Y(Enemy_Step)=10+rnd*230 Enemy_Angle(Enemy_Step)=rnd*6 Enemy_Health(Enemy_Step)=6 endif end if Enemy_Step=Enemy_Step+1 if Enemy_Step=11 then Enemy_Step=1 UpdateAndDrawEnemies() RunExplosions() UpdatePlayerBullets() ' Move the player up the rankings if High_Score_Cursor>1 then if Player_Score>HighScore(High_Score_Cursor-1) then High_Score_Cursor=High_Score_Cursor-1 endif DrawUserInterface() 'draw player x=player_spritex*64 y=0 if x>639 then x=x-640:y=80 if GameState = GAME_STATE_RUNNING then blit x,y,168,163,64,74,SCREEN_PLAYER_SPRITES_1,&B100 if GameState = GAME_STATE_RUNNING and (Player_Armour<=0 or Player_Fuel<=0) then GameState=GAME_STATE_GAME_OVER EndOfGameCounter=0 UpdateHighScoreTable(Player_Score) for j=1 to 20 StartExplosion(Player_X+(rnd)-0.5,player_Y+(rnd)-0.5,-1) next j endif if Player_Fuel<25 then if LongFlash>10 then text 200,310,"LOW FUEL",CM,2,1,rgb(red) endif if Player_Fuel<20 then text 200,330,"HOVER OVER A FUEL DUMP TO REFUEL",CM,1,1,rgb(red) endif if Player_Fuel<0.5 then text 200,310,"OUT OF FUEL",CM,2,1,rgb(red) endif endif if GameState = GAME_STATE_RUNNING and Player_Ammo<100 then if LongFlash>10 then text 200,350,"LOW AMMO",CM,2,1,rgb(red) endif if Player_Ammo<20 then text 200,370,"HOVER OVER AN AMMO DUMP TO REFUEL",CM,1,1,rgb(red) endif endif FPS_Actual = (1000/(timer-FPS_Timer))*0.1 + (FPS_Actual)*0.9 ' weight the FPS to average it out Text 585,2, "FPS:" + str$(int(FPS_Actual)),,,,RGB(white),RGB(64,32,0) ' print @(410,220,1) str$(int(FPS_Actual)) ' print " " + str$(Count_of_Active_Explosions) ' frameCount=frameCount+1 ' longFPS=frameCount/((timer-lt)/1000) ' print @(0,0,1) "Long FPS:" + str$(longFPS) EndOfGameLoop: page copy SCREEN_BUFFER, 0, B ' page copy 3, 0, B loop end sub ScanKeyboard() kbd_up=0 kbd_down=0 kbd_left=0 kbd_right=0 kbd_a=0 kbd_d=0 kbd_s=0 kbd_w=0 kbd_f1=0 kbd_space=0 kd=keydown(0) for key=1 to kd if keydown(key)=130 then kbd_left=1 if keydown(key)=131 then kbd_right=1 if keydown(key)=128 then kbd_up=1 if keydown(key)=129 then kbd_down=1 if keydown(key)=119 or keydown(key)=87 then kbd_w=1 if keydown(key)=115 or keydown(key)=83 then kbd_s=1 if keydown(key)=65 or keydown(key)=97 then kbd_a=1 if keydown(key)=100 or keydown(key)=68 then kbd_d=1 if keydown(key)=32 then kbd_space=1 if keydown(key)=145 then kbd_f1=1 if keyDown(key)=146 and MasterVol>=2 then MasterVol=MasterVol-2 if keyDown(key)=147 and MasterVol<=62 then MasterVol=MasterVol+2 next key end sub sub DrawRotatedMapSprites() pad%=int(Player_Angle_Degrees) cc%=0 page write SCREEN_BUFFER ' Get reference from center of screen PopulateLXandLY(0,0) x1=lx y1=ly ' Get reference one square away on x PopulateLxandLY(1,0) lx2=lx ly2=ly ' Get reference one square away on y PopulateLXandLY(0,1) lx3=lx ly3=ly dxx=lx2-x1 dxy=ly2-y1 dyx=lx3-x1 dyy=ly3-y1 for j=Grid_Min_X%(pad%) to Grid_Max_X%(pad%) x=int(Player_X)+j dxxj=x1+dxx*j dxyj=y1+dxy*j for s=Grid_Min_Y%(pad%,j+10) to Grid_Max_Y%(pad%,j+10) y=int(Player_Y)+s if Map_Ground(x,y)>0 then x2=dxxj+dyx*s y2=dxyj+dyy*s grnd%=Map_Ground(x,y) Rotation_Error%=abs(Asset_Rotation%(grnd%)-pad%) ' Try to limit only doing 8 rotations per cycle, unless the cached image is ' more than 5 degrees out (then do the one with the big error as well) xindex=GrndSpriteX(grnd%) yindex=GrndSpriteY(grnd%) if (Rotation_Error%>3 and cc%<8) or Rotation_Error%>5 then page write SCREEN_GROUND_SPRITES_1 image rotate_fast xindex*46,yindex*92,45,45,xindex*46,yindex*92+46,-pad%,3 Asset_Rotation%(grnd%)=pad% page write SCREEN_BUFFER cc%=cc%+1 end if blit xindex*46,yindex*92+46, x2+180,y2+184,45,45,3,blitFlag end if next s next j end sub sub PopulateLXandLY(tx, ty) x=Player_X+tx diffx = (int(x)-Player_X)*32+16 diffxcl = diffx*cl diffxsl=diffx*sl y=Player_Y+ty diffy = (int(y)-Player_Y)*32+16 lx = diffxcl+diffy*sl ly = diffy*cl-diffxsl end sub sub UpdateAndDrawEnemies() for e=1 to 10 ' Update enemy position Enemy_X(e)=Enemy_X(e)+Enemy_DX(e)*Enemy_Speed(e) Enemy_Y(e)=Enemy_Y(e)+Enemy_DY(e)*Enemy_Speed(e) if Enemy_OnRadar(e)=1 then diffx=Enemy_X(e)-Player_X diffy=Enemy_Y(e)-Player_Y if abs(diffx)<8 and abs(diffy)<8 then ' They might be on screen tx=(diffx)*32 ty=(diffy)*32 tx2 = tx*cl+ty*sl ty2 = ty*cl-tx*sl diffangle=Enemy_Angle(e)-Player_Angle_Radians if diffangle<0 then diffangle=diffangle+6.283 if diffangle>6.283 then diffangle-diffangle-6.283 index=int(diffangle*11.459) 'Change radians into 0 to 72 i.e. 5 deg steps (360/6.283)/5=11.459 x=(index mod 13)*46 y=int(index/13)*46 blit x,y, tx2+177,ty2+177,46,46,SCREEN_ENEMY_SPRITES,&B100 end if endif next e end sub sub StartExplosion(ex, ey, explosionType) if GameState=GAME_STATE_RUNNING THEN PlaySound(3) 'Boom if ExplosionType=0 then Player_Score=Player_Score+100 ' Missile if ExplosionType>0 then Player_Score=Player_Score+50 ' Building if ExplosionType=2 then Player_Money=Player_Money+10 ' Yellow house if ExplosionType=33 then Player_Money=Player_Money+100 ' Yellow pyramid if ExplosionType=3 then Player_Money=Player_Money+5 ' Yellow fuel dump endif for expNum=1 to 20 if Explosion_Step%(expNum)=0 then Explosion_Step%(expNum)=1 Explosion_X(expNum)=ex Explosion_Y(expNum)=ey Explosion_Type(expNum)=explosionType if ExplosionType<>0 then ' Non missile for expJ=1 to 4 Explosion_DX(expNum,expJ)=rnd*20-10 Explosion_DY(expNum,expJ)=rnd*20-10 next expJ else for expJ=1 to 4 Explosion_DX(expNum,expJ)=0 Explosion_DY(expNum,expJ)=0 next expJ endif if expNum>Count_Of_Active_Explosions then Count_Of_Active_Explosions = expNum exit sub end if next expNum end sub sub RunExplosions ' if Count_Of_Active_Explosions>19 then Count_Of_Active_Explosions=20 loopCount = Count_Of_Active_Explosions ' C_Of_A_E can be updated within the loop for et=1 to loopCount if Explosion_Step%(et) <> 0 then ' Draw sprite diffx = (Explosion_X(et)-Player_X)*32+16 diffxcl = diffx*cl diffxsl=diffx*sl diffy = (Explosion_Y(et)-Player_Y)*32+16 ' x2 = diffx*cos(Player_Angle_Radians)+diffy*sin(Player_Angle_Radians) ' y2 = diffy*cos(Player_Angle_Radians)-diffx*sin(Player_Angle_Radians) x2 = diffxcl+diffy*sl if x2>-232 and x2<200 then y2 = diffy*cl-diffxsl if y2>-232 and y2<200 then ey=int(Explosion_Step%(et) / 8) ex=int(Explosion_Step%(et) mod 8) blit ex*32,ey*32,x2+180,y2+184,32,32,SCREEN_EXPLOSIONS,blitFlag ' If fuel or ammo dump, do shock wave if (Explosion_Type(et)=3 or Explosion_Type(et)=6) and Explosion_Step%(et)<7 then index=6-Explosion_Step%(et) size=(5-index)*20 if size<10 then size=10 blit index*100,0,x2+196-size/2,y2+200-size/2,size,size,SCREEN_BLAST,blitFlag endif endif endif xbase=x2+180+16 ybase=y2+184+16 for expJ=1 to 4 x1= xbase+Explosion_DX(et,expJ)*Explosion_Step%(et) y1= ybase+Explosion_DY(et,expJ)*Explosion_Step%(et) x2= xbase+Explosion_DX(et,expJ)*(Explosion_Step%(et)+1) y2= ybase+Explosion_DY(et,expJ)*(Explosion_Step%(et)+1) line x1,y1,x2,y2,,rgb(red) next expJ Explosion_Step%(et)=Explosion_Step%(et)+1 if Explosion_Step%(et)=15 then ' Fuel tank if Explosion_Type(et)=3 or Explosion_Type(et)=6 then ' Fuel or ammo dump - chain reaction for expX=Explosion_X(et)-1 to Explosion_X(et)+1 for expY=Explosion_Y(et)-1 to Explosion_Y(et)+1 if Map_Health(expX, expY)>0 then StartExplosion(expX,expY,Map_Ground(expX,expY)) Map_Health(expX,expY)=0 Map_Ground(expX,expY)=0 endif next expY next expX endif endif if Explosion_Step%(et)=38 then Explosion_Step%(et)=0 'Update the Count of explosions, so we don't waste time each loop looking for them Count_Of_Active_Explosions=0 for st=1 to 20 if Explosion_Step%(st)>0 and st>Count_Of_Active_Explosions then Count_Of_Active_Explosions=st next st end if end if next et end sub MaxBullets=1 sub UpdatePlayerBullets() BulletCountChanged=0 'Update and draw bullets if Player_Fire>0 and Player_Ammo>0 then MaxBullets=MaxBullets+4 ' create pace for 4 new bullets if MaxBullets>40 then MaxBullets=40 for b=1 to MaxBullets '40 if Bullet_X(b)<>-1000 then ' It is active tx=(Bullet_X(b)-Player_X)*32 ty=(Bullet_Y(b)-Player_Y)*32 tx2 = tx*cl+ty*sl ty2 = ty*cl-tx*sl ' Update bullet position Bullet_X(b)=Bullet_X(b)+Bullet_DX(b) Bullet_Y(b)=Bullet_Y(b)+Bullet_DY(b) ' And rotate based on player rotation bx=(Bullet_X(b)-Player_X)*32 by=(Bullet_Y(b)-Player_Y)*32 bx2 = bx*cl+by*sl by2 = by*cl-bx*sl if bx2>-232 and bx2<200 and by2>-232 and by2<200 then line tx2+200,ty2+200,bx2+200,by2+200,1,rgb(yellow) pixel bx2+200,by2+200,rgb(red) 'Check if it hit something bbx=int(Bullet_X(b)) bby=int(Bullet_Y(b)) ' Check for ground targets if Map_Health(bbx,bby)>0 then PlaySound(2) Map_Health(bbx,bby) = Map_Health(bbx, bby)-Player_Damage if Map_Health(bbx, bby)<=0 then ' Target destroyed StartExplosion(bbx,bby,Map_Ground(bbx,bby)) Map_Ground(bbx,bby)=0 ' Remove this ground item from the world endif Bullet_X(b)=-1000 ' destroy bullet BulletCountChanged=1 else ' Check for air targets for e=1 to 10 if Enemy_OnRadar(e) then diffx=abs(Enemy_X(e)-Bullet_X(b)) if diffx<1 then diffy=abs(Enemy_Y(e)-Bullet_Y(b)) if diffy<1 then Enemy_Health(e)=Enemy_Health(e)-Player_Damage if Enemy_Health(e)<1 then StartExplosion(Enemy_X(e),Enemy_Y(e),0) 'Respawn enemy Enemy_X(e)=10+rnd*230 Enemy_Y(e)=10+rnd*230 Enemy_Angle(e)=rnd*6 Enemy_Health(e)=6 end if Bullet_X(b)=-1000 BulletCountChanged=1 end if end if end if next e end if else 'Remove this bullet from active service Bullet_X(b)=-1000 BulletCountChanged=1 end if end if 'Now check and see if we need to respawn a new bullet if Player_Fire>0 and Bullet_X(b)=-1000 and Player_Ammo>0 then PlaySound(1) ' Gunfire BulletCountChanged=1 ' Create new bullet if Player_Fire=1 then Bullet_X(b)=Player_X+cl*0.2 Bullet_Y(b)=Player_Y+sl*0.2 end if if Player_Fire=2 then Bullet_X(b)=Player_X+cl*-0.2 Bullet_Y(b)=Player_Y+sl*-0.2 endif if Player_Fire=3 then Bullet_X(b)=Player_X+cl*0.4 Bullet_Y(b)=Player_Y+sl*0.4 end if if Player_Fire=4 then Bullet_X(b)=Player_X+cl*-0.4 Bullet_Y(b)=Player_Y+sl*-0.4 endif ' Set direction as straight up from player Bullet_DX(b)=sl*1 Bullet_DY(b)=-cl*1 Player_Fire=Player_Fire-1 Player_Ammo=Player_Ammo-1 end if next b 'Compact the bullet arrays MaxBullets=0 for t=1 to 40 if Bullet_X(t)<>-1000 then MaxBullets=MaxBullets+1 Bullet_X(MaxBullets)=Bullet_X(t) Bullet_Y(MaxBullets)=Bullet_Y(t) Bullet_DX(MaxBullets)=Bullet_DX(t) Bullet_DY(MaxBullets)=Bullet_DY(t) if t>maxBullets then Bullet_X(t)=-1000 endif next t end sub sub DrawUserInterface() ' Draw User Interace box 380,0,260,400,1,rgb(255,255,255),rgb(64,32,0) ' Right hand panel box 0,380,380,20,1,rgb(255,255,255),rgb(64,32,0) ' bottom panel ' Update satelite radar page write SCREEN_UI_ELEMENTS Radar_Step=Radar_Step+1 if Radar_Step=10 then Radar_Step=0 line 20,5+Radar_Line/2,170,5+Radar_Line/2,1, RGB(50,200,50) ' Blank out this line ready for pixels end if y = Radar_Line startx=Radar_Step*30 for t=startx to startx+29 step 2 tempa=Map_Health(t,y)+ Map_Health(t+1,y)+Map_Health(t,y+1)+Map_Health(t+1,y+1) tempb=Map_Health(t,y+2)+ Map_Health(t+1,y+2)+Map_Health(t,y+3)+Map_Health(t+1,y+3) if Map_Health(t,y)+ Map_Health(t+1,y)+Map_Health(t,y+1)+Map_Health(t+1,y+1)>0 then pixel 20+t/2,5+Radar_Line/2,rgb(red) endif next t if Radar_Step=9 then ' Move to next line Radar_Line = Radar_Line+4 if Radar_Line=300 then Radar_line=0 if Radar_Line<294 then line 20,5+Radar_Line/2+2,170,5+Radar_Line/2+2,1, RGB(200,200,250) ' Draw a white line scanning down endif page write SCREEN_BUFFER blit 0,0,410,25,210,370,SCREEN_UI_ELEMENTS,&B000 box 430+Player_X/2-4, 30+Player_Y/2-4, 9,9,1, RGB(yellow) ' Draw box in satelite radar 'Draw local Radar for e=1 to 10 if Enemy_OnRadar(e)=1 then diffx=(Enemy_X(e)-Player_X)*3 diffy=(Enemy_Y(e)-Player_Y)*3 newx=diffx*cl+diffy*sl newy=diffy*cl-diffx*sl if newy<35 then pixel 457+newx, 270+newy, rgb(yellow) ' If in boost mode items might shoot off bottomo radar endif next e pixel 457,270, rgb(white) Text 427,10, "Live Satellite Feed",,,,RGB(yellow),RGB(64,32,0) 'Draw compass arrow tempcl=cos(Player_Angle_Radians-0.785) ' -0.785 = Minus 45 degrees (but in radians) tempsl=sin(Player_Angle_Radians-0.785) tempcl2=cos(Player_Angle_Radians-2.356) tempsl2=sin(Player_Angle_Radians-2.356) 'front point p0x=550+(15*tempcl+15*tempsl) p0y=270+(15*tempsl-15*tempcl) p1x=550+(-15*tempcl-15*tempsl) p1y=270+(-15*tempsl+15*tempcl) p2x=p1x+(5*tempcl2+5*tempsl2) p2y=p1y+(5*tempsl2-5*tempcl2) p3x=p1x+(-5*tempcl2-5*tempsl2) p3y=p1y+(-5*tempsl2+5*tempcl2) triangle p0x,p0y,p1x,p1y,p2x,p2y,rgb(white), rgb(100,100,100) triangle p0x,p0y,p1x,p1y,p3x,p3y,rgb(white), rgb(100,100,100) colour RGB(black) print @(230, 190,1) "Ammo: " + str$(Player_Ammo) print @(230,215,1) "Fuel: " + str$(Player_Fuel) print @(230,240,1) "Armour: " + str$(Player_Armour) print @(230,265,1) "Boost" box 220,205,100,5,1,rgb(green),rgb(black) box 220,205,100*(Player_Ammo/Player_Max_Ammo),5,1,rgb(black), rgb(green) box 220,230,100,5,1,rgb(green),rgb(black) box 220,230,100*(Player_Fuel/Player_Max_Fuel),5,1,rgb(black), rgb(green) box 220,255,100,5,1,rgb(green),rgb(black) box 220,255,100*(Player_Armour/100),5,1,rgb(black), rgb(green) box 220,280,100,5,1,rgb(green),rgb(black) box 220,280,100*(Player_Boost_Charge/100),5,1,rgb(black), rgb(green) colour RGB(green) print @(10,385,1) "Score: " +str$(Player_Score); if High_Score_Cursor=1 then print @(110,385,1) "HIGH SCORE !!!"; else print @(110,385,1) "Rank " + str$(High_Score_Cursor) + " Next @ " +str$(HighScore(High_Score_Cursor-1)); end if print @(280,385,1) "Cash $" + str$(Player_Money); end sub sub LoadHighScoreTable() on error skip open "highscore.dat" for input as #1 if MM.ERRNO=0 then for i=1 to 100 input #1, HighScore(i) next i close #1 else ' Create new file for i=1 to 100 HighScore(i)=(101-i)*500 next i WriteHighScoreTable() endif end sub sub WriteHighScoreTable() open "highscore.dat" for output as #1 for i=1 to 100 print #1, HighScore(i) next i close #1 end sub sub UpdateHighScoreTable(score) for i=1 to 100 if score >HighScore(i) then ' This is the spot to insert 'Move everything down one for j=99 to i step -1 HighScore(j+1)=HighScore(j) next j HighScore(i)=score exit for endif next i WriteHighScoreTable() end sub sub ResetGameVariables Player_Angle_Degrees = 0 ' Angle in degrees of the players helicopter Player_Angle_Radians = 0 ' Derived from Player_Angle_Degrees (read only) Player_X = 150 ' Player X co-ordinate in 300 x 300 world Player_Y = 150 ' Player Y co-ordinate in 300 x 300 world Player_Inertia_X=0 Player_Inertia_Y=0 Player_Boost=0 Player_Boost_Charge=0 Player_Armour=100 Player_Ammo=1000 Player_Max_Ammo=1000 Player_Fuel=100 Player_Max_Fuel=100 Player_Damage=1 Player_Score=0 Player_Money=2000 Player_Hover_Count=0 ' Used to detect if the player is hovering long enough to refuel Player_Hover_Limit=50 Player_Gun_Count=2 Player_Speed=0.25 High_Score_Cursor=100 menuCursor=0 menuTextCursor=1 menuTextLine=1 HighScoreBillBoard=1 ' LastHighScore=40000 end sub sub DrawHighScoreScreen() page write 1 blit 0,0,0,0,640,400,SCREEN_HIGHSCORE Colour_Cycle%=Colour_Cycle%+1 if Colour_Cycle%>20 then Colour_Cycle%=1 map(255)=rgb(0,0,255) for t=1 to 20 map(t)=rgb(0,0,0) if t=Colour_Cycle% then map(t)=rgb(0,0,255) next t map set font 3 for t=0 to 9 colour rgb(yellow) font 3 if HighScore(HighScoreBillBoard+t)=LastHighScore then colour rgb(green) font 5 print @(340,60+t*30,1) "Last Score" box 98,58+t*30,500,30,1,rgb(green) endif print @(100,60+t*30,1) str$(HighScoreBillBoard+t) print @(170,60+t*30,1) str$(HighScore(HighScoreBillBoard+t)) next t color rgb(red) font 5 print @(200,5,1) "HIGH SCORERS" font 3 print @(80,30,1) "Rank Score" font 7 colour rgb(yellow) print @(200,380,1) "Press 'space' to continue" font 1 print @(290,290,1) "CREDITS" print @(290,305,1) "Game Design and Programming by Pete Cotton" print @(290,320,1) "(Poorly drawn) graphics by Pete Cotton" print @(290,335,1) "Music by 'stranger' on ModArchive.com" print @(290,350,1) "Title page generated by photofunia.com" font 7 if LastHighScore <>0 and HighScoreBillboard<91 and HighScore(HighScoreBillBoard+5)>LastHighScore then HighScoreBillboard=HighScoreBillBoard+1 endif ScanKeyboard() if kbd_space then GameState = GAME_STATE_START_SCREEN debounce=1 ' stop the space being registered straight away on the next screen map reset map(32)=RGB(0,0,0) ' Remap my 'black' map(68)=RGB(32,32,32) map set endif end sub sub DrawMenuScreen() blit 0,0,0,0,640,400,SCREEN_BLUEPRINT colour RGB(green) font 4 print @(0,0,1) "Mission Briefing" font 7 menuText$(1)= "The International Terrorist Organisation Red Dawn are planning an attack" menuText$(2)= "on the World Leaders Summit in Kirzmekistan. Their base of operations has" menuText$(3)= "been located, but it is too remote for friendly forces to reach it in time" menuText$(4)= "to stop the attack. You have been authorised to take the prototype Helix" menuText$(5)= "HX-9000 attack helicopter and cause as much damage to the base as possible." menuText$(6)= "The base is heavily defended with surface to air missiles. However, you" menuText$(7)= "will be able to re-arm and refuel by hovering over arms and fuel dumps." menuText$(8)= " Good luck pilot!" menuTextCursor=menuTextCursor+1 for txt=1 to 8 if menuTextLine>txt then print @(2,6+12*txt,1) menuText$(txt) endif if menuTextLine=txt then print @(2,6+12*txt,1) mid$(menuText$(txt),1,menuTextCursor) if menuTextCursor=len(menuText$(txt)) then menuTextCursor=1:menuTextLine=menuTextLine+1 endif next txt ScanKeyboard() Colour RGB(yellow) font 1 print @(10,115,1) "You have $" + str$(Player_Money) + " to spend" print @(10,130,1) "Use cursor keys to navigate, and 'space' to buy" 'font 7 if Player_Max_Ammo<4000 then Colour RGB(white) ammo_cost=1000 * (2^(Player_Max_Ammo/1000)) if Player_Money0 then colour RGB(white) hover_cost=1000*(2^((60-Player_Hover_Limit)/10)) if Player_Money0 then menuCursor=menuCursor-1 if kbd_space then ' try and purchase if menuCursor=0 and Player_Money>= ammo_Cost then Player_Money=Player_Money-ammo_Cost:Player_max_Ammo=Player_Max_Ammo+1000 if menuCursor=1 and Player_Money>= fuel_Cost then Player_Money=Player_Money-fuel_Cost:Player_max_Fuel=Player_Max_Fuel+50 if menuCursor=2 and Player_Money>= damage_Cost then Player_Money=Player_Money-damage_Cost:Player_Damage=Player_Damage+0.5 if menuCursor=3 and Player_Money>= hover_Cost then Player_Money=Player_Money-hover_Cost:Player_Hover_Limit=Player_Hover_Limit-10 if menuCursor=4 and Player_Money>= 2000 then Player_Money=Player_Money-2000:Player_Gun_Count=4 if menuCursor=5 and Player_Money>= speed_Cost then Player_Money=Player_Money-speed_Cost:Player_Speed=Player_Speed+0.05 if menuCursor=6 then if GameState=GAME_STATE_START_SCREEN then GameState=GAME_STATE_RUNNING GenerateWorld() else GameState=GAME_STATE_RUNNING endif endif endif endif if menuCursor<0 then menuCursor=0 'Debounce keyboard if kd=0 then debounce=0 else debounce=1 end if end sub sub PlaySound(snd) if snd=1 then play modsample 6,1,MasterVol/2 if snd=2 then play modsample 7,2,MasterVol if snd=3 then play modsample 8,boomChannel,MasterVol boomChannel=boomChannel+1 if boomChannel=5 then boomChannel=3 endif end sub sub GenerateWorld() page write 0 cls load png "assets\title_8bit3.png",0,0 print "Please wait while we randomly generate the world." print "=================================================" print print "Clearing out squatters..." for x=1 to 300 for y=1 to 300 Map_Ground(x,y)=0 Map_Health(x,y)=0 next y next x print "Paving roads..." 'Draw the roads 'Outer edge for x=11 to 289 Map_Ground(x,11)=27 Map_Ground(x,189)=27 Map_Ground(11,x)=12 Map_Ground(189,x)=12 next x 'In between buildings for x=11 to 289 step 28 for y=11 to 289 Map_Ground(x,y)=12 Map_Ground(y,x-1)=9 Map_Ground(y,x)=27 next y next x print "Populating world...." ' Do random 6 line vertical and horizontal rows for a=1 to 2000 x1=12+rnd*270 y1=12+rnd*276 x2=12+rnd*276 y2=12+rnd*270 t1=int(rnd*7) type1=2 ' Yellow house if t1=1 then type1=13 ' small horizontal power if t1=2 then type1=10 ' oval power thingy if t1=3 then type1=11 ' Hatch if t1=4 then type1=6 'Ammo if t1=5 then type1=3 'Fuel if t1=6 then type1=29 'k30 yellow strip type2=type1 if type1=29 then type2=30 ' vertical yellow stripe count=int(rnd*4)+1 for j=0 to count if Map_Ground(x1+j,y1)=0 then Map_Ground(x1+j,y1)=type1 if Map_Ground(x1+j,y1+1)=0 then Map_Ground(x1+j,y1+1)=type1 if Map_Ground(x2,y2+j)=0 then Map_Ground(x2,y2+j)=type2 if Map_Ground(x2+1,y2+j)=0 then Map_Ground(x2+1,y2+j)=type2 next j next a print "Flaunting bylaws...." 'Random indivdiual squares for a=1 to 1000 x1=12+rnd*276 y1=12+rnd*276 if Map_Ground(x1,y1)=0 then Map_Ground(x1,y1)=33 next a print "Flooding poor areas...." for y=0 to 300 for x=0 to 300 if x<10 or x>290 or Y<10 or Y>290 then ' sea Map_Ground(x,y)=22 else if x=10 then Map_Ground(x,y)=20 else if x=290 then Map_Ground(x,y)=16 else if y=10 then Map_Ground(x,y)=14 else if y=290 then Map_Ground(x,y)=18 else if y=149 or y=150 or y=151 then Map_Ground(x,y)=9 endif ' else if rnd<0.5 and Map_Ground(x,y)=0 then ' Map_Ground(x,y)=int(rnd*13)+1 next x next y Map_Ground(10,10)=21 Map_Ground(290,10)=15 Map_Ground(10,290)=19 Map_Ground(290,290)=17 Map_Ground(150,150)=10 Map_Ground(151,150)=10 Map_Ground(152,150)=10 Map_Ground(153,150)=10 Map_Ground(154,150)=10 Map_Ground(155,150)=10 print "Having a coffee break" ' Now do raised section ' split 280x280 grid into 10x10. Each one has a raised section for y=1 to 10 for x=1 to 10 tlx=10+(x-1)*28 tly=10+(y-1)*28 'large square for k=2 to 24 SetGround(tlx+k,tly+2,14) SetGround(tlx+k, tly+24,18) SetGround(tlx+2,tly+k,20) SetGround(tlx+24,tly+k,16) next k 'corners SetGround(tlx+2,tly+2,21) SetGround(tlx+24,tly+2,15) SetGround(tlx+2,tly+24,19) SetGround(tlx+24,tly+24,17) tlx2=tlx+int(rnd*6)+3 tly2=tly+int(rnd*6)+3 width=int(rnd*10)+2 height=int(rnd*5)+2 'First small grid and duplicate below it for k=tlx2 to tlx2+width SetGround(k,tly2,14) SetGround(k,tly2+height,18) next k for k =tly2 to tly2+height SetGround(tlx2, k,20) SetGround(tlx2+width,k,16) next k SetGround(tlx2,tly2,21) SetGround(tlx2+width,tly2,15) SetGround(tlx2,tly2+height,19) SetGround(tlx2+width,tly2+height,17) 'Duplicate grid below it tly3=tly2+height+5 height2=int(rnd*4)+2 for k=tlx2 to tlx2+width SetGround(k,tly3,14) SetGround(k,tly3+height2,18) next k for k =tly3 to tly3+height2 SetGround(tlx2, k,20) SetGround(tlx2+width,k,16) next k SetGround(tlx2,tly3,21) SetGround(tlx2+width,tly3,15) SetGround(tlx2,tly3+height2,19) SetGround(tlx2+width,tly3+height2,17) 'bridge between the two bw=rnd*width+1 if bw+33 then for k=tlx4 to tlx4+width4 SetGround(k,tly4,14) SetGround(k,tly4+height4,18) next k for k =tly4 to tly4+height4 SetGround(tlx4, k,20) SetGround(tlx4+width4,k,16) next k SetGround(tlx4,tly4,21) SetGround(tlx4+width4,tly4,15) SetGround(tlx4,tly4+height4,19) SetGround(tlx4+width4,tly4+height4,17) end if next x next y print "Counting costs...." CountOfBuildings=0 for x=0 to 300 for y=0 to 300 a=Map_Ground(x,y) if a=13 or a=2 then Map_Health(x,y)=10 CountOfBuildings=CountOfBuildings+1 endif if a=6 or a=3 then Map_Health(x,y)=5 CountOfBuildings=CountOfBuildings+1 endif if a=10 then Map_Health(x,y)=1 CountOfBuildings=CountOfBuildings+1 endif if a=33 then Map_Health(x,y)=30 CountOfBuildings=CountOfBuildings+1 endif next y next x lt=timer frameCount=0 end sub sub SetGround(x%,y%,v%) Map_Ground(x%,y%)=v% Map_Health(x%,y%)=0 end sub sub CalculateScreenAreaBasedOnAngle() ' For each 5 degree angle increment, work out what the min and max values ' for the x and y offsets are to fit everything on the screen ' I used to just do -9 to +9 for both, but this causes a lot of wasted ' processing time. page write 0 for k = 0 to 360 ' *4 for angle angleRad= (k/180) * 3.1415 cl5 =cos(angleRad) sl5 =sin(angleRad) minx=0 maxx=0 for j=-9 to 9 ' xaxis miny=0 maxy=0 diffx5 = j*32 diffxcl5 = diffx5*cl5 diffxsl5 = diffx5*sl5 for s=-9 to 9 ' yaxis diffy5 = s*32 '+16 ' x2 = diffx*cos(Player_Angle_Radians)+diffy*sin(Player_Angle_Radians) ' y2 = diffy*cos(Player_Angle_Radians)-diffx*sin(Player_Angle_Radians) x5 = diffxcl5+diffy5*sl5 y5 = diffy5*cl5-diffxsl5 if x5>-232 and x5<200 and y5>-232 and y5<200 then ' This grid is visible at this angle if jmaxx then maxx=j if smaxy then maxy=s endif next s Grid_Min_Y%(k,j+10)=miny Grid_Max_Y%(k,j+10)=maxy ' print str$(Grid_Min_X%(k)) + " " + str$(Grid_Max_X%(k)) + " " +str$(Grid_Min_Y%(k,j+10)) + " " + str$(Grid_Max_Y%(k,j+10)) ' for grog=1 to 10000: next grog next j ' At this stage minx,maxx, miny,maxy should hold the optimal sizes for this angle Grid_Min_X%(k)=minx Grid_Max_X%(k)=maxx ' print str$(Grid_Min_X%(k)) + " " + str$(Grid_Max_X%(k)) + " " +str$(Grid_Min_Y%(k,j+10)) + " " + str$(Grid_Max_Y%(k,j+10)) ' for grog=1 to 10000: next grog next j ' At this stage minx,maxx, miny,maxy should hold the optimal sizes for this angle Grid_Min_X%(k)=minx Grid_Max_X%(k)=maxx ' print str$(Grid_Min_X%(k)) + " " + str$(Grid_Max_X%(k)) + " " +str$(Grid_Min_Y%(k,j+10)) + " " + str$(Grid_Max_Y%(k,j+10)) 'for grog=1 to 1000000: next grog next k open "gridarray.dat" for output as #1 for k=0 to 360 print #1, Grid_Min_X%(k) print #1, Grid_Max_X%(k) for j=0 to 20 print #1, Grid_Min_Y%(k,j) print #1, Grid_Max_Y%(k,j) next j next k close #1 end sub