Import Dom From "lib/web/dom.bas"
' -----------------------------------------------
' QB64 FlappyBird Clone by Terry Ritchie 02/28/14
'
' This program was created to accompany the QB64
' Game Programming course located at:
' http://www.qb64sourcecode.com
'
' You may not sell or distribute this game! It
' was made for instructional purposes only.
'
' Update: 04/29/20
'
' Added EXE icon support in lines 18 and 19
' Any key press now starts game in line 274
' Any key press now flaps bird in line 196
'
' -----------------------------------------------

'$ExeIcon:'.\fbird.ico'
'_Icon

'--------------------------------
'- Variable declaration section -
'--------------------------------

Const FALSE = 0 '            boolean: truth  0
Const TRUE = Not FALSE '     boolean: truth -1
Const LARGE = 0 '            large numbers
Const SMALL = 1 '            small numbers (not used in current version of game)
Const GOLD = 0 '             gold medal
Const SILVER = 1 '           silver medal
Const LIGHT = 0 '            light colored gold/silver medal
Const DARK = 1 '             dark colored gold/silver medal

Type PARALLAX '              parallax scenery settings
    image As Long '          scene image
    x As Integer '           scene image x location
    y As Integer '           scene image y location
    frame As Integer '       current parallax frame
    fmax As Integer '        maximum parallax frames allowed
End Type

Type INFLIGHT '              flappy bird inflight characterisitcs
    y As Single '            flappy bird y location
    yvel As Single '         flappy bird y velocity
    flap As Integer '        wing flap position
    flapframe As Integer '   wing flap frame counter
    angle As Integer '       angle of flappy bird
End Type

Type PIPE '                  pipe characteristics
    x As Integer '           pipe x location
    y As Integer '           pipe y location
End Type

Dim Shared Pipes(3) As PIPE '       define 3 moving sets of pipes
Dim Shared Pipe&(1) '               pipe images 0=top 1=bottom
Dim Shared PipeImage& '             all three pipes drawn image
Dim Shared Birdie As INFLIGHT '     bird flight characteristics
Dim Shared Scenery(4) As PARALLAX ' define 4 moving scenes in parallax
Dim Shared Fbird&(8, 3) '           flapping bird images
Dim Shared Num&(9, 1) '             big and small numeral images
Dim Shared Plaque& '                medal/score plaque
Dim Shared FlappyBird& '            Flappy Bird title image
Dim Shared GameOver& '              Game Over image
Dim Shared GetReady& '              Get Ready image
Dim Shared Medal&(1, 1) '           gold/silver medal images
Dim Shared Finger& '                tap finger image
Dim Shared ScoreButton& '           score button image
Dim Shared ShareButton& '           share button image
Dim Shared StartButton& '           start button image
Dim Shared OKButton& '              OK button image
Dim Shared RateButton& '            RATE button image
Dim Shared MenuButton& '            MENU button image
Dim Shared PlayButton& '            PLAY [|>] button image
Dim Shared PauseButton& '           PAUSE [||] button image
Dim Shared HazardBar& '             Hazard bar parallax image
Dim Shared Clouds& '                Clouds parallax image
Dim Shared City& '                  Cityscape parallax image
Dim Shared Bushes& '                Bushes parallax image
Dim Shared New& '                   red NEW image
Dim Shared Clean& '                 clean playing screen image
Dim Shared HitBird% '               boolean: TRUE if bird hits something
Dim Shared HighScore% '             high score
Dim Shared Score% '                 current score
Dim Shared Paused% '                boolean: TRUE if game paused
Dim Shared Ding& '                  ding sound
Dim Shared Flap& '                  flapping sound
Dim Shared Smack& '                 bird smack sound
Dim Shared Latch% '                 boolean: TRUE if mouse button held down
Dim WinX% '                  stops player from exiting program at will


'------------------------
'- Main Program Section -
'------------------------

Screen _NewImage(432, 768, 32) '                        create 432x768 game screen
_Title "FlappyBird" '                                   give window a title
Cls '                                                   clear the screen
'_Delay .5 '                                             slight delay before moving screen to middle
'_ScreenMove _Middle '                                   move window to center of desktop
'WinX% = _Exit '                                         program will handle all window close requests
LOADASSETS '                                            set/load game graphics/sounds/settings

_FullScreen
If Not _FullScreen Then GXSceneScale Dom.Container().clientHeight / _Height

Birdie.flap = 1 '                                       set initial wing position of bird
Do '                                                    BEGIN MAIN GAME LOOP
    _Limit 60 '                                         60 frames per second
    UPDATESCENERY '                                     update parallaxing scenery
    _PutImage (40, 265), FlappyBird& '                  place game title on screen
    _PutImage (350, 265), Fbird&(2, FLAPTHEBIRD%) '     place flapping bird on screen
    If BUTTON%(64, 535, StartButton&) Then PLAYGAME '   if start button pressed play game
    If BUTTON%(248, 535, ScoreButton&) Then SHOWSCORE ' if score button pressed show scores
