b+ Asteroids M11
#1
Oldie but goodie:
Code: (Select All)
Option _Explicit
_Title "b+QB64 Asteroids M11" 'started 2018-07-13
'2020 - Oct and Nov: Special thanks to SierraKen who has been helpful with suggestions, ideas and fixes.
Randomize Timer

' Far far away in a universe where Newton's 1st Law of Motion is not obeyed...    ;-))


'                                            New Controls
' key a or left arrow = turn left
' key s or right arrow = turn right
' enter or spacebar =  "hyperspace" show up somewhere else  better or worse use when collision is imminent
' key k or up arrow = thrust  just a burst in direction you are pointed but doesn't last
' fire! owwha, owha, owha...  is now continuous

'=================================================================================================================

' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
' 2020-10-28 another makeover explosions and split asteroids
' 2020-10-29 fix baby rock management, break between lives
' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
' points:
' The higher the speed the better    speed range .5 to 2.5, diff = 2 * 50 = 100          s - .5 * 50
' DELETE The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
'        ((speed - .5) * 50 + (90 - (r - 10)) * 1.1111) / 2 = 100 best score per hit
' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
' 2020-11-01 M5 FX Moving through space, Oh yeah, more aliens!
' 2020-11-01 M6 add play again and save high game , continuous shoot
' 2020-11-01 M7 fix hits count when hit alien ship or Bolder of Death. Fix lights on aliens ship. I want to see collsions with ship.
' Ken recommends removing text in middle of screen, yeah, distracting. Makeover ship as with mouse x, y it's center. Add Splash screen.
' Show mouse in between lives so can be in screen center when press key to start next run.

' 2020-11-03 M9 watching videos on Asteroids, I found a view and description of the control panel, it is:
' 2 buttons on left and lower button in middle and 2 buttons on right level with 2 on left.
' 2 buttons on left are left and right turns they will be Keys A and S
' The middle will be spacebar for Hypespace or these days we might call it worm hole, jump to another location better or worse!
' 2 buttons on right K and L: K will be a thruster of sorts you eventually come to a stop (not what Newton would like) L is the fire button.
' So let's try that. I am impressed by hitting thruster and shooting all around as you dift in direction gun was pointed when hit thruster.
' Lighten rocks and change points, based now only on size and speed of Asteroids.
' 2020-11-04 M9 Install new update to thrust control. Thanks to SierraKen for finding out what happened to Hyperspace jump when press
' spacebar a 2nd time in a life. Oh also Boulders of Death are now more like smooth colored spheres. Ahhhh Fixed the crashing at the borders
' now fly out one side and come back in on the other! This is getting good! Adding some sound effects.
' 2020-11-05 M10 set some constants for starting game so can just change them to level of play desired.
' speed points =  50 * (rockSpeed - minRockSpeed)/rockSpeedRange > fastest rock gets 50 points
' size points = 50 * (rockSizeRange - (rockSize - minRockSize))/rockSizeRange  > smallest rock gets 50 points
' points = points +  50 * ( (rockSpeed - minRockSpeed)/rockSpeedRange +  (rockSizeRange - (rockSize - minRockSize))/rockSizeRange )
' Dav's comments: Add arrow keys for left right turns and up for thrust, continuous fire now! A little score board in top left corner.
' Dav I am keeping spacebar for Hyperspace but also Enter, don't need fire button now.
' Try the A for left and the right arrow for right turns.
' 2020-11-05 p is for pause
' 2020-11-06 Move it or lose it!
' 2020-11-06 Put the dang mouse back in!  Press m for mouse target rich environment! Use left and right mouse buttons to aim guns,
' 2020-11-08 add mouse mode you can enter at splash screen,

' 2021-09-24 b+QB64 Asteroids M11 best mouse only
' fix p for play again because it is also pause
' don't like enter to start next life, spacebar preferred

'================================================================================================================

'    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just press enter,  as in enter a new life!

'================================================================================================================

