

'**********************************  S T A R  B L A S T  (Begun on 2018.4.16)  ************************************

' Last Edit: 2018.7.10 / Day 26

'-------------------------------
' N E W E S T  Features/Changes:
'-------------------------------

'* Objects now break up into  T W O  or  T H R E E  smaller objects, depending on
'  the Round #.  Possibly, I'll make it so Player can choose 2 or 3 at Intro Screen.

'* ANIMATION added: GREEN Power-Ups and RED Drainers now boast a cool ELECTRIC action.
'  Plus, your Ship in motion now has ENGINE exhaust, or whatever you wanna call it.

'* Structure is now in place for on-screen MESSAGES.  They will remain for a
'  few seconds and can be cleared w/ almost any keyboard input.  Values must
'  be set for Msg.Time, Msg.Dur, Message$ and the RGB colors: MR, MG, MB.

'* Ship can now be made to SLIDE sideways by holding down <Shift> while pressing
'  an ARROW key or moving the MOUSE sideways.

'* Higher Rounds can be accessed by entry of 2-digit numbers during a game.

'* A special Drainer Object has been added.  When destroyed, your Ship's energy level
'  drops by 50%.  Consequently, if Energy was < 50 to begin with, you LOSE a Ship.
'  (Should Shield also drop?  Find: Energy = Energy - 50 ': Shield.Up = 50)

'* Objects will now make right-angle TURNS and/or VANISH and reappear elsewhere
'  just to make things more challenging.  As they vanish, a "phantom" or residual
'  Object fades from old location and into new one.

'* Corner Map can now have an opaque background (Alt-M).

'* Extra/Bonus Ships (Lives) are awarded, and the next Score level for a Bonus
'  is displayed below Score;  but NO BONUS if Player has too many Ships already.

'* Expanding CIRCLEs simulate Ship exploding when it's hit and Energy is low.

'* Game's progress can now be SAVED to disk. (May need more work.)

'* Player can now turn OFF/ON the Expanding and/or Triple Projectiles

'* Several  A S T E R O I D S  have been fashioned from my photographs
'  of actual rocks/stones.  The smaller versions of them are the same ones,
'  only shrunken by the _PUTIMAGE stmts.

'* Object will now SPLIT into TWO SMALLER Objects when hit.

'* Sound can be turned ON/OFF using Ctrl-S.
'  Also, CHEAT KEYS Ctrl-O will JUMP us into Super Object Mode, and Ctrl-R jumps us to
'  the next Round.  (Intended for TESTING purposes.)

'* SUPER OBJECT now appears SOMEWHERE in nearby space after the last Normal Object is destroyed.
'  It's surrounded by multiple SHIELDS, each of which must be hit by numerous Projectiles.  Guide
'  ARROWS appear when the Super Object is farther away and no blips are shown on the Corner Map.

'* M O U S E  input is now recognised.  Can now fire w/ SPACEBAR while also TURNING, accelerating, etc.

'* 1: Triple-Projectile Spread - When Energy is high, Ship fires 3 instead of 1; they spread/diverge as they go.
'  2: Plasma Bomb (F5, S/D/F/G) is now available when Energy is high enough.

'* Protective invisible Shield:  Each time an Object touches the Ship, the Shield's power
'  drops a little;  when all power has gone....it BEEPs.....for now.

'----------
' N O T E :
'----------
'(Latest @ Top)

'* Projectiles' range (MaxDist) is adjusted w/ every LaserBall fired, taking into consideration
'  the current Round, Skill, Energy level, etc.  [Find: IF MaxDist < 30 THEN MaxDist = 30]

'* Currently, if Ship is lost in Super mode, Round DOES NOT ADVANCE.  Do we want it this way?

'* To better control how often Objects vanish in the different Skill levels, maybe
'  change "AND RND * 999 < (25 + Skill * 2)"  ---->  "AND RND * (999 + Skill * 20) < (25 + Skill * 2)"

'* Changed "Rad3 = 15" to "Rad3 = 20" for non-Asteroids mode.

'* Prog. ver. 03cc has the _NEWIMAGE(640, 480, 256) that I tried to use for the
'  Intro Screen, but upon exiting Play Game, the Menu is functional but invisible!

'  THIS copy was meant for UPLOAD, with many COMMENTED lines removed.        < = = = = = = = = = = = = = = = = = = =

'* If Energy drops too much/little with each LaserBall fired...
'  Find: Energy = Energy - (1 + PNum)   and   PRate = .14 - Energy / 1600: IF PRate < .105 THEN PRate = .105

'* Test w/o using OMax as temp holder.  Find: "OMax = Obj.Max"
'* If  Next_Round  is unused, delete all instances of it.
'* Changed line (added 2nd part): Obj.Cnt = Obj.Cnt + 1: Obj.Max = Obj.Max + 2
'* Added "IF Exist(O) THEN " to 2 lines in Jump Ship;  mind it carefully.

'--------------
' I S S U E S :
'--------------

'* Not sure, but it seemed that the Energy Drainer Object was already ACTIVE upon
'  starting a new Round, after activating in previous Round.  How and at what point
'  I went to next Round, I do not remember.  Find: ED.Active  or  ED.Max

'* When Objects are splitting, it may be necessary to improve the check to
'  make sure they don't MOVE TOGETHER too closely.
'  Find: IF OO >= Obj.Max + Split.Num THEN

'* If the behaviour of the ARROW keys with and w/o _KEYDOWN is the same, then
'  there's no need for variable TI (turn increment)...
'  Find: THEN TI = 2: GOTO TurnLeft

'* When a game is Resumed in Super Object mode, the S.O.'s Shields are not as they should be.          <------------
'  (Partly fixed by adding variables to Saved file, but needs work.)
'  Find:

'* Tried to prevent the Phantom Object's CIRCLEs being drawn when off-screen, but long version of
'  IF...THEN  block opener doesn't do the trick.  No big deal, really.
'  Find: IF Jumping(O) AND Jump.X(O) >= 0 AND Jump.X(O) < 1280 AND Jump.Y(O) >= 0 AND Jump.Y(O) < 720 THEN

'* NoSnd is now saved to disk in Save Game; must it also be saved in the .ini file?      [FIXED?]
'  If Ctrl-S makes only the Snd OFF sound, then probably YES.

'* MENU/INTRO Screen does NOT appear when we exit from game!      [FIXED]
'  (Per forum advice, I added _AUTODISPLAY after Play Game loop.)
'  Find: CLEAR: END '* * * * EXIT PROGRAM here

'* When Game is SAVED during Super Object, that play mode appears to START OVER.
'  Make sure all needed VARIABLES are saved to file.
'  Find: IF Super.Obj THEN Super.Obj = 0: Obj.Cnt = 0

'* Larger Objects aren't hit unless Projectile is much closer to center than it should need to be.

'* Sometimes 2 Added Objects move together TOO CLOSE to each other, despite preventative measures.
'  Find: IF OO = Obj.Max + 2 AND Stp.X(OO) = Stp.X(OO - 1) AND Stp.Y(OO) = Stp.Y(OO - 1) GOTO Get.Stp

'* Make sure that both the 100 x 100 and 120 x 120 asteroid image files work just as well.
'  Find: SB_Graphics/Asteroid_

'* On a couple of occasions, LaserBalls WOULD NOT FIRE.
'  Find: IF TIMER - LastProj > PRate THEN CALL Fire_Laser

'* ALL Objects now SPLIT into smaller ones, but the MID-SIZED one sometimes seems      [FIXED?]
'  to become a SINGLE small one.  Also, and maybe related, Obj Cnt may show as 1
'  when there are NO OBJECTS remaining...
'  Find: FOR OOO = 1 TO OO - 1   and   FOR O = Obj.Max + 1 TO Obj.Max + 2   and   Add_Objects   and   IF O < Obj.Max THEN Obj.Max = O

'* When Ship reaches MaxSpeed, cannot change course w/o slowing first, except by MOUSE.     [Minor issue?]

'* Have point values and difficulty increase with the Rounds.  And BStp and others.          <---------
'  Find: Score = Score +

'  In "has run its course" section of sub Projectiles, should the FOR/NEXT loop begin
'  with   FOR PP = 1 TO PCnt - PNum   or   FOR PP = P TO PCnt - PNum  ?

'* Also: Make sure all P-Bomb stuff works correctly.  I think it showed 0 Objects hit, yet
'  awarded some Bonus points anyway.  Also, when fresh Objects are SCATTERED, if I use the
'  P-Bomb immediately, the Hit count seems somewhat high, like 9 or 10.  Make sure all
'  instances of "Objects.Hit = 0" are where they should be.  And "PB.Bonus = 0", too.
'  Find: Objects.Hit   and  : Objects.Hit = 0: Os.Hit = 0

'  Currently NOT SHOWING how many Hits from P-Bomb!                                      <---------
'  Find: IF TIMER - PB.Time < 3 THEN

'* Maybe improve structure of lines including:                               <---------
'  IF PRad(P) < 10 THEN PRad = 3 ELSE PRad = PRad(P) / 4

'* Seems that sometimes the same Projectile "destroys" an Object repeatedly, resulting in     [FIXED?]
'  Obj Cnt RAPIDLY going < 0.  May happen more often when Projectiles  E X P A N D.
'  Maybe use arrays, such as Hit.X(P) & Hit.Y(P), to mark that Object as destroyed, based
'  on its X/Y at the moment of initial impact.
'  Find: Old.Obj

'* For more precise Ship-Object collision, maybe tweak the 380 in line below:
'  IF ABS(Ship.X - Obj.X) < ObRad AND ABS(380 - Obj.Y) < ObRad THEN


_FULLSCREEN , _SMOOTH: _MOUSEHIDE