'    If BUTTON%(248, 480, RateButton&) Then RATEGAME '   if rate button pressed bring up browser
    _Display '                                          update screen with changes
Loop Until _KeyDown(27) 'Or _Exit '                      END MAIN GAME LOOP when ESC pressed or window closed
CLEANUP '                                               clean the computer's RAM before leaving
System '                                                return to Windows desktop

'-------------------------------------
'- Subroutines and Functions section -
'-------------------------------------

'----------------------------------------------------------------------------------------------------------------------

Function FLAPTHEBIRD% ()

    '*
    '* Returns the next index value used in Fbird&() to animate the bird's
    '* flapping wings.
    '*

    'Shared Birdie As INFLIGHT

    Birdie.flapframe = Birdie.flapframe + 1 '     increment frame counter
    If Birdie.flapframe = 4 Then '                hit limit?
        Birdie.flapframe = 0 '                    yes, reset frame counter
        Birdie.flap = Birdie.flap + 1 '           increment flap counter
        If Birdie.flap = 4 Then Birdie.flap = 1 ' reset flap counter when limit hit
    End If
    FLAPTHEBIRD% = Birdie.flap '                  return next index value

End Function

'----------------------------------------------------------------------------------------------------------------------

Sub MOVEPIPES ()

    '*
    '* Creates and moves the pipe images across the screen.
    '*

    'Shared Pipes() As PIPE , Pipe&(), PipeImage&, Paused%, Score%, Ding&

    Dim p% ' counter indicating which pipe being worked on

    _Dest PipeImage& '                                    work on this image
    Cls , _RGBA32(0, 0, 0, 0) '                           clear image with transparent black
    _Dest 0 '                                             back to work on screen
    Do '                                                  BEGIN PIPE LOOP
        p% = p% + 1 '                                     increment pipe counter
        If Not Paused% Then '                             is game paused?
            Pipes(p%).x = Pipes(p%).x - 3 '               no, move pipe to the left
            If Pipes(p%).x < -250 Then '                  hit lower limit?
                Pipes(p%).x = 500 '                       yes, move pipe all the way right
                Pipes(p%).y = -(Int(Rnd(1) * 384) + 12) ' generate random pipe height position
            End If
            If Pipes(p%).x = 101 Then '                   is pipe crossing bird location?
                _SndPlay Ding& '                          play ding sound
                Score% = Score% + 1 '                     increment player score
            End If
        End If
        If Pipes(p%).x > -78 And Pipes(p%).x < 432 Then ' is pipe currently seen on screen?
            _PutImage (Pipes(p%).x, Pipes(p%).y), Pipe&(0), PipeImage& ' place top pipe
            _PutImage (Pipes(p%).x, Pipes(p%).y + 576), Pipe&(1), PipeImage& ' place bottom pipe
        End If
    Loop Until p% = 3 '                                   END PIPE LOOP when all pipes moved
    _PutImage (0, 0), PipeImage& '                        place pipe image on screen

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub FLYBIRDIE ()

    '*
    '* Controls the flight of bird on screen.
    '*

    'Shared Birdie As INFLIGHT, Fbird&(), Paused%, Flap&, HitBird%, Latch%, Smack&

    Dim b% '     boolean: TRUE if left mouse button pressed
    Dim Angle% ' angle of bird in flight

    If Not Paused% Then '                             is game paused?
        While _MouseInput: Wend '                     no, get latest mouse information
        b% = _MouseButton(1) '                        get left mouse button status
        If _KeyHit > 0 Then b% = -1 '                 any key will also make bird flap    (added 04/29/20)
        If Not b% Then Latch% = FALSE '               release latch if button let go
        If Not HitBird% Then '                        has bird hit something?
            If Not Latch% Then '                      no, has left button been release?
                If b% Then '                          yes, was left button pressed?
                    Birdie.yvel = -8 '                yes, reset bird y velocity
                    _SndPlay Flap& '                  play flap sound
                    Latch% = TRUE '                   remember mouse button pressed
                End If
            End If
        End If
        Birdie.yvel = Birdie.yvel + .5 '              bleed off some bird y velocity
        Birdie.y = Birdie.y + Birdie.yvel '           add velocity to bird's y direction
        If Not HitBird% Then '                        has bird hit something?
            If Birdie.y < -6 Or Birdie.y > 549 Then ' no, has bird hit top/bottom of screen?
                HitBird% = TRUE '                     yes, remeber bird hit something
                _SndPlay Smack& '                     play smack sound
            End If
        End If
        If Birdie.yvel < 0 Then '                     is bird heading upward?
            Birdie.angle = 1 '                        yes, set angle of bird accordingly
        Else
            Angle% = Int(Birdie.yvel * .5) + 1 '      calculate angle according to bird velocity
            If Angle% > 8 Then Angle% = 8 '           keep angle within limits
            Birdie.angle = Angle% '                   set bird angle
        End If
    End If
    _PutImage (100, Birdie.y), Fbird&(Birdie.angle, FLAPTHEBIRD%) ' place bird on screen

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub UPDATESCORE ()

    '*
    '* Displays player's score on screen.
    '*

    'Shared Num&(), Score%

    Dim s$ ' score in string format
    Dim w% ' width of score string
    Dim x% ' x location of score digits
    Dim p% ' position counter

    s$ = LTrim$(RTrim$(Str$(Score%))) ' convert score to string
    w% = Len(s$) * 23 '                 calculate width of score
    x% = (432 - w%) / 2 '               calculate x position of score
    For p% = 1 To Len(s$) '             cycle through each position in score string
        _PutImage (x%, 100), Num&(Asc(Mid$(s$, p%, 1)) - 48, LARGE) ' place score digit on screen
        x% = x% + 23 '                  move to next digit position
    Next p%

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub READY ()

    '*
    '* displays instructions to the player and waits for player to start game.
    '*

    'Shared Fbird&(), Finger&, GetReady&

    Dim b% ' boolean: TRUE if left mouse button pressed

    Do '                                 BEGIN READY LOOP
        _Limit 60 '                      60 frames per second
        UPDATESCENERY '                  move parallax scenery
        _PutImage (180, 350), Finger& '  place finger instructions on screen
        _PutImage (85, 225), GetReady& ' place get ready image on screen
        _PutImage (100, 375), Fbird&(2, FLAPTHEBIRD%) ' place bird on screen
        UPDATESCORE '                    place score on screen
        _Display '                       update screen with changes
        While _MouseInput: Wend '        get latest mouse information
        b% = _MouseButton(1) '           get status of left mouse button
        If _KeyHit > 0 Then b% = -1 '    any key press will also begin game           (added 04/29/20)
        'If _Exit Then CLEANUP: System '  leave game if user closes game window
    Loop Until b% '                      END READY LOOP when left button pressed
    _Delay .2 '                          slight delay to allow mouse button release

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub PLAYGAME ()

    '*
    '* Allows player to play the game.
    '*

    'Shared Pipes() As PIPE, Birdie As INFLIGHT, PauseButton&, PlayButton&, Paused%, HitBird%, Score%

    'Randomize Timer '                                seed random number generator
    Score% = 0 '                                     reset player score
    Birdie.y = 0 '                                   reset bird y location
    Birdie.yvel = 0 '                                reset bird y velocity
    Birdie.flap = 1 '                                reset bird wing flap index
    Pipes(1).x = 500 '                               reset position of first pipe
    Pipes(2).x = 749 '                               reset position of second pipe
    Pipes(3).x = 998 '                               reset position of third pipe
    Pipes(1).y = -(Int(Rnd(1) * 384) + 12) '         calculate random y position of pipe 1
    Pipes(2).y = -(Int(Rnd(1) * 384) + 12) '         calculate random y position of pipe 2
    Pipes(3).y = -(Int(Rnd(1) * 384) + 12) '         calculate random y position of pipe 3
    READY '                                          display instructions to player
    Do '                                             BEGIN GAME PLAY LOOP
        _Limit 60 '                                  60 frames per second
        UPDATESCENERY '                              move parallax scenery
        MOVEPIPES '                                  move pipes
        UPDATESCORE '                                display player score
        FLYBIRDIE '                                  move and display bird
        CHECKFORHIT '                                check for bird hits
        If Not Paused% Then '                        is game paused?
            If BUTTON%(30, 100, PauseButton&) Then ' no, was pause button pressed?
                Paused% = TRUE '                     yes, place game in pause state
            End If
        Else '                                       no, game is not paused
            If BUTTON%(30, 100, PlayButton&) Then '  was play button pressed?
                Paused% = FALSE '                    yes, take game out of pause state
            End If
        End If
        _Display '                                   update screen with changes
        'If _Exit Then CLEANUP: System '              leave game if user closes game window
    Loop Until HitBird% '                            END GAME PLAY LOOP if bird hits something
    Do '                                             BEGIN BIRD DROPPING LOOP
        _Limit 60 '                                  60 frames per second
        Paused% = TRUE '                             place game in paused state
        UPDATESCENERY '                              draw parallax scenery
        MOVEPIPES '                                  draw pipes
        Paused% = FALSE '                            take game out of pause state
        FLYBIRDIE '                                  move bird on screen
        _Display '                                   update screen with changes
        'If _Exit Then CLEANUP: System '              leave game if user closes game window
    Loop Until Birdie.y >= 546 '                     END BIRD DROPPING LOOP when bird hits ground
    SHOWSCORE '                                      display player's score plaque
    HitBird% = FALSE '                               reset bird hit indicator

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub CHECKFORHIT ()

    '*
    '* Detects if bird hits a pipe.
    '*

    'Shared Pipes() As PIPE, Birdie As INFLIGHT, HitBird%, Smack&

    Dim p% ' pipe counter

    For p% = 1 To 3 '                                      cycle through all pipe positions
        If Pipes(p%).x <= 153 And Pipes(p%).x >= 22 Then ' is pipe in bird territory?
            If BOXCOLLISION(105, Birdie.y + 6, 43, 41, Pipes(p%).x, Pipes(p%).y, 78, 432) Then ' collision?
                HitBird% = TRUE '                          yes, remember bird hit pipe
            End If
            If BOXCOLLISION(105, Birdie.y + 6, 43, 41, Pipes(p%).x, Pipes(p%).y + 576, 78, 432) Then ' collision?
                HitBird% = TRUE '                          yes, remember bird hit pipe
            End If
        End If
    Next p%
    If HitBird% Then _SndPlay Smack& '                     play smack sound if bird hit pipe

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub RATEGAME ()

    '*
    '* Allows player to rate game.
    '*

    'Shell "https://www.qb64.org/forum/index.php?topic=437.0" ' go to QB64 web site forum area for flappy bird

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub SHOWSCORE ()

    '*
    '* Display's current and high scores on score plaque
    '*

    'Shared Fbird&(), Num&(), Medal&(), FlappyBird&, GameOver&, Plaque&, OKButton&, ShareButton&
    'Shared HitBird%, HighScore%, Score%, New&

    Dim Ok% '        boolean: TRUE if OK button pressed
    Dim Scores%(1) ' current and high scores
    Dim sc% '        current score being drawn
    Dim x% '         x location of score digits
    Dim p% '         digit position counter
    Dim ShowNew% '   boolean: TRUE if score is a new high score
    Dim s$ '         score in string format

    If Score% > HighScore% Then '                               is this a new high score?
        'Open "fbird.sco" For Output As #1 '                     yes, open score file
        'Print #1, Score% '                                      save new high score
        'Close #1 '                                              close score file
        HighScore% = Score% '                                   remember new high score
        ShowNew% = TRUE '                                       remember this is a new high score
    End If
    Scores%(0) = Score% '                                       place score in array
    Scores%(1) = HighScore% '                                   place high score in array
    Ok% = FALSE '                                               reset OK button status indicator
    Do '                                                        BEGIN SCORE LOOP
        _Limit 60 '                                             60 frames per second
        If HitBird% Then '                                      did bird hit something?
            _PutImage (75, 200), GameOver& '                    yes, place game over image on screen
        Else '                                                  no, bird did not hit anything
            UPDATESCENERY '                                     move parallax scenery
            _PutImage (40, 200), FlappyBird& '                  place flappy bird title on screen
            _PutImage (350, 200), Fbird&(2, FLAPTHEBIRD%) '     place flapping bird on screen
        End If
        _PutImage (46, 295), Plaque& '                          place plaque on screen
        'Select Case HighScore% '                                what is range of high score?
        '    Case 25 TO 49 '                                     from 25 to 49
        '        _PutImage (85, 360), Medal&(SILVER, LIGHT) '    display a light silver medal
        '    Case 50 TO 99 '                                     from 50 to 99
        '        _PutImage (85, 360), Medal&(SILVER, DARK) '     display a dark silver medal
        '    Case 100 TO 199 '                                   from 100 to 199
        '        _PutImage (85, 360), Medal&(GOLD, LIGHT) '      display a light gold medal
        '    Case Is > 199 '                                     from 200 and beyond
        '        _PutImage (85, 360), Medal&(GOLD, DARK) '       display a dark gold medal
        'End Select
        For sc% = 0 To 1 '                                      cycle through both scores
            s$ = LTrim$(RTrim$(Str$(Scores%(sc%)))) '           convert score to string
            x% = 354 - Len(s$) * 23 '                           calculate position of score digit
            For p% = 1 To Len(s$) '                             cycle through score string
                _PutImage (x%, 346 + sc% * 64), Num&(Asc(Mid$(s$, p%, 1)) - 48, LARGE) ' place digit on plaque
                x% = x% + 23 '                                  increment digit position
            Next p%
        Next sc%
        If ShowNew% Then _PutImage (250, 382), New& '           display red new image if new high score
        If BUTTON%(64, 535, OKButton&) Then Ok% = TRUE '        remember if OK button was pressed
        'If BUTTON%(248, 535, ShareButton&) Then '               was share button pressed?
        '    SHAREPROGRAM '                                      yes, share program with others
        '    UPDATESCENERY '                                     draw parallax scenery
        '    MOVEPIPES '                                         draw pipes
        'End If
        _Display '                                              update screen with changes
        'If _Exit Then CLEANUP: System '                         leave game if user closes game window
    Loop Until Ok% '                                            END SCORE LOOP when OK button pressed

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub SHAREPROGRAM ()

    '*
    '* Allows player to share program with others
    '*

    'Shared Fbird&(), FlappyBird&, OKButton&

    Dim Message& ' composed message to player's friend(s)
    Dim Ok% '      boolean: TRUE if OK button pressed

    Message& = _NewImage(339, 174, 32) '                   create image to hold message to player
    '_Clipboard$ = "I just discovered a great game! You can download it here: http:\\www.qb64sourcecode.com\fbird.exe"
    '_PrintMode _KeepBackground '                           printed text will save background
    Line (58, 307)-(372, 453), _RGB32(219, 218, 150), BF ' clear plaque image
    Color _RGB32(210, 170, 79) '                           compose message to player on plaque
    _PrintString (66, 316), "The following message has been copied"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 315), "The following message has been copied"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 331), "to your computer's clipboard:"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 330), "to your computer's clipboard:"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 351), "'I just discovered a great game! You"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 350), "'I just discovered a great game! You"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 366), "can download it here:"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 365), "can download it here:"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 381), "www.qb64sourcecode.com\fbird.exe'"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 380), "www.qb64sourcecode.com\fbird.exe'"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 401), "Create an email for your friends and"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 400), "Create an email for your friends and"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 416), "paste this message into it! Go ahead,"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 415), "paste this message into it! Go ahead,"
    Color _RGB32(210, 170, 79)
    _PrintString (66, 431), "do it now before you change your mind!"
    Color _RGB32(82, 55, 71)
    _PrintString (65, 430), "do it now before you change your mind!"
    _PutImage , _Dest, Message&, (46, 295)-(384, 468) '    place message in image
    Do '                                                   BEGIN SHARE LOOP
        _Limit 60 '                                        60 frames per second
        UPDATESCENERY '                                    move parallax scenery
        _PutImage (40, 200), FlappyBird& '                 place flappy bird title on screen
        _PutImage (350, 200), Fbird&(2, FLAPTHEBIRD%) '    place flapping bird on screen
        _PutImage (46, 295), Message& '                    place message on plaque
        If BUTTON%(156, 535, OKButton&) Then Ok% = TRUE '  remeber if OK button pressed
        _Display '                                         update screen with changes
        'If _Exit Then CLEANUP: System '                    leave game if user closes game window
    Loop Until Ok% '                                       END SHRE LOOP when OK button pressed
    _FreeImage Message& '                                  message image no longer needed