Const xmax = 1200, ymax = 700, pi = _Pi, polyAngle = _Pi / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
Const startRocks = 2, minRockSpeed = 0.7500, maxRockSpeed = 3.2500, minRockSize = 10, maxRockSize = 100
Const rockSpeedRange = maxRockSpeed - minRockSpeed, rockSizeRange = maxRockSize - minRockSize
Const alienSpeed = rockSpeedRange / 2 + minRockSpeed ' average rock speed

Type alienType
    x As Single
    y As Single
    dx As Single
    dy As Single
    ls As Long ' lights offset and gray scale
    c As _Unsigned Long ' color
    live As Long
    attackFrame As Long
    fireX As Single
    fireY As Single
    transform As Long
End Type

Type particle
    x As Single
    y As Single
    dx As Single
    dy As Single
    size As Single
    kolor As _Unsigned Long
End Type

Type bullet
    x As Single
    y As Single
    dx As Single
    dy As Single
    live As Long
End Type

Type shipType
    x As Single
    y As Single
    live As Long
    speed As Single '       just a constant now when Thrust is applied
    thrustAngle As Single ' ship/gun angle at moment Thrust is pressed
    angle As Single '       rotated position ship/gun now A or S keypress or hold down
    thrust As Long '        this now tracks how many frames ship will move at speed and thrustAngle
End Type

Type rock
    x As Single
    y As Single
    r As Long '            radius
    ra As Single '         rotation position   a = a + spin
    heading As Single '    heading from which dx, dy are calc with speed
    speed As Single '      speed
    spin As Single '       rotation direction and amount
    seed As Long '         for drawing rocks with RND USING
    c As Long '            color   rgb(c, c, c)
    live As Long '         need this to track rocks still active like bullets
    explodeFrame As Long ' after a rock is hit by bullet, it explodes and in more than one frame
End Type

ReDim Shared aliens(1 To 5) As alienType
Dim Shared dots(2000) As particle ' explosions
Dim Shared b(nBullets) As bullet
Dim Shared ship As shipType
Dim Shared r(nRocks) As rock
Dim Shared lives As Long
Dim Shared points As Long
Dim Shared rocks As Long 'rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds

Dim HS As Long, fnt As Long, fnt2 As Long ' file LOAD handles
Dim i As Long, bullets As Long, fire As Long ' index and bullets
Dim r As Long, newRockN As Long, maxBabyRocks As Long, br As Long, hits As Long ' rock stuff
Dim ai As Long, alienN As Long ' alien index and number
Dim kh As Long 'key hit for ship thrust k or up arrow or hyperspace jump spacebar
Dim hs$, s$, k$, t, lastt 'high score, general string and times for bullets
Dim rockPoints As Long, roundPoints As Long ' various points scores

'Dim mouseMode As Long 'either key press hyperdrive and thrust or mouse moves
ship.speed = 3.5 'this would be a constant but ship has to declared as Ship Type first, Hyperspace jump

Screen _NewImage(xmax, ymax, 32)
_ScreenMove 100, 20
_FullScreen

fnt = _LoadFont("ARLRDBD.ttf", 16, "MONOSPACE")
fnt2 = _LoadFont("ARLRDBD.ttf", 40, "MONOSPACE")
_Font fnt2
Color &HFF00FFFF, &H00000000

If _FileExists("Asteroids High Score.txt") Then
    Open "Asteroids High Score.txt" For Input As #1
    Input #1, HS
    Close #1
End If
hs$ = "High Score:" + Str$(HS)

'a little splash screen
rocks = 7: alienN = 3
For i = 1 To nRocks
    newRock i
    If i > rocks Then r(i).live = 0
Next
For i = 1 To alienN
    newAlien i