DO 'until Intro/Menu Screen is exited

    'SCREEN 0: WIDTH 80, 25: : BEEP  * * * * DELETE here?

    DO 'until Play Game is exited   o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o

        DEFINT A-Z: OPTION BASE 1: RANDOMIZE TIMER ': ON ERROR GOTO Errors

        '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        DIM SHARED Score AS SINGLE, NexBon AS SINGLE, Msg.Time AS SINGLE, Asteroids, Clouds,_
          Skill, Round, Lives, Snd, NoSnd, O, OO, Resumed_Game, TEST.SLEEP '* * * * TESTING ONLY * * * *

        'Background-image & "Window" variables...

        DIM SHARED X AS SINGLE, Y AS SINGLE, Star1.X AS SINGLE, Star1.Y AS SINGLE, Star2.X AS SINGLE, Star2.Y AS SINGLE

        'Ship-related variables & arrays...

        DIM SHARED Ship.X, Ship.Y, Angle, Inc AS SINGLE, MaxSpeed, Ship.Destroyed, DesTime AS SINGLE
        DIM SHARED Step_X AS SINGLE, Step_Y AS SINGLE, Energy AS SINGLE, BLine, EOCnt, Shield.Up '* * * * Shield.Up may not need to be shared GLOBALLY * * * *

        'Object & Super Object...

        DIM SHARED Split.Num, OZone, ObRad, Rad1, Rad2, Rad3, Obj.Cnt, Obj.Max, PwrUps, Rock.Cnt, Drainer, ED.Max, ED.Active 'Energy Drainer
        DIM SHARED Super.Obj, Shields, Outer.Clr, BugCtr, Bug.X AS SINGLE, Bug.Y AS SINGLE, BStp, Sup.X AS SINGLE, Sup.Y AS SINGLE 'Super Object + its "Bug"
        DIM SHARED Flash.X, Flash.Y, FRad, Objects.Hit, Os.Hit, PB.Time AS SINGLE, Jump.OK, Turn.OK

        REDIM SHARED Hit.X(12), Hit.Y(12) 'The 12 here is just and estimate of how many Objects the P-Bomb may reach

        Max = 160 '99 'Max. # of Objects
        DIM SHARED Obj.X(Max), Obj.Y(Max), ObRad(Max), Stp.X(Max), Stp.Y(Max),_
          Rock(Max), Exist(Max), Jumping(Max), Jump.X(Max), Jump.Y(Max) : Max = 0 'Objects-related arrays

        '!!!  Values loaded from SAVED-GAME file:  !!!

        '  Skill, Lives, Snd, NoSnd, Round, Score, Clouds, Asteroids
        '  Step_X, Step_Y, Angle, Energy, Shield.Up, MaxDist, Ship.Destroyed
        '  Obj.Max, Obj.Cnt, Super.Obj, Drainer, PRate, Expand, Tri.Ball


        'Next: Projectiles' X/Y, direction, radius, distance traveled, rapid-fire regulator, etc.

        DIM SHARED PCnt, PNum, PMax, Expand, Tri.Ball, PRate AS SINGLE, LastProj AS SINGLE 'Tri-Ball ON = 3 Projectiles can emerge
        PMax = 24 'Max. # of on-screen Projectiles
        DIM SHARED PX(PMax), PY(PMax), Live(PMax), Ang(PMax), PRad(PMax) AS SINGLE, Dist(PMax), MaxDist

        '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        Lives = 3: Round = 1: Ship.X = 640: Ship.Y = 360: Inc = .25: MaxSpeed = 30
        Snd = -1: Expand = -1: Tri.Ball = -1: BStp = 3 '* * * * Some values are set/reset in MENU or data file * * * *
        '!!!  MaxDist (Projectiles) will either be read from SAVED-GAME file, or set (based on Round) in Scatter Objects  !!!

        Asteroids = -1: Clouds = -1: Jump.OK = -1: Turn.OK = -1 ': Map.BG = 0 '<------ If Map BG starts as TRANSPARENT, it need not be included here -------


        IF NOT Resumed_Game AND _FILEEXISTS("SB_User_Pref.ini") THEN
            OPEN "SB_User_Pref.ini" FOR INPUT AS #1 'Load the User Preferences
            INPUT #1, Skill, Asteroids, Clouds, Snd, Expand, Tri.Ball, Jump.OK, Turn.OK, Map.BG
            CLOSE 1
        END IF: IF Snd THEN NoSnd = 0 ELSE NoSnd = -1


        '===================  P r e s e n t   the   I n t r o   S c r e e n  ===================

        :::::::::::::::::::::: CALL Intro_Screen 'Display the Menu :::::::::::::::::::::::

        '=======================================================================================

        'MaxSpeed........Ship's maximum speed
        'ObRad...........Objects' radius (CIRCLEs only, not incl. Shield/Outer Ring)
        'OZone...........Projectile's minimum distance from Object's center for a HIT
        'Expand..........Will Projectiles expand as they travel?
        'Tri.Ball........Single or Triple Projectile
        'BStp............How fast the "Bug" travels from Super Object's center


        ''*******************  SET the BACKGROUND-IMAGE PAGES  *********************

        'Large& = _NEWIMAGE(2560, 1440, 32) 'Large image page (e.g. Nebula w/ Stars)

        'Star_BG1& = _NEWIMAGE(2560, 1440, 32) 'Large BG for Stars (nearer)
        'Star_BG2& = _NEWIMAGE(2560, 1440, 32) 'Large BG for Stars (farther)
        ''(Stars will be randomly PSET'd onto these 2 pages.)
        ''**************************************************************************

        Scr& = _NEWIMAGE(1280, 720, 32) 'Program screen ("Window" onto BG image)

        SCREEN Scr& 'Use the "Window" screen

        ':::: Asteroids = -1:::: '* * * * To be set in future thru Menu or other method * * * *

        IF Asteroids THEN

            Rock1& = _LOADIMAGE("SB_Graphics/Asteroid_01c_100x100_P1280782.gif") 'Asteroid Image File
            Rock2& = _LOADIMAGE("SB_Graphics/Asteroid_02a_100x100_P1040670.gif")
            Rock3& = _LOADIMAGE("SB_Graphics/Asteroid_03a_100x100.gif") 'Unknown photo P#
            Rock4& = _LOADIMAGE("SB_Graphics/Asteroid_04_120x120.gif")
            Rock5& = _LOADIMAGE("SB_Graphics/Asteroid_05a_120x120_P1040214.gif")
            Rock.Cnt = 5 'How many "Asteroid" graphics I've prepared

            IF Skill = 3 THEN Rad1 = 54: Rad2 = 36: Rad3 = 20 ELSE Rad1 = 60: Rad2 = 45: Rad3 = 25 'Radii of the 3 (L/M/S) Asteroid sizes

        ELSE 'CIRCLEs only       * * * * Debug: ObRaD(O) =  * * * *

            IF Skill = 3 THEN Rad1 = 50: Rad2 = 27: Rad3 = 15 ELSE Rad1 = 55: Rad2 = 32: Rad3 = 18 'Radii of the "Orbs"
        END IF

        ':::: Clouds  = -1:::: '* * * * For TESTING only * * * *

        ''-------------- Load the Cloud Image File & Place It Onto Large BG Page... --------------
        'IF Clouds THEN
        '    Cloud_BG1& = _LOADIMAGE("SB_Graphics/Nebula_2560x1440_Tileable_Quartered_" + Cloud_Clr$ + "_01].png") 'Disk file:
        '    'Cloud_BG1& = _LOADIMAGE("SB_Graphics/Nebula (clouds only, red) [2560x1440_Tileable_Quartered_01].png") ', 32) 'Disk file:

        '    _DEST Large& 'Stars/Image placed onto Large blank image to be used as SOURCE in PUTIMAGE below
        '    _PUTIMAGE , Cloud_BG1& 'From disk file
        'END IF
        ''-----------------------------  S c a t t e r  S t a r s  -------------------------------     * * * *  M O V E D  into DO/LOOP within Play Game * * * *

        '_DEST Star_BG1&: Scatter_Stars_1 'Randomly scatter NEARER stars across Star BG #1
        '_DEST Star_BG2&: Scatter_Stars_2 'Randomly scatter FARTHER stars across Star BG #2

        ''(Star-scattering SUBs are near below)

        ''----------------------------------------------------------------------------------------


        _DEST Scr& 'The "Window" onto the various BG images


        CALL Play_Game(Large&, Star_BG1&, Star_BG2&, Scr&, Rock1&, Rock2&, Rock3&, Rock4&, Rock5&, Shields, Map.BG)

        CLEAR ': END '* * * * EXIT PROGRAM here because Menu won't appear again as it should * * * *

    LOOP 'Exit to Menu  o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o

LOOP 'Exit to System


Errors:

IF ERR = 9 THEN:: SOUND 111, 1:: _FONT 14:: LOCATE 24, 1:: COLOR _RGB(255, 55, 55):: PRINT "ERL:"; ERL:: TEST.SLEEP = 55

RESUME NEXT ': RETURN



SUB Intro_Screen

    SCREEN 12 ': _DEST 0 ': CLS

    Opt1.R = 12: Opt1.C = 30: Opt2.R = 13: Opt2.C = Opt1.C: Opt3.R = 15: Opt3.C = Opt1.C:
    KRow = 19: KCol = 27: IF Skill = 0 THEN Skill = 2

    LOCATE 5, 32: COLOR 9: PRINT "S t a r B l a s t"

    'Set Asteroids & Clouds status; if need be, swap values according to settings in User Prefs. file...

    ObType$ = "Asteroids": AltType$ = "Spheres  ": IF NOT Asteroids THEN SWAP ObType$, AltType$
    Cloud$ = "YES": AltCld$ = "NO ": IF NOT Clouds THEN SWAP Cloud$, AltCld$

    LOCATE Opt1.R, Opt1.C: COLOR 11: PRINT "Object Type: ";: COLOR 15: PRINT ObType$
    LOCATE Opt2.R, Opt2.C: COLOR 10: PRINT "Show Clouds: ";: COLOR 14: PRINT Cloud$
    LOCATE Opt3.R, Opt3.C: COLOR 9: PRINT "Skill Level:";: COLOR 11: PRINT Skill

    LINE (200, 155)-(436, 258), 5, B 'Box around Options

    LINE (200, 385)-(436, 385), 3, B

    LOCATE KRow, KCol:
    COLOR 7: PRINT "<SPACE> = Change Object Type": LOCATE , KCol + 5
    COLOR 3: PRINT "F9 = Change Clouds Y/N": LOCATE , KCol
    COLOR 7: PRINT " Arrows = Change Skill Level": LOCATE KRow + 7, KCol + 1:

    COLOR 15: PRINT "<Enter> = Play StarBlast!": PRINT: LOCATE , KCol
    IF _FILEEXISTS("SB_Saved_Game.dat") THEN COLOR 8: PRINT "      F3 = Load Saved Game"

    DO 'until Enter or Esc

        WHILE K$ = "": K$ = INKEY$: WEND: SOUND 111, .5

        IF K$ = CHR$(13) OR K$ = CHR$(27) THEN EXIT DO

        IF K$ = CHR$(0) + CHR$(61) AND _FILEEXISTS("SB_Saved_Game.dat") THEN Load_Game: EXIT DO 'F3 = Load Saved Game

        SELECT CASE K$

            CASE CHR$(32) '<Space> = Rocks/Orbs
                SWAP ObType$, AltType$
                LOCATE Opt1.R, Opt1.C: COLOR 11: PRINT "Object Type: ";: COLOR 15: PRINT ObType$

            CASE CHR$(0) + CHR$(67) 'F9 = Clouds On/Off
                SWAP Cloud$, AltCld$ ': IF Cloud$ = "YES" THEN Clouds  = -1 ELSE Clouds  = 0
                LOCATE Opt2.R, Opt2.C: COLOR 10: PRINT "Show Clouds: ";: COLOR 14: PRINT Cloud$

            CASE CHR$(0) + "H", CHR$(0) + "M" 'Arrows = Skill Level
                Skill = Skill + 1: IF Skill > 3 THEN Skill = 1

            CASE CHR$(0) + "P", CHR$(0) + "K" 'Arrows
                Skill = Skill - 1: IF Skill < 1 THEN Skill = 3

        END SELECT: K$ = ""

        LOCATE Opt3.R, Opt3.C: COLOR 9: PRINT "Skill Level:";: COLOR 11: PRINT Skill

    LOOP

    IF K$ = CHR$(27) THEN 'exit program entirely
        END

    ELSEIF K$ = CHR$(13) THEN '<Enter> pressed; save user prefs. & start Game...

        IF ObType$ = "Asteroids" THEN Asteroids = -1 ELSE Asteroids = 0
        IF Cloud$ = "YES" THEN Clouds = -1 ELSE Clouds = 0 '* * * * TEST

        '================  S a v e   U s e r   P r e f s.  ================
        OPEN "SB_User_Pref.ini" FOR OUTPUT AS #1 'Save User Preferences
        PRINT #1, Skill; Asteroids; Clouds; Snd; Expand; Tri.Ball; Jump.OK; Turn.OK; Map.BG
        CLOSE 1
        '==================================================================

    END IF

    'IF ObType$ = "Asteroids" THEN Asteroids = -1
    ':: IF Cloud$ = "YES" THEN Clouds  = -1 ELSE Clouds  = 0 '* * * * TEST
    ObType$ = "": AltType$ = "": Cloud$ = "": AltCld$ = ""

END SUB


SUB Scatter_Stars_1 'PSET will place Stars (NEARER and FASTER) onto destination page Star_BG1&

    '------------------------- R A N D O M  S T A R S  (CLOSER) -------------------------
    FOR I = 1 TO 150 'How Many Stars

        XX = RND(1) * 1280 'Random location in UL quarter of Large BG
        YY = RND(1) * 720 '(to be MIRRORED below)

        IF RND < .4 THEN Grey = 255: GOTO Put.CIRC 'Largest, closest, BRIGHTEST stars
        IF RND < .4 THEN Grey = 255: GOTO Put.Star 'Max BRIGHT for this star

        Get.Grey:
        Grey = RND * 100 + 150 'Mid to Full Brightness

        'Clr& = _RGB32(RND * 256, 0, RND * 256) 'Random Multi-Colored Stars
        Clr& = _RGB32(Grey, Grey, Grey) 'Random intensities of GREY only

        Put.Star:
        PSET (XX, YY), Clr&: PSET (XX + 1280, YY), Clr& 'Mirrored horizontally  * * * *  + 1280 or + 1279 ?  * * * *
        PSET (XX, YY + 720), Clr&: PSET (XX + 1280, YY + 720), Clr& 'Mirrored vertically & then both H & V
        GOTO NexStar

        Put.CIRC:
        CIRCLE (XX, YY), 1, Clr&: CIRCLE (XX + 1280, YY), 1, Clr& 'Mirrored horizontally  * * * *  + 1280 or + 1279 ?  * * * *
        CIRCLE (XX, YY + 720), 1, Clr&: CIRCLE (XX + 1280, YY + 720), 1, Clr& 'Mirrored vertically & then both H & V

        NexStar:
    NEXT '-------------------------------------------------------------------------------

END SUB


SUB Scatter_Stars_2 'Place stars that will appear FARTHER and SLOWER onto Star_BG2&...

    '------------------------ R A N D O M  S T A R S  (FARTHER) -------------------------
    FOR I = 1 TO 2500 'How Many Stars

        XX = RND(1) * 1280 'Random location in UL quarter of Large BG
        YY = RND(1) * 720 '(to be MIRRORED below)
        IF RND < .4 THEN Grey = 255: GOTO Put.Star 'More BRIGHT stars

        Get.Grey: 'Random grey shade...
        Grey = RND * 200: IF Grey < 10 GOTO Get.Grey 'Not too dim

        Clr& = _RGB32(Grey, Grey, Grey) 'Random intensities of GREY only

        Put.Star:
        PSET (XX, YY), Clr&: PSET (XX + 1280, YY), Clr& 'Mirrored horizontally
        PSET (XX, YY + 720), Clr&: PSET (XX + 1280, YY + 720), Clr& 'Mirrored vertically & then both H & V
    NEXT '-------------------------------------------------------------------------------

END SUB


SUB Play_Game (Large&, Star_BG1&, Star_BG2&, Scr&, Rock1&, Rock2&, Rock3&, Rock4&, Rock5&, Shields, Map.BG) '======================================================================

    DIM JC(156) '* * * * Maybe auto-REDIM _PRESERVE it when "out of range" error occurs? * * * *
    '                   (For the tri-splitting version, 156 should be the highest that Obj Max will ever get.)

    IF NOT Resumed_Game THEN
        X = 0: Y = 0: Energy = 60: Shield.Up = 100: MaxSpeed = 30 '* * * * Why doesn't the DIM SHARED in main module work for MaxSpeed ??? ***
        CALL Scatter_Objects 'Acquire random X/Y coords. of fresh Objects
    ELSE
        Resumed_Game = 0
    END IF

    Clr.R1 = 0: Clr.G1 = 100: Clr.B1 = 255 'RGB of Object #1 (may be various types of Objects at once)
    'Obj.Clr.2& = _RGB(100, 0, 255)


    SCREEN Scr&: Get_NexBon 'Determine when next Bonus Ship will be awarded

    'F1&  = _LOADFONT("/usr/share/fonts/truetype/liberation/LiberationMono-Bold.ttf", 28) ' , " BOLD") 'Font for Round, Score, etc.
    F1& = _LOADFONT("/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf", 28) ' , " BOLD") 'Font for Round, Score, etc.
    F2& = _LOADFONT("/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf", 25) 'Font for special MESSAGES
    ' "UNICODE" loads Unicode fonts such as cyberbit.ttf

    ''Snd_Pop& = _SNDOPEN("SB_Sounds/J_Pop_002.mp3") ', "VOL") 'Sound file for Object hit
    'Snd_Pop& = _SNDOPEN("SB_Sounds/J_Pop_001.wav", "VOL") 'Sound file for Object hit
    '_SNDVOL Snd_Pop&, 1: '_SNDCLOSE Snd.Name& '* * * * CLOSE it each time or NOT ?
    ''* * * * Debug: _SNDPLAY


    DO 'until Super Object is Destroyed or Game Exited


        '*******************  SET the BACKGROUND-IMAGE PAGES  *********************

        Large& = _NEWIMAGE(2560, 1440, 32) 'Large image page (e.g. Nebula w/ Stars)

        Star_BG1& = _NEWIMAGE(2560, 1440, 32) 'Large BG for Stars (nearer)
        Star_BG2& = _NEWIMAGE(2560, 1440, 32) 'Large BG for Stars (farther)
        '(Stars will be randomly PSET'd onto these 2 pages.)
        '**************************************************************************

        '))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

        IF Round / 2 = INT(Round / 2) THEN Cloud_Clr$ = "PURPLE" ELSE Cloud_Clr$ = "GREEN"
        'Cloud_Clr$ = "GREEN"

        ': :_FONT 14: : LOCATE 6, 1:: PRINT USING "Round: ##  Cloud_Clr$: &    "; Round; Cloud_Clr$: : SLEEP 4

        '-------------- Load the Cloud Image File & Place It Onto Large BG Page... --------------
        IF Clouds THEN
            Cloud_BG1& = _LOADIMAGE("SB_Graphics/Nebula_2560x1440_Tile_Quad_" + Cloud_Clr$ + "_01.png")
            'Cloud_BG1& = _LOADIMAGE("SB_Graphics/Nebula_2560x1440_Tile_Quad_PURPLE_01.png") 'Disk file:
            'Cloud_BG1& = _LOADIMAGE("SB_Graphics/Nebula (clouds only, red) [2560x1440_Tileable_Quartered_01].png") ', 32) 'Disk file:
            'Nebula_2560x1440_Tile_Quad_PURPLE_01]
            _DEST Large& 'Stars/Image placed onto Large blank image to be used as SOURCE in PUTIMAGE below
            _PUTIMAGE , Cloud_BG1& 'From disk file
        END IF
        '-----------------------------  S c a t t e r  S t a r s  -------------------------------

        _DEST Star_BG1&: Scatter_Stars_1 'Randomly scatter NEARER stars across Star BG #1
        _DEST Star_BG2&: Scatter_Stars_2 'Randomly scatter FARTHER stars across Star BG #2

        '(Star-scattering SUBs are near below)

        '----------------------------------------------------------------------------------------

        '))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

        _DEST Scr&


        DO UNTIL Lives = 0 'or <Esc> is pressed  > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

            CLS: _LIMIT 60

            IF Drainer > 0 AND Energy <= 0 THEN 'Energy was REDUCED to zero by zapping the Drainer
                Drainer = 0: Ship.Destroyed = -1: Msg.Time = TIMER: Msg.Dur = 7: MR = 255: MG = 60: MB = 20 'Message colors
                Message$ = "You zapped the ENERGY DRAINER with < 50% Energy remaining."
            END IF

            IF Tri.Ball AND NOT Super.Obj AND Energy >= 80 THEN PNum = 3 ELSE PNum = 1 '1 or 3 LaserBalls are fired (single in Super Obj. mode)

            '= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
            _PUTIMAGE (0, 0), Large&, 0, (X, Y)-(X + 1279, Y + 719) 'Show a portion of Source Image            [  ]
            '= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

            '_PUTIMAGE (0, 0), Stars& 'Starfield (transparent; will remain STATIC)
            '_PUTIMAGE (0, 0), Stars&, 0, (StarX, StarY)-(StarX + 1279, StarY + 719) 'Starfield (transparent; moves slower)
            _PUTIMAGE (0, 0), Star_BG1&, 0, (Star1.X, Star1.Y)-(Star1.X + 1279, Star1.Y + 719) 'Starfield (transparent; moves slower than Clouds)
            _PUTIMAGE (0, 0), Star_BG2&, 0, (Star2.X, Star2.Y)-(Star2.X + 1279, Star2.Y + 719) 'Starfield (transparent; moves somewhat faster)

            '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

            IF Map.BG THEN LINE (1, 1)-(255, 143), _RGB(0, 0, 0), BF 'Clear the stars for Map

            LINE (0, 0)-(256, 144), _RGB(60, 60, 60), B 'Map in UL corner (surrounds Play Area)                             O B J E C T S   M A P
            MX = 64: MY = 36 'UL corner of Play Area map
            LINE (MX, MY)-(MX + 128, MY + 72), _RGB(140, 120, 20), B 'Map-in-Map in UL corner (actual Play Area)
            '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


            ':::: LINE (1279 - 256, 0)-(1279, 144), _RGB(60, 60, 60), B '* * * * Map in UR corner for TESTING * * * *
            ':::: LINE (1279 - 256 + X / 10, Y / 10)-STEP(128, 72), _RGB(160, 160, 160), B


            IF Ship.Destroyed THEN '>< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< ><

                FOR S = 0 TO ExpCnt 'Explosion Count: # of rings drawn @ each iteration
                    _LIMIT 130

                    SELECT CASE S
                        CASE IS < 7
                            CIRCLE (Ship.X, Ship.Y), 40 + S * 20, _RGB(105 - S * 30, 40, 255 - S * 30)
                            'CIRCLE (Ship.X, Ship.Y), 60 + S * 20, _RGB(105 - S * 30, 40, 255 - S * 20)
                        CASE ELSE
                            CIRCLE (Ship.X, Ship.Y), 40 + (S - 6) * 20, _RGB(125 - (S - 6) * 20, 125, 255 - (S - 6) * 20) 'Bright expanding ring
                    END SELECT

                NEXT: S = 0: ExpCnt = ExpCnt + 1


                IF ExpCnt >= 12 THEN '(See Explosion Count above)

                    Lives = Lives - 1

                    IF Lives > 0 THEN

                        Ship.Destroyed = 0: ExpCnt = 0: Shield.Up = 100 'Must restore Shield power so Ship can be destroyed again

                        IF Super.Obj THEN

                            Scatter_Objects: _AUTODISPLAY 'Need to pause for text...

                            T$ = "R e p e a t   R o u n d "
                            COLOR _RGB(255, 20, 20), _RGBA(0, 0, 0, 0): _PRINTSTRING (640 - _PRINTWIDTH(T$) / 2, 210), T$ 'Transparent BG
                            'COLOR _RGB(95, 0, 0),: _PRINTSTRING (638 - _PRINTWIDTH(T$) / 2, 208), T$  * * * * DELETE if no drop shadow here

                            _DELAY 2: _DISPLAY 'Revert to delayed display

                        ELSE DesTime = TIMER 'Ship may need time to get clear of Objects

                        END IF

                        _DELAY 1 '            Many variables will be reset @ Scatter Objects

                    END IF
                END IF

            END IF 'Ship Destroyed  >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< >< ><



            IF Super.Obj THEN 'a single, larger Super Object

                CALL Super_Object(MX, MY, MClr&, Sup.X, Sup.Y) 'Draw/place the Super Object
                IF BugCtr > 0 THEN CALL Super_Bug

            ELSE 'many Normal (and a few Special) Objects

                FOR O = 1 TO Obj.Max 'Set each Object's Location & Direction...
                    IF Exist(O) THEN

                        'Set different color for special Power-Up or Drainer Object...

                        IF O <= PwrUps THEN 'Objs. #1 - #n are Power-Ups -------------
                            Obj.Clr.1& = _RGB(0, 255, 0)
                            MClr& = _RGB(0, 255, 80) 'Green dots on Map
                        ELSEIF O = Drainer THEN
                            Obj.Clr.1& = _RGB(255, 0, 0)
                            MClr& = _RGB(255, 0, 0) 'RED dots on Map
                        ELSE 'Normal Obj.
                            Obj.Clr.1& = _RGB(Clr.R1, Clr.G1, Clr.B1)
                            IF Cloud_Clr$ = "PURPLE" THEN MClr& = _RGB(250, 220, 55) ELSE MClr& = _RGB(170, 130, 255) 'Yellow/Purple dots (Nebula-dependent)
                        END IF '------------------------------------------------------


                        ObRad = ObRad(O): OZone = ObRad '!!! In future, OZone may be set differently w/ Asteroids than w/ CIRCLEs !!!


                        IF Round > 5 AND Turn.OK AND RND * 999 < Skill * 3 THEN 'Obj. RANDOMLY Changes Direction /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

                            IF Stp.X(O) > 0 THEN IF Stp.Y(O) < 0 THEN Dir = 1 ELSE Dir = 2 'Up/Right or Down/Right
                            IF Stp.X(O) < 0 THEN IF Stp.Y(O) > 0 THEN Dir = 3 ELSE Dir = 4 'Down/Left or Up/Left

                            SELECT CASE Dir
                                CASE 1, 3 'Moving UP/RIGHT or DOWN/LEFT
                                    IF RND < .5 THEN Stp.X(O) = -Stp.X(O) ELSE Stp.Y(O) = -Stp.Y(O)
                                CASE 2, 4 'Moving DOWN/RIGHT or UP/LEFT
                                    IF RND < .5 THEN Stp.Y(O) = -Stp.Y(O) ELSE Stp.X(O) = -Stp.X(O)
                            END SELECT: Dir = 0

                        ELSEIF Round > 7 AND Jump.OK AND NOT Jumping(O) AND Obj.Max > 59 AND Obj.Cnt < 19 AND RND * (2700 + Skill * 20) < (Skill * 20) THEN '    Object      V A N I S H E S
                            '  NOT Jumping(O) AND Obj.Max > 47 AND RND * 999 < (25 + Skill * 20) - Obj.Cnt   * * * * Debug: "Max:

                            IF Skill > 1 OR ObRad > Rad3 THEN 'Smallest ones WON'T vanish at Skill 1

                                'Object "Jumps" to a Random Location...

                                Get.Obj.XY: Jump.X(O) = Obj.X(O): Jump.Y(O) = Obj.Y(O)

                                'Jumping Objects will be FORCED into Play Area (only when FEW remain)...
                                '("May the Force be with you")

                                IF Obj.Cnt < 7 THEN Obj.X(O) = RND * 1280: Obj.Y(O) = RND * 720 ELSE Obj.X(O) = RND * 2560: Obj.Y(O) = RND * 1440
                                IF ABS(Obj.X(O) - Jump.X(O)) + ABS(Obj.Y(O) - Jump.Y(O)) < 210 / Skill GOTO Get.Obj.XY

                                JC(O) = 250: Jumping(O) = -1 'This Object has JUMPED (traces remain awhile)

                                'JC is Jump Color (fading color of "Phant om Object"; starts @ nearly brightest white; inner rings are dimmer)
                            END IF
                        END IF '/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/


                        IF Jumping(O) THEN 'Draw a fading PHANTOM Object in its pre-Jump spot
                            'IF Jumping(O) AND Jump.X(O) >= 0 AND Jump.X(O) < 1280 AND Jump.Y(O) >= 0 AND Jump.Y(O) < 720 THEN   * * * * DELETE if won't work * * * *

                            IF NOT Asteroids THEN CIRCLE (Jump.X(O), Jump.Y(O)), ObRad + ObRad / 4, _RGB(JC(O), JC(O), JC(O)) 'JC = Jump Color (shade of grey, fades away)
                            IF Asteroids OR ObRad > Rad3 THEN CIRCLE (Jump.X(O), Jump.Y(O)), ObRad, _RGB(JC(O) - 50, JC(O) - 50, JC(O) - 50)
                            CIRCLE (Jump.X(O), Jump.Y(O)), ObRad / 2, _RGB(JC(O) - 50, JC(O) - 50, JC(O) - 50)
                            CIRCLE (Jump.X(O), Jump.Y(O)), ObRad / 4, _RGB(JC(O), JC(O), JC(O))

                            'Corresponding CIRCLES in post-Jump location are done in ELSE section of "IF Asteroids" block below.

                            Jump.X(O) = Jump.X(O) + Stp.X(O) - Step_X: IF Jump.X(O) > 2559 THEN Jump.X(O) = 0 'Phantom's position changes w/ adjustment
                            Jump.Y(O) = Jump.Y(O) + Stp.Y(O) - Step_Y: IF Jump.Y(O) > 1439 THEN Jump.Y(O) = 0 'based on Ship's movement, if any.
                            JC(O) = JC(O) - 10: IF JC(O) = 0 THEN Jumping(O) = 0
                        END IF


                        Obj.X = Obj.X(O): Obj.Y = Obj.Y(O) 'Loc  (Temp holders for Move Object sub.)
                        Stp.X = Stp.X(O): Stp.Y = Stp.Y(O) 'Dir

                        CALL Move_Object(Obj.X, Obj.Y, Stp.X, Stp.Y, O) 'Change Object's X/Y using holders set above

                        Obj.X(O) = Obj.X: Obj.Y(O) = Obj.Y 'Transfer back new coords.

                        '**********************************************************************************************


                        '         Now Either Draw or _PUT Each Object/Orb/Sphere in Its Random Location...

                        'ObRad = ObRad(O): OZone = ObRad '!!! In future, OZone may be set differently w/ Asteroids than w/ CIRCLEs !!!  * * * * TEST: MOVED near above for JUMP * * * *


                        ': : IF O < 52 THEN:: _FONT 14: : LOCATE O, 1:: PRINT O; USING "Stp.X/Y: ## ##   Obj.X/Y: #### ####    "; Stp.X(O); Stp.Y(O); Obj.X(O); Obj.Y(O);
                        ':: IF O < 52 THEN: : _FONT 14: : LOCATE O, 1: : PRINT O; USING "ObRad: ##  OZone: ##  Obj.X/Y: #### ####   "; ObRad; OZone; Obj.X(O); Obj.Y(O);


                        IF Asteroids THEN 'Place a rock-photo "cutout"...

                            '***************************  Place Image from Graphic File  ******************************
                            SELECT CASE Rock(O)

                                CASE 1: _PUTIMAGE (Obj.X - ObRad, Obj.Y - ObRad)-(Obj.X + ObRad, Obj.Y + ObRad), Rock1& 'From disk "Asteroid" file
                                CASE 2: _PUTIMAGE (Obj.X - ObRad, Obj.Y - ObRad)-(Obj.X + ObRad, Obj.Y + ObRad), Rock2&
                                CASE 3: _PUTIMAGE (Obj.X - ObRad, Obj.Y - ObRad)-(Obj.X + ObRad, Obj.Y + ObRad), Rock3&
                                CASE 4: _PUTIMAGE (Obj.X - ObRad, Obj.Y - ObRad)-(Obj.X + ObRad, Obj.Y + ObRad), Rock4&
                                CASE 5: _PUTIMAGE (Obj.X - ObRad, Obj.Y - ObRad)-(Obj.X + ObRad, Obj.Y + ObRad), Rock5&

                            END SELECT
                            '******************************************************************************************

                            IF O <= PwrUps OR O = Drainer THEN CIRCLE (Obj.X, Obj.Y), 6, Obj.Clr.1& 'Mark Asteroid as GREEN or RED Special Object

                        ELSE 'we have Orbs/Spheres instead...

                            '***************************  Draw "Orb" Using CIRCLE & PAINT  ****************************

                            'IF Jumping(O) AND Jump.X(O) >= 0 AND Jump.X(O) < 1280 AND Jump.Y(O) >= 0 AND Jump.Y(O) < 720 THEN 'Draw PHANTOM Object (CIRCLEs only) FADING IN at its new location...

                            IF Jumping(O) THEN 'Draw PHANTOM Object (CIRCLEs only) FADING IN at its new location...

                                CIRCLE (Obj.X(O), Obj.Y(O)), ObRad + ObRad / 4, _RGB(250 - JC(O), 250 - JC(O), 250 - JC(O)) 'JC = Jump Color
                                IF ObRad > Rad3 THEN CIRCLE (Obj.X(O), Obj.Y(O)), ObRad, _RGB(200 - JC(O), 200 - JC(O), 200 - JC(O))
                                CIRCLE (Obj.X(O), Obj.Y(O)), ObRad / 2, _RGB(200 - JC(O), 200 - JC(O), 200 - JC(O))
                                CIRCLE (Obj.X(O), Obj.Y(O)), ObRad / 4, _RGB(200 - JC(O), 200 - JC(O), 200 - JC(O))

                            ELSE 'Normal Object drawn normally...  (CIRCLEs drawn from inner to outer)

                                FOR r = 2 TO 5 'Draw a few inner circles  ' 5 TO 2 STEP -1

                                    SELECT CASE Cloud_Clr$ 'Avoid Object's core colour blending into Nebula
                                        CASE "PURPLE": IF r = 5 THEN Obj.Clr.2& = _RGB(250, 225, 50) ELSE Obj.Clr.2& = _RGB(200, 100, 0)
                                        CASE ELSE: IF r = 5 THEN Obj.Clr.2& = _RGB(200, 155, 250) ELSE Obj.Clr.2& = _RGB(100, 0, 255)
                                    END SELECT

                                    CIRCLE (Obj.X, Obj.Y), ObRad / r, Obj.Clr.2& 'Painted Circle (Inward)
                                    IF r = 4 THEN PAINT (Obj.X, Obj.Y), Obj.Clr.2&, Obj.Clr.2& 'Paint w/ Obj. color #2
                                NEXT

                                IF O <= PwrUps THEN 'Electric arcs inside Power-Up Object
                                    'FOR P = 1 TO 7
                                    '    'PSET (Obj.X + RND * ObRad * 2 - ObRad, Obj.Y + RND * ObRad * 2 - ObRad), _RGB(255, 255, 255)
                                    '    CIRCLE (Obj.X, Obj.Y), ObRad, AC&, RND * -6
                                    'NEXT
                                END IF '/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

                                IF O <= PwrUps OR O = Drainer AND ED.Active THEN 'Make SPARKS and ARCS
                                    IF Cloud_Clr$ = "PURPLE" THEN AC& = _RGB(200, 160, 0) ELSE AC& = _RGB(160, 0, 255)

                                    FOR P = 1 TO 7 'Make SPARKLES inside Power-Up or Active Drainer Object
                                        CIRCLE (Obj.X, Obj.Y), ObRad, AC&, RND * -6
                                    NEXT

                                    FOR P = 1 TO ObRad / 2 'Make electric "arcs" in same Object
                                        PSET (Obj.X + RND * ObRad * 2 - ObRad, Obj.Y + RND * ObRad * 2 - ObRad), _RGB(255, 255, 255)
                                    NEXT
                                END IF

                                CIRCLE (Obj.X, Obj.Y), ObRad, Obj.Clr.1& 'Inner Circle (Outermost; GREEN in Power-Ups, RED in Drainer)

                                CIRCLE (Obj.X, Obj.Y), ObRad + ObRad / 4, _RGB(255, 255, 255) 'Shield / Outer ring

                            END IF
                            '******************************************************************************************
                        END IF


                        '---------------------------------------------------
                        CIRCLE (MX + Obj.X / 10, MY + Obj.Y / 10), 1, MClr& 'Corner-Map "Blips"             [  ]
                        '---------------------------------------------------


                        'If Object touches Ship, reduce SHIELD power by a little...

                        IF TIMER - DesTime > 3 AND ABS(Ship.X - Obj.X) < ObRad AND ABS(Ship.Y + 20 - Obj.Y) < ObRad THEN '* * * * Maybe something other than Ship.Y + 20 ? * * * *

                            'If Touched, then ignore same Object till it passes...

                            IF Shield.Up > 0 AND NOT Touched THEN

                                Shield.Up = Shield.Up - Skill - 3: Touched = -1 'Ship touched Object
                                IF Shield.Up <= 0 THEN Ship.Destroyed = -1:: FOR S = 100 TO 600 STEP 50: SOUND S, .2: SOUND S * 3, .2: NEXT '     ( ((  )) )
                                'Above: If Ship was touched w/o active Shield, lose a Ship.

                                IF Energy > 5 THEN Energy = Energy - 5

                            END IF: DesTime = 0

                        ELSE 'Ship not touching Object
                            Touched = 0
                        END IF

                    END IF 'Exist()

                NEXT 'Each Object (O = 1 to Obj.Max)

            END IF 'Many normal Objects or single Super Object



            IF NOT Ship.Destroyed THEN Draw_Ship (Angle) 'Call sub to draw our Ship

            DO WHILE _MOUSEINPUT: _LIMIT 1200 '% % % % % % % % % % %  M O U S E  I N P U T  % % % % % % % % % % % % % %

                IF _MOUSEBUTTON(1) + _MOUSEBUTTON(2) + _MOUSEBUTTON(3) = 0 THEN '* * * * Trying to prevent ERRATIC jumping by 90 deg. * * * *

                    IF _KEYDOWN(100304) AND _MOUSEX < Old_Mouse_X THEN Slide = -1: Ship_Speed (Slide): GOTO Mouse.Done '<Shift> + Mouse slide
                    IF _KEYDOWN(100304) AND _MOUSEX > Old_Mouse_X THEN Slide = 1: Ship_Speed (Slide): GOTO Mouse.Done

                    IF _MOUSEX < Old_Mouse_X THEN Angle = Angle + 3: IF Angle > 360 THEN Angle = 3
                    IF _MOUSEX > Old_Mouse_X THEN Angle = Angle - 3: IF Angle < 3 THEN Angle = 360
                    IF _MOUSEX < 1 THEN _MOUSEMOVE 1279, _MOUSEY ELSE IF _MOUSEX > 1278 THEN _MOUSEMOVE X, _MOUSEY
                END IF

                Old_Mouse_X = _MOUSEX 'For next use above

                IF _MOUSEWHEEL <> 0 THEN 'Speed Up or Down
                    Inc = -_MOUSEWHEEL: Ship_Speed (Slide) 'This allows Ship to move BACKWARD from stopped
                    'IF _MOUSEWHEEL < 0 THEN Ship_ Speed ELSE Ship_Slow 'Accelerate or slow to stop, but NO REVERSE  * * * * DELETE?
                END IF

                IF _MOUSEBUTTON(3) THEN Step_X = 0: Step_Y = 0 'Scroll wheel = Full Stop

                'IF _MOUSEBUTTON(1) THEN Angle = Angle + 90: IF Angle  > 360 THEN Angle = Angle - 360 'Anti-clockwise by 90  * * * * Turning Ship by 90 deg. can
                'IF _MOUSEBUTTON(2) THEN Angle = Angle - 90: IF Angle  < 0 THEN Angle  = 360 - Angle 'Clockwise by 90                 cause ERRATIC behaviour  * * * *
                IF _MOUSEBUTTON(1) THEN Angle = 90 'Left button = Aim Ship LEFT
                IF _MOUSEBUTTON(2) THEN Angle = 270 'Right button = Aim Ship RIGHT

                Mouse.Done:
                WHILE _MOUSEINPUT: WEND

                ': : LOCATE 40, 4: PRINT USING "X/Y: #### ####  MOUSE X/Y: #### ####  Old X: ####  Angle: ###   "; X; Y; _MOUSEX; _MOUSEY; Old_Mouse_X; Angle;

            LOOP '% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %


            '= = = = = = = = = = = = = = = = = = = = = = =  K E Y B O A R D  I N P U T  ?  = = = = = = = = = = = = = = = = = = = = = = = = =


            K$ = INKEY$: IF INSTR("abcdefghijklmnopqrstuvwxyz", K$) THEN K$ = UCASE$(K$)
            LastKey = TIMER

            'IF K$ > "" AND INSTR("0123456789", K$) THEN SOUND 120, .5: R$ = R$ + K$: IF LEN(R$) = 2 AND VAL(R$) > 0 AND VAL(R$) < 1000 THEN Round = VAL(R$): R$ = "" ELSE ELSE R$ = "": EXIT DO 'Jump to higher level/Round

            IF K$ > "" THEN
                IF INSTR("0123456789", K$) THEN 'Jump directly to Round ##
                    SOUND 120, .5: R$ = R$ + K$:
                    IF LEN(R$) = 2 AND VAL(R$) > 0 AND VAL(R$) < 100 THEN Round = VAL(R$): R$ = "": EXIT DO 'Jump to higher level/Round
                ELSE
                    R$ = "" 'Null the Round-Jump number string                Below: RGB colours for Message
                    IF Msg.Dur THEN Message$ = "": Msg.Dur = 0: Msg.Time = 0: MR = 0: MG = 0: MB = 0: SOUND 5555, .5: _KEYCLEAR 'If MESSAGE is on screen, clear it
                END IF
            END IF

            ':: _FONT 14: : LOCATE 14, 4: PRINT USING "R$: &   MaxDist: ##   "; R$; MaxDist;



            '                                _KEYDOWN Keyboard Values
            '
            'Esc  F1    F2    F3    F4    F5    F6    F7    F8    F9    F10   F11   F12   Sys  ScL Pause
            ' 27 15104 15360 15616 15872 16128 16384 16640 16896 17152 17408 34048 34304 +316 +302 +019
            '`~  1!  2@  3#  4$  5%  6^  7&  8*  9(  0) -_ =+ BkSp   Ins   Hme   PUp   NumL   /     *    -
            '126 33  64  35  36  37  94  38  42  40  41 95 43   8   20992 18176 18688 +300   47    42   45
            '96 49  50  51  52  53  54  55  56  57  48 45 61
            'Tab Q   W   E   R   T   Y   U   I   O   P  [{  ]}  \|   Del   End   PDn   7Hme  8/   9PU   +
            ' 9  81  87  69  82  84  89  85  73  79  80 123 125 124 21248 20224 20736 18176 18432 18688 43
            '113 119 101 114 116 121 117 105 111 112  91  93  92                    55    56    57
            'CapL   A   S   D   F   G   H   J   K   L   ;:  '" Enter                   4/-   5    6/-
            '+301  65  83  68  70  71  72  74  75  76  58  34  13                     19200 19456 19712    E
            '      97 115 100 102 103 104 106 107 108  59  39                          52    53    54      n
            '  Shift   Z   X   C   V   B   N   M   ,<  .>  /?    Shift                  1End  2/   3PD     t
            ' +304    90  88  67  86  66  78  77  60  62  63    +303       18432        20224 20480 20736  e
            '        122 120  99 118  98 110 109  44  46  47                             49    50    51    r
            'Ctrl   Win  Alt     Spacebar      Alt  Win  Menu  Ctrl   -      -      0Ins        .Del
            '+306  +311 +308       32         +307 +312 +319  +305 19200 20480 19712  20992       21248 13
            '                                                                          48          46
            '
            '         Lower value = LCase/NumLock On __________________ + = add 100000

            'IF _KEYHIT THEN
            IF _KEYDOWN(100306) AND _KEYDOWN(19200) THEN GOTO JumpLeft 'Ctrl + Arrow = Jump-TURN the Ship
            IF _KEYDOWN(100306) AND _KEYDOWN(19712) THEN GOTO JumpRight
            IF _KEYDOWN(100306) AND _KEYDOWN(18432) THEN GOTO JumpUp
            IF _KEYDOWN(100306) AND _KEYDOWN(20480) THEN GOTO JumpDown

            '<Shift> + Arrow = Slide Ship sideways...

            IF _KEYDOWN(100304) AND _KEYDOWN(19200) THEN Slide = -1: Ship_Speed (Slide): GOTO SkipKey 'Ship slides LEFT
            IF _KEYDOWN(100304) AND _KEYDOWN(19712) THEN Slide = 1: Ship_Speed (Slide): GOTO SkipKey '...RIGHT

            DIM KeyDownCheck AS _BYTE
            KeyDownCheck = -1
            TI = 5
            IF _KEYDOWN(19200) THEN TI = 2: GOSUB TurnLeft 'Arrow key
            IF _KEYDOWN(19712) THEN TI = 2: GOSUB TurnRight
            IF _KEYDOWN(18432) THEN GOSUB Accelerate
            IF _KEYDOWN(20480) THEN GOSUB SlowDown

            IF _KEYDOWN(32) OR _KEYDOWN(120) OR _KEYDOWN(99) OR _KEYDOWN(118) THEN GOSUB FireLaser '<Space> / X / C / V
            KeyDownCheck = 0

            'K$ = ""

            'ELSE
            Slide = 0
            'END IF

            SELECT CASE K$ '= = = = = = = = = = = = = = = = =  W H A T   K E Y  ?  = = = = = = = = = = = = = = = = = = =

                'Ship's Orientation...

                CASE "6", CHR$(0) + "M":
                    TurnRight:
                    Angle = Angle - TI: IF Angle < TI THEN Angle = 360 'AntiClockwise
                    IF KeyDownCheck THEN RETURN
                CASE "4", CHR$(0) + "K":
                    TurnLeft:
                    Angle = Angle + TI: IF Angle > 360 THEN Angle = TI 'Clockwise
                    IF KeyDownCheck THEN RETURN
                    'CHR$(0) + CHR$(71)         [Home]               "G"
                    'CHR$(0) + CHR$(72)         [Up Arrow]           "H"
                    'CHR$(0) + CHR$(73)         [Page Up]            "I"
                    'CHR$(0) + CHR$(75)         [Left Arrow]         "K"
                    'CHR$(0) + CHR$(76)         [5 on NumPad]        "L" (NumLock off in QB64)
                    'CHR$(0) + CHR$(77)         [Right Arrow]        "M"
                    'CHR$(0) + CHR$(79)         [End]                "O"
                    'CHR$(0) + CHR$(80)         [Down Arrow]         "P"
                    'CHR$(0) + CHR$(81)         [Page Down]          "Q"
                    'CHR$(0) + CHR$(82)         [Insert]             "R"
                    'CHR$(0) + CHR$(83)         [Delete]             "S"

                    '(Jump (Ctrl-End) to BOTTOM for full version of list above.)

                CASE "8", CHR$(0) + "H" 'Ship Accelerates
                    Accelerate:

                    IF Ang = Last.Ang THEN IF ABS(Step_X) = MaxSpeed OR ABS(Step_Y) = MaxSpeed GOTO Skip.Speed
                    Last.Ang = Ang '* * * * WHERE to put this? * * * *

                    Inc = ABS(Inc): CALL Ship_Speed(Slide) 'Accelerate
                    'Above: Restore Inc to + in case MOUSE wheel has put Ship in reverse
                    Skip.Speed:
                    IF KeyDownCheck THEN RETURN
                CASE "2", CHR$(0) + "P" 'Ship Slows or Stops
                    SlowDown:
                    IF Step_X <> 0 OR Step_Y <> 0 THEN CALL Ship_Slow
                    IF KeyDownCheck THEN RETURN
                CASE "5", CHR$(0) + "L", CHR$(0) + ""

                    JumpUp: Angle = 360 'Point Ship straight UP  (5, Ctrl-UP)

                CASE CHR$(0) + "s"
                    JumpLeft: Angle = 90 ' Point Ship LEFT   (Ctrl + Arrow)
                    IF KeyDownCheck THEN RETURN
                CASE CHR$(0) + "t"
                    JumpRight: Angle = 270 'Point Ship RIGHT
                    IF KeyDownCheck THEN RETURN
                CASE CHR$(0) + ""
                    JumpDown: Angle = 180 'Point Ship DOWN
                    IF KeyDownCheck THEN RETURN
                CASE "7": Angle = 45 'Point Ship UP-LEFT  (NumPad Corners)
                CASE "9": Angle = 315 'UP-RIGHT
                CASE "1": Angle = 135 'DOWN-LEFT
                CASE "3": Angle = 225 'DOWN-RIGHT

                CASE CHR$(32), "X", "C", "V":
                    FireLaser:
                    IF TIMER - LastProj > PRate THEN CALL Fire_Laser(PCnt, PX(), PY(), Dist()) 'Fire a LaserBall (but not too rapidly)
                    IF KeyDownCheck THEN RETURN

                CASE CHR$(0) + CHR$(66): SOUND 220, 3 'F8 = Toggle Projectile Expansion

                    IF Expand THEN Expand = 0: SOUND 140, 1 ELSE Expand = -1: SOUND 300, 1 'Turn it OFF/ON

                CASE CHR$(0) + CHR$(67): SOUND 300, 3 'F9 = Toggle Single/Triple Projectile

                    IF Tri.Ball THEN Tri.Ball = 0: SOUND 220, 1 ELSE Tri.Ball = -1: SOUND 380, 1 'Turn it OFF/ON

                CASE CHR$(0) + "?", "S", "D", "F", "G" 'F5 = Plasma Bomb   * * * *  Ctrl + "?" / CHR$(63)

                    IF Energy >= 80 AND Shield.Up > 60 THEN
                        CALL Check_Proximity

                        IF Objects.Hit THEN 'Drain some Energy and...
                            Energy = Energy - 10: FRad = ObRad + 20 'Initial size of Flash
                            PB.Bonus = Objects.Hit ^ 2 * 100
                            Score = Score + PB.Bonus: IF Score >= NexBon THEN Lives = Lives + 1: Get_NexBon 'Calc. next Bonus Ship level
                        END IF
                    END IF

                CASE CHR$(13): IF NOT Super.Obj THEN CALL Jump_Ship(XX, YY, Ship.Vanished) '<Enter> = Transport Ship to Random Loc.  * * * * DELETE Ship Vanished or not?

                CASE CHR$(19): SWAP Snd, NoSnd: SOUND 222, 3: _DELAY .1: IF Snd THEN SOUND 333, 1 ELSE SOUND 111, 1 'Ctrl-S = Laserfire Sound ON/OFF        ( (( )) )

                CASE CHR$(0) + CHR$(60): SOUND 300, 3: Save_Game 'F2 = Save Game Progress
                CASE CHR$(0) + CHR$(96): IF _FILEEXISTS("SB_Saved_Game.dat") THEN Load_Game ELSE BEEP 'Ctrl-F3

                    '===================================  C H E A T   K E Y S  ====================================

                CASE CHR$(0) + CHR$(50): SOUND 120, 1: IF Map.BG THEN Map.BG = 0 ELSE Map.BG = -1 'Alt-M = Map's opaque background ON/OFF
                CASE CHR$(0) + CHR$(24): IF Round > 1 AND NOT Super.Obj THEN Obj.Cnt = 0: SOUND 222, 1: _DELAY .4 'Alt-O = Jump to Super Object mode
                CASE CHR$(0) + CHR$(19): SOUND 160, 1: _DELAY .4: Round = Round + 1: EXIT DO 'Alt-R = Jump to next Round

                CASE CHR$(10): SOUND 800, 2: _DELAY .1: IF Jump.OK THEN Jump.OK = 0: SOUND 720, 1 ELSE Jump.OK = -1: SOUND 880, 1 'Ctrl-J = Objects may (not) vanish & reappear
                CASE CHR$(20): SOUND 200, 2: _DELAY .1: IF Turn.OK THEN Turn.OK = 0: SOUND 120, 1 ELSE Turn.OK = -1: SOUND 280, 1 'Ctrl-T = Objects may (not) suddenly change dir.

                    '==============================================================================================

                CASE CHR$(27): EXIT DO 'Will save User Pref. file before exiting SUB

                    'CHR$(0) + CHR$(16-50)      [Alt] + A-Z

                    'CHR$(0) + CHR$(59)         [F1]                 ";"
                    'CHR$(0) + CHR$(60)         [F2]                 "<"
                    'CHR$(0) + CHR$(61)         [F3]                 "="
                    'CHR$(0) + CHR$(62)         [F4]                 ">"
                    'CHR$(0) + CHR$(63)         [F5]                 "?"
                    'CHR$(0) + CHR$(64)         [F6]                 "@"
                    'CHR$(0) + CHR$(65)         [F7]                 "A"
                    'CHR$(0) + CHR$(66)         [F8]                 "B"
                    'CHR$(0) + CHR$(67)         [F9]                 "C"
                    'CHR$(0) + CHR$(68)         [F10]                "D"
                    'CHR$(0) + CHR$(133)        [F11]                "à"
                    'CHR$(0) + CHR$(134)        [F12]                "å"

            END SELECT 'What Key?  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

            _KEYCLEAR


            SkipKey:

            IF Step_X < -MaxSpeed THEN Step_X = -MaxSpeed ELSE IF Step_X > MaxSpeed THEN Step_X = MaxSpeed
            IF Step_Y < -MaxSpeed THEN Step_Y = -MaxSpeed ELSE IF Step_Y > MaxSpeed THEN Step_Y = MaxSpeed

            X = X + Step_X: IF X > 1279 THEN X = 0 ELSE IF X < 0 THEN X = 1279 'Position of "Window" on 2560x1440 BG (e.g. Nebula) Image
            Y = Y + Step_Y: IF Y > 719 THEN Y = 0 ELSE IF Y < 0 THEN Y = 719

            Star1.X = Star1.X + Step_X / 3: IF Star1.X > 1279 THEN Star1.X = 0 ELSE IF Star1.X < 0 THEN Star1.X = 1279 'Position of "Window" on 2560x1440 BG Starfield Image
            Star1.Y = Star1.Y + Step_Y / 3: IF Star1.Y > 719 THEN Star1.Y = 0 ELSE IF Star1.Y < 0 THEN Star1.Y = 719 ' (the NEARER Stars)

            Star2.X = Star2.X + Step_X / 6: IF Star2.X > 1279 THEN Star2.X = 0 ELSE IF Star2.X < 0 THEN Star2.X = 1279 'Position of "Window"
            Star2.Y = Star2.Y + Step_Y / 6: IF Star2.Y > 719 THEN Star2.Y = 0 ELSE IF Star2.Y < 0 THEN Star2.Y = 719 ' (the FARTHER Stars)


            IF Super.Obj THEN 'Change Super Object's coords.
                Sup.X = Sup.X - Step_X: IF Sup.X > 5000 THEN Sup.X = 5000 ELSE IF Sup.X < -5000 THEN Sup.X = -5000
                Sup.Y = Sup.Y - Step_Y: IF Sup.Y > 5000 THEN Sup.Y = 5000 ELSE IF Sup.Y < -5000 THEN Sup.Y = -5000

                IF ABS(Ship.X - Sup.X) + ABS(Ship.Y - Sup.Y) < 40 + Shields * 20 THEN Ship.Destroyed = -1 'Ship DESTROYED
                ': CALL Scatter_ Objects '* * * * If not SCATTERING/resetting here, then something else here * * * *
            END IF

            FOR L = 1 TO Lives 'Show Lives-remaining symbols/icons
                CIRCLE (1000 - L * 37, 678), 10, _RGB(60, 0, 220) 'Purple circles
                CIRCLE (1000 - L * 37, 678), 8, _RGB(100, 0, 240)
                CIRCLE (1000 - L * 37, 678), 4, _RGB(190, 140, 255)
            NEXT


            ': : _FONT 14: : LOCATE 6, 1:: COLOR _RGB(222, 222, 222): : PRINT: PRINT USING "Lives: ##  Destroyed: ##  Super: ##  ObMax: ##  ObCnt: ##  ObRad: ###  PRate: #.##    "_
            '  ; Lives; Ship.Destroyed; Super.Obj; Obj.Max; Obj.Cnt; ObRad ;PRate

            ': : LOCATE 3, 4: PRINT USING "Step_X + ##.##  Step_Y - ##.##   "; (Inc - Inc * (Angle / 360)); (Inc * (Angle / 360)) '271 - 360

            ': : LOCATE 43, 4: PRINT USING "X/Y: #### ####  Step X/Y: ###.## ###.##  Angle: ###  Ang/Last.Ang: ### ###   "; X; Y; Step_X; Step_Y; Angle; Ang; Last.Ang;

            _FONT 14: COLOR _RGB(55, 55, 55), _RGBA(0, 0, 0, 0): _PRINTSTRING (150, 670), STRING$(10, "") 'Grey, full-length
            IF Energy < 80 THEN EnClr& = _RGB(100, 0, 255) ELSE EnClr& = _RGB(180, 20, 255)
            COLOR EnClr&: _PRINTSTRING (150, 670), STRING$(Energy \ 10, "") 'Purple/Pink Energy Meter
            EnClr& = 0
            COLOR _RGB(55, 55, 55): _PRINTSTRING (1040, 670), STRING$(10, "") 'Grey, full-length
            COLOR _RGB(0, 255, 0): _PRINTSTRING (1040, 670), STRING$(Shield.Up / 10, "") 'Ship's Shield
            COLOR , _RGB(0, 0, 0) 'Reset BG to black

            IF PCnt > 0 THEN 'At least 1 Projectile is "alive" (on screen or off) ----------------------

                Ang = Angle '* * * * Will we need Ang() for each projectile?  Or already using it? * * * *

                IF Super.Obj THEN CALL Proj_Super(Sup.X, Sup.Y, Ang, PCnt, PX(), PY(), Dist(), Snd_Pop&)_
                  ELSE CALL Projectiles(Ang, PCnt, PX(), PY(), Dist(), Snd_Pop&)

            END IF '------------------------------------------------------------------------------------

            '  Check whether any Objects were hit, by either Energy Balls or Plasma Bomb...
            '  (P-Bomb & T-Bomb (if implemented) strikes are determined in sub Check Proximity.)

            IF Flash.X > 0 AND Flash.Y > 0 THEN 'Hit by LaserBall, not P-Bomb
                Objects.Hit = 1
                Hit.X(1) = Flash.X: Hit.Y(1) = Flash.Y
            END IF

            FOR O = 1 TO Objects.Hit 'Call SUB to FLASH blown-up Objects
                Flash.X = Hit.X(O): Flash.Y = Hit.Y(O)
                CALL Blow_em_Up
            NEXT



            IF Obj.Cnt <= 0 THEN 'Last/only Object (or Ship) has been destroyed

                '!!!  In IF line below, we will check whether Round > 1 so that Super Object mode is skipped in 1st Round  !!!

                IF Round > 1 AND NOT Super.Obj THEN '=================  Activate Super Object mode  ===========================

                    Super.Obj = -1: MClr& = _RGB(255, 0, 0) 'Super Obj's Map blip clr.

                    Get.Sup.XY: 'Random starting coords. for Super Object

                    Sup.X = INT(RND * 3000) + 2400: IF RND < .5 THEN Sup.X = -Sup.X 'Super Object's starting coords.
                    Sup.Y = INT(RND * 3000) + 2400: IF RND < .5 THEN Sup.Y = -Sup.Y 'quite far from our Ship

                    Obj.Cnt = 1:: Shields = 4: Outer.Clr = 205: PRate = Skill / 10 + .1 '.3 'Rapid-fire rate (SLOWER in Super Obj. mode)
                    Resumed_Game = 0

                ELSE 'Super Object was destroyed (or N/A in early Round)

                    '* * * Here, other actions may eventually be done (or SUB called) BEFORE Scattering/Resetting for next Round * * *

                    Round = Round + 1: IF Round > 1 AND PCnt <= 0 THEN _DELAY 2
                    'DO: K$ = INKEY$: LOOP UNTIL K$ = "" * * * * DELETE?

                    IF Msg.Dur AND NOT Super.Obj THEN _DELAY 1: SLEEP 4 'Pause for on-screen Message, if any
                    EXIT DO

                END IF '=========================================================================================

                ': : _FONT 14: : LOCATE 17, 1: : PRINT USING "Resumed: ##  Exist(1): ##  ObMax: ##  Cnt: ##   "; Resumed_Game; Exist(1); Obj.Max; Obj.Cnt;: TEST.SLEEP  = 55

            END IF 'Obj Cnt = 0


            K$ = ""

            '#############################   D i s p l a y   S t a t s   O n   S c r e e n   ###############################


            Score$ = LTRIM$(STR$(Score)): NexBon$ = "Next Bonus @" + STR$(NexBon) 'Set the _PRINT strings for below

            IF F1& > 0 THEN _FONT F1& ELSE _FONT 14

            COLOR _RGB(120, 180, 140), _RGBA(0, 0, 0, 0) 'Current Round  -------------------------
            _PRINTSTRING (300, 30), "Round: " + STR$(Round)

            COLOR _RGB(130, 0, 180) 'Skill  ------------------------------------------------------
            _PRINTSTRING (490, 30), "Skill: " + STR$(Skill)

            'COLOR _RGB(220, 0, 0) 'Obj Max (TESTING ONLY)  --------------------------------------
            '_PRINTSTRING (760 - _PRINTWIDTH(Score$), 30), "Max:  " + STR$(Obj.Max)

            COLOR _RGB(0, 200, 220) 'Remaining Objects  ------------------------------------------
            _PRINTSTRING (920 - _PRINTWIDTH(Score$), 30), "Rem: " + STR$(Obj.Cnt)

            COLOR _RGB(222, 222, 222) 'Score  ----------------------------------------------------
            _PRINTSTRING (1120 - _PRINTWIDTH(Score$), 30), "Score:  " + Score$

            IF Lives < 8 THEN COLOR _RGB(0, 240, 30): _PRINTSTRING (1225 - _PRINTWIDTH(NexBon$), 75), NexBon$ 'Show Next Bonus Level?


            '% % % % % % % % % % % % % % % %  Display a  M E S S A G E  for a Few Seconds  % % % % % % % % % % % % % % % % %

            IF Msg.Dur > 0 THEN 'there must be a Message to display
                IF TIMER - Msg.Time < Msg.Dur THEN
                    IF F2& > 0 THEN _FONT F2& ELSE _FONT 14
                    COLOR _RGB(MR, MG, MB): _PRINTSTRING (640 - _PRINTWIDTH(Message$) / 2, 500), Message$
                ELSE 'Msg. time has elapsed
                    Msg.Time = 0: Msg.Dur = 0: Message$ = "" '* * * * Debug: F1& =  * * * *
                END IF
            END IF ' % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %


            'Show P-Bomb indicator if applicable...

            IF NOT Super.Obj AND Energy >= 80 AND Shield.Up >= 60 THEN COLOR _RGB(220, 180, 60): _PRINTSTRING (300, 667), "P-BOMB"

            IF PB.Bonus > 0 THEN 'Show P-Bomb Bonus if...

                ': : _FONT 14: : LOCATE 17, 1: : PRINT USING "Objs Hit: ##  OsHit: ##   Bonus: ####  TIMER: #####  PB.Time: ####.##   "; Objects.Hit; Os.Hit; PB.Bonus; TIMER; PB.Time: TEST.SLEEP = 55

                IF TIMER - PB.Time < 3 THEN '...3 secs. haven't elapsed...
                    COLOR _RGB(200, 170, 110): _PRINTSTRING (438, 665), "x " + STR$(Os.Hit) + "  = " + STR$(PB.Bonus)
                ELSE 'reset variables
                    PB.Bonus = 0: Os.Hit = 0: PB.Time = 0
                END IF
            END IF

            '###############################################################################################################

            ':: _FONT 14 : : LOCATE 12, 4: : PRINT USING "Obj.X/Y: #### ####  Obj.Cnt: ##  Energy: ###.##  Shield: ###.##  PCnt: ##    "; Obj.X, Obj.Y; Obj.Cnt; Energy; Shield.Up; PCnt


            IF NOT Super.Obj THEN
                Obj.Cnt = 0 '+ + + + +  C o u n t  R e m a i n i n g  O b j e c t s  + + + + +          * * * * 2018.6.18 * * * *

                FOR O = 1 TO Obj.Max 'Tally all existing Objects
                    IF Exist(O) THEN Obj.Cnt = Obj.Cnt + 1 ': : LOCATE 12 + Obj.Cnt, 5:: PRINT O; USING " Exists ... Cnt: "; Obj.Cnt; '* * * * TEST PRINT
                NEXT: O = 0 ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            END IF


            ': : _FONT 14: : LOCATE 20, 4:: COLOR _RGB(200, 170, 110): : PRINT USING "Aster: ##  Clouds: ##  Snd: ##  Expand: ##  TriBall: ##    "; Asteroids; Clouds; Snd; Expand; Tri.Ball ': : TEST.SLEEP = 1


            _DISPLAY:::: IF TEST.SLEEP THEN SLEEP TEST.SLEEP: TEST.SLEEP = 0 '* * * *  Pause after a TEST PRINT if > 0  * * * *


        LOOP 'until Lives or Obj Cnt = 0, or <Esc> or Alt-R is pressed  > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >


        _AUTODISPLAY

        '================  S a v e   U s e r   P r e f s.  ================
        OPEN "SB_User_Pref.ini" FOR OUTPUT AS #1 'Save User Preferences
        PRINT #1, Skill; Asteroids; Clouds; Snd; Expand; Tri.Ball; Jump.OK; Turn.OK; Map.BG
        CLOSE 1
        '==================================================================

        IF Large& < -1 THEN _FREEIMAGE Large& 'Free these images, as they will be LOAD'd anew at LOOP's top
        IF Cloud_BG1& < -1 THEN _FREEIMAGE Cloud_BG1&
        IF Star_BG1& < -1 THEN _FREEIMAGE Star_BG1&
        IF Star_BG2& < -1 THEN _FREEIMAGE Star_BG2&


        IF K$ = CHR$(27) THEN EXIT DO 'Back to Intro Screen

        _DELAY .4: IF F1& > 0 THEN _FONT F1& ELSE _FONT 14

        COLOR , _RGBA(0, 0, 0, 0) 'Transparent BG for text below

        IF Lives = 0 THEN

            T$ = "G  A  M  E    O  V  E  R"
            COLOR _RGB(255, 20, 20): _PRINTSTRING (641 - _PRINTWIDTH(T$) / 2, 310), T$
            COLOR _RGB(95, 0, 0),: _PRINTSTRING (639 - _PRINTWIDTH(T$) / 2, 308), T$

            _DELAY 2: SLEEP 4: DO: K$ = INKEY$: LOOP UNTIL K$ = "": EXIT DO

        ELSE 'IF FRad <= 0 THEN  * * * * Tried to make this happen only after Flash has gone * * * *

            IF Round > 9 AND Round < 100 THEN R$ = STR$(INT(Round / 10)) + STR$(Round - INT(Round / 10) * 10) ELSE R$ = STR$(Round)
            '   16  -->  1 + 6   |   103  -->  10 + 3  -->  1 0 3

            T$ = "R o u n d  " + R$
            COLOR _RGB(255, 200, 20): _PRINTSTRING (641 - _PRINTWIDTH(T$) / 2, 290), T$ 'Trans. BG + Drop Shadow
            COLOR _RGB(95, 60, 0),: _PRINTSTRING (639 - _PRINTWIDTH(T$) / 2, 288), T$ 'Dark over light "shadow"

            T$ = "G e t   R e a d y !"
            COLOR _RGB(200, 200, 200): _PRINTSTRING (640 - _PRINTWIDTH(T$) / 2, 410), T$ 'Light
            COLOR _RGB(0, 77, 0),: _PRINTSTRING (639 - _PRINTWIDTH(T$) / 2, 409), T$ 'Dark

            T$ = "": R$ = "": _DELAY 1: SLEEP 2 ': DO: K$  = INKEY$: LOOP UNTIL K$  = ""

            Scatter_Objects 'Reset for new Round w/ Normal Objects
        END IF

        'IF K$ = CHR$(27) THEN EXIT DO 'Back to Intro Screen


        'DO: K$ = INKEY$: LOOP UNTIL K$ = ""

    LOOP 'Lost a Ship, but maybe not last one (or <Esc> used)