End Sub

'----------------------------------------------------------------------------------------------------------------------

Function BUTTON% (xpos As Integer, ypos As Integer, Img As Long)

    '*
    '* Creates a button on the screen the player can click with the mouse button.
    '*
    '* xpos%  - x coordinate position of button on screen
    '* ypos%  - y coordinate position of button on screen
    '* Image& - button image
    '*
    '* Returns: boolean: TRUE  if button pressed
    '*                   FALSE if button not pressed
    '*

    Dim x% ' current mouse x coordinate
    Dim y% ' current mouse y coordinate
    Dim b% ' boolean: TRUE if left mouse button pressed

    _PutImage (xpos, ypos), Img '                      place button image on the screen
    While _MouseInput: Wend '                               get latest mouse information
    x% = _MouseX '                                          get current mouse x coordinate
    y% = _MouseY '                                          get current mouse y coordinate
    b% = _MouseButton(1)
    If b% Then '                                            is left mouse button pressed?
        If x% >= xpos Then '                               yes, is mouse x within lower limit of button?
            If x% <= xpos + _Width(Img) Then '          yes, is mouse x within upper limit of button?
                If y% >= ypos Then '                       yes, is mouse y within lower limit of button?
                    If y% <= ypos + _Height(Img) Then ' yes, is mouse y within upper limit of button?
                        BUTTON% = TRUE '                    yes, remember that button was clicked on
                        _Delay .2 '                         slight delay to allow button to release
                    End If
                End If
            End If
        End If
    End If

End Function

'----------------------------------------------------------------------------------------------------------------------

Sub UPDATESCENERY ()

    '*
    '* Updates the moving parallax scenery
    '*

    'Shared Scenery() As PARALLAX, Clean&, HazardBar&, Paused%

    Dim c% ' scenery index indicator

    _PutImage (0, 0)-(432, 768), Clean& '                                              clear screen with clean image
    Do '                                                              BEGIN SCENERY LOOP
        c% = c% + 1 '                                                 increment index value
        If Not Paused% Then '                                         is game in paused state?
            Scenery(c%).frame = Scenery(c%).frame + 1 '               no, update frame counter of current scenery
            If Scenery(c%).frame = Scenery(c%).fmax Then '            frame counter hit limit?
                Scenery(c%).frame = 0 '                               yes, reset frame counter
                Scenery(c%).x = Scenery(c%).x - 1 '                   move scenery 1 pixel to left
                If Scenery(c%).x = -432 Then '                        scenery hit lower limit?
                    Scenery(c%).x = 0 '                               yes, reset scenery to start position
                End If
            End If
        End If
        _PutImage (Scenery(c%).x, Scenery(c%).y), Scenery(c%).image ' place current scenery on screen
    Loop Until c% = 3 '                                               END SCENERY LOOP when all scenery updated
    If Not Paused% Then '                                             is game in paused state?
        Scenery(4).x = Scenery(4).x - 3 '                             no, move hazard bar 3 pixels to left
        If Scenery(4).x = -21 Then Scenery(4).x = 0 '                 reset to start position if lower limit hit
    End If
    _PutImage (Scenery(4).x, Scenery(4).y), HazardBar& '              place hazard bar on screen