Next
i = 0
Do
    drawStars 0
    i = i + 1
    If i Mod 30 = 29 And rocks < nRocks Then rocks = rocks + 1: r(rocks).live = 1
    For r = 1 To nRocks
        If r(r).live Then drawRock r
    Next
    For i = 1 To alienN
        drawAliens i
    Next

    _Font fnt2
    s$ = "*** b+QB64 Asteroids ***"
    _PrintString ((_Width - _PrintWidth(s$)) / 2, 60), s$
    _PrintString ((_Width - _PrintWidth(hs$)) / 2, 140), hs$
    s$ = "A or arrow = Left Spin"
    _PrintString ((_Width - _PrintWidth(s$)) / 2, 300), s$
    s$ = "S or arrow = Right Spin"
    _PrintString ((_Width - _PrintWidth(s$)) / 2, 380), s$
    's$ = "Space or Enter = Hyper Jump"
    '_PrintString ((_Width - _PrintWidth(s$)) / 2, 380), s$
    s$ = "p = Pause or end Pause"
    _PrintString ((_Width - _PrintWidth(s$)) / 2, 460), s$
    s$ = "Mouse L/R Button = Guns"
    _PrintString ((_Width - _PrintWidth(s$)) / 2, 540), s$
    _Font fnt
    If _KeyDown(27) Then System
    k$ = InKey$
    _Display
    _Limit 60
Loop Until Len(k$)

_MouseHide
restart:
If _FileExists("Asteroids High Score.txt") Then
    Open "Asteroids High Score.txt" For Input As #1
    Input #1, HS
    Close #1
End If
hs$ = "  High Score:" + Str$(HS)
lives = 10: alienN = 1: rocks = startRocks ' always active rocks
points = 0: hits = 0: bullets = 0

'If k$ = "m" Then ' undocumented use of mouse
'mouseMode = -1:
alienN = 3: rocks = 5 ' M11 mouse mode assumed only other key is space or enter for hyper jump
'End If