END SUB 'Play Game


SUB Get_NexBon 'Figure next Extra Life level based on current Score

    SELECT CASE Score
        CASE IS < 10001: NexBon = 10000
        CASE 10001 TO 24999: NexBon = 25000 'Every 25,000 pts. till => 75,000
        CASE 25000 TO 49999: NexBon = 50000
        CASE 50000 TO 74999: NexBon = 75000
        CASE ELSE: NexBon = INT(Score / 1000) * 1000 + 30000 'Every 30,000 points
    END SELECT

END SUB


SUB Draw_Ship (Angle) '===================================================================

    PRESET (Ship.X, Ship.Y)

    ShipClr& = _RGB(111, 111, 111) '* * * * Maybe move these where they'll be done just ONCE per game? * * * *
    CirClr& = _RGB(44, 0, 177)
    EngClr& = _RGB(66, 66, 66)
    AddClr& = _RGB(188, 188, 188)

    DRAW "C" + STR$(ShipClr&) 'Set to main Ship color

    DRAW "TA=" + VARPTR$(Angle)
    DRAW "BU3 L5 H4 G20 D9 E5 R5 E4 R29" 'LEFT half (wing) of Ship
    PRESET (Ship.X, Ship.Y)
    DRAW "C" + STR$(ShipClr&) 'Back to Ship color
    DRAW "BU3 R5 E4 F20 D9 H5 L5 H4 " 'RIGHT half of Ship (most of it)

    PAINT (Ship.X, Ship.Y), ShipClr&, ShipClr&

    PRESET (Ship.X, Ship.Y) 'Reset for details on wings
    DRAW "C" + STR$(AddClr&) 'Wing-detail color
    DRAW "L13 G16 " 'LEFT Wing's details
    PRESET (Ship.X, Ship.Y) 'Reset
    DRAW "C" + STR$(AddClr&)
    DRAW "R13 F16 " 'RIGHT Wing's details

    PRESET (Ship.X, Ship.Y) 'Set to draw Engine

    DRAW "C" + STR$(EngClr&) 'Engine Color

    DRAW "BU1 L5 D18 R10 U18 L5" 'Engine Rectangle
    PAINT (Ship.X, Ship.Y), EngClr&, EngClr&

    PRESET (Ship.X, Ship.Y) 'Reset for darker details on wings
    DRAW "C" + STR$(EngClr&) 'Engine Color
    DRAW "bD15 bL8 nU10 bL3 nU10 bL3 nU7  bR22 " 'Left Wing Details, move to right Wing
    DRAW "nU10 bR3 nU10 bR3 U7"

    CIRCLE (Ship.X, Ship.Y), 6, CirClr& 'The Energy-Ball Source (Sphere)
    PAINT (Ship.X, Ship.Y), CirClr&, CirClr&

    CIRCLE (Ship.X, Ship.Y), 4, ShipClr&, .4, 1.5 'Shine on Sphere
    CIRCLE (Ship.X, Ship.Y), 3, ShipClr&, .3, 1.8

    '----------------- Draw Engine Output (Exhaust) ------------------
    IF EOCnt < 4 AND (Step_X <> 0 OR Step_Y <> 0) AND BLine / 4 = INT(BLine / 4) THEN
        'EOC1& = _RGB(20, 120, 180) 'Dimmer Engine-output color
        EOC2& = _RGB(0, 190, 255) 'Brighter Engine-output color

        Speed = ABS(Step_X) + ABS(Step_Y)
        IF Speed > 14 THEN LoLine = 38 ELSE IF Speed > 4 THEN LoLine = 32 ELSE LoLine = 28

        'PRESET (Ship.X, Ship.Y) 'Set back to Sphere ctr.           '* * * * DELETE if darker lines are NOT drawn at all * * * *
        'DRAW "C" + STR$(EOC1&) 'Engine Output Color (dimmer)
        'DRAW "bL5 bD22  R10 bD4 L10 bD4 R10 bD4 L10" 'Stacked 4 lines
        ''_DELAY 1

        PRESET (Ship.X, Ship.Y)
        DRAW "C" + STR$(EOC2&) 'Engine Output Color (lighter)
        DRAW "bL5 bD=" + VARPTR$(BLine) + "R10"

        BLine = BLine + 4: IF BLine > LoLine THEN BLine = 24 'Lines are drawn @ 24, 28, 32 and 34 down from Ship.X/Y
    END IF '----------------------------------------------------------

    EOCnt = EOCnt + 1: IF EOCnt > 4 THEN EOCnt = 1
    ShipClr& = 0: CirClr& = 0: EngClr& = 0

END SUB

'  E = /  UP/RIGHT
'  F = \  DOWN/RIGHT
'  G = /  DOWN/LEFT
'  H = \  UP/LEFT

'  L = -- LEFT
'  R = -- RIGHT
'  U = |  UP
'  D = |  DOWN


SUB Jump_Ship (XX, YY, Ship.Vanished)

    'Sub is called repeatedly, if needed, until a safe jump-to location is found.
    'Otherwise, Ship just continues being drawn in old location as usual in order
    'to let all other action continue uninterrupted.


    ': : COLOR _RGB(111, 111, 111): _ PRINTSTRING (0, 222), "OCnt:" + STR$(OCnt): ': SLEEP

    DO UNTIL OCnt = Obj.Cnt '.Max '* * * * Confirmed that Obj Max > 0 * * * *

        XX = RND * 1280 'New horiz. position for Window
        YY = RND * 720 'Vert.

        ': : LOCATE 13, 1: PRINT OCnt, XX; YY;:: SLEEP
        :: COLOR _RGB(111, 111, 111): ' _ PRINTSTRING (222, 222), "OCnt:" + STR$(OCnt) ':: SLEEP

        FOR O = 1 TO Obj.Max
            IF Exist(O) AND ABS(XX - Obj.X(O)) > 99 AND ABS(YY - Obj.Y(O)) > 99 THEN OCnt = OCnt + 1
            ': COLOR _RGB(111, 111, 111): _ PRINTSTRING (222, 222), "OCnt:" + STR$(OCnt) ':: SLEEP
        NEXT
    LOOP

    FOR O = 1 TO Obj.Max
        IF Exist(O) THEN Obj.X(O) = Obj.X(O) + (X - XX): Obj.Y(O) = Obj.Y(O) + (Y - YY)
    NEXT: O = 0

    Ship.Vanished = 0: X = XX: Y = YY: OCnt = 0

END SUB 'Jump Ship


SUB Ship_Speed (Slide) '=============================================================================================

    Orig.Ang = Angle 'Angle MAY change TEMPORARILY below for Slide purposes

    SELECT CASE Angle 'Set Angle quarter...          * * * * Debug: Slide =  * * * *
        CASE 1 TO 90: Ang = 1 'Up + left
        CASE 91 TO 180: Ang = 2 'Down + left
        CASE 181 TO 270: Ang = 3 'Down + right
        CASE 271 TO 360: Ang = 4 'Up + right
    END SELECT

    IF Slide < 0 THEN Angle = Angle + 90: IF Angle > 360 THEN Angle = Angle - 360 'Angle 90 deg. anticlockwise for Slide LEFT
    IF Slide > 0 THEN Angle = Angle - 90: IF Angle < 1 THEN Angle = Angle + 360 'Slide RIGHT

    Got.Slide:

    SELECT CASE Angle 'Ship's X/Y change independently, based on Ship's curr. Angle

        CASE 1 TO 90: Ang = 1
            UpLeft:
            Step_X = Step_X - Inc * (Angle / 90):: Step_Y = Step_Y - (Inc - Inc * (Angle / 90)) 'Left or Up-Left
        CASE 91 TO 180: Ang = 2
            DownLeft:
            Step_X = Step_X - (Inc - Inc * ((Angle - 90) / 90)):: Step_Y = Step_Y + (Inc * ((Angle - 90) / 90)) 'Down or Down-Left
        CASE 181 TO 270: Ang = 3
            DownRight:
            Step_X = Step_X + (Inc * ((Angle - 180) / 90)):: Step_Y = Step_Y + (Inc - Inc * ((Angle - 180) / 90)) 'Down or Down-Right
        CASE 271 TO 360: Ang = 4
            UpRight:
            Step_X = Step_X + (Inc - Inc * ((Angle - 270) / 90)):: Step_Y = Step_Y - (Inc * ((Angle - 270) / 90)) 'Up or Up-Right

    END SELECT '* * * * Debug: Inc =

    Angle = Orig.Ang

END SUB


SUB Ship_Slow '--------------------------------------

    IF Step_X <> 0 OR Step_Y <> 0 THEN

        IF ABS(Step_X) < 1 AND ABS(Step_Y) < 1 THEN
            Step_X = 0: Step_Y = 0 'Full Stop

        ELSE 'Slow according to Step_X/Y

            Step_X = Step_X - Step_X / 10 '5
            Step_Y = Step_Y - Step_Y / 10 '5
        END IF
    END IF


END SUB


SUB Fire_Laser (PCnt, PX(), PY(), Dist()) '==================================================================

    IF Snd THEN
        FOR F = 6000 TO 5500 STEP -100: SOUND F, .25: NEXT 'Ver. 1  (HIGH pitch)                 ( ((  )) )
        'FOR F = 600 TO 500 STEP -50: SOUND F, .3: NEXT 'Ver. 2
        'FOR F = 600 TO 100 STEP -100: SOUND F, .3: NEXT 'Ver. 3
        'FOR F = 300 TO 100 STEP -45: SOUND F, .3: NEXT 'Ver. 4
        'FOR F = 150 TO 50 STEP -25: SOUND F, .3: NEXT 'Ver. 5

        'Snd.Name& = _SNDOPEN("SB_Sounds/J_Waka_[half_001].mp3") ', "VOL") 'Play sound file
        '_SNDVOL Snd.Name&, 1: IF Snd.Name& THEN _SNDPLAY Snd.Name&
        '_SNDCLOSE Snd.Name& '* * * * CLOSE it each time or NOT ? * * * *
    END IF

    IF PCnt < PMax + 1 - PNum THEN ' < max. # of LaserBalls are active
        LastProj = TIMER

        FOR P = 1 TO PNum 'PNum = How many LaserBalls emerge at once (1-3)
            PCnt = PCnt + 1

            PX(PCnt) = Ship.X: PY(PCnt) = Ship.Y: Dist(PCnt) = 0 'New Projectile
            Live(PCnt) = -1: PRad(PCnt) = 5

            IF P = 1 THEN Ang(PCnt) = Angle ELSE IF P = 2 THEN Ang(PCnt) = Angle + 20 ELSE Ang(PCnt) = Angle - 20
            IF Ang(PCnt) > 360 THEN Ang(PCnt) = Ang(PCnt) - 360 ELSE IF Ang(PCnt) <= 0 THEN Ang(PCnt) = Ang(PCnt) + 360
        NEXT: P = 0

        SELECT CASE Energy
            CASE IS >= 80: Energy = Energy - (1 + PNum) 'Expanding LaserBalls (except in Super Obj. mode)
            CASE 5.5 TO 79.9: Energy = Energy - .5
        END SELECT

        'IF Round > 4 THEN
        'MaxDist = 80 - Round * Skill + Energy / 5:
        MaxDist = 100 - Round / 2 - 20 * Skill + Energy / 5 'The Projectiles' range is adjusted
        IF MaxDist < 30 THEN MaxDist = 30 ELSE IF MaxDist > 80 THEN MaxDist = 80

        IF Score > 9999 AND NOT Super.Obj THEN PRate = .14 - Energy / 1600: IF PRate < .105 THEN PRate = .105 'Rapid-fire rate/limit is set

        ': : LOCATE 21, 1: PRINT USING "MaxDist: ##  PRate: ##.###  Energy: ##.##     "; MaxDist; PRate; Energy
    END IF

END SUB


SUB Projectiles (Ang, PCnt, PX(), PY(), Dist(), Snd_Pop&) '==================================================================

    PStp = 12 'Projectile moves by this step
    OMax = Obj.Max


    FOR P = 1 TO PCnt 'for each on-screen Projectile...

        ': : LOCATE 11 + P, 1: PRINT USING "PX/Y(#): #### ####  Dist: ###.##  Live: ##  Angle: ###  Ang: ###    "; P; PX(P); PY(P); Dist(P); Live(P); Ang(P); Ang;

        IF Live(P) THEN 'Projectile still alive

            'PRad = Projectile's radius; if Energy's higher (and Expand = ON), Projectiles will EXPAND as they travel...

            CIRCLE (PX(P), PY(P)), PRad(P), _RGB(88, 22, 222) 'The Projectile: Outer Ring         o   o   o      o   o
            'IF PRad(P) > 10 THEN CIRCLE (PX(P), PY(P)), PRad(P) - PRad(P) / 4, _RGB(140, 88, 225) 'Larger, dimmer inner ring
            IF PRad(P) < 10 THEN PRad = 3 ELSE PRad = PRad(P) / 4
            CIRCLE (PX(P), PY(P)), PRad, _RGB(210, 180, 255) 'Smaller, brighter inner

            IF Expand AND Energy > 79 AND PRad(P) < 30 THEN PRad(P) = PRad(P) + .25 'Projectile EXPANDS        .     o     O

            FOR O = 1 TO OMax 'Obj. Max 'Did LaserBall hit Object?

                '----------------------------------------------
                IF O = Drainer AND NOT ED.Active GOTO Skip.Obj 'Can't zap the Drainer too early in Round
                '----------------------------------------------

                'IF ABS(PX(P) - Obj.X(O)) < 25 AND ABS(PY(P) - Obj.Y(O)) < 25 THEN _font 8: : LOCATE 1 + P, 1: PRINT USING "Obj: ##  Proj: #  Dist: ##  Obj.X/Y: #### ####   PX/Y: #### ####   "_
                '   ; O; P; Dist(P); Obj.X(O); Obj.Y(O); PX(P); PY(P);:: TEST.SLEEP  = 15

                ': :  LOCATE 1 + O, 1: : _FONT 14: :PRINT: : PRINT USING "Obj: ##  Obj.X/Y: #### ####   "; O; Obj.X(O); Obj.Y(O): ': TEST.SLEEP  = 15


                ObRad = ObRad(O): OZone = ObRad '* * * *  MUST be set here, as well as in Normal Objects block in sub Play Game  * * * *


                IF PX(P) > 0 AND Obj.X(O) > 0 AND PY(P) > 0 AND Obj.Y(O) > 0 THEN 'Make sure they're not 0

                    IF ABS(PX(P) - Obj.X(O)) < OZone + PRad(P) AND ABS(PY(P) - Obj.Y(O)) < OZone + PRad(P) THEN 'It's a Hit!  ><  ><  ><  ><  ><  ><  ><  ><

                        'OZone  =  Min. distance of Proj. to Obj. for a HIT

                        Flash.X = Obj.X(O): Flash.Y = Obj.Y(O) 'A destroyed Object will FLASH
                        FRad = ObRad + 20 'Initial size of Flash

                        IF Energy <= 94 THEN Energy = Energy + 6 'Normal Object hit (-1 per Ball, hit or not; so, +6 instead of +5)
                        IF Shield.Up < 100 THEN Shield.Up = Shield.Up + 2

                        Live(P) = 0 'Projectile expires

                        ':: IF O < 52 THEN : : _FONT 14: : LOCATE  O, 1:: COLOR _RGB(0, 222, 255): : PRINT P; USING "ObMax: ##  ObCnt: ##  ObRad: ##  OZone: ##  PRad: ##  "_
                        '; Obj.Max; Obj.Cnt; ObRad; OZone; PRad(P): : TEST.SLEEP = 10

                        IF (Round > 1 OR Skill = 3) AND ObRad(O) > Rad3 THEN 'add 2 new medium/small Objects - - - - - - - -
                            Hit.X = Obj.X(O): Hit.Y = Obj.Y(O)
                            CALL Add_Objects(Hit.X, Hit.Y, O)

                            Obj.Max = Obj.Max + Split.Num
                        END IF '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

                        Exist(O) = 0: Obj.X(O) = 0: Obj.Y(O) = 0 '                                  O B J E C T   E L I M I N A T E D

                        IF O <= PwrUps THEN 'A Power-Up Object was hit
                            FOR F = 700 TO 100 STEP -100: SOUND F, .75: NEXT
                            Energy = 100: Shield.Up = 100: Score = Score + 1000
                        ELSEIF O = Drainer THEN 'the Energy-Drain Object
                            FOR F = 1700 TO 1100 STEP -100: SOUND F, .75: NEXT
                            Energy = Energy - 50: IF Shield.Up > 50 THEN Shield.Up = Shield.Up - 50
                        ELSE
                            IF Snd_Pop& THEN _SNDPLAY Snd_Pop& 'Sound of destroyed Object         ( (( )) )
                            Score = Score + 10
                        END IF

                        IF Round > 1 AND Obj.Cnt = ED.Max + 1 AND NOT ED.Active THEN ED.Active = -1:: FOR S = 1 TO 3: SOUND 180, 4: SOUND 0, 2: NEXT: S = 0

                        IF Score >= NexBon THEN Lives = Lives + 1: Get_NexBon 'Calc. next Bonus Ship level

                    END IF '  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><
                END IF ' > 0

                Skip.Obj:

            NEXT: O = 0 'Object


            '-------------------------------------------------------
            Proj_X = PX(P): Proj_Y = PY(P): Ang = Ang(P) 'Temp holders                     (May not matter where these 3 lines go, here or above the FOR/NEXT.)

            GOSUB Move_Proj: PX(P) = Proj_X: PY(P) = Proj_Y 'Call sub to change Projectile's X/Y      * * * *  T E S T  LOCATION  B  * * * *

            Dist(P) = Dist(P) + 1: IF Dist(P) >= MaxDist THEN Live(P) = 0 'Travel/Distance/Range of Proj.
            '-------------------------------------------------------

            'Proj_X = 0: Proj_Y = 0: Ang = 0  * * * * DELETE?
            IF PCnt = 0 THEN Proj_X = 0: Proj_Y = 0: Ang = 0

        ELSE 'Proj. has run its course

            PX(P) = 0: PY(P) = 0: Dist(P) = 0

            FOR PP = P TO PCnt - 1 'Shift the remaining Projectiles' X/Y, direction, etc.
                PX(PP) = PX(PP + 1): PY(PP) = PY(PP + 1): Live(PP) = Live(PP + 1)
                Dist(PP) = Dist(PP + 1): PRad(PP) = PRad(PP + 1): Ang(PP) = Ang(PP + 1)
            NEXT: PP = 0

            PCnt = PCnt - 1 'There are now 1 fewer Projectiles
        END IF

    NEXT: P = 0

    GOTO Exit.Proj 'Skip over GOSUB called from above


    Move_Proj: '---------------------------------

    SELECT CASE Ang 'Projectile's X/Y changes according to Ship's angle (and whether 1 or 3 are fired)

        CASE 1 TO 90
            Proj_X = Proj_X - PStp * (Ang / 90):: Proj_Y = Proj_Y - (PStp - PStp * (Ang / 90)) 'Left or Up-Left
        CASE 91 TO 180
            Proj_X = Proj_X - (PStp - PStp * ((Ang - 90) / 90)):: Proj_Y = Proj_Y + (PStp * ((Ang - 90) / 90)) 'Down or Down-Left
        CASE 181 TO 270
            Proj_X = Proj_X + (PStp * ((Ang - 180) / 90)):: Proj_Y = Proj_Y + (PStp - PStp * ((Ang - 180) / 90)) 'Right or Down-Right
        CASE 271 TO 360
            Proj_X = Proj_X + (PStp - PStp * ((Ang - 270) / 90)):: Proj_Y = Proj_Y - (PStp * ((Ang - 270) / 90)) 'Up or Up-Right

    END SELECT

    RETURN 'Move Projectile ---------------------

    Exit.Proj:

END SUB 'Projectiles


SUB Proj_Super (Sup.X, Sup.Y, Ang, PCnt, PX(), PY(), Dist(), Snd_Pop&) '==================================================================

    PRad = 5: PStp = 14 'Projectile's outer radius & Travel step
    ObRad = 40 + Shields * 20: OZone = ObRad

    '! ! !  If NOT USING ObRad here, then assign only OZone above instead  ! ! !


    ': : LOCATE 38, 8: PRINT USING "Super.Obj: ##  ObRad/OZone: ### ###  Shields: #  Outer.Clr: ###    Sup.X/Y: #### ####   "; Super.Obj; ObRad; OZone; Shields; Outer.Clr; Sup.X; Sup.Y;:: TEST.SLEEP = 30


    FOR P = 1 TO PCnt 'for each on-screen Projectile...

        ': : LOCATE 11 + P, 1: PRINT USING "PX/Y(#): #### ####  Dist: ###.##  Live: ##  Angle: ###  Ang: ###    "; P; PX(P); PY(P); Dist(P); Live(P); Ang(P); Ang;

        IF Live(P) THEN 'Projectile still alive

            'PRad = Projectile's radius; Projectiles will NOT EXPAND in Super mode...

            CIRCLE (PX(P), PY(P)), PRad, _RGB(88, 22, 222) 'The Projectile: Outer Ring         o   o   o      o   o
            CIRCLE (PX(P), PY(P)), PRad - 2, _RGB(210, 180, 255) 'Smaller, brighter inner

            IF PX(P) > 0 AND Sup.X > 0 AND PY(P) > 0 AND Sup.Y > 0 THEN 'Make sure they're not 0

                IF ABS(PX(P) - Sup.X) < OZone + PRad AND ABS(PY(P) - Sup.Y) < OZone + PRad THEN 'It's a Hit!  ><  ><  ><  ><  ><  ><  ><  ><
                    'OZone  =  Min. distance of Proj. to Obj. for a HIT

                    Flash.X = PX(P): Flash.Y = PY(P) 'A destroyed Object will FLASH
                    FRad = 30 'Small Flash on outer shield

                    IF Energy <= 94 THEN Energy = Energy + 6 'Normal Object hit (-1 per Ball, hit or not; so, +6 instead of +5)
                    IF Shield.Up < 100 THEN Shield.Up = Shield.Up + 2

                    Outer.Clr = Outer.Clr - 40
                    IF Outer.Clr < 51 THEN Shields = Shields - 1: Outer.Clr = 205

                    Live(P) = 0 'Projectile expires (Super Mode)

                    IF Shields <= -1 THEN ' 0 THEN
                        Exist(1) = 0: Sup.X = 0: Sup.Y = 0: Obj.Cnt = 0: Bug.X = 0: Bug.Y = 0: BugCtr = 0 '    S u p e r  O b j e c t   D  E  S  T  R  O  Y  E  D

                        FOR F = 700 TO 100 STEP -100: SOUND F, 1.75: NEXT '          ( (( )) )
                        Energy = 100: Shield.Up = 100: Score = Score + 5000 ': Next_Round = -1 ' Round  = Round + 1  * * * * DELETE here?

                        SELECT CASE Round 'Set Bug's speed per Round
                            CASE 3 TO 7: BStp = Skill + 2
                            CASE 8 TO 24: BStp = Skill + 3
                            CASE IS > 24: BStp = Skill + 4
                        END SELECT

                    ELSE
                        Score = Score + 10
                    END IF

                    IF Score >= NexBon THEN Lives = Lives + 1: Get_NexBon 'Calc. next Bonus Ship level

                END IF '  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><
            END IF

            'NEXT: O = 0

            '-------------------------------------------------------
            Proj_X = PX(P): Proj_Y = PY(P): Ang = Ang(P) 'Temp holders

            GOSUB Move_Proj: PX(P) = Proj_X: PY(P) = Proj_Y 'Call sub to change Projectile's X/Y

            Dist(P) = Dist(P) + 1: IF Dist(P) >= MaxDist THEN Live(P) = 0 'Travel/Distance/Range of Proj.
            '-------------------------------------------------------

            IF PCnt = 0 THEN Proj_X = 0: Proj_Y = 0: Ang = 0

        ELSE 'Proj. has run its course

            PX(P) = 0: PY(P) = 0: Dist(P) = 0

            FOR PP = P TO PCnt - 1 'Shift the remaining Projectiles' X/Y, direction, etc.
                PX(PP) = PX(PP + 1): PY(PP) = PY(PP + 1): Live(PP) = Live(PP + 1)
                Dist(PP) = Dist(PP + 1): Ang(PP) = Ang(PP + 1)
            NEXT: PP = 0

            PCnt = PCnt - 1 'There are now 1 fewer Projectiles
        END IF
    NEXT: P = 0

    GOTO Exit.Proj 'Skip over GOSUB called from above


    Move_Proj: '---------------------------------

    SELECT CASE Ang 'Projectile's X/Y changes according to Ship's angle (and whether 1 or 3 are fired)

        CASE 1 TO 90
            Proj_X = Proj_X - PStp * (Ang / 90):: Proj_Y = Proj_Y - (PStp - PStp * (Ang / 90)) 'Left or Up-Left
        CASE 91 TO 180
            Proj_X = Proj_X - (PStp - PStp * ((Ang - 90) / 90)):: Proj_Y = Proj_Y + (PStp * ((Ang - 90) / 90)) 'Down or Down-Left
        CASE 181 TO 270
            Proj_X = Proj_X + (PStp * ((Ang - 180) / 90)):: Proj_Y = Proj_Y + (PStp - PStp * ((Ang - 180) / 90)) 'Right or Down-Right
        CASE 271 TO 360
            Proj_X = Proj_X + (PStp - PStp * ((Ang - 270) / 90)):: Proj_Y = Proj_Y - (PStp * ((Ang - 270) / 90)) 'Up or Up-Right

    END SELECT

    RETURN 'Move Projectile ---------------------

    Exit.Proj:

END SUB 'Projectiles: Super Obj. version


SUB Check_Proximity 'Has the Plasma Bomb zapped any nearby Objects?

    Objects.Hit = 0: OMax = Obj.Max
    PBZ = OZone + 120 + Energy - Skill * 20 'The P-Bomb Zone

    FOR O = 1 TO OMax 'Obj. Max


        '----------------------------------------------
        IF O = Drainer AND NOT ED.Active GOTO Next.Obj 'Can't zap the Drainer too early in Round
        '----------------------------------------------


        IF ABS(Ship.X - Obj.X(O)) < PBZ AND ABS(Ship.Y - Obj.Y(O)) < PBZ THEN 'It's within range!  ><  ><  ><  ><  ><  ><  ><  ><
            'OZone  =  Min. distance of Proj. to Obj. for a HIT

            Objects.Hit = Objects.Hit + 1

            Hit.X(Objects.Hit) = Obj.X(O): Hit.Y(Objects.Hit) = Obj.Y(O) 'Remember each Object's X/Y fo its FLASH

            IF ObRad(O) > Rad3 THEN 'add 2 new medium/small Objects - - - - - - - -
                Hit.X = Obj.X(O): Hit.Y = Obj.Y(O)
                CALL Add_Objects(Hit.X, Hit.Y, O)

                Obj.Max = Obj.Max + Split.Num
            END IF '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


            Exist(O) = 0: Obj.X(O) = 0: Obj.Y(O) = 0 ': Obj.Cnt  = Obj.Cnt - 1 ': : SOUND 444, .5

            IF O <= PwrUps THEN 'A Power Orb was hit
                FOR F = 700 TO 100 STEP -100: SOUND F, .75: NEXT
                Energy = 100: Shield.Up = 100: Score = Score + 1000

            ELSEIF O = Drainer THEN 'the Energy-Drain Object

                FOR F = 1700 TO 1100 STEP -100: SOUND F, .75: NEXT
                Energy = Energy - 50: IF Shield.Up > 50 THEN Shield.Up = Shield.Up - 50

            ELSE
                'Snd.Name& = _SNDOPEN("SB_Sounds/J_Pop_002.mp3", "VOL") 'Play sound file
                '_SNDVOL Snd.Name&, 1: IF Snd.Name& THEN _SNDPLAY Snd.Name&
                '_SNDCLOSE Snd.Name&

                IF Snd_Pop& THEN _SNDPLAY Snd_Pop& 'Sound of destroyed Object         ( (( )) )

                Score = Score + 10
            END IF

            IF Score >= NexBon THEN Lives = Lives + 1: Get_NexBon

        END IF '   ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><  ><

        Next.Obj:

    NEXT: O = 0: OMax = 0: Os.Hit = Objects.Hit

    IF Os.Hit > 0 THEN PB.Time = TIMER '# of Objects hit will be shown for a few secs.

END SUB 'Check Proximity


SUB Blow_em_Up 'Series of Smaller-and-Smaller Painted CIRCLEs as Object "Explodes"

    ': : LOCATE 44, 4: PRINT USING "Obj. Hit: #  FRad: ###  Flash.X/Y: #### ####    "; Objects.Hit; FRad; Flash.X; Flash.Y;:: TEST.SLEEP  = 1

    CIRCLE (Flash.X, Flash.Y), FRad, _RGB(210, 120, 25)
    PAINT (Flash.X, Flash.Y), _RGB(210, 120, 25), _RGB(210, 120, 25)
    FRad = FRad - FRad / 2: IF FRad <= ObRad / 8 THEN Flash.X = 0: Flash.Y = 0: FRad = 0: Objects.Hit = 0

END SUB


SUB Scatter_Objects '===========================================================================================

    'Each new Round will begin with a screenful of fresh Objects to zap...

    Obj.Max = 12 'Starting # of Objects
    IF Round < 4 THEN Split.Num = 2 ELSE Split.Num = 3

    Obj.Cnt = Obj.Max: PwrUps = Obj.Cnt \ 6 '# of Power-up Objects (the GREEN ones)
    '* * * * New Round always starts w/ 12 Objects, to be increased by SPLITTING...?  * * * *
    Super.Obj = 0: Ship.Destroyed = 0: PCnt = 0: BugCtr = 0: Step_X = 0: Step_Y = 0: Angle = 360

    MaxDist = 80 '!!!  Must set MaxDist to starting amount in case we've direct-jumped back to a low Round  !!!
    PRate = .12 'Rapid-fire rate (diff. in Super Obj. mode)    * * * * Debug: Energy =

    ED.Active = 0: ED.Max = 6 - Skill 'Max. no. of Objects remaining when Energy Drainer is activated

    FOR O = 1 TO Obj.Max
        Get.Obj.X:
        Obj.X(O) = RND * 1280: IF ABS(Ship.X - Obj.X(O)) < 120 GOTO Get.Obj.X 'Not too close to Ship's loc. (640, 360 or similar)
        Get.Obj.Y:
        Obj.Y(O) = RND * 720: IF ABS(Ship.Y - Obj.Y(O)) < 120 GOTO Get.Obj.Y

        Get.Stp: LC = LC + 1

        IF LC > 999 THEN EXIT FOR 'Failed to find loc. away from other Objects

        Stp.X(O) = RND * 2 + 1: Stp.Y(O) = RND * 2 + 1
        RANDOMIZE TIMER: IF RND < .5 THEN Stp.X(O) = -Stp.X(O) 'Moves leftward
        RANDOMIZE TIMER: IF RND < .5 THEN Stp.Y(O) = -Stp.Y(O) 'Moves upward

        'Check current Object's X/Y and direction against all previous ones...

        FOR OO = 1 TO O - 1
            IF (ABS(Obj.X(OO) - Obj.X(O)) < 90 OR ABS(Obj.Y(OO) - Obj.Y(O)) < 90) AND Stp.X(OO) = Stp.X(O) AND Stp.Y(OO) = Stp.Y(O) GOTO Get.Stp
        NEXT

        IF Asteroids THEN Rock(O) = INT(RND * Rock.Cnt) + 1 '* * * * In future, more than 3 Rock varieties * * * *

        ObRad(O) = Rad1: Exist(O) = -1 'This Object now exists!   * * * * Radius Rad1 (50 or 60) may vary when Object-size options become available * * * *

    NEXT: IF O < Obj.Max THEN Obj.Max = O:: SOUND 7777, 10 'In case escaping endless loop results in fewer Objects

    '-----------------------------
    IF Round > 1 THEN Drainer = 8 'This Object is the Energy Drainer
    '-----------------------------

    IF Energy < 80 THEN Energy = 80
    IF Shield.Up < 80 THEN Shield.Up = 80

    O = 0: OO = 0: LC = 0: Objects.Hit = 0: Os.Hit = 0 '* * * * MUST we zero Objects/Os.Hit here? * * * *

END SUB 'Scatter Objects



SUB Add_Objects (Hit.X, Hit.Y, O) 'An Object was hit and SPLIT/DIVIDED...

    FOR OO = Obj.Max + 1 TO Obj.Max + Split.Num '* * * * Debug: Obj.Cnt =    SCREEN
        1000
        ': : _FONT 14:: PRINT USING "[Projectiles] O: ##  Rad: ##  Max: ##   "; O; ObRad(O); Obj.Max:: TEST.SLEEP = 5
        ':: if OO < 49 THEN : : _FONT 14: : LOCATE 4 + OO: : COLOR _RGB(222, 222, 0): : PRINT USING "##  Exist: ##  Rad: ##  Obj.X/Y: #### ####  Stp.X/Y: ## ##  LC: ###    "_
        '   ; OO; Exist(OO); ObRad(OO); Obj.X(OO); Obj.Y(OO); Stp.X(OO); Stp.Y(OO); LC:: TEST.SLEEP = 15

        LC = 0

        2000
        Get.Obj.X:::
        IF RND < .5 THEN PosNeg = -1 ELSE PosNeg = 1
        Obj.X(OO) = Hit.X - RND * (ObRad(O) + 30) * PosNeg 'a little to left/right of orig. Obj.
        Get.Obj.Y:::
        IF RND < .5 THEN PosNeg = -1 ELSE PosNeg = 1
        Obj.Y(OO) = Hit.Y - RND * (ObRad(O) + 30) * PosNeg 'a little above/below

        Get.Stp: LC = LC + 1: RANDOMIZE TIMER

        IF LC > 999 THEN EXIT FOR 'Failed to find loc. away from other Objects
        3000
        Stp.X(OO) = RND * 2 + 1: Stp.Y(OO) = RND * 2 + 1 'Object's speed

        IF RND < .5 THEN Stp.X(OO) = -Stp.X(OO) 'Travels leftward
        IF RND < .5 THEN Stp.Y(OO) = -Stp.Y(OO) 'Travels upward


        'Check current Object's [X/Y and] direction against all previous ones...

        IF OO >= Obj.Max + Split.Num THEN

            FOR OOO = Obj.Max + 1 TO OO - 1
                'IF (ABS(Obj.X(OOO) - Obj.X(OO)) < 90 OR ABS(Obj.Y(OOO) - Obj.Y(OO)) < 90) AND Stp.X(OOO) = Stp.X(OO) AND Stp.Y(OOO) = Stp.Y(OO) GOTO Get.Stp
                IF Stp.X(OO) = Stp.X(OOO) AND Stp.Y(OO) = Stp.Y(OOO) GOTO Get.Stp
            NEXT

        END IF


        IF ObRad(O) = Rad1 THEN ObRad(OO) = Rad2 ELSE ObRad(OO) = Rad3

        Rock(OO) = Rock(O) '* * * * In future, more than 5 Rock varieties? * * * *

        5000
        Exist(OO) = -1 'This Medium/Small Object now exists!

        ': : IF OO < 49 THEN:: _FONT 14: : LOCATE 4 + OO:: COLOR _RGB(222, 222, 222):: PRINT USING "##  Exist: ##  Max: ##  Rad: ##  Obj.X/Y: #### ####  Stp.X/Y: ## ##  LC: ###    "; OO; Exist(OO); Obj.Max; ObRad(OO); Obj.X(OO); Obj.Y(OO); Stp.X(OO); Stp.Y(OO); LC:: TEST.SLEEP = 15

    NEXT: OO = 0: PosNeg = 0: LC = 0 ': OOO = 0

    ':::: CLOSE 1

END SUB


SUB Move_Object (Obj.X, Obj.Y, Stp.X, Stp.Y, O) '==================================================================

    'Change Object's X/Y position...

    Ext.X1 = -2560: Ext.Y1 = -1440: Ext.X2 = 2560: Ext.Y2 = 1440 'Extremes well OUTSIDE of Play Area

    IF Obj.X >= Ext.X1 AND Obj.X <= Ext.X2 AND Obj.Y >= Ext.Y1 AND Obj.Y <= Ext.Y2 THEN 'Change by normal Step/Increment
        Obj.X = Obj.X + Stp.X - Step_X: IF Obj.X > 2560 THEN Obj.X = 0 'If reached edge, wraparound
        Obj.Y = Obj.Y + Stp.Y - Step_Y: IF Obj.Y > 1440 THEN Obj.Y = 0
    ELSE 'Wraparound at extreme edge
        IF Obj.X > Ext.X2 THEN Obj.X = Ext.X1 ELSE IF Obj.X < Ext.X1 THEN Obj.X = Ext.X2
        IF Obj.Y > Ext.Y2 THEN Obj.Y = Ext.Y1 ELSE IF Obj.Y < Ext.Y1 THEN Obj.Y = Ext.Y2
    END IF

    'NOTE: The X/Y values (Obj.X/Y) of Objects within the Play Area
    '      that move EXACTLY with the Ship will remain static.

END SUB


SUB Super_Object (MX, MY, MClr&, Sup.X, Sup.Y) '===============================================


    ' Place the Super Object, on screen or off.  If it's OFF SCREEN, then either
    ' the Map blips or the directional Arrows will guide Player to the Object...


    IF Sup.X < 1936 AND Sup.X > -649 AND Sup.Y < 1101 AND Sup.Y > -374 THEN
        CIRCLE (MX + Sup.X / 10, MY + Sup.Y / 10), 2, MClr& 'Corner-Map "Blips"             [  ]

        IF BugCtr = 0 THEN ' AND Sup.X < 1280 AND Sup.X >= 0 AND Sup.Y < 720 AND Sup.Y >= 0 THEN 'Set the Bug's start coords.  * * * * DELETE part?
            Bug.X = Sup.X: Bug.Y = Sup.Y: BugCtr = 1 'Set the Bug's start coords. (even if S.O. is still off-screen)
        END IF

    ELSE 'Show Guide Arrows...

        GuideClr& = _RGB(255, 220, 180)
        PRESET (Ship.X, Ship.Y): DRAW "C" + STR$(GuideClr&)
        IF Sup.X < -650 THEN DRAW "bL90 nF10 E10" ELSE IF Sup.X > 1935 THEN DRAW "bR90 nH10 G10" 'Left/Right arrow
        PRESET (Ship.X, Ship.Y): DRAW "C" + STR$(GuideClr&)
        IF Sup.Y < -375 THEN DRAW "bU80 nG10 F10" ELSE IF Sup.Y > 1100 THEN DRAW "bD80 nH10 E10" 'Up/Down arrow

        GOTO Exit_Sub
    END IF

    ': : LOCATE 20, 1: PRINT USING "Super: ##  MX/MY: ## ##  Sup.X/Y: #### ####  Shields: #  OutClr: ###   "; Super.Obj; MX; MY; Sup.X; Sup.Y; Shields; Outer.Clr;
    ': : LOCATE 20, 1: PRINT USING "Super: ##  MX/MY: ## ##  Sup.X/Y: #### ####    "; Super.Obj; MX; MY; Sup.X; Sup.Y;
    ': : LOCATE 22, 1: PRINT USING "X/Y: #### ####  CIRCLE(#### ####)  Map CIRCLE(#### ####)    "; X; Y; Sup.X; Sup.Y; MX + Sup.X / 10; MY + Sup.Y / 10;

    '- - - - - - - - - - - - - - - -  D R A W  S U P E R  O B J E C T  - - - - - - - - - - - - - - - - -

    FOR C = 0 TO 40 STEP 2 'Object's Core
        CIRCLE (Sup.X, Sup.Y), C, _RGB(255 - C * 5, 0, 0) 'Cool, glowy effect
    NEXT

    ':::: IF Shield s > 0 THEN

    FOR S = 0 TO Shields - 1 'All except outer Shield
        CIRCLE (Sup.X, Sup.Y), 40 + S * 20, _RGB(105, 40, 255) 'An INNER Shield (diff. color from outer)

        'SELECT CASE S 'for alternating colors
        'CASE 1, 3: CIRCLE (Sup.X, Sup.Y), 40 + S * 20, _RGB(255, 255, 255) 'An INNER Shield
        'CASE 2, 4: CIRCLE (Sup.X, Sup.Y), 40 + S * 20, _RGB(105, 20, 255)
        'END SELECT
    NEXT: S = 0 '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    ':::: END IF

    CIRCLE (Sup.X, Sup.Y), ObRad, _RGB(Outer.Clr * .6, Outer.Clr * .6, Outer.Clr) 'Object's OUTER Shield
    '* * * * Debug: Sup.X =

    Exit_Sub:
END SUB 'Super Object


SUB Super_Bug '(BStp) 'Move the Bug toward Ship (in meandering fashion?)

    IF RND < .3 THEN Bug.X = Bug.X + BStp * SGN(Ship.X - Bug.X) 'Bug goes LEFT or RIGHT (depends on Ship.X in relation to Bug.X)
    IF RND < .3 THEN Bug.Y = Bug.Y + BStp * SGN(Ship.Y - Bug.Y) 'Bug goes UP or DOWN

    'Now compensate for the Ship's changing X/Y...

    Bug.X = Bug.X - Step_X '* (ABS(Ship.X - Bug.X) / ABS(Ship.Y - Bug.Y)) '* * * *  Attempt to even up Bug's movement on X/Y fails, so far  * * * *
    Bug.Y = Bug.Y - Step_Y '* (ABS(Ship.Y - Bug.Y) / ABS(Ship.X - Bug.X))

    ': : LOCATE 30, 1: PRINT USING "Super: ##  Step_X/Y: ##.# ##.#  Bug.X/Y: ####.# ####.#  BugCtr: ###   "; Super.Obj; Step_X; Step_Y; Bug.X; Bug.Y; BugCtr
    ': : LOCATE 31, 1: PRINT USING "SGN(Ship.X - Bug.X): ##   SGN(Ship.Y - Bug.Y): ##   "; SGN(Ship.X - Bug.X); SGN(Ship.Y - Bug.Y)

    ': : LOCATE 32, 1: PRINT USING "X: ####.#  Y: ####.#  X / Y: ##.#  Y / X: ##.#     "; ABS(Ship.X - Bug.X); ABS(Ship.Y - Bug.Y); ABS(Ship.X - Bug.X) / ABS(Ship.Y - Bug.Y); ABS(Ship.Y - Bug.Y) / ABS(Ship.X - Bug.X);

    CIRCLE (Bug.X, Bug.Y), 7, _RGB(15, 90, 155)
    CIRCLE (Bug.X, Bug.Y), 4, _RGB(60, 200, 255) 'Brighter core

    BugCtr = BugCtr + 1: IF BugCtr >= 800 THEN BugCtr = 0 'The Bug's step/duration counter

    IF ABS(Ship.X - Bug.X) + ABS(Ship.Y - Bug.Y) < 20 THEN Ship.Destroyed = -1

END SUB


SUB Save_Game '===========================================================

    OPEN "SB_Saved_Game.dat" FOR OUTPUT AS #1

    PRINT #1, Skill; Lives; Snd; NoSnd; Round; Score; Clouds; Asteroids
    PRINT #1, Step_X; Step_Y; Angle; Energy; Shield.Up; MaxDist; Ship.Destroyed '* * * * Ship Destroyed may not need saving * * * *
    PRINT #1, Obj.Max; Obj.Cnt; Super.Obj; Drainer; ED.Max; ED.Active; PRate; Expand; Tri.Ball

    IF Super.Obj THEN 'Save SINGLE Object's X/Y and Shields data
        PRINT #1, Sup.X; Sup.Y, Shields, Outer.Clr
        ': : SOUND 3333, 2
    ELSE 'Save multiple Objects' X/Y, movement, size, etc.

        FOR OO = 1 TO Obj.Max
            PRINT #1, Exist(OO), Obj.X(OO); Obj.Y(OO), Stp.X(OO); Stp.Y(OO), ObRad(OO), Rock(OO)
        NEXT: OO = 0
    END IF: CLOSE 1: SOUND 200, 1

    ': : _FONT 14: : LOCATE 35, 1:: PRINT USING "Super: ##  Exist(1): ##  ObMax: ##  Cnt: ##  Shields: ###.##  OuterClr: ###  "; Super.Obj; Exist(1); Obj.Max; Obj.Cnt; Shields; Outer.Clr: TEST.SLEEP = 55

END SUB


SUB Load_Game 'Here, Resumed Game is turned ON (variable becomes -1)

    OPEN "SB_Saved_Game.dat" FOR INPUT AS #1

    INPUT #1, Skill, Lives, Snd, NoSnd, Round, Score, Clouds, Asteroids
    INPUT #1, Step_X, Step_Y, Angle, Energy, Shield.Up, MaxDist, Ship.Destroyed
    INPUT #1, Obj.Max, Obj.Cnt, Super.Obj, Drainer, ED.Max, ED.Active, PRate, Expand, Tri.Ball

    IF Super.Obj THEN 'Load SINGLE Object's X/Y and Shields data
        INPUT #1, Sup.X, Sup.Y, Shields, Outer.Clr
        ': : SOUND 7777, 20
    ELSE 'Load multiple Objects' X/Y, movement, size, etc.

        FOR OO = 1 TO Obj.Max
            INPUT #1, Exist(OO), Obj.X(OO), Obj.Y(OO), Stp.X(OO), Stp.Y(OO), ObRad(OO), Rock(OO)
        NEXT: OO = 0
    END IF: CLOSE 1: SOUND 200, 4: SOUND 320, 1: Resumed_Game = -1

    ': : _FONT 14: : LOCATE 37, 1:: PRINT USING "Super: ##  ObMax: ##  Cnt: ##  Shields: ###.##  OuterClr: ###  "; Super.Obj; Obj.Max; Obj.Cnt; Shields; Outer.Clr: TEST.SLEEP = 55

END SUB '=================================================================



'CHR$(0) + CHR$(16-50)      [Alt] + A-Z
'CHR$(0) + CHR$(59)         [F1]                 ";"
'CHR$(0) + CHR$(60)         [F2]                 "<"
'CHR$(0) + CHR$(61)         [F3]                 "="
'CHR$(0) + CHR$(62)         [F4]                 ">"
'CHR$(0) + CHR$(63)         [F5]                 "?"
'CHR$(0) + CHR$(64)         [F6]                 "@"
'CHR$(0) + CHR$(65)         [F7]                 "A"
'CHR$(0) + CHR$(66)         [F8]                 "B"
'CHR$(0) + CHR$(67)         [F9]                 "C"
'CHR$(0) + CHR$(68)         [F10]                "D"
'CHR$(0) + CHR$(133)        [F11]                "à"
'CHR$(0) + CHR$(134)        [F12]                "å"
'CHR$(0) + CHR$(71)         [Home]               "G"
'CHR$(0) + CHR$(72)         [Up Arrow]           "H"
'CHR$(0) + CHR$(73)         [Page Up]            "I"
'CHR$(0) + CHR$(75)         [Left Arrow]         "K"
'CHR$(0) + CHR$(76)         [5 on NumPad]        "L" (NumLock off in QB64)
'CHR$(0) + CHR$(77)         [Right Arrow]        "M"
'CHR$(0) + CHR$(79)         [End]                "O"
'CHR$(0) + CHR$(80)         [Down Arrow]         "P"
'CHR$(0) + CHR$(81)         [Page Down]          "Q"
'CHR$(0) + CHR$(82)         [Insert]             "R"
'CHR$(0) + CHR$(83)         [Delete]             "S"
'CHR$(0) + CHR$(84-93)      [Shift] + F1-10
'CHR$(0) + CHR$(94-103)     [Ctrl] + F1-10
'CHR$(0) + CHR$(104-113)    [Alt] + F1-10
'CHR$(0) + CHR$(114-119)    [Ctrl] + keypad
'CHR$(0) + CHR$(120-129)    [Alt] + number
'CHR$(0) + CHR$(130 or 131) [Alt] + _/- or +/=   "é" or "â"

'CHR$(0) + CHR$(135)        [Shift] + [F11]      "ç"
'CHR$(0) + CHR$(136)        [Shift] + [F12]      "ê"
'CHR$(0) + CHR$(137)        [Ctrl] + [F11]       "ë"
'CHR$(0) + CHR$(138)        [Ctrl] + [F12]       "è"
'CHR$(0) + CHR$(139)        [Alt] + [F11]        "ï"
'CHR$(0) + CHR$(140)        [Alt] + [F12]        "î"