End Sub

'----------------------------------------------------------------------------------------------------------------------

Sub LOADASSETS ()

    '*
    '* Loads game graphics, sounds and initial settings.
    '*

    'Shared Scenery() As PARALLAX, Birdie As INFLIGHT, Pipes() As PIPE, Pipe&(), Fbird&()
    'Shared Num&(), Medal&(), Plaque&, FlappyBird&, GameOver&, GetReady&, Finger&
    'Shared ScoreButton&, ShareButton&, StartButton&, OKButton&, RateButton&, MenuButton&
    'Shared PlayButton&, PauseButton&, HazardBar&, Clouds&, City&, Bushes&, New&, Clean&
    'Shared HighScore%, PipeImage&, Ding&, Flap&, Smack&

    Dim Sheet& '    sprite sheet image
    Dim x% '        generic counter
    Dim y% '        generic counter
    Dim PipeTop& '  temporary top of pipe image
    Dim PipeTube& ' temporary pipe tube image

    Ding& = _SndOpen("data:audio/ogg;base64,[encoded data, 11064 characters]") '         load game sounds
    Flap& = _SndOpen("data:audio/ogg;base64,[encoded data, 6296 characters]")
    Smack& = _SndOpen("data:audio/ogg;base64,[encoded data, 13672 characters]")
    Sheet& = _LoadImage("data:image/png;base64,[encoded data, 77960 characters]") '             load sprite sheet
    For y% = 0 To 2 '                                          cycle through bird image rows
        For x% = 0 To 7 '                                      cycle through bird image columns
            Fbird&(x% + 1, y% + 1) = _NewImage(53, 53, 32) '   create image holder then get image
            _PutImage , Sheet&, Fbird&(x% + 1, y% + 1), (x% * 53, y% * 53)-(x% * 53 + 52, y% * 53 + 52)
        Next x%
    Next y%
    For x% = 0 To 9 '                                          cycle trough 9 numeral images
        Num&(x%, 0) = _NewImage(21, 30, 32) '                  create image holder for big
        Num&(x%, 1) = _NewImage(18, 21, 32) '                  create image holder for small
        _PutImage , Sheet&, Num&(x%, 0), (x% * 21, 159)-(x% * 21 + 20, 188) ' get images
        _PutImage , Sheet&, Num&(x%, 1), (x% * 18 + 210, 159)-(x% * 18 + 227, 179)
    Next x%
    Plaque& = _NewImage(339, 174, 32) '                        define remaining image sizes
    FlappyBird& = _NewImage(288, 66, 32)
    GameOver& = _NewImage(282, 57, 32)
    GetReady& = _NewImage(261, 66, 32)
    PipeTop& = _NewImage(78, 36, 32)
    PipeTube& = _NewImage(78, 36, 32)
    Pipe&(0) = _NewImage(78, 432, 32)
    Pipe&(1) = _NewImage(78, 432, 32)
    PipeImage& = _NewImage(432, 596, 32)
    Medal&(0, 0) = _NewImage(66, 66, 32)
    Medal&(0, 1) = _NewImage(66, 66, 32)
    Medal&(1, 0) = _NewImage(66, 66, 32)
    Medal&(1, 1) = _NewImage(66, 66, 32)
    Finger& = _NewImage(117, 147, 32)
    ScoreButton& = _NewImage(120, 42, 32)
    ShareButton& = _NewImage(120, 42, 32)
    StartButton& = _NewImage(120, 42, 32)
    OKButton& = _NewImage(120, 42, 32)
    RateButton& = _NewImage(120, 42, 32)
    MenuButton& = _NewImage(120, 42, 32)
    PlayButton& = _NewImage(39, 42, 32)
    PauseButton& = _NewImage(39, 42, 32)
    HazardBar& = _NewImage(462, 24, 32)
    Clouds& = _NewImage(864, 120, 32)
    City& = _NewImage(864, 57, 32)
    Bushes& = _NewImage(864, 27, 32)
    New& = _NewImage(48, 21, 32)
    _PutImage , Sheet&, Plaque&, (0, 189)-(338, 362) '         grab images from sprite sheet
    _PutImage , Sheet&, FlappyBird&, (0, 363)-(287, 428)
    _PutImage , Sheet&, GameOver&, (588, 246)-(869, 302)
    _PutImage , Sheet&, GetReady&, (588, 303)-(847, 368)
    _PutImage , Sheet&, Medal&(0, 0), (339, 327)-(404, 392)
    _PutImage , Sheet&, Medal&(0, 1), (405, 327)-(470, 392)
    _PutImage , Sheet&, Medal&(1, 0), (339, 261)-(404, 326)
    _PutImage , Sheet&, Medal&(1, 1), (405, 261)-(470, 326)
    _PutImage , Sheet&, Finger&, (471, 246)-(587, 392)
    _PutImage , Sheet&, ScoreButton&, (288, 417)-(407, 458)
    _PutImage , Sheet&, ShareButton&, (408, 417)-(527, 458)
    _PutImage , Sheet&, StartButton&, (528, 417)-(647, 458)
    _PutImage , Sheet&, OKButton&, (424, 204)-(543, 245)
    _PutImage , Sheet&, RateButton&, (544, 204)-(663, 245)
    _PutImage , Sheet&, MenuButton&, (664, 204)-(783, 245)
    _PutImage , Sheet&, PlayButton&, (784, 204)-(822, 245)
    _PutImage , Sheet&, PauseButton&, (823, 204)-(861, 245)
    _PutImage , Sheet&, HazardBar&, (288, 393)-(749, 416)
    _PutImage (0, 0)-(431, 119), Sheet&, Clouds&, (424, 0)-(855, 119)
    _PutImage (432, 0)-(863, 119), Sheet&, Clouds&, (424, 0)-(855, 119)
    _PutImage (0, 0)-(431, 56), Sheet&, City&, (424, 120)-(855, 176)
    _PutImage (432, 0)-(863, 56), Sheet&, City&, (424, 120)-(855, 176)
    _PutImage (0, 0)-(431, 26), Sheet&, Bushes&, (424, 177)-(855, 203)
    _PutImage (432, 0)-(863, 26), Sheet&, Bushes&, (424, 177)-(855, 203)
    _PutImage , Sheet&, New&, (289, 363)-(336, 383)
    _PutImage , Sheet&, PipeTop&, (339, 189)-(416, 224)
    '_PutImage , Sheet&, PipeTube&, (339, 225)-(416, 260)
    _PutImage , Sheet&, PipeTube&, (339, 225)-(416, 260)
    _PutImage (0, 431)-(77, 395), PipeTop&, Pipe&(0) '         create bottom of upper tube image
    _PutImage (0, 0), PipeTop&, Pipe&(1) '                     create top of lower tube image
    For y% = 0 To 395 Step 36 '                                cycle through tube body of pipes
        _PutImage (0, y% + 35)-(77, y%), PipeTube&, Pipe&(0) ' draw tube on upper pipe image
        _PutImage (0, 36 + y%), PipeTube&, Pipe&(1) '          draw tube on lower pipe image
    Next y%
    _FreeImage PipeTop& '                                      temporary image no longer needed
    _FreeImage PipeTube& '                                     temporary image no longer needed
    _FreeImage Sheet& '                                        sprite sheet no longer needed

    Clean& = _NewImage(432, 768, 32) '                         create clean image holder
    'Clean& = _NewImage(_Width, _Height, 32)
    _Dest Clean& '                                             work on clean image
    Cls , _RGB32(84, 192, 201) '                               clear image with sky blue color
    Line (0, 620)-(431, 767), _RGB32(219, 218, 150), BF '      create brown ground portion of image
    Line (0, 577)-(431, 595), _RGB32(100, 224, 117), BF '      create green grass portion of image
    _Dest 0 '                                                  back to work on screen
    Scenery(1).image = Clouds& '                               set scenery parallax information
    Scenery(1).y = 457
    Scenery(1).fmax = 8
    Scenery(2).image = City&
    Scenery(2).y = 510
    Scenery(2).fmax = 4
    Scenery(3).image = Bushes&
    Scenery(3).y = 550
    Scenery(3).fmax = 2
    Scenery(4).image = HazardBar&
    Scenery(4).y = 596
    'If _FileExists("fbird.sco") Then '                         does high score file exist?
    '    Open "fbird.sco" For Input As #1 '                     yes, open high score file
    '    Input #1, HighScore% '                                 get high score from file
    '    Close #1 '                                             close high score file
    'End If

End Sub

'----------------------------------------------------------------------------------------------------------------------

Function BOXCOLLISION% (Box1X As Integer, Box1Y As Integer, Box1Width As Integer, Box1Height As Integer, Box2X As Integer, Box2Y As Integer, Box2Width As Integer, Box2Height As Integer)

    '**
    '** Detects if two bounding box areas are in collision
    '**
    '** INPUT : Box1X%      - upper left corner X location of bounding box 1
    '**         Box1Y%      - upper left corner Y location of bounding box 1
    '**         Box1Width%  - the width of bounding box 1
    '**         Box1Height% - the height of bounding box 1
    '**         Box2X%      - upper left corner X location of bounding box 2
    '**         Box2Y%      - upper left corner Y location of bounding box 2
    '**         Box2Width%  - the width of bounding box 2
    '**         Box2Height% - the height of bounding box 2
    '**
    '** OUTPUT: BOXCOLLISION - 0 (FALSE) for no collision, -1 (TRUE) for collision
    '**

    If Box1X <= Box2X + Box2Width - 1 Then '              is box1 x within lower limit of box2 x?
        If Box1X + Box1Width - 1 >= Box2X Then '          yes, is box1 x within upper limit of box2 x?
            If Box1Y <= Box2Y + Box2Height - 1 Then '     yes, is box1 y within lower limit of box2 y?
                If Box1Y + Box1Height - 1 >= Box2Y Then ' yes, is box1 y within upper limit of box2 y?
                    BOXCOLLISION = TRUE '                   yes, then a collision occured, return result
                End If
            End If
        End If
    End If

End Function

'----------------------------------------------------------------------------------------------------------------------

Sub CLEANUP ()

    '*
    '* Removes all game assets from the computer's RAM.
    '*

    'Shared Fbird&(), Pipe&(), Num&(), Medal&(), Plaque&, FlappyBird&, GameOver&, GetReady&
    'Shared Finger&, ScoreButton&, ShareButton&, StartButton&, OKButton&, RateButton&
    'Shared MenuButton&, PlayButton&, PauseButton&, HazardBar&, Clouds&, City&, Bushes&
    'Shared New&, Clean&, PipeImage&, Ding&, Flap&, Smack&

    Dim x% '              generic counter
    Dim y% '              generic counter

    _SndClose Ding& '                           remove game sounds from RAM
    _SndClose Flap&
    _SndClose Smack&
    For y% = 0 To 2 '                           cycle through bird image rows
        For x% = 0 To 7 '                       cycle through bird image columns
            _FreeImage Fbird&(x% + 1, y% + 1) ' remove bird image from RAM
        Next x%
    Next y%
    For x% = 0 To 9 '                           cycle trough 9 numeral images
        _FreeImage Num&(x%, 0) '                remove large numeral image from RAM
        _FreeImage Num&(x%, 1) '                remove small numeral image from RAM
    Next x%
    _FreeImage Plaque& '                        remove all remaining images from RAM
    _FreeImage FlappyBird&
    _FreeImage GameOver&
    _FreeImage GetReady&
    _FreeImage Pipe&(0)
    _FreeImage Pipe&(1)
    _FreeImage PipeImage&
    _FreeImage Medal&(0, 0)
    _FreeImage Medal&(0, 1)
    _FreeImage Medal&(1, 0)
    _FreeImage Medal&(1, 1)
    _FreeImage Finger&
    _FreeImage ScoreButton&
    _FreeImage ShareButton&
    _FreeImage StartButton&
    _FreeImage OKButton&
    _FreeImage RateButton&
    _FreeImage MenuButton&
    _FreeImage PlayButton&
    _FreeImage PauseButton&
    _FreeImage HazardBar&
    _FreeImage Clouds&
    _FreeImage City&
    _FreeImage Bushes&
    _FreeImage New&
    _FreeImage Clean&

End Sub

'----------------------------------------------------------------------------------------------------------------------