While lives > 0 And _KeyDown(27) = 0 ' init start restart
    ReDim aliens(1 To alienN) As alienType
    For ai = 1 To alienN
        newAlien ai
    Next
    For i = 1 To nRocks 'reset rocks mainly clear baby rocks
        newRock (i)
        If i > rocks Then r(i).live = 0
    Next
    ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
    ship.y = ymax / 2
    ship.angle = 0
    ship.thrustAngle = 0
    ship.thrust = 0
    ship.live = 1
    rockPoints = 0
    roundPoints = 0
    While ship.live And _KeyDown(27) = 0

        'draw everything then process bullets
        drawStars 1
        Locate 1, 1: Print "Lives:"; lives
        Locate 2, 1: Print "Last Rock:"; Str$(rockPoints)
        Locate 3, 1: Print "Round:;"; Str$(roundPoints)
        Locate 4, 1: Print "Points:"; Str$(points)
        Locate 5, 1: Print "High Score:"; Str$(HS)

        For ai = 1 To alienN
            drawAliens ai
        Next
        For i = 1 To nRocks
            If r(i).live Then 'make sure if we crash into a ship it is a live rock, not one sitting on side waiting to be called up
                drawRock i ' while drawing rocks the ship could be blown up
                If ((r(i).x - ship.x) ^ 2 + (r(i).y - ship.y) ^ 2) ^ .5 < r(i).r + 20 Then 'rock collides with ship?
                    For br = 1 To 200 Step 5
                        Circle ((ship.x + r(i).x) / 2, (ship.y + r(i).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
                    Next
                    drawRock i
                    drawship
                    ship.live = 0
                    If i <= rocks Then newRock i Else r(i).live = 0
                End If
            End If
        Next
        For i = 1 To nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
            If r(i).explodeFrame Then
                r(i).explodeFrame = r(i).explodeFrame + 1
                If r(i).explodeFrame > .25 * r(i).r Then
                    r(i).explodeFrame = 0
                    If i <= rocks Then newRock i ' now replace the rock
                Else
                    explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
                End If
            End If
        Next
        If ship.live Then
            For ai = 1 To alienN
                If Sqr((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 55 Then 'aliens and ship collisde boom boom
                    For br = 1 To 200 Step 5
                        Circle ((ship.x + aliens(ai).x) / 2, (ship.y + aliens(ai).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
                    Next
                    drawship
                    ship.live = 0
                    _Continue
                Else
                    drawship
                End If
            Next
            'If mouseMode Then
            While _MouseInput: Wend
            ship.x = _MouseX: ship.y = _MouseY
            If _MouseButton(1) Then ship.angle = pi
            If _MouseButton(2) Then ship.angle = 0
            'End If
            '                                                                   ship controls update
            'a key or left arrow = left spin
            If _KeyDown(97) Or _KeyDown(19200) Then ship.angle = ship.angle - pi / 48

            's key or right arrow = right spin
            If _KeyDown(115) Or _KeyDown(19712) Then ship.angle = ship.angle + pi / 48

            'l is Fire!  JUST CONTINUOUS FIRE
            fire = 0
            'IF _KEYDOWN(108) THEN
            t = Timer(.01)
            If lastt = 0 Or t - lastt > .15 Then fire = 1: Sound 2088, .01: lastt = t
            'END IF

            kh = _KeyHit
            Select Case kh
                Case 112 ' p for pause
                    kh = 0
                    While _KeyHit <> 112: _Limit 60: Wend
                    'Case 107, 18432 'thrust  k key or up arrow
                    '    If mouseMode = 0 Then
                    '        Sound 488, .01
                    '        ship.thrustAngle = ship.angle: ship.thrust = 120
                    '    End If
                    'Case 13, 32 ' space = hyperspace jump
                    '    'If mouseMode = 0 Then
                    '    Randomize Timer
                    '    ship.x = (xmax - 300) * Rnd + 150: ship.y = (ymax - 300) * Rnd + 150: ship.thrust = 0
                    '    'End If
            End Select

            '                                                                   locate ship
            'If ship.thrust > 0 Then
            '    'relocate ship position
            '    ship.x = ship.x + ship.speed * Cos(ship.thrustAngle)
            '    ship.y = ship.y + ship.speed * Sin(ship.thrustAngle)
            'End If
            '                                                                    jump borders
            'If ship.x < 0 Then ship.x = xmax - Abs(ship.x)
            'If ship.x > xmax Then ship.x = ship.x - xmax
            'If ship.y < 0 Then ship.y = ymax - Abs(ship.y)
            'If ship.y > ymax Then ship.y = ship.y - ymax


            For i = 0 To nBullets '                                               handle bullets
                If b(i).live = 0 And fire = 1 Then 'have inactive bullet to use
                    b(i).x = ship.x + 2 * bSpeed * Cos(ship.angle)
                    b(i).y = ship.y + 2 * bSpeed * Sin(ship.angle)
                    b(i).dx = bSpeed * Cos(ship.angle)
                    b(i).dy = bSpeed * Sin(ship.angle)
                    b(i).live = -1
                    bullets = bullets + 1
                    fire = 0
                End If
                If b(i).live Then 'new location
                    b(i).x = b(i).x + b(i).dx
                    b(i).y = b(i).y + b(i).dy
                    If b(i).x > 0 And b(i).x < xmax And b(i).y > 0 And b(i).y < ymax Then 'in bounds draw it

                        'bullet hit aliens?
                        For ai = 1 To alienN
                            If Sqr((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 Then
                                For br = 1 To 120
                                    Circle (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
                                Next
                                _Display
                                _Delay .05
                                hits = hits + 1
                                roundPoints = roundPoints + 100
                                points = points + 100
                                aliens(ai).live = 0
                                newAlien ai
                                b(i).live = 0
                                _Continue
                            End If
                        Next
                        For r = 1 To nRocks 'check for collision with rock
                            If r(r).live Then
                                If Sqr((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r Then 'its a hit!
                                    r(r).explodeFrame = 1 'linger with explosion
                                    r(r).live = 0
                                    hits = hits + 1
                                    rockPoints = 50 * ((r(r).speed - minRockSpeed) / rockSpeedRange + (rockSizeRange - (r(r).r - minRockSize)) / rockSizeRange)
                                    roundPoints = roundPoints + rockPoints
                                    points = points + rockPoints
                                    If r(r).r > 30 Then '       split rock  into ? new ones
                                        maxBabyRocks = Int((r(r).r - 10) / 10)
                                        maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
                                        For br = 1 To maxBabyRocks
                                            '                        new rock
                                            newRockN = freeRock& '                          get inactive rock number
                                            newRock newRockN '                              new identity and activate
                                            r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
                                            r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
                                            r(newRockN).y = r(r).y + irnd&(-30, 30)
                                            r(newRockN).c = r(r).c '                   same color as parent
                                            r(newRockN).heading = rrnd(ship.angle - .75 * pi, ship.angle + .75 * pi)
                                        Next
                                    End If ' big enough to split
                                    b(i).live = 0 'kill bullet
                                End If ' hit rock
                            End If 'rock is there
                        Next ' rock
                        If b(i).live Then fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
                    Else
                        b(i).live = 0 'out of bounds
                    End If ' bullet is in bounds
                End If ' bullet live
            Next ' bullet
        End If ' if ship still live
        _Display
        If ship.live = 0 Then
            lives = lives - 1
            If lives Mod 4 = 0 Then rocks = rocks + 1
            If lives Mod 4 = 2 Then alienN = alienN + 1
            s$ = "Lives:" + Str$(lives) + "  Hits:" + Str$(hits) + "  Bullets:" + Str$(bullets) + "  Shooting:" + Str$(Int(hits * 100 / bullets)) + "%"
            _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 - 80), s$
            _Font fnt2
            s$ = Str$(points) + hs$
            _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2), s$
            _Font fnt
            s$ = "Press enter to enter next life."
            _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 + 120), s$
            _Display
            kh = 0
            While kh <> 13
                kh = _KeyHit
            Wend 'wait for enter key
        Else
            _Limit 60 ' if ship dies let's rest and regroup  before restart next life
        End If
    Wend
    _Display
Wend
If points > HS Then
    Open "Asteroids High Score.txt" For Output As #1
    Print #1, points
    Close #1
End If
ship.x = -200: ship.y = -200 'get it out of the way
i = 0
Do
    drawStars 0
    i = i + 1
    If i Mod 30 = 29 And rocks < nRocks Then rocks = rocks + 1: r(rocks).live = 1
    For r = 1 To nRocks
        If r(r).live Then drawRock r
    Next
    s$ = "Lives:" + Str$(lives) + "  Hits:" + Str$(hits) + "  Bullets:" + Str$(bullets) + "  Shooting:" + Str$(Int(hits * 100 / bullets)) + "%"
    _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 - 80), s$
    _Font fnt2
    s$ = Str$(points)
    If points > HS Then s$ = s$ + " a New Record!" Else s$ = Str$(points) + hs$
    _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2), s$
    _Font fnt
    s$ = "Press q to quit, p or a to Play Again..."
    _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 + 120), s$
    If _KeyDown(Asc("a")) Or _KeyDown(Asc("p")) Then GoTo restart
    _Display
    _Limit 60
Loop Until _KeyDown(Asc("q"))
System

Sub drawStars (moving)
    Type starType
        x As Single
        y As Single
        size As Single
        c As Integer
    End Type
    Static beenHere, stars(200) As starType, cy As Long
    Dim i As Long
    If beenHere = 0 Then 'static part
        For i = 0 To 100
            stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = .3
            stars(i).c = irnd&(80, 140)
        Next
        For i = 101 To 150
            stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = .6
            stars(i).c = irnd&(110, 170)
        Next
        For i = 151 To 195
            stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = 1.2
            stars(i).c = irnd&(140, 200)
        Next
        For i = 196 To 200
            stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = 2.4
            stars(i).c = irnd&(170, 235)
        Next
        cy = ymax / 2
        beenHere = 1
    End If
    For i = 0 To cy
        Line (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
        Line (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
    Next
    For i = 0 To 200
        If moving Then
            stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
            If stars(i).x > xmax Then stars(i).x = -1 * Rnd * 20
        End If
        fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
    Next
End Sub

Sub newAlien (i As Long)
    Dim side As Long, heading
    Randomize Timer * Rnd 'to avoid making twins
    side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
    If Rnd < .6 Then
        aliens(i).fireX = ship.x: aliens(i).fireY = ship.y
    Else
        aliens(i).fireX = irnd(10, xmax - 10): aliens(i).fireY = irnd(10, ymax - 10)
    End If
    aliens(i).attackFrame = irnd(50, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
    Select Case side
        Case 1
            aliens(i).x = -10
            aliens(i).y = rrnd(80, ymax - 80)
        Case 2
            aliens(i).x = xmax + 10
            aliens(i).y = rrnd(80, ymax - 80)
        Case 3
            aliens(i).x = rrnd(80, xmax - 80)
            aliens(i).y = -10
        Case 4
            aliens(i).x = rrnd(80, xmax - 80)
            aliens(i).y = ymax + 10
    End Select
    heading = _Atan2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
    aliens(i).dx = alienSpeed * Cos(heading)
    aliens(i).dy = alienSpeed * Sin(heading)
    aliens(i).live = 0
    aliens(i).transform = 0
    aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
End Sub

Function plasma~& (new As Long)
    Static r, g, b, cnt, beenHere
    If beenHere = 0 Or new Then
        r = Rnd: g = Rnd: b = Rnd: beenHere = 1: cnt = 0
    End If
    cnt = cnt + .2
    plasma~& = _RGB32(127 + 127 * Sin(r * cnt), 127 + 127 * Sin(g * cnt), 127 + 127 * Sin(b * cnt))
End Function

Sub drawAliens (i As Long) 'shipType
    Dim light As Long, heading, r As Long, g As Long, b As Long
    If aliens(i).live Then
        Sound 6000 + i * 200, .07
        If aliens(i).transform = 0 Then
            r = _Red32(aliens(i).c): g = _Green32(aliens(i).c): b = _Blue32(aliens(i).c)
            fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
            fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
            fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
            For light = 0 To 5
                fcirc aliens(i).x - 30 + 11 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
            Next
            aliens(i).ls = aliens(i).ls + 1
            If aliens(i).ls > 5 Then aliens(i).ls = 0
        Else
            drawBall aliens(i).x, aliens(i).y, 30, aliens(i).c
        End If
        'time to shoot?
        aliens(i).x = aliens(i).x + aliens(i).dx
        aliens(i).y = aliens(i).y + aliens(i).dy
        If Sqr((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 Then 'transform into the bolder of death
            aliens(i).transform = 1
            heading = _Atan2(ship.y - aliens(i).y, ship.x - aliens(i).x)
            aliens(i).dx = 2.5 * Cos(heading)
            aliens(i).dy = 2.5 * Sin(heading)
        End If
        If aliens(i).x < -10 Or aliens(i).x > xmax + 10 Then
            If aliens(i).y < -10 Or aliens(i).y > ymax + 10 Then '  out of bounds goodbye bolder of death!
                aliens(i).live = 0 'man we dodged a bullet here!!!!
                newAlien i 'reset the trap
            End If
        End If
    Else
        If aliens(i).attackFrame Then
            aliens(i).attackFrame = aliens(i).attackFrame - 1
            If aliens(i).attackFrame = 0 Then
                aliens(i).live = 1
            End If
        End If
    End If
End Sub

Function freeRock&
    Dim i As Long
    For i = rocks + 1 To nRocks ' look for inactive rock number
        If r(i).live = 0 And r(i).explodeFrame = 0 Then freeRock& = i: Exit Function
    Next
End Function

Sub explode (x As Long, y As Long, r As Long, frm As Long)
    Dim maxParticles As Long, i As Long, rounds As Long, loopCount As Long
    maxParticles = r * 4
    For i = 1 To r
        NewDot i, x, y, r
    Next
    rounds = r
    For loopCount = 0 To frm
        If _KeyDown(27) Then End
        For i = 1 To rounds
            dots(i).x = dots(i).x + dots(i).dx
            dots(i).y = dots(i).y + dots(i).dy
            fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
        Next
        If rounds < maxParticles Then
            For i = 1 To r
                NewDot (rounds + i), x, y, r
            Next
            rounds = rounds + r
        End If
    Next
End Sub

Sub NewDot (i As Long, x As Long, y As Long, r As Long)
    Dim angle, rd
    angle = pi * 2 * Rnd
    rd = Rnd * 30
    dots(i).x = x + rd * Cos(angle)
    dots(i).y = y + rd * Sin(angle)
    dots(i).size = Rnd * r * .05
    rd = Rnd 'STxAxTIC recommended for rounder spreads
    dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * Cos(angle)
    dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * Sin(angle)
    rd = 20 + Rnd * 70
    dots(i).kolor = _RGBA32(rd, rd, rd, 80)
End Sub

Sub drawship 'simple red iso triangle pointed towards radianAngle
    Dim x1 As Long, y1 As Long, x2 As Long, y2 As Long, x3 As Long, y3 As Long
    Dim x4 As Long, y4 As Long, x5 As Long, y5 As Long
    If ship.thrust > 0 Then
        'burn out flame as thruster dies out
        x4 = ship.x + .5 * ship.thrust * Cos(ship.angle - 17 / 18 * pi)
        y4 = ship.y + .5 * ship.thrust * Sin(ship.angle - 17 / 18 * pi)
        x5 = ship.x + .5 * ship.thrust * Cos(ship.angle - 19 / 18 * pi)
        y5 = ship.y + .5 * ship.thrust * Sin(ship.angle - 19 / 18 * pi)
        ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
        ship.thrust = ship.thrust - 1
    End If
    'draw ship dead or alive thrust or not, calculate 3 points of triangle ship
    fcirc ship.x, ship.y, 30, &H05FFFFFF
    x1 = ship.x + 30 * Cos(ship.angle) ' front point
    y1 = ship.y + 30 * Sin(ship.angle) '
    x2 = ship.x + 30 * Cos(ship.angle + .6666 * pi) ' wing
    y2 = ship.y + 30 * Sin(ship.angle + .6666 * pi)
    x3 = ship.x + 30 * Cos(ship.angle - .6666 * pi) ' other wing
    y3 = ship.y + 30 * Sin(ship.angle - .6666 * pi)
    ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
    ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
    Line (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
    Line (x1, y1)-(x2, y2), _RGB32(255, 180, 40)
    Line (x1, y1)-(x3, y3), _RGB32(255, 180, 40)
End Sub

Sub drawRock (iRock)
    Randomize Using r(iRock).seed 'this prevents having to save a particular sequence of random number
    Dim dx, dy, j As Long, rRad As Single, leg As Single, x0 As Long, y0 As Long, rc As Long, c~&, x1 As Long, y1 As Long, xoff, yoff, i As Long
    Dim x2 As Long, y2 As Long
    dx = r(iRock).speed * Cos(r(iRock).heading)
    dy = r(iRock).speed * Sin(r(iRock).heading) 'update location
    r(iRock).ra = r(iRock).ra + r(iRock).spin
    If r(iRock).x + dx + r(iRock).r < 0 Or r(iRock).x + dx - r(iRock).r > xmax Or r(iRock).y + dy + r(iRock).r < 0 Or r(iRock).y + dy - r(iRock).r > ymax Then
        If iRock <= rocks Then newRock iRock Else r(iRock).live = 0
        Exit Sub ' reassigned get out of here
    Else
        r(iRock).x = r(iRock).x + dx
        r(iRock).y = r(iRock).y + dy
    End If
    For j = 10 To 3 Step -1 '                  rock drawing (see demo program where developed code)
        rRad = .1 * j * r(iRock).r
        leg = rRad * (Rnd * .7 + .3)
        x0 = r(iRock).x + leg * Cos(r(iRock).ra)
        y0 = r(iRock).y + leg * Sin(r(iRock).ra)
        rc = r(iRock).c + 30 * Rnd - 15
        c~& = _RGB32(rc + 5, rc - 10, rc + 5)
        x1 = x0
        y1 = y0
        xoff = Rnd * 20 - 10 + r(iRock).x
        yoff = Rnd * 20 - 10 + r(iRock).y
        For i = 1 To 12
            leg = rRad * (Rnd * .35 + .65)
            If i = 12 Then
                x2 = x0: y2 = y0
            Else
                x2 = xoff + leg * Cos(i * polyAngle + r(iRock).ra)
                y2 = yoff + leg * Sin(i * polyAngle + r(iRock).ra)
            End If
            ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
            x1 = x2: y1 = y2
        Next
    Next
End Sub

Sub newRock (iRock)
    Dim side As Long
    Randomize Timer * Rnd 'to avoid making twins
    side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
    Select Case side
        Case 1
            r(iRock).x = -100
            r(iRock).y = rrnd(80, ymax - 80)
            If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = 3 * pi / 2 + Rnd * pi
        Case 2
            r(iRock).x = xmax + 100
            r(iRock).y = rrnd(80, ymax - 80)
            If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = pi / 2 + Rnd * pi
        Case 3
            r(iRock).x = rrnd(80, xmax - 80)
            r(iRock).y = -100
            If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = Rnd * pi
        Case 4
            r(iRock).x = rrnd(80, xmax - 80)
            r(iRock).y = ymax + 100
            If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = pi + Rnd * pi
    End Select
    r(iRock).speed = rrnd(minRockSpeed, maxRockSpeed) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
    r(iRock).ra = Rnd * 2 * pi
    r(iRock).r = irnd&(minRockSize * 3, maxRockSize) 'every parent rock can be split up into at least 2 - 10 size rocks
    r(iRock).c = irnd&(60, 110) ' Ken request increase in rock color
    r(iRock).spin = rrnd(-pi / 20, pi / 20)
    r(iRock).seed = Int(Rnd * 64000) - 32000
    r(iRock).explodeFrame = 0
    r(iRock).live = 1
End Sub

Function irnd& (n1, n2) 'return an integer between 2 numbers
    Dim l%, h%
    If n1 > n2 Then l% = n2: h% = n1 Else l% = n1: h% = n2
    irnd& = Int(Rnd * (h% - l% + 1)) + l%
End Function

Function rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
    rrnd = (n2 - n1) * Rnd + n1
End Function

Sub drawBall (x, y, r, c As _Unsigned Long)
    Dim red As Long, grn As Long, blu As Long, rr As Long, f
    red = _Red32(c): grn = _Green32(c): blu = _Blue32(c)
    For rr = r To 0 Step -1
        f = 1 - rr / r
        fcirc x, y, rr, _RGB32(red * f, grn * f, blu * f)
    Next
End Sub

Sub fellipse (CX As Long, CY As Long, xr As Long, yr As Long, C As _Unsigned Long)
    If xr = 0 Or yr = 0 Then Exit Sub
    Dim h2 As _Integer64, w2 As _Integer64, h2w2 As _Integer64
    Dim x As Long, y As Long
    w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
    Line (CX - xr, CY)-(CX + xr, CY), C, BF
    Do While y < yr
        y = y + 1
        x = Sqr((h2w2 - y * y * w2) \ h2)
        Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
        Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
    Loop
End Sub

Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
    Dim D As Long
    Static a&
    D = _Dest
    If a& = 0 Then a& = _NewImage(1, 1, 32)
    _Dest a&
    _DontBlend a& '  '<<<< new 2019-12-16 fix
    PSet (0, 0), K
    _Blend a& '<<<< new 2019-12-16 fix
    _Dest D
    _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
End Sub

Sub fcirc (x As Long, y As Long, R As Long, C As _Unsigned Long) 'vince version
    Dim x0 As Long, y0 As Long, e As Long
    x0 = R: y0 = 0: e = 0
    Do While y0 < x0
        If e <= 0 Then
            y0 = y0 + 1
            Line (x - x0, y + y0)-(x + x0, y + y0), C, BF
            Line (x - x0, y - y0)-(x + x0, y - y0), C, BF
            e = e + 2 * y0
        Else
            Line (x - y0, y - x0)-(x + y0, y - x0), C, BF
            Line (x - y0, y + x0)-(x + y0, y + x0), C, BF
            x0 = x0 - 1: e = e - 2 * x0
        End If
    Loop
    Line (x - R, y)-(x + R, y), C, BF
End Sub

The zip has source and font file if you don't have Windows.

   


Attached Files
.zip   b+ Asteroids M11.zip (Size: 40.21 KB / Downloads: 52)
b = b + ...
Reply




Users browsing this thread: 1 Guest(s)