Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 308
» Latest member: Donaldvem
» Forum threads: 1,741
» Forum posts: 17,901

Full Statistics

Latest Threads
The QB64 IDE shell
Forum: Utilities
Last Post: JasonPag
09-16-2024, 05:37 PM
» Replies: 9
» Views: 764
Importance regarding Ches...
Forum: Utilities
Last Post: JasonPag
09-01-2024, 06:34 PM
» Replies: 0
» Views: 31
Chess and Analysis and En...
Forum: Utilities
Last Post: JasonPag
08-28-2024, 02:37 PM
» Replies: 0
» Views: 32
DAY 009:_PutImage
Forum: Keyword of the Day!
Last Post: grymmjack
09-02-2023, 02:57 PM
» Replies: 54
» Views: 2,034
Fall Banner Contest?
Forum: Site Suggestions
Last Post: grymmjack
08-31-2023, 11:50 PM
» Replies: 36
» Views: 1,262
ColorPicker - Function th...
Forum: Dav
Last Post: Dav
08-31-2023, 11:04 PM
» Replies: 3
» Views: 316
Goals(1) = New Tile()
Forum: Works in Progress
Last Post: RhoSigma
08-31-2023, 09:45 PM
» Replies: 3
» Views: 127
micro(A)v11
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 09:14 PM
» Replies: 90
» Views: 3,589
Updating The Single Most ...
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 09:13 PM
» Replies: 7
» Views: 254
QBJS Image Question
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 05:49 PM
» Replies: 5
» Views: 155

 
Bug QBZERK doesn't work on Linux 64-bit
Posted by: mnrvovrfc - 10-28-2022, 09:04 PM - Forum: General Discussion - Replies (7)

I'm informing that I wanted to play the "QBZERK" on Linux. It seems to be strictly for Windows only because it compiles successfully but the executable refuses to start. Tried it just now on dead-duck Fedora 36 MATE on one computer, and on Manjaro KDE on my main 10-year-old laptop. This was all 64-bit and with QB64PE v3.3. I declined trying the "official" QB64.

It gives out an error message starting with "freeglut" then the executable name as was written at the command line, then colon and nothing afterward. Was it supposed to display the reason for the failure?

I picked up the ZIP from the "dot-rip" frozen forum but it had been sitting there in my backups for months.

I was going to post this in the thread about the game tutorials (EDIT: so much that I had to make one edit), to indicate this isn't really a big deal, no pressure requested. I'd play this game for Windows if that was intended, no problem for me.

Print this item

  simple 2D vector graphics part 2: moving in the direction of an angle
Posted by: madscijr - 10-28-2022, 07:02 PM - Forum: Works in Progress - Replies (4)

Now given an angle in degrees (0-359) we can calculate dx and dy needed to move in that direction. 
(Next - rotating objects!)
Enjoy!

Code: (Select All)
_Title "Simple vector graphics v0.22 mostly by madscijr" ' display in the Window's title bar

' Simple test of vector graphics,
' borrowed graphics objects and format from Widescreen Asteroids by Terry Ritchie.

' DONE:
' * define vector objects line by line and draw to screen
' * translate rotation angle into dx,dy to move in direction of angle

' TO DO:
' * rotate objects
' * detect collisions
' * move back to storing vector object definitions in a file instead of DATA statements
' * object editor to draw/edit with the mouse/keyboard and save the coordinates
' * speed up?

' BOOLEAN CONSTANTS
Const FALSE = 0
Const TRUE = Not FALSE

' HOLDS POSITION AND VELOCITY OF ALL OBJECTS
Type ObjectType
    x As Integer
    y As Integer
    dx As Integer
    dy As Integer
    cx As Integer
    cy As Integer
    IsEnabled As Integer
End Type ' ObjectType

' HOLDS DEFINITION OF ALL OBJECTS
Type CoordType
    x1 As Integer
    y1 As Integer
    x2 As Integer
    y2 As Integer
    color As _Unsigned Long
    IsLast As Integer
End Type ' CoordType

' ENABLE / DISABLE DEBUG CONSOLE
Dim Shared m_bDebug As Integer: m_bDebug = TRUE

' BASIC PROGRAM METADATA
Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)

' OBJECT VARIABLES
ReDim Shared m_arrObject(1 To 8) As ObjectType
ReDim Shared m_arrLines(1 To 8, 1 To 32) As CoordType ' (object #, line segment #)

' ****************************************************************************************************************************************************************
' ACTIVATE DEBUGGING WINDOW
If m_bDebug = TRUE Then
    $Console
    _Delay 4
    _Console On
    _Echo "Started " + m_ProgramName$
    _Echo "Debugging on..."
End If
' ****************************************************************************************************************************************************************

' =============================================================================
' START THE MAIN ROUTINE
main

' =============================================================================
' FINISH
'Screen 0
'Print m_ProgramName$ + " finished."
'Sleep

' ****************************************************************************************************************************************************************
' DEACTIVATE DEBUGGING WINDOW
If m_bDebug = TRUE Then
    _Console Off
End If
' ****************************************************************************************************************************************************************

System ' return control to the operating system
'End

' ################################################################################################################################################################
' BEGIN MAIN MENU
' ################################################################################################################################################################

' /////////////////////////////////////////////////////////////////////////////

Sub main
    Dim RoutineName As String: RoutineName = "main"
    Dim in$
    Dim bFinished As Integer: bFinished = FALSE
    Dim result$: result$ = ""
    Dim iScreen&

    ' SET UP SCREEN
    iScreen& = _NewImage(800, 640, 32) ' 100 text columns x 40 text rows
    _ScreenMove 0, 0

    ' MAIN MENU LOOP, UNTIL QUIT
    Do
        Screen iScreen&: Cls

        Print m_ProgramName$
        Print
        Print "Simple vector drawing"
        Print
        Print "1) Draw vector objects       "
        Print "2) Calculate dx,dy per angle "
        Print "3) Rotate vector objects     <- UNDER CONSTRUCTION"
        Print "4) Collision detection       <- UNDER CONSTRUCTION"
        Print
        Print "Q) Exit program"
        Do
            in$ = InKey$
            If UCase$(in$) = "Q" Then
                bFinished = TRUE: Exit Do
            ElseIf UCase$(in$) = "1" Then
                DrawVectorObjectTest1: Exit Do
            ElseIf UCase$(in$) = "2" Then
                Calculate_DX_DY_per_angle_TEST_2: Exit Do
            ElseIf UCase$(in$) = "3" Then
                result$ = "UNDER CONSTRUCTION": Exit Do
            ElseIf UCase$(in$) = "4" Then
                result$ = "UNDER CONSTRUCTION": Exit Do
            End If
        Loop

        If Len(result$) > 0 Then
            Screen iScreen&: Cls
            Print result$
            Print
            Print "Press <ENTER> to continue."
            Do: Loop Until InKey$ = Chr$(13)
            _KeyClear
            result$ = ""
        End If

    Loop Until bFinished = TRUE
End Sub ' main

' ################################################################################################################################################################
' END MAIN MENU
' ################################################################################################################################################################

' /////////////////////////////////////////////////////////////////////////////
' Precalculates dx,dy for 0-359 degrees
' and returns as 2 arrays (one for dx, one for dy)

' Helped by code from
' https://wiki.qb64.dev/qb64wiki/index.php/SIN

Sub Calculate_DX_DY_per_angle (arrAngleToDX() As Single, arrAngleToDY() As Single)
    Dim PI As Single
    Dim iDegree As Integer
    Dim sngRadians As Single
    Dim iAngle As Integer
    Dim iDiff As Integer

    ' Make sure arrays are dimensioned
    ReDim arrAngleToDX(0 To 359) As Single
    ReDim arrAngleToDY(0 To 359) As Single

    ' Calculate Pi
    PI = 4 * Atn(1)

    ' Calculate dx,dy for each of 360 degrees
    For iDegree = 0 To 359
        ' re-orient so 0 degrees is 12 o'clock, 180 degrees is 6 o'clock
        If iDegree <= 180 Then
            iAngle = 180 - iDegree
        ElseIf iDegree = 181 Then
            iDiff = 178
            iAngle = iDegree + iDiff
        Else
            iDiff = iDiff - 2
            iAngle = iDegree + iDiff
        End If

        ' calculate dx, dy for the current angle
        sngRadians = iDegree * PI / 180
        arrAngleToDX(iAngle) = Sin(sngRadians)
        arrAngleToDY(iAngle) = Cos(sngRadians)
    Next iDegree
End Sub ' Calculate_DX_DY_per_angle

'Sub Calculate_DX_DY_per_angle_TEST_1
'   Dim arrAngleToDX(0 To 359) As Single
'   Dim arrAngleToDY(0 To 359) As Single
'   Dim iAngle As Integer
'    Dim in$
'
'   Calculate_DX_DY_per_angle arrAngleToDX(), arrAngleToDY()
'
'   for iAngle = 0 to 359
'       DebugPrint _
'           LeftPadString$(cstr$(iAngle), 3, " ") + " deg. " + _
'           "DX=" + SngRoundedToStr$(arrAngleToDX(iAngle), 6) + " " + _
'           "DY=" + SngRoundedToStr$(arrAngleToDY(iAngle), 6) + " " + _
'           ""
'   next iAngle
'
'    Input "Press <ENTER> to continue", in$
'End Sub ' Calculate_DX_DY_per_angle_TEST_1

' /////////////////////////////////////////////////////////////////////////////

Sub Calculate_DX_DY_per_angle_TEST_2
    Dim RoutineName As String: RoutineName = "Calculate_DX_DY_per_angle_TEST_2"
    Dim iFPS As Integer: iFPS = 120
    Dim iMinX As Integer: iMinX = 0
    Dim iMaxX As Integer: iMaxX = 800
    Dim iMinY As Integer: iMinY = 0
    Dim iMaxY As Integer: iMaxY = 640
    Dim arrAngleToDX(0 To 359) As Single
    Dim arrAngleToDY(0 To 359) As Single
    Dim iAngle As Integer
    Dim iX As Integer
    Dim iY As Integer
    Dim sngX As Single
    Dim sngY As Single
    Dim sngVX As Single: sngVX = 4
    Dim sngVY As Single: sngVY = 4
    Dim sngDX As Single
    Dim sngDY As Single
    Dim bQuit As Integer: bQuit = FALSE
    Dim in$

    Calculate_DX_DY_per_angle arrAngleToDX(), arrAngleToDY()

    Screen _NewImage(800, 640, 32) ' 100 text columns x 40 text rows
    _KeyClear

    While TRUE = TRUE
        For iAngle = 0 To 359

            ' CALCULATE DIRECTION FOR ANGLE
            sngDX = sngVX * arrAngleToDX(iAngle)
            sngDY = sngVY * arrAngleToDY(iAngle)

            ' Start in center
            iX = iMaxX \ 2: sngX = iX
            iY = iMaxY \ 2: sngY = iY

            ' Move object outward at current iAngle
            While TRUE = TRUE
                ' CLEAR SCREEN
                _Dest 0: Cls , cBlack

                ' DRAW CIRCLE
                ' CIRCLE (x, y), radius, color
                'CIRCLE [[[STEP]]](column, row), radius%, [drawColor%][, startRadian!, stopRadian!] [, aspect!]
                'Circle (dblX + 4, dblY + 8), 4, cGray
                iX = SngToInt%(sngX)
                iY = SngToInt%(sngY)

                'Line (iLoop * 8, iHeight * 16)-(iLoop * 8 + 8, _Height), cGray, BF
                'Circle (iX, iY), 4, cRed
                DrawCircleSolid iX, iY, 8, cRed

                ' SHOW VALUES
                PrintAt 1, 1, RoutineName
                PrintAt 3, 1, _
                    "iAngle=" + LeftPadString$(cstr$(iAngle), 3, " ")
                PrintAt 5, 1, _
                    "iX    =" + LeftPadString$(cstr$(iX), 3, " ") + " " + _
                    "sngDX =" + SngRoundedToStr$(sngDX, 6)
                PrintAt 7, 1, _
                    "iY    =" + LeftPadString$(cstr$(iY), 3, " ") + " " + _
                    "sngDY =" + SngRoundedToStr$(sngDY, 6)

                Color cWhite, cBlue
                PrintAt 9, 1, "Press ESC to exit."
                Color cWhite, cEmpty

                ' MOVE OBJECT
                sngX = sngX + sngDX
                sngY = sngY + sngDY

                ' PROCESS INPUT
                While _DeviceInput(1): Wend ' clear and update the keyboard buffer

                ' IF OUT OF BOUNDS, GOTO NEXT ANGLE
                If iX < 0 Or iX > iMaxX Or iY < 0 Or iY > iMaxY Then
                    Exit While
                End If
                'If _Button(KeyCode_A%) Then
                '   Exit While
                'end if

                ' QUIT?
                If _Button(KeyCode_Escape%) Then
                    bQuit = TRUE
                    Exit While
                End If

                ' CLEAR KEYBOARD BUFFER
                _KeyClear

                ' UPDATE THE SCREEN
                _Display

                ' CONTROL GAME SPEED
                _Limit iFPS
            Wend

            If bQuit = TRUE Then Exit For
        Next iAngle

        If bQuit = TRUE Then Exit While
    Wend

    ' RETURN TO AUTODISPLAY
    _AutoDisplay

    'Input "Press <ENTER> to continue", in$
End Sub ' Calculate_DX_DY_per_angle_TEST_2

' /////////////////////////////////////////////////////////////////////////////

Sub DrawVectorObjectTest1
    Dim RoutineName As String: RoutineName = "DrawVectorObjectTest1"
    Dim iFPS As Integer: iFPS = 120
    Dim iLoop As Integer
    Dim iObject As Integer
    Dim iLine As Integer
    Dim imgBack&
    Dim imgMiddle&
    Dim imgFront&
    Dim iWhich As Integer: iWhich = 1
    Dim bQuit As Integer: bQuit = FALSE
    Dim in$
    Dim sError As String: sError = ""
    Dim iX As Integer
    Dim iY As Integer
    Dim sKey As String
    Dim iMinX As Integer: iMinX = 0
    Dim iMaxX As Integer: iMaxX = 800
    Dim iMinY As Integer: iMinY = 0
    Dim iMaxY As Integer: iMaxY = 640
    Dim iPrintX As Integer
    Dim iPrintY As Integer

    ' =============================================================================
    ' INITIALIZE
    Screen _NewImage(800, 640, 32) ' 100 text columns x 40 text rows
    'imgBack& = _NewImage(800, 640, 32) ' background
    'imgMiddle& = _NewImage(800, 640, 32) ' other stuff
    'imgFront& = _NewImage(800, 640, 32) ' foreground

    ' =============================================================================
    ' START NEW GAME
    Do
        _KeyClear

        ' CONFIGURE PRINTING FOR _PrintString
        _PrintMode _FillBackground
        '_PrintMode _KEEPBACKGROUND

        ' INIT VARS
        sKey = ""
        iX = 0: iY = 0
        For iObject = LBound(m_arrObject) To UBound(m_arrObject)
            m_arrObject(iObject).IsEnabled = FALSE
            m_arrObject(iObject).x = iX
            m_arrObject(iObject).y = iY
            m_arrObject(iObject).dx = RandomNumber%(-5, 5)
            m_arrObject(iObject).dy = RandomNumber%(-5, 5)
            m_arrObject(iObject).cx = 0
            m_arrObject(iObject).cy = 0
            iX = iX + 200
            If iX > 800 Then
                iX = 0
                iY = iY + 200
                If iY > 640 Then
                    iY = 0
                    iX = 100
                End If
            End If
        Next iObject
        InitVectorObjects

        ' MAIN LOOP
        While TRUE = TRUE
            ' REDRAW BACKGROUND LAYERS
            DrawLayers imgBack&, imgMiddle&, imgFront&
            '_Dest 0: Cls , cBlack

            ' -----------------------------------------------------------------------------
            ' BEGIN SHOW VALUES ON SCREEN
            ' -----------------------------------------------------------------------------
            Color cWhite
            PrintAt 1, 1, RoutineName

            Color cYellow
            PrintAt 3, 1, "Press 1-6 to select active object."
            PrintAt 4, 1, "Arrow keys move active object."

            Color cWhite, cBlue
            PrintAt 5, 1, "Press ESC to exit."

            Color cWhite, cEmpty
            iPrintY = 7
            For iObject = LBound(m_arrObject) To UBound(m_arrObject)
                If m_arrObject(iObject).IsEnabled = TRUE Then
                    Color cCyan
                Else
                    Color cGray
                End If
                PrintAt iPrintY, 1, "" + _
                    "obj #" + cstr$(iObject) + _
                    "(" + cstr$(m_arrObject(iObject).x) + "," + cstr$(m_arrObject(iObject).y) + ")" + _
                    "(" + cstr$(m_arrObject(iObject).dx) + "," + cstr$(m_arrObject(iObject).dy) + ")" + _
                    "(" + cstr$(m_arrObject(iObject).cx) + "," + cstr$(m_arrObject(iObject).cy) + ")" + _
                    ""
                iPrintY = iPrintY + 1
            Next iObject

            ' SHOW INPUT
            Color cLime
            PrintAt 20, 1, "Controls   : " + RightPadString$(sKey, 10, " ") + "   "

            Color cWhite
            PrintAt 21, 1, "Object #   : " + cstr$(iWhich)
            ' -----------------------------------------------------------------------------
            ' END SHOW VALUES ON SCREEN
            ' -----------------------------------------------------------------------------

            ' MOVE + DRAW ENABLED OBJECTS
            For iObject = LBound(m_arrObject) To UBound(m_arrObject)
                ' Only enabled objects
                If m_arrObject(iObject).IsEnabled = TRUE Then

                    ' Move along X axis
                    m_arrObject(iObject).cx = m_arrObject(iObject).cx + 1
                    If m_arrObject(iObject).cx > (10 - Abs(m_arrObject(iObject).dx)) Then
                        m_arrObject(iObject).cx = 0
                        If m_arrObject(iObject).dx < 0 Then
                            m_arrObject(iObject).x = m_arrObject(iObject).x - 1
                            If m_arrObject(iObject).x < iMinX Then
                                m_arrObject(iObject).x = iMaxX
                            End If
                        ElseIf m_arrObject(iObject).dx > 0 Then
                            m_arrObject(iObject).x = m_arrObject(iObject).x + 1
                            If m_arrObject(iObject).x > iMaxX Then
                                m_arrObject(iObject).x = iMinX
                            End If
                        End If
                    End If

                    ' Move along Y axis
                    m_arrObject(iObject).cy = m_arrObject(iObject).cy + 1
                    If m_arrObject(iObject).cy > (10 - Abs(m_arrObject(iObject).dy)) Then
                        m_arrObject(iObject).cy = 0
                        If m_arrObject(iObject).dy < 0 Then
                            m_arrObject(iObject).y = m_arrObject(iObject).y - 1
                            If m_arrObject(iObject).y < iMinY Then
                                m_arrObject(iObject).y = iMaxY
                            End If
                        ElseIf m_arrObject(iObject).dy > 0 Then
                            m_arrObject(iObject).y = m_arrObject(iObject).y + 1
                            If m_arrObject(iObject).y > iMaxY Then
                                m_arrObject(iObject).y = iMinY
                            End If
                        End If
                    End If

                    ' Draw object's line segments
                    For iLine = LBound(m_arrLines, 2) To UBound(m_arrLines, 2)
                        'Line (x1%, y1%)-(x2%, y2%), arrColor(arrStars(iLoop).ColorIndex), BF
                        Line _
                            (m_arrObject(iObject).x + m_arrLines(iObject, iLine).x1, _
                            m_arrObject(iObject).y + m_arrLines(iObject, iLine).y1) _
                            - _
                            (m_arrObject(iObject).x + m_arrLines(iObject, iLine).x2, _
                            m_arrObject(iObject).y + m_arrLines(iObject, iLine).y2) _
                            , _
                            m_arrLines(iObject, iLine).color ' , BF
                        If m_arrLines(iObject, iLine).IsLast = TRUE Then
                            Exit For
                        End If
                    Next iLine

                End If
            Next iObject

            ' UPDATE THE SCREEN
            _Display

            ' PROCESS INPUT
            While _DeviceInput(1): Wend ' clear and update the keyboard buffer
            sKey = ""

            ' QUIT?
            If _Button(KeyCode_Escape%) Then
                bQuit = TRUE
                Exit While
            End If

            ' OTHER INPUT 1-6 SELECTS WHICH OBJECT TO CHANGE
            If _Button(KeyCode_1%) Then
                sKey = sKey + "1,"
                iWhich = 1
            ElseIf _Button(KeyCode_2%) Then
                sKey = sKey + "2,"
                iWhich = 2
            ElseIf _Button(KeyCode_3%) Then
                sKey = sKey + "3,"
                iWhich = 3
            ElseIf _Button(KeyCode_4%) Then
                sKey = sKey + "4,"
                iWhich = 4
            ElseIf _Button(KeyCode_5%) Then
                sKey = sKey + "5,"
                iWhich = 5
            ElseIf _Button(KeyCode_6%) Then
                sKey = sKey + "6,"
                iWhich = 6
            End If

            ' GET DIRECTION
            If _Button(KeyCode_Left%) Then
                sKey = sKey + "LEFT,"
                m_arrObject(iWhich).dx = m_arrObject(iWhich).dx - 1
                If m_arrObject(iWhich).dx < -10 Then m_arrObject(iWhich).dx = -10
            ElseIf _Button(KeyCode_Right%) Then
                sKey = sKey + "RIGHT,"
                m_arrObject(iWhich).dx = m_arrObject(iWhich).dx + 1
                If m_arrObject(iWhich).dx > 10 Then m_arrObject(iWhich).dx = 10
            ElseIf _Button(KeyCode_Up%) Then
                sKey = sKey + "UP,"
                m_arrObject(iWhich).dy = m_arrObject(iWhich).dy - 1
                If m_arrObject(iWhich).dy < -10 Then m_arrObject(iWhich).dy = -10
            ElseIf _Button(KeyCode_Down%) Then
                sKey = sKey + "DOWN,"
                m_arrObject(iWhich).dy = m_arrObject(iWhich).dy + 1
                If m_arrObject(iWhich).dy > 10 Then m_arrObject(iWhich).dy = 10
            End If

            ' CLEAR KEYBOARD BUFFER
            _KeyClear

            ' CONTROL GAME SPEED
            _Limit iFPS
        Wend

        ' UPDATE THE SCREEN
        _Display

        ' CLEAR KEYBOARD BUFFER
        _KeyClear ': _Delay 2

        ' PLAY ANOTHER ROUND OR QUIT?
        If bQuit = FALSE Then
            If bExit = FALSE Then Sleep
            Color cWhite, cBlack
        Else
            Exit Do
        End If
    Loop

    ' RETURN TO AUTODISPLAY
    _AutoDisplay

End Sub ' DrawVectorObjectTest1

' /////////////////////////////////////////////////////////////////////////////
' VECTOR OBJECT DEFINITIONS

' This version stores the vector object definitions in DATA statements
' but we will move back to storing them in an external file.

Sub InitVectorObjects
    Dim RoutineName As String: RoutineName = "InitVectorObjects"
    Dim iLoop As Integer
    Dim iObject As Integer
    Dim iLine As Integer

    Dim x1 As Integer
    Dim y1 As Integer
    Dim x2 As Integer
    Dim y2 As Integer
    Dim r1 As Integer
    Dim g1 As Integer
    Dim b1 As Integer

    iObject = 1
    iLine = 1

    Restore VectorData
    For iLoop = 1 To 1024
        Read x1
        Read y1
        Read x2
        Read y2
        Read r1
        Read g1
        Read b1 ' -255 means no more data, -254 means last set for this object

        If b1 = -255 Then
            ' done with everything, finish last object & exit
            m_arrLines(iObject, iLine).IsLast = TRUE
            m_arrObject(iObject).IsEnabled = TRUE
            Exit For
        ElseIf b1 = -254 Then
            ' done with this object, finish & move to next
            m_arrLines(iObject, iLine).IsLast = TRUE
            m_arrObject(iObject).IsEnabled = TRUE
            iObject = iObject + 1
            iLine = 1

            ' if more data than array, quit
            If iObject > UBound(m_arrLines, 1) Then
                Exit For
            End If
        Else
            ' if more data than array,
            ' just keep reading until either
            ' we get to the next object or time to quit
            If iLine <= UBound(m_arrLines, 2) Then
                m_arrLines(iObject, iLine).x1 = x1
                m_arrLines(iObject, iLine).y1 = y1
                m_arrLines(iObject, iLine).x2 = x2
                m_arrLines(iObject, iLine).y2 = y2
                m_arrLines(iObject, iLine).color = _RGB32(r1, g1, b1)
                m_arrLines(iObject, iLine).IsLast = FALSE
                iLine = iLine + 1
            End If
        End If
    Next iLoop%

    VectorData:

    ' Objects are defined as a collection of line segments, in the form:
    '     Data {x1},{y1},{x2},{y2},{red},{green},{blue}
    ' where
    ' * {x1},{y1} are the starting point of the line
    ' * {x2},{y2} are the ending point of the line
    ' * {red},{green},{blue} are the RGB color of the line segment
    ' * 0,0 is the origin,
    ' * negative numbers mean to the left or above the origin
    ' * positive numbers mean to the right or below the origin
    ' * if the {blue} value is -254 like
    '     Data 0,0,0,0,-254,-254,-254
    '   then that line is not used,
    '   it just exists to tell the parser that object's definition is done,
    ' * if the {blue} value is -255 like
    '     Data 0,0,0,0,-255,-255,-255
    '   then that line is not used
    '   it just exists to tell the parser no more data, stop parsing.

    ' For now we're using data statements, but later might store
    ' these definitions in a separate file that an editor can read/write.

    'objaster1 = purple
    Data 2,-41,31,-50,128,0,255
    Data 31,-50,56,-23,128,0,255
    Data 56,-23,37,-10,128,0,255
    Data 37,-10,61,13,128,0,255
    Data 61,13,32,62,128,0,255
    Data 32,62,-22,43,128,0,255
    Data -22,43,-40,57,128,0,255
    Data -40,57,-62,34,128,0,255
    Data -62,34,-47,7,128,0,255
    Data -47,7,-62,-26,128,0,255
    Data -62,-26,-32,-63,128,0,255
    Data -32,-63,2,-41,128,0,255
    Data 0,0,0,0,-254,-254,-254

    'objaster2 = red
    Data -28,-62,22,-62,255,0,0
    Data 22,-62,61,-28,255,0,0
    Data 61,-28,61,13,255,0,0
    Data 61,13,23,57,255,0,0
    Data 23,57,-6,62,255,0,0
    Data -6,62,-6,15,255,0,0
    Data -6,15,-36,47,255,0,0
    Data -36,47,-59,14,255,0,0
    Data -59,14,-35,1,255,0,0
    Data -35,1,-62,-9,255,0,0
    Data -62,-9,-28,-62,255,0,0
    Data 0,0,0,0,-254,-254,-254

    'objaster3 = orange
    Data 9,-62,60,-21,255,165,0
    Data 60,-21,62,-3,255,165,0
    Data 62,-3,24,13,255,165,0
    Data 24,13,53,34,255,165,0
    Data 53,34,38,55,255,165,0
    Data 38,55,20,40,255,165,0
    Data 20,40,-37,61,255,165,0
    Data -37,61,-63,15,255,165,0
    Data -63,15,-57,-24,255,165,0
    Data -57,-24,-24,-24,255,165,0
    Data -24,-24,-38,-45,255,165,0
    Data -38,-45,9,-62,255,165,0
    Data 0,0,0,0,-254,-254,-254

    'objmouse = yellow
    Data 0,-10,6,3,255,255,0
    Data 6,3,1,2,255,255,0
    Data 1,2,1,10,255,255,0
    Data 1,10,-1,10,255,255,0
    Data -1,10,-1,2,255,255,0
    Data -1,2,-6,3,255,255,0
    Data -6,3,0,-10,255,255,0
    Data 0,0,0,0,-254,-254,-254

    'objship = cyan
    Data 0,-15,10,15,0,255,255
    Data 10,15,6,11,0,255,255
    Data 6,11,-6,11,0,255,255
    Data -6,11,-10,15,0,255,255
    Data -10,15,0,-15,0,255,255
    Data 0,0,0,0,-254,-254,-254

    'objufo = green
    Data -4,-16,4,-16,0,255,0
    Data 4,-16,10,-6,0,255,0
    Data 10,-6,25,5,0,255,0
    Data 25,5,10,16,0,255,0
    Data 10,16,-10,16,0,255,0
    Data -10,16,-25,5,0,255,0
    Data -25,5,-10,-6,0,255,0
    Data -10,-6,-4,-16,0,255,0
    Data -10,-6,10,-6,0,255,0
    Data -25,5,25,5,0,255,0
    Data 0,0,0,0,-255,-255,-255

End Sub ' InitVectorObjects

' /////////////////////////////////////////////////////////////////////////////
' (RE)DRAW SCREEN

Sub DrawLayers (imgBack&, imgMiddle&, imgFront&)
    Dim RoutineName As String: RoutineName = "DrawLayers"

    _Dest 0
    Cls , cBlack

    If TRUE = FALSE Then
        If imgBack& < -1 Then
            _PutImage , imgBack&, 0
        End If

        If imgMiddle& < -1 Then
            _PutImage , imgMiddle&, 0
        End If

        If imgFront& < -1 Then
            _PutImage , imgFront&, 0
        End If
    End If

End Sub ' DrawLayers


' ****************************************************************************************************************************************************************
' BEGIN TEST CODE
' ****************************************************************************************************************************************************************

' /////////////////////////////////////////////////////////////////////////////

'Sub TestDivideAndRound1
'    Dim mySingle As Single
'    Dim myDouble As Double
'    Dim myFloat1 As _Float
'    Dim in$
'    ' Excel 1/360 = 0.002778
'    mySingle = 1 / 360
'    myDouble = 1 / 360
'    myFloat1 = 1 / 360
'    Print "Single 1/360 = " + _Trim$(Str$(mySingle)) + " or " + SngToStr$(mySingle) + " or " + SngRoundedToStr$(mySingle, 6)
'    Print "Double 1/360 = " + _Trim$(Str$(myDouble)) + " or " + DblToStr$(myDouble) + " or " + DblRoundedToStr$(myDouble, 6)
'    Print "_FLOAT 1/360 = " + _Trim$(Str$(myFloat1)) + " or " + FloatToStr$(myFloat1) + " or " + FloatRoundedToStr$(myFloat1, 6)
'
'    Input "Press <ENTER> to continue", in$
'End Sub ' TestDivideAndRound1

' ****************************************************************************************************************************************************************
' END TEST CODE
' ****************************************************************************************************************************************************************


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN GENERAL PURPOSE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' /////////////////////////////////////////////////////////////////////////////
' Integer to string

Function cstr$ (myValue)
    'cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
    cstr$ = _Trim$(Str$(myValue))
End Function ' cstr$

' /////////////////////////////////////////////////////////////////////////////
' Hack function, to be replaced with something better

Function DblToInt% (dblOld As Double)
    Dim dblNew As Double
    Dim sValue As String
    Dim iPos As Integer

    dblNew = RoundDouble#(dblOld, 0)
    'sValue = _Trim$(Str$(dblNew))

    sValue = DblToStr$(dblNew)

    'iPos = InStr(1, sValue, ".")
    'If iPos > 0 Then
    '    DblToInt% = Val(Left$(sValue, iPos - 1))
    'Else
    '    DblToInt% = Val(sValue)
    'End If

    DblToInt% = Val(sValue)
End Function ' DblToInt%

' /////////////////////////////////////////////////////////////////////////////
' Scientific notation - QB64 Wiki
' https://www.qb64.org/wiki/Scientific_notation

' Example: A string function that displays extremely small or large exponential decimal values.

Function DblToStr$ (n#)
    Dim result$: result$ = ""
    Dim value$
    Dim Xpos%
    Dim expo%
    Dim sign$
    Dim valu$
    Dim dot%
    Dim L%
    Dim add$
    Dim min$
    Dim DP$
    Dim n%

    value$ = UCase$(LTrim$(Str$(n#)))
    Xpos% = InStr(value$, "D") + InStr(value$, "E") ' only D or E can be present
    If Xpos% Then
        expo% = Val(Mid$(value$, Xpos% + 1))
        If Val(value$) < 0 Then
            sign$ = "-"
            valu$ = Mid$(value$, 2, Xpos% - 2)
        Else
            valu$ = Mid$(value$, 1, Xpos% - 1)
        End If
        dot% = InStr(valu$, ".")
        L% = Len(valu$)
        If expo% > 0 Then
            add$ = String$(expo% - (L% - dot%), "0")
        End If
        If expo% < 0 Then
            min$ = String$(Abs(expo%) - (dot% - 1), "0")
            DP$ = "."
        End If
        For n% = 1 To L%
            If Mid$(valu$, n%, 1) <> "." Then
                num$ = num$ + Mid$(valu$, n%, 1)
            End If
        Next n%
        result$ = _Trim$(sign$ + DP$ + min$ + num$ + add$)
    Else
        result$ = value$
    End If

    DblToStr$ = result$
End Function ' DblToStr$

' /////////////////////////////////////////////////////////////////////////////

Function DblRoundedToStr$ (dblValue As Double, intNumPlaces As Integer)
    Dim dblNew As Double
    dblNew = RoundDouble#(dblValue, intNumPlaces)
    DblRoundedToStr$ = DblToStr$(dblNew)
End Function ' DblRoundedToStr$

' /////////////////////////////////////////////////////////////////////////////

Function DoubleABS# (dblValue As Double)
    If Sgn(dblValue) = -1 Then
        DoubleABS# = 0 - dblValue
    Else
        DoubleABS# = dblValue
    End If
End Function ' DoubleABS#

' /////////////////////////////////////////////////////////////////////////////
' bplus: The Gold Standard is even better than THE QB64 CIRCLE sub in this respect!
' https://forum.qb64.org/index.php?topic=1044.135

' from Steve Gold standard
' Renamed fcirc to DrawCircleSolid

' Not as fast as DrawCircleTopLeft but pretty fast.

' Example:
' Screen _NewImage(800, 600, 32)
' _ScreenMove 250, 60
' For r = 250 To 0 Step -60
'     DrawCircleSolid 400, 300, r, _RGBA(255, 255, 255, 100)
' Next r

Sub DrawCircleSolid (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
    Dim Radius As Integer, RadiusError As Integer
    Dim X As Integer, Y As Integer

    Radius = Abs(R)
    RadiusError = -Radius
    X = Radius
    Y = 0

    If Radius = 0 Then PSet (CX, CY), C: Exit Sub

    ' Draw the middle span here so we don't draw it twice in the main loop,
    ' which would be a problem with blending turned on.
    Line (CX - X, CY)-(CX + X, CY), C, BF

    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend
End Sub ' DrawCircleSolid

' /////////////////////////////////////////////////////////////////////////////

Function FloatRoundedToStr$ (fValue As _Float, intNumPlaces As Integer)
    Dim fNew As _Float
    fNew = Round##(fValue, intNumPlaces)
    FloatRoundedToStr$ = FloatToStr$(fNew)
End Function ' DblRoundedToStr$

' /////////////////////////////////////////////////////////////////////////////
' Scientific notation - QB64 Wiki
' https://www.qb64.org/wiki/Scientific_notation

' Example: A string function that displays extremely small or large exponential decimal values.

Function FloatToStr$ (n##)
    value$ = UCase$(LTrim$(Str$(n##)))
    Xpos% = InStr(value$, "D") + InStr(value$, "E") 'only D or E can be present
    If Xpos% Then
        expo% = Val(Mid$(value$, Xpos% + 1))
        If Val(value$) < 0 Then
            sign$ = "-"
            valu$ = Mid$(value$, 2, Xpos% - 2)
        Else
            valu$ = Mid$(value$, 1, Xpos% - 1)
        End If
        dot% = InStr(valu$, ".")
        L% = Len(valu$)
        If expo% > 0 Then
            add$ = String$(expo% - (L% - dot%), "0")
        End If
        If expo% < 0 Then
            min$ = String$(Abs(expo%) - (dot% - 1), "0")
            DP$ = "."
        End If
        For n = 1 To L%
            If Mid$(valu$, n, 1) <> "." Then
                num$ = num$ + Mid$(valu$, n, 1)
            End If
        Next n
    Else
        FloatToStr$ = value$
        Exit Function
    End If
    FloatToStr$ = _Trim$(sign$ + DP$ + min$ + num$ + add$)
End Function ' FloatToStr$

' /////////////////////////////////////////////////////////////////////////////
' By sMcNeill from https://www.qb64.org/forum/index.php?topic=896.0

Function IsNum% (text$)
    Dim a$
    Dim b$
    a$ = _Trim$(text$)
    b$ = _Trim$(Str$(Val(text$)))
    If a$ = b$ Then
        IsNum% = TRUE
    Else
        IsNum% = FALSE
    End If
End Function ' IsNum%

' /////////////////////////////////////////////////////////////////////////////
' Split and join strings
' https://www.qb64.org/forum/index.php?topic=1073.0

'Combine all elements of in$() into a single string with delimiter$ separating the elements.

Function join$ (in$(), delimiter$)
    Dim result$
    Dim i As Long
    result$ = in$(LBound(in$))
    For i = LBound(in$) + 1 To UBound(in$)
        result$ = result$ + delimiter$ + in$(i)
    Next i
    join$ = result$
End Function ' join$

' /////////////////////////////////////////////////////////////////////////////

Function LeftPadString$ (myString$, toWidth%, padChar$)
    LeftPadString$ = Right$(String$(toWidth%, padChar$) + myString$, toWidth%)
End Function ' LeftPadString$

' /////////////////////////////////////////////////////////////////////////////
' ABS was returning strange values with type LONG
' so I created this which does not.

Function LongABS& (lngValue As Long)
    If Sgn(lngValue) = -1 Then
        LongABS& = 0 - lngValue
    Else
        LongABS& = lngValue
    End If
End Function ' LongABS&

' /////////////////////////////////////////////////////////////////////////////
' iRow% and iCol% are 0-based in this version

Sub PrintAt (iRow%, iCol%, sText$)
    '_PrintString (iCol% * 8, iRow% * 16), sText$
    _PrintString (iCol% * 8, iRow% * 16), sText$
    '_PrintString (iCol%, iRow%), sText$
End Sub ' PrintAt

' /////////////////////////////////////////////////////////////////////////////
' Generate random value between Min and Max.

Function RandomNumber% (Min%, Max%)
    Dim NumSpread%

    ' SET RANDOM SEED
    'Randomize ' Initialize random-number generator.
    Randomize Timer

    ' GET RANDOM # Min%-Max%
    'RandomNumber = Int((Max * Rnd) + Min) ' generate number

    NumSpread% = (Max% - Min%) + 1

    RandomNumber% = Int(Rnd * NumSpread%) + Min% ' GET RANDOM # BETWEEN Max% AND Min%

End Function ' RandomNumber%

' /////////////////////////////////////////////////////////////////////////////

Function RightPadString$ (myString$, toWidth%, padChar$)
    RightPadString$ = Left$(myString$ + String$(toWidth%, padChar$), toWidth%)
End Function ' RightPadString$

' /////////////////////////////////////////////////////////////////////////////
' https://www.qb64.org/forum/index.php?topic=3605.0
' Quote from: SMcNeill on Today at 03:53:48 PM
'
' Sometimes, you guys make things entirely too  complicated.
' There ya go!  Three functions to either round naturally,
' always round down, or always round up, to whatever number of digits you desire.
' EDIT:  Modified to add another option to round scientific,
' since you had it's description included in your example.

' Receives + returns _FLOAT myVar## (-1.18E-4932 to +1.18E+4932)

' =============================================================================
' ROUNDING FUNCTIONS FOR TYPE _FLOAT

Function Round## (num##, digits%)
    Round## = Int(num## * 10 ^ digits% + .5) / 10 ^ digits%
End Function

Function RoundUp## (num##, digits%)
    RoundUp## = _Ceil(num## * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundDown## (num##, digits%)
    RoundDown## = Int(num## * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundScientific## (num##, digits%)
    RoundScientific## = _Round(num## * 10 ^ digits%) / 10 ^ digits%
End Function

' =============================================================================
' ROUNDING FUNCTIONS FOR TYPE DOUBLE

Function RoundDouble# (num#, digits%)
    RoundDouble# = Int(num# * 10 ^ digits% + .5) / 10 ^ digits%
End Function

Function RoundUpDouble# (num#, digits%)
    RoundUpDouble# = _Ceil(num# * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundDownDouble# (num#, digits%)
    RoundDownDouble# = Int(num# * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundScientificDouble# (num#, digits%)
    RoundScientificDouble# = _Round(num# * 10 ^ digits%) / 10 ^ digits%
End Function

' =============================================================================
' ROUNDING FUNCTIONS FOR TYPE SINGLE

Function RoundSingle! (num!, digits%)
    RoundSingle! = Int(num! * 10 ^ digits% + .5) / 10 ^ digits%
End Function

' NOTE: not sure this one works: when digits%=3, it rounds .31 to .32
Function RoundUpSingle! (num!, digits%)
    RoundUpSingle! = _Ceil(num! * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundDownSingle! (num!, digits%)
    RoundDownSingle! = Int(num! * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundScientificSingle! (num!, digits%)
    RoundScientificSingle! = _Round(num! * 10 ^ digits%) / 10 ^ digits%
End Function

' /////////////////////////////////////////////////////////////////////////////

Function SmallestOf3% (i1%, i2%, i3%)
    Dim iMin%
    iMin% = i1%
    If i2% < iMin% Then iMin% = i2%
    If i3% < iMin% Then iMin% = i3%
    SmallestOf3% = iMin%
End Function ' SmallestOf3

' /////////////////////////////////////////////////////////////////////////////

Function SngRoundedToStr$ (sngValue As Single, intNumPlaces As Integer)
    Dim sngNew As Single
    sngNew = RoundSingle!(sngValue, intNumPlaces)
    SngRoundedToStr$ = SngToStr$(sngNew)
End Function ' SngRoundedToStr$

' /////////////////////////////////////////////////////////////////////////////
' Hack function, to be replaced with something better

Function SngToInt% (sngOld As Single)
    Dim sngNew As Single
    Dim sValue As String
    Dim iPos As Integer

    sngNew = RoundSingle!(sngOld, 0)
    'sValue = _Trim$(Str$(sngNew))

    sValue = SngToStr$(sngNew)

    'iPos = InStr(1, sValue, ".")
    'If iPos > 0 Then
    '    SngToInt% = Val(Left$(sValue, iPos - 1))
    'Else
    '    SngToInt% = Val(sValue)
    'End If

    SngToInt% = Val(sValue)
End Function ' SngToInt%

' /////////////////////////////////////////////////////////////////////////////
' Scientific notation - QB64 Wiki
' https://www.qb64.org/wiki/Scientific_notation

' Example: A string function that displays extremely small or large exponential decimal values.

Function SngToStr$ (n!)
    Dim result$: result$ = ""
    Dim value$
    Dim Xpos%
    Dim expo%
    Dim sign$
    Dim valu$
    Dim dot%
    Dim L%
    Dim add$
    Dim min$
    Dim DP$
    Dim n%

    value$ = UCase$(LTrim$(Str$(n!)))
    Xpos% = InStr(value$, "D") + InStr(value$, "E") ' only D or E can be present
    If Xpos% Then
        expo% = Val(Mid$(value$, Xpos% + 1))
        If Val(value$) < 0 Then
            sign$ = "-"
            valu$ = Mid$(value$, 2, Xpos% - 2)
        Else
            valu$ = Mid$(value$, 1, Xpos% - 1)
        End If
        dot% = InStr(valu$, ".")
        L% = Len(valu$)
        If expo% > 0 Then
            add$ = String$(expo% - (L% - dot%), "0")
        End If
        If expo% < 0 Then
            min$ = String$(Abs(expo%) - (dot% - 1), "0")
            DP$ = "."
        End If
        For n% = 1 To L%
            If Mid$(valu$, n%, 1) <> "." Then
                num$ = num$ + Mid$(valu$, n%, 1)
            End If
        Next n%
        result$ = _Trim$(sign$ + DP$ + min$ + num$ + add$)
    Else
        result$ = value$
    End If

    SngToStr$ = result$
End Function ' SngToStr$

' /////////////////////////////////////////////////////////////////////////////
' Split and join strings
' https://www.qb64.org/forum/index.php?topic=1073.0
'
' FROM luke, QB64 Developer
' Date: February 15, 2019, 04:11:07 AM
'
' Given a string of words separated by spaces (or any other character),
' splits it into an array of the words. I've no doubt many people have
' written a version of this over the years and no doubt there's a million
' ways to do it, but I thought I'd put mine here so we have at least one
' version. There's also a join function that does the opposite
' array -> single string.
'
' Code is hopefully reasonably self explanatory with comments and a little demo.
' Note, this is akin to Python/JavaScript split/join, PHP explode/implode.

'Split in$ into pieces, chopping at every occurrence of delimiter$. Multiple consecutive occurrences
'of delimiter$ are treated as a single instance. The chopped pieces are stored in result$().
'
'delimiter$ must be one character long.
'result$() must have been REDIMmed previously.

' Modified to handle multi-character delimiters

Sub split (in$, delimiter$, result$())
    Dim start As Integer
    Dim finish As Integer
    Dim iDelimLen As Integer
    ReDim result$(-1)

    iDelimLen = Len(delimiter$)

    start = 1
    Do
        'While Mid$(in$, start, 1) = delimiter$
        While Mid$(in$, start, iDelimLen) = delimiter$
            'start = start + 1
            start = start + iDelimLen
            If start > Len(in$) Then
                Exit Sub
            End If
        Wend
        finish = InStr(start, in$, delimiter$)
        If finish = 0 Then
            finish = Len(in$) + 1
        End If

        ReDim _Preserve result$(0 To UBound(result$) + 1)

        result$(UBound(result$)) = Mid$(in$, start, finish - start)
        start = finish + 1
    Loop While start <= Len(in$)
End Sub ' split

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END GENERAL PURPOSE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN COLOR FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Function cRed~& ()
    cRed = _RGB32(255, 0, 0)
End Function

Function cOrangeRed~& ()
    cOrangeRed = _RGB32(255, 69, 0)
End Function ' cOrangeRed~&

Function cDarkOrange~& ()
    cDarkOrange = _RGB32(255, 140, 0)
End Function ' cDarkOrange~&

Function cOrange~& ()
    cOrange = _RGB32(255, 165, 0)
End Function ' cOrange~&

Function cGold~& ()
    cGold = _RGB32(255, 215, 0)
End Function ' cGold~&

Function cYellow~& ()
    cYellow = _RGB32(255, 255, 0)
End Function ' cYellow~&

' LONG-HAIRED FRIENDS OF JESUS OR NOT,
' THIS IS NOT YELLOW ENOUGH (TOO CLOSE TO LIME)
' TO USE FOR OUR COMPLEX RAINBOW SEQUENCE:
Function cChartreuse~& ()
    cChartreuse = _RGB32(127, 255, 0)
End Function ' cChartreuse~&

' WE SUBSTITUTE THIS CSS3 COLOR FOR INBETWEEN LIME AND YELLOW:
Function cOliveDrab1~& ()
    cOliveDrab1 = _RGB32(192, 255, 62)
End Function ' cOliveDrab1~&

Function cLime~& ()
    cLime = _RGB32(0, 255, 0)
End Function ' cLime~&

Function cMediumSpringGreen~& ()
    cMediumSpringGreen = _RGB32(0, 250, 154)
End Function ' cMediumSpringGreen~&

' ADDED THIS FOR THE GAUGE COLOR:
Function cSpringGreen~& ()
    cSpringGreen = _RGB32(0, 255, 160)
End Function ' cSpringGreen~&

Function cCyan~& ()
    cCyan = _RGB32(0, 255, 255)
End Function ' cCyan~&

Function cDeepSkyBlue~& ()
    cDeepSkyBlue = _RGB32(0, 191, 255)
End Function ' cDeepSkyBlue~&

Function cDodgerBlue~& ()
    cDodgerBlue = _RGB32(30, 144, 255)
End Function ' cDodgerBlue~&

Function cSeaBlue~& ()
    cSeaBlue = _RGB32(0, 64, 255)
End Function ' cSeaBlue~&

Function cBlue~& ()
    cBlue = _RGB32(0, 0, 255)
End Function ' cBlue~&

Function cBluePurple~& ()
    cBluePurple = _RGB32(64, 0, 255)
End Function ' cBluePurple~&

Function cDeepPurple~& ()
    cDeepPurple = _RGB32(96, 0, 255)
End Function ' cDeepPurple~&

Function cPurple~& ()
    cPurple = _RGB32(128, 0, 255)
End Function ' cPurple~&

Function cPurpleRed~& ()
    cPurpleRed = _RGB32(128, 0, 192)
End Function ' cPurpleRed~&

Function cDarkRed~& ()
    cDarkRed = _RGB32(160, 0, 64)
End Function ' cDarkRed~&

Function cBrickRed~& ()
    cBrickRed = _RGB32(192, 0, 32)
End Function ' cBrickRed~&

Function cDarkGreen~& ()
    cDarkGreen = _RGB32(0, 100, 0)
End Function ' cDarkGreen~&

Function cGreen~& ()
    cGreen = _RGB32(0, 128, 0)
End Function ' cGreen~&

Function cOliveDrab~& ()
    cOliveDrab = _RGB32(107, 142, 35)
End Function ' cOliveDrab~&

Function cLightPink~& ()
    cLightPink = _RGB32(255, 182, 193)
End Function ' cLightPink~&

Function cHotPink~& ()
    cHotPink = _RGB32(255, 105, 180)
End Function ' cHotPink~&

Function cDeepPink~& ()
    cDeepPink = _RGB32(255, 20, 147)
End Function ' cDeepPink~&

Function cMagenta~& ()
    cMagenta = _RGB32(255, 0, 255)
End Function ' cMagenta~&

Function cBlack~& ()
    cBlack = _RGB32(0, 0, 0)
End Function ' cBlack~&

Function cDimGray~& ()
    cDimGray = _RGB32(105, 105, 105)
End Function ' cDimGray~&

Function cGray~& ()
    cGray = _RGB32(128, 128, 128)
End Function ' cGray~&

Function cDarkGray~& ()
    cDarkGray = _RGB32(169, 169, 169)
End Function ' cDarkGray~&

Function cSilver~& ()
    cSilver = _RGB32(192, 192, 192)
End Function ' cSilver~&

Function cLightGray~& ()
    cLightGray = _RGB32(211, 211, 211)
End Function ' cLightGray~&

Function cGainsboro~& ()
    cGainsboro = _RGB32(220, 220, 220)
End Function ' cGainsboro~&

Function cWhiteSmoke~& ()
    cWhiteSmoke = _RGB32(245, 245, 245)
End Function ' cWhiteSmoke~&

Function cWhite~& ()
    cWhite = _RGB32(255, 255, 255)
    'cWhite = _RGB32(254, 254, 254)
End Function ' cWhite~&

Function cDarkBrown~& ()
    cDarkBrown = _RGB32(128, 64, 0)
End Function ' cDarkBrown~&

Function cLightBrown~& ()
    cLightBrown = _RGB32(196, 96, 0)
End Function ' cLightBrown~&

Function cKhaki~& ()
    cKhaki = _RGB32(240, 230, 140)
End Function ' cKhaki~&

Function cEmpty~& ()
    'cEmpty~& = -1
    cEmpty = _RGB32(0, 0, 0, 0)
End Function ' cEmpty~&

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END COLOR FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ################################################################################################################################################################
' BEGIN KEYBOARD CODE FUNCTIONS
' NOTE: ALL CODES ARE FOR _BUTTON, EXCEPT:
' cF10 (_KEYDOWN)
' cAltLeft (_KEYHIT)
' cAltRight (_KEYHIT)
' cPrintScreen (_KEYHIT) <- may slow down pc?
' cPauseBreak (_KEYHIT) <- may not work?
' ################################################################################################################################################################

Function KeyCode_Escape% ()
    KeyCode_Escape% = 2
End Function

Function KeyCode_F1% ()
    KeyCode_F1% = 60
End Function

Function KeyCode_F2% ()
    KeyCode_F2% = 61
End Function

Function KeyCode_F3% ()
    KeyCode_F3% = 62
End Function

Function KeyCode_F4% ()
    KeyCode_F4% = 63
End Function

Function KeyCode_F5% ()
    KeyCode_F5% = 64
End Function

Function KeyCode_F6% ()
    KeyCode_F6% = 65
End Function

Function KeyCode_F7% ()
    KeyCode_F7% = 66
End Function

Function KeyCode_F8% ()
    KeyCode_F8% = 67
End Function

Function KeyCode_F9% ()
    KeyCode_F9% = 68
End Function

'_KEYDOWN CODE, NOT _BUTTON CODE
Function KeyCode_F10% ()
    KeyCode_F10% = 17408
End Function

Function KeyCode_F11% ()
    KeyCode_F11% = 88
End Function

Function KeyCode_F12% ()
    KeyCode_F12% = 89
End Function

'_KEYHIT CODE, NOT _BUTTON CODE
Function KeyCode_PrintScreen% ()
    KeyCode_PrintScreen% = -44
End Function

Function KeyCode_ScrollLock% ()
    KeyCode_ScrollLock% = 71
End Function

'_KEYHIT CODE, NOT _BUTTON CODE
Function KeyCode_PauseBreak% ()
    KeyCode_PauseBreak% = 31053
End Function

Function KeyCode_Tilde% ()
    KeyCode_Tilde% = 42
End Function

Function KeyCode_1% ()
    KeyCode_1% = 3
End Function

Function KeyCode_2% ()
    KeyCode_2% = 4
End Function

Function KeyCode_3% ()
    KeyCode_3% = 5
End Function

Function KeyCode_4% ()
    KeyCode_4% = 6
End Function

Function KeyCode_5% ()
    KeyCode_5% = 7
End Function

Function KeyCode_6% ()
    KeyCode_6% = 8
End Function

Function KeyCode_7% ()
    KeyCode_7% = 9
End Function

Function KeyCode_8% ()
    KeyCode_8% = 10
End Function

Function KeyCode_9% ()
    KeyCode_9% = 11
End Function

Function KeyCode_0% ()
    KeyCode_0% = 12
End Function

Function KeyCode_Minus% ()
    KeyCode_Minus% = 13
End Function

Function KeyCode_Equal% ()
    KeyCode_Equal% = 14
End Function

Function KeyCode_BkSp% ()
    KeyCode_BkSp% = 15
End Function

Function KeyCode_Ins% ()
    KeyCode_Ins% = 339
End Function

Function KeyCode_Home% ()
    KeyCode_Home% = 328
End Function

Function KeyCode_PgUp% ()
    KeyCode_PgUp% = 330
End Function

Function KeyCode_Del% ()
    KeyCode_Del% = 340
End Function

Function KeyCode_End% ()
    KeyCode_End% = 336
End Function

Function KeyCode_PgDn% ()
    KeyCode_PgDn% = 338
End Function

Function KeyCode_NumLock% ()
    KeyCode_NumLock% = 326
End Function

Function KeyCode_KeypadSlash% ()
    KeyCode_KeypadSlash% = 310
End Function

Function KeyCode_KeypadMultiply% ()
    KeyCode_KeypadMultiply% = 56
End Function

Function KeyCode_KeypadMinus% ()
    KeyCode_KeypadMinus% = 75
End Function

Function KeyCode_Keypad7Home% ()
    KeyCode_Keypad7Home% = 72
End Function

Function KeyCode_Keypad8Up% ()
    KeyCode_Keypad8Up% = 73
End Function

Function KeyCode_Keypad9PgUp% ()
    KeyCode_Keypad9PgUp% = 74
End Function

Function KeyCode_KeypadPlus% ()
    KeyCode_KeypadPlus% = 79
End Function

Function KeyCode_Keypad4Left% ()
    KeyCode_Keypad4Left% = 76
End Function

Function KeyCode_Keypad5% ()
    KeyCode_Keypad5% = 77
End Function

Function KeyCode_Keypad6Right% ()
    KeyCode_Keypad6Right% = 78
End Function

Function KeyCode_Keypad1End% ()
    KeyCode_Keypad1End% = 80
End Function

Function KeyCode_Keypad2Down% ()
    KeyCode_Keypad2Down% = 81
End Function

Function KeyCode_Keypad3PgDn% ()
    KeyCode_Keypad3PgDn% = 82
End Function

Function KeyCode_KeypadEnter% ()
    KeyCode_KeypadEnter% = 285
End Function

Function KeyCode_Keypad0Ins% ()
    KeyCode_Keypad0Ins% = 83
End Function

Function KeyCode_KeypadPeriodDel% ()
    KeyCode_KeypadPeriodDel% = 84
End Function

Function KeyCode_Tab% ()
    KeyCode_Tab% = 16
End Function

Function KeyCode_Q% ()
    KeyCode_Q% = 17
End Function

Function KeyCode_W% ()
    KeyCode_W% = 18
End Function

Function KeyCode_E% ()
    KeyCode_E% = 19
End Function

Function KeyCode_R% ()
    KeyCode_R% = 20
End Function

Function KeyCode_T% ()
    KeyCode_T% = 21
End Function

Function KeyCode_Y% ()
    KeyCode_Y% = 22
End Function

Function KeyCode_U% ()
    KeyCode_U% = 23
End Function

Function KeyCode_I% ()
    KeyCode_I% = 24
End Function

Function KeyCode_O% ()
    KeyCode_O% = 25
End Function

Function KeyCode_P% ()
    KeyCode_P% = 26
End Function

Function KeyCode_BracketLeft% ()
    KeyCode_BracketLeft% = 27
End Function

Function KeyCode_BracketRight% ()
    KeyCode_BracketRight% = 28
End Function

Function KeyCode_Backslash% ()
    KeyCode_Backslash% = 44
End Function

Function KeyCode_CapsLock% ()
    KeyCode_CapsLock% = 59
End Function

Function KeyCode_A% ()
    KeyCode_A% = 31
End Function

Function KeyCode_S% ()
    KeyCode_S% = 32
End Function

Function KeyCode_D% ()
    KeyCode_D% = 33
End Function

Function KeyCode_F% ()
    KeyCode_F% = 34
End Function

Function KeyCode_G% ()
    KeyCode_G% = 35
End Function

Function KeyCode_H% ()
    KeyCode_H% = 36
End Function

Function KeyCode_J% ()
    KeyCode_J% = 37
End Function

Function KeyCode_K% ()
    KeyCode_K% = 38
End Function

Function KeyCode_L% ()
    KeyCode_L% = 39
End Function

Function KeyCode_Semicolon% ()
    KeyCode_Semicolon% = 40
End Function

Function KeyCode_Apostrophe% ()
    KeyCode_Apostrophe% = 41
End Function

Function KeyCode_Enter% ()
    KeyCode_Enter% = 29
End Function

Function KeyCode_ShiftLeft% ()
    KeyCode_ShiftLeft% = 43
End Function

Function KeyCode_Z% ()
    KeyCode_Z% = 45
End Function

Function KeyCode_X% ()
    KeyCode_X% = 46
End Function

Function KeyCode_C% ()
    KeyCode_C% = 47
End Function

Function KeyCode_V% ()
    KeyCode_V% = 48
End Function

Function KeyCode_B% ()
    KeyCode_B% = 49
End Function

Function KeyCode_N% ()
    KeyCode_N% = 50
End Function

Function KeyCode_M% ()
    KeyCode_M% = 51
End Function

Function KeyCode_Comma% ()
    KeyCode_Comma% = 52
End Function

Function KeyCode_Period% ()
    KeyCode_Period% = 53
End Function

Function KeyCode_Slash% ()
    KeyCode_Slash% = 54
End Function

Function KeyCode_ShiftRight% ()
    KeyCode_ShiftRight% = 55
End Function

Function KeyCode_Up% ()
    KeyCode_Up% = 329
End Function

Function KeyCode_Left% ()
    KeyCode_Left% = 332
End Function

Function KeyCode_Down% ()
    KeyCode_Down% = 337
End Function

Function KeyCode_Right% ()
    KeyCode_Right% = 334
End Function

Function KeyCode_CtrlLeft% ()
    KeyCode_CtrlLeft% = 30
End Function

Function KeyCode_WinLeft% ()
    KeyCode_WinLeft% = 348
End Function

' _KEYHIT CODE NOT _BUTTON CODE
Function KeyCode_AltLeft% ()
    KeyCode_AltLeft% = -30764
End Function

Function KeyCode_Spacebar% ()
    KeyCode_Spacebar% = 58
End Function

' _KEYHIT CODE NOT _BUTTON CODE
Function KeyCode_AltRight% ()
    KeyCode_AltRight% = -30765
End Function

Function KeyCode_WinRight% ()
    KeyCode_WinRight% = 349
End Function

Function KeyCode_Menu% ()
    KeyCode_Menu% = 350
End Function

Function KeyCode_CtrlRight% ()
    KeyCode_CtrlRight% = 286
End Function

' ################################################################################################################################################################
' END KEYBOARD CODE FUNCTIONS
' ################################################################################################################################################################

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN DEBUGGING ROUTINES #DEBUGGING
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub DebugPrint (MyString As String)
    If m_bDebug = TRUE Then
        '_Echo MyString

        ReDim arrLines(-1) As String
        Dim iLoop As Integer
        split MyString, Chr$(13), arrLines()
        For iLoop = LBound(arrLines) To UBound(arrLines)
            _Echo arrLines(iLoop)
        Next iLoop
    End If
End Sub ' DebugPrint

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END DEBUGGING ROUTINES @DEBUGGING
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ################################################################################################################################################################
' #REFERENCE

' =============================================================================
' SOME USEFUL STUFF FOR REFERENCE:

' Type Name               Type suffix symbol   Minimum value                  Maximum value                Size in Bytes
' ---------------------   ------------------   ----------------------------   --------------------------   -------------
' _BIT                    `                    -1                             0                            1/8
' _BIT * n                `n                   -128                           127                          n/8
' _UNSIGNED _BIT          ~`                   0                              1                            1/8
' _BYTE                   %%                   -128                           127                          1
' _UNSIGNED _BYTE         ~%%                  0                              255                          1
' INTEGER                 %                    -32,768                        32,767                       2
' _UNSIGNED INTEGER       ~%                   0                              65,535                       2
' LONG                    &                    -2,147,483,648                 2,147,483,647                4
' _UNSIGNED LONG          ~&                   0                              4,294,967,295                4
' _INTEGER64              &&                   -9,223,372,036,854,775,808     9,223,372,036,854,775,807    8
' _UNSIGNED _INTEGER64    ~&&                  0                              18,446,744,073,709,551,615   8
' SINGLE                  ! or none            -2.802597E-45                  +3.402823E+38                4
' DOUBLE                  #                    -4.490656458412465E-324        +1.797693134862310E+308      8
' _FLOAT                  ##                   -1.18E-4932                    +1.18E+4932                  32(10 used)
' _OFFSET                 %&                   -9,223,372,036,854,775,808     9,223,372,036,854,775,807    Use LEN
' _UNSIGNED _OFFSET       ~%&                  0                              18,446,744,073,709,551,615   Use LEN
' _MEM                    none                 combined memory variable type  N/A                          Use LEN

' div: int1% = num1% \ den1%
' mod: rem1% = num1% MOD den1%

'#END

Print this item

  What bone-head thing did I miss this time?
Posted by: Pete - 10-28-2022, 05:11 PM - Forum: Help Me! - Replies (12)

Windows API for set window active should register a number in this little test routine, but it doesn't. I threw in a couple of other API functions that register just fine. Anyone know what I missed here?

Code: (Select All)
DECLARE DYNAMIC LIBRARY "user32"
    FUNCTION SetActiveWindow& (BYVAL hwnd AS LONG)
    FUNCTION GetWindow& (BYVAL hwnd AS LONG, BYVAL nCmdShow AS LONG)
    FUNCTION FindWindowA& (BYVAL ClassName AS LONG, WindowName$) 'handle by title
END DECLARE

title$ = "Set Window Active Test"
_TITLE (title$)
_DELAY .1

DO
    hwnd& = FindWindowA(0, title$)
LOOP UNTIL hwnd&

DO
    _LIMIT 10
    c& = GetWindow(hwnd&, 1) ' Just put this in to show it does register.
    a& = SetActiveWindow(hwnd&) ' This one should registere, but doesn't. <==============
    PRINT "This should be non-zero:"; a&; " These are fine:"; c&, hwnd&
    SLEEP 4
    IF LEN(INKEY$) THEN END
LOOP

Pete

Print this item

  ClipScribble
Posted by: James D Jarvis - 10-28-2022, 03:51 PM - Forum: Works in Progress - Replies (2)

A paint program with control panels in sperate windows. This uses the clipboard method to communicate between the different programs.

This piece of code is the color picker. The control has a simple slide bar for the red, green, and blue channels.
This will need to be saved and compiled as colorpickmix to be called by the clipscribble main program. 

compile the main program and the control panels. Keep all the exe files in the same folder and it's a multi-window program in QB64.  If you close a control panel by accident just manually open it again, it'll work fine.

colorpickmix

Code: (Select All)
Screen _NewImage(240, 160, 32)
_ScreenMove 600, 50
_Title "colorpickmix"
'a color mixer that sends it's out put to the clipboard
rr = 127
gg = 127
bb = 127
rx = rr / 2 + 50
gx = gg / 2 + 50
bx = bb / 2 + 50
_PrintMode _KeepBackground
Line (10, 10)-(229, 40), _RGB32(rr, gg, bb), BF
_PrintString (1, 60), "[<]": _PrintString (215, 60), "[>]"
_PrintString (1, 90), "[<]": _PrintString (215, 90), "[>]"
_PrintString (1, 120), "[<]": _PrintString (215, 120), "[>]"
Do
    _Limit 100
    Do While _MouseInput 'mouse status changes only
        x = _MouseX
        y = _MouseY
        If _MouseButton(1) Then
            If y >= 59 And y <= 77 Then
                If x <= rx + 8 Then rr = rr - 1 Else rr = rr + 1
                If rr < 1 Then rr = 0
                If rr > 255 Then rr = 255
            End If
            If y >= 89 And y <= 107 Then
                If x <= gx + 8 Then gg = gg - 1 Else gg = gg + 1
                If gg < 1 Then gg = 0
                If gg > 255 Then gg = 255

            End If
            If y >= 119 And y <= 137 Then
                If x <= bx + 8 Then bb = bb - 1 Else bb = bb + 1
                If bb < 1 Then bb = 0
                If bb > 255 Then bb = 255
            End If
            rt$ = packnum$(rr)
            gt$ = packnum$(gg)
            bt$ = packnum$(bb)
            pp$ = "CMX" + rt$ + gt$ + bt$
            _Clipboard$ = pp$
        End If
    Loop
    rx = rr / 2 + 50
    gx = gg / 2 + 50
    bx = bb / 2 + 50
    Line (50, 60)-(202, 76), _RGB32(rr, 0, 0), BF
    _PrintString (rx, 60), _Trim$(Str$(rr))
    Line (50, 90)-(202, 106), _RGB32(0, gg, 0), BF
    _PrintString (gx, 90), _Trim$(Str$(gg))
    Line (50, 120)-(202, 136), _RGB32(0, 0, bb), BF
    _PrintString (bx, 120), _Trim$(Str$(bb))
    Line (10, 10)-(229, 40), _RGB32(rr, gg, bb), BF

    kk$ = InKey$
    inx$ = _Clipboard$
    If inx$ = "QUITCOLORMIX" Then kk$ = Chr$(27)
Loop Until kk$ = Chr$(27)
_Clipboard$ = "colorpickmix quit"
System



Function packnum$ (num)
    pad$ = "000"
    nn$ = _Trim$(Str$(num))
    Select Case Len(nn$)
        Case 1
            Mid$(pad$, 3, 1) = nn$
        Case 2
            Mid$(pad$, 2, 2) = nn$
        Case 3
            pad$ = nn$
    End Select
    packnum$ = pad$
End Function

Print this item

  MazeRogue
Posted by: James D Jarvis - 10-28-2022, 12:12 AM - Forum: Works in Progress - Replies (6)

A micro rogue-like game. 
Navigate with arrow keys.
Collect gems, health potions, and power runes.
Monsters are just window dressing for now.

Code: (Select All)
'mazerogue
' a micro rogue by James D. Jarvis October 2022
'navigate with arrow keys
Screen _NewImage(81, 30, 0)
Randomize Timer
Dim T$
Dim crn$(4)
_ControlChr Off
_Scrolllock Off
Dim mz(0 To 80, 1 To 25) As String
Dim crnr(4, 2), loot(3), monst(3)
loot(1) = 4: loot(2) = 3: loot(3) = 15
monst(1) = 132: monst(2) = 42: monst(3) = 111
crnr(1, 1) = 1: crnr(1, 2) = 1
crnr(2, 1) = 79: crnr(2, 2) = 1
crnr(3, 1) = 1: crnr(3, 2) = 25
crnr(4, 1) = 79: crnr(4, 2) = 25
maxx = 80: maxy = 25: mlevel = 0
herox = Int(_Width / 2): heroy = Int(_Height / 2)
php = 10: ppow = 0: pgems = 0
newlevel:
mlevel = mlevel + 1
mlabel$ = "MazeRogue Level " + Str$(mlevel)
_Title mlabel$
For y = 1 To maxy
    For x = 0 To maxx
        mz(x, y) = Chr$(219)
    Next
Next
nx = 3: ny = 3: done = 0
Do While done = 0
    _Limit 1000
    For reps = 0 To 99
        ox = nx: oy = ny
        Rem move in random direction
        Select Case Int(Rnd * 4)
            Case 0
                If nx + 2 <= maxx Then nx = nx + 2
            Case 1
                If ny + 2 <= maxy Then ny = ny + 2
            Case 2
                If nx - 2 > 0 Then nx = nx - 2
            Case 3
                If ny - 2 > 0 Then ny = ny - 2
        End Select
        If mz(nx, ny) = Chr$(219) Then
            mz(nx, ny) = ".": If 1 + Int(Rnd * 50) = 1 Then mz(nx, ny) = Chr$(loot(1 + Int(Rnd * 3)))
            If mz(nx, ny) = "." And 1 + Int(Rnd * 50) <= mlevel Then mz(nx, ny) = Chr$(monst(1 + Int(Rnd * 3)))
            mz(Int((nx + ox) / 2), ((ny + oy) / 2)) = "."
        End If
    Next
    done = 1
    For x = 1 To maxx - 1 Step 2
        For y = 1 To maxy - 1 Step 2
            If mz(x, y) = Chr$(219) Then done = 0
        Next y
    Next x
Loop
cr = 1 + Int(Rnd * 4) 'set a corner for the exit
If herox = crnr(cr, 1) And heroy = crnr(cr, 2) Then cr = 5 - cr
mz(crnr(cr, 1), crnr(cr, 2)) = Chr$(239)
T$ = "" 'load the maze into t$
For y = 1 To 25: For x = 0 To 80: T$ = T$ + mz$(x, y): Next x: Next y
ll$ = String$(81, 219) 'top and botton maze display edges becasue I didn't want to fix the maze generator to account for top and bottom edge
lastX = herox: lasty = heroy
Do 'game play loop
    _Limit 20
    Mid$(T$, (heroy) * 81 + herox - 81) = Chr$(1)
    _PrintString (1, 1), ll$: _PrintString (1, 27), ll$: _PrintString (1, 2), T$
    _PrintString (1, 28), String$(80, " ")
    pcc$ = "Hit Points: " + Str$(php) + "  Power: " + Str$(ppow) + "   Gems: " + Str$(pgems)
    _PrintString (3, 28), pcc$
    If _KeyDown(19200) Then herox = herox - 1
    If _KeyDown(19712) Then herox = herox + 1
    If _KeyDown(18432) Then heroy = heroy - 1
    If _KeyDown(20480) Then heroy = heroy + 1
    If herox < 1 Then herox = 1
    If herox > _Width Then herox = _Width
    If heroy < 1 Then heroy = 1
    If heroy > 25 Then heroy = 25
    Mid$(T$, (lasty) * 81 + lastX - 81) = "."
    If Mid$(T$, (heroy * 81 + herox - 81), 1) = Chr$(219) Then
        herox = lastX: heroy = lasty
    End If
    For lp = 1 To 3
        If Mid$(T$, (heroy * 81 + herox - 81), 1) = Chr$(loot(lp)) Then
            Select Case lp
                Case 1
                    pgems = pgems + 1
                Case 2
                    php = php + 3
                Case 3
                    ppow = ppow + 2
            End Select
        End If
    Next lp
    If Mid$(T$, (heroy * 81 + herox - 81), 1) = Chr$(239) Then
        Beep: Cls: Print: Print "Continue to Next Level ?": Print: Input "Yes or No", ask$
        If Left$(UCase$(ask$), 1) = "N" Then
            heroy = lasty: herox = lastX
        Else
            Cls: GoTo newlevel
        End If
    End If

    lastX = herox: lasty = heroy
    k$ = InKey$
Loop Until k$ = Chr$(27)
System

Print this item

  simple 2D vector graphics
Posted by: madscijr - 10-27-2022, 07:45 PM - Forum: Works in Progress - Replies (18)

I've been wanting to make a multiplayer Spacewar! type game, maybe with elements of Asteroids and other similar games, and what better way to learn than to look under the hood of a similar program and modify it? So I studied Terry Ritchie's "Widescreen Asteroids", which is very nicely done, but it turned out to be a lot more complicated than I have time and brain power for. However, Terry's game uses a simple method of defining vector objects line by line, so using that as a starting point, I have the beginning of a game. 

So far all it does is draw some of the objects from Widescreen Asteroids and move them around the screen. Next is to figure out how to rotate them and translate the rotation angle into dx, dy to move in a given direction, and then figure out how to do collisions. 

Anyway maybe this will help someone interested in learning about this... enjoy

Code: (Select All)
_Title "Simple vector graphics v0.09 mostly by madscijr" ' display in the Window's title bar

' Simple test of vector graphics,
' borrowed graphics objects and format from Widescreen Asteroids by Terry Ritchie.

' TO DO:
' * rotate objects
' * translate rotation angle into dx,dy to move in direction of angle
' * speed up?
' * detect collisions

' BOOLEAN CONSTANTS
Const FALSE = 0
Const TRUE = Not FALSE

' HOLDS POSITION AND VELOCITY OF ALL OBJECTS
Type ObjectType
    x As Integer
    y As Integer
    dx As Integer
    dy As Integer
    cx As Integer
    cy As Integer
    IsEnabled As Integer
End Type ' ObjectType

' HOLDS DEFINITION OF ALL OBJECTS
Type CoordType
    x1 As Integer
    y1 As Integer
    x2 As Integer
    y2 As Integer
    color As _Unsigned Long
    IsLast As Integer
End Type ' CoordType

' ENABLE / DISABLE DEBUG CONSOLE
Dim Shared m_bDebug As Integer: m_bDebug = TRUE

' BASIC PROGRAM METADATA
Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)

' OBJECT VARIABLES
ReDim Shared m_arrObject(1 To 8) As ObjectType
ReDim Shared m_arrLines(1 To 8, 1 To 32) As CoordType

' ****************************************************************************************************************************************************************
' ACTIVATE DEBUGGING WINDOW
If m_bDebug = TRUE Then
    $Console
    _Delay 4
    _Console On
    _Echo "Started " + m_ProgramName$
    _Echo "Debugging on..."
End If
' ****************************************************************************************************************************************************************

' =============================================================================
' START THE MAIN ROUTINE
main

' =============================================================================
' FINISH
Screen 0
Print m_ProgramName$ + " finished."
Input "Press <ENTER> to continue", in$

' ****************************************************************************************************************************************************************
' DEACTIVATE DEBUGGING WINDOW
If m_bDebug = TRUE Then
    _Console Off
End If
' ****************************************************************************************************************************************************************

System ' return control to the operating system
End

' /////////////////////////////////////////////////////////////////////////////

Sub main
    ' LOCAL VARIABLES
    Dim iFPS As Integer: iFPS = 120
    Dim iLoop As Integer
    Dim iObject As Integer
    Dim iLine As Integer
    Dim imgBack&
    Dim imgMiddle&
    Dim imgFront&
    Dim iWhich As Integer: iWhich = 1
    Dim bQuit As Integer: bQuit = FALSE
    Dim in$
    Dim sError As String: sError = ""
    Dim iX As Integer
    Dim iY As Integer
    Dim sKey As String
    Dim iMinX As Integer: iMinX = 0
    Dim iMaxX As Integer: iMaxX = 800
    Dim iMinY As Integer: iMinY = 0
    Dim iMaxY As Integer: iMaxY = 640

    ' =============================================================================
    ' INITIALIZE
    Screen _NewImage(800, 640, 32) ' 100 text columns x 40 text rows
    'imgBack& = _NewImage(800, 640, 32) ' background
    'imgMiddle& = _NewImage(800, 640, 32) ' other stuff
    'imgFront& = _NewImage(800, 640, 32) ' foreground
   
    ' =============================================================================
    ' START NEW GAME
    Do
        _KeyClear
       
        ' CONFIGURE PRINTING FOR _PrintString
        _PrintMode _FillBackground
        '_PrintMode _KEEPBACKGROUND
       
        ' INIT VARS
        sKey = ""
        iX = 0: iY = 0
        For iObject = LBound(m_arrObject) To UBound(m_arrObject)
            m_arrObject(iObject).IsEnabled = FALSE
            m_arrObject(iObject).x = iX
            m_arrObject(iObject).y = iY
            m_arrObject(iObject).dx = RandomNumber%(-5, 5)
            m_arrObject(iObject).dy = RandomNumber%(-5, 5)
            m_arrObject(iObject).cx = 0
            m_arrObject(iObject).cy = 0
            iX = iX + 200
            If iX > 800 Then
                iX = 0
                iY = iY + 200
                If iY > 640 Then
                    iY = 0
                End If
            End If
        Next iObject
        InitVectorObjects
       
        ' MAIN LOOP
        While TRUE = TRUE
            ' REDRAW BACKGROUND LAYERS
            DrawLayers imgBack&, imgMiddle&, imgFront&
            '_Dest 0: Cls , cBlack
           
            ' SHOW TEXT
            DrawText sKey, iWhich
           
            ' MOVE + DRAW ENABLED OBJECTS
            For iObject = LBound(m_arrObject) To UBound(m_arrObject)
                ' Only enabled objects
                If m_arrObject(iObject).IsEnabled = TRUE Then
                   
                    ' Move along X axis
                    m_arrObject(iObject).cx = m_arrObject(iObject).cx + 1
                    If m_arrObject(iObject).cx > (10 - Abs(m_arrObject(iObject).dx)) Then
                        m_arrObject(iObject).cx = 0
                        If m_arrObject(iObject).dx < 0 Then
                            m_arrObject(iObject).x = m_arrObject(iObject).x - 1
                            If m_arrObject(iObject).x < iMinX Then
                                m_arrObject(iObject).x = iMaxX
                            End If
                        ElseIf m_arrObject(iObject).dx > 0 Then
                            m_arrObject(iObject).x = m_arrObject(iObject).x + 1
                            If m_arrObject(iObject).x > iMaxX Then
                                m_arrObject(iObject).x = iMinX
                            End If
                        End If
                    End If

                    ' Move along Y axis
                    m_arrObject(iObject).cy = m_arrObject(iObject).cy + 1
                    If m_arrObject(iObject).cy > (10 - Abs(m_arrObject(iObject).dy)) Then
                        m_arrObject(iObject).cy = 0
                        If m_arrObject(iObject).dy < 0 Then
                            m_arrObject(iObject).y = m_arrObject(iObject).y - 1
                            If m_arrObject(iObject).y < iMinY Then
                                m_arrObject(iObject).y = iMaxY
                            End If
                        ElseIf m_arrObject(iObject).dy > 0 Then
                            m_arrObject(iObject).y = m_arrObject(iObject).y + 1
                            If m_arrObject(iObject).y > iMaxY Then
                                m_arrObject(iObject).y = iMinY
                            End If
                        End If
                    End If

                    ' Draw object's line segments
                    For iLine = LBound(m_arrLines, 2) To UBound(m_arrLines, 2)
                        'Line (x1%, y1%)-(x2%, y2%), arrColor(arrStars(iLoop).ColorIndex), BF
                        Line _
                            (m_arrObject(iObject).x + m_arrLines(iObject, iLine).x1, _
                            m_arrObject(iObject).y + m_arrLines(iObject, iLine).y1) _
                            - _
                            (m_arrObject(iObject).x + m_arrLines(iObject, iLine).x2, _
                            m_arrObject(iObject).y + m_arrLines(iObject, iLine).y2) _
                            , _
                            m_arrLines(iObject, iLine).color ' , BF
                        If m_arrLines(iObject, iLine).IsLast = TRUE Then
                            Exit For
                        End If
                    Next iLine

                End If
            Next iObject

            ' UPDATE THE SCREEN
            _Display

            ' PROCESS INPUT
            While _DeviceInput(1): Wend ' clear and update the keyboard buffer
            sKey = ""

            ' QUIT?
            If _Button(KeyCode_Escape%) Then
                bQuit = TRUE
                Exit While
            End If
           
            ' OTHER INPUT 1-6 SELECTS WHICH OBJECT TO CHANGE
            If _Button(KeyCode_1%) Then
                sKey = sKey + "1,"
                iWhich = 1
            ElseIf _Button(KeyCode_2%) Then
                sKey = sKey + "2,"
                iWhich = 2
            ElseIf _Button(KeyCode_3%) Then
                sKey = sKey + "3,"
                iWhich = 3
            ElseIf _Button(KeyCode_4%) Then
                sKey = sKey + "4,"
                iWhich = 4
            ElseIf _Button(KeyCode_5%) Then
                sKey = sKey + "5,"
                iWhich = 5
            ElseIf _Button(KeyCode_6%) Then
                sKey = sKey + "6,"
                iWhich = 6
            End If
           
            ' GET DIRECTION
            If _Button(KeyCode_Left%) Then
                sKey = sKey + "LEFT,"
                m_arrObject(iWhich).dx = m_arrObject(iWhich).dx - 1
                If m_arrObject(iWhich).dx < -10 Then m_arrObject(iWhich).dx = -10
            ElseIf _Button(KeyCode_Right%) Then
                sKey = sKey + "RIGHT,"
                m_arrObject(iWhich).dx = m_arrObject(iWhich).dx + 1
                If m_arrObject(iWhich).dx > 10 Then m_arrObject(iWhich).dx = 10
            ElseIf _Button(KeyCode_Up%) Then
                sKey = sKey + "UP,"
                m_arrObject(iWhich).dy = m_arrObject(iWhich).dy - 1
                If m_arrObject(iWhich).dy < -10 Then m_arrObject(iWhich).dy = -10
            ElseIf _Button(KeyCode_Down%) Then
                sKey = sKey + "DOWN,"
                m_arrObject(iWhich).dy = m_arrObject(iWhich).dy + 1
                If m_arrObject(iWhich).dy > 10 Then m_arrObject(iWhich).dy = 10
            End If
           
            ' CLEAR KEYBOARD BUFFER
            _KeyClear
           
            ' CONTROL GAME SPEED
            _Limit iFPS
        Wend
       
        ' UPDATE THE SCREEN
        _Display
       
        ' CLEAR KEYBOARD BUFFER
        _KeyClear: _Delay 2
       
        ' PLAY ANOTHER ROUND OR QUIT?
        If bQuit = FALSE Then
            If bExit = FALSE Then Sleep
            Color cWhite, cBlack
        Else
            Exit Do
        End If
    Loop
   
    ' RETURN TO AUTODISPLAY
    _AutoDisplay
   
End Sub ' main

' /////////////////////////////////////////////////////////////////////////////
' VECTOR OBJECT DEFINITIONS
Sub InitVectorObjects
    Dim iLoop As Integer
    Dim iObject As Integer
    Dim iLine As Integer
   
    Dim x1 As Integer
    Dim y1 As Integer
    Dim x2 As Integer
    Dim y2 As Integer
    Dim r1 As Integer
    Dim g1 As Integer
    Dim b1 As Integer
   
    iObject = 1
    iLine = 1
   
    Restore VectorData
    For iLoop = 1 To 1024
        Read x1
        Read y1
        Read x2
        Read y2
        Read r1
        Read g1
        Read b1 ' -255 means no more data, -254 means last set for this object
       
        If b1 = -255 Then
            m_arrLines(iObject, iLine).IsLast = TRUE
            m_arrObject(iObject).IsEnabled = TRUE
            Exit For
        ElseIf b1 = -254 Then
            m_arrLines(iObject, iLine).IsLast = TRUE
            m_arrObject(iObject).IsEnabled = TRUE
            iObject = iObject + 1
            iLine = 1
            If iObject > UBound(m_arrLines, 1) Then Exit For
        Else
            m_arrLines(iObject, iLine).x1 = x1
            m_arrLines(iObject, iLine).y1 = y1
            m_arrLines(iObject, iLine).x2 = x2
            m_arrLines(iObject, iLine).y2 = y2
            m_arrLines(iObject, iLine).color = _RGB32(r1, g1, b1)
            m_arrLines(iObject, iLine).IsLast = FALSE
            iLine = iLine + 1
            If iLine > UBound(m_arrLines, 2) Then Exit For
        End If
    Next iLoop%
   
    VectorData:
    'objaster1 = purple
    Data 2,-41,31,-50,128,0,255
    Data 31,-50,56,-23,128,0,255
    Data 56,-23,37,-10,128,0,255
    Data 37,-10,61,13,128,0,255
    Data 61,13,32,62,128,0,255
    Data 32,62,-22,43,128,0,255
    Data -22,43,-40,57,128,0,255
    Data -40,57,-62,34,128,0,255
    Data -62,34,-47,7,128,0,255
    Data -47,7,-62,-26,128,0,255
    Data -62,-26,-32,-63,128,0,255
    Data -32,-63,2,-41,128,0,255
    Data 0,0,0,0,-254,-254,-254
   
    'objaster2 = red
    Data -28,-62,22,-62,255,0,0
    Data 22,-62,61,-28,255,0,0
    Data 61,-28,61,13,255,0,0
    Data 61,13,23,57,255,0,0
    Data 23,57,-6,62,255,0,0
    Data -6,62,-6,15,255,0,0
    Data -6,15,-36,47,255,0,0
    Data -36,47,-59,14,255,0,0
    Data -59,14,-35,1,255,0,0
    Data -35,1,-62,-9,255,0,0
    Data -62,-9,-28,-62,255,0,0
    Data 0,0,0,0,-254,-254,-254
   
    'objaster3 = orange
    Data 9,-62,60,-21,255,165,0
    Data 60,-21,62,-3,255,165,0
    Data 62,-3,24,13,255,165,0
    Data 24,13,53,34,255,165,0
    Data 53,34,38,55,255,165,0
    Data 38,55,20,40,255,165,0
    Data 20,40,-37,61,255,165,0
    Data -37,61,-63,15,255,165,0
    Data -63,15,-57,-24,255,165,0
    Data -57,-24,-24,-24,255,165,0
    Data -24,-24,-38,-45,255,165,0
    Data -38,-45,9,-62,255,165,0
    Data 0,0,0,0,-254,-254,-254
   
    'objmouse = yellow
    Data 0,-10,6,3,255,255,0
    Data 6,3,1,2,255,255,0
    Data 1,2,1,10,255,255,0
    Data 1,10,-1,10,255,255,0
    Data -1,10,-1,2,255,255,0
    Data -1,2,-6,3,255,255,0
    Data -6,3,0,-10,255,255,0
    Data 0,0,0,0,-254,-254,-254
   
    'objship = cyan
    Data 0,-15,10,15,0,255,255
    Data 10,15,6,11,0,255,255
    Data 6,11,-6,11,0,255,255
    Data -6,11,-10,15,0,255,255
    Data -10,15,0,-15,0,255,255
    Data 0,0,0,0,-254,-254,-254
    'Data 0,18,0,18,0,255,255
    'Data 0,0,0,0,-254,-254,-254
   
    'objufo = green
    Data -4,-16,4,-16,0,255,0
    Data 4,-16,10,-6,0,255,0
    Data 10,-6,25,5,0,255,0
    Data 25,5,10,16,0,255,0
    Data 10,16,-10,16,0,255,0
    Data -10,16,-25,5,0,255,0
    Data -25,5,-10,-6,0,255,0
    Data -10,-6,-4,-16,0,255,0
    Data -10,-6,10,-6,0,255,0
    Data -25,5,25,5,0,255,0
    Data 0,0,0,0,-255,-255,-255
   
End Sub ' InitVectorObjects

' /////////////////////////////////////////////////////////////////////////////
' (RE)DRAW SCREEN

Sub DrawLayers (imgBack&, imgMiddle&, imgFront&)
    _Dest 0
    Cls , cBlack

    If TRUE = FALSE Then
        If imgBack& < -1 Then
            _PutImage , imgBack&, 0
        End If

        If imgMiddle& < -1 Then
            _PutImage , imgMiddle&, 0
        End If

        If imgFront& < -1 Then
            _PutImage , imgFront&, 0
        End If
    End If

End Sub ' DrawLayers

' /////////////////////////////////////////////////////////////////////////////
' SHOW INSTRUMENTS + INSTRUCTIONS
' 800x600 = 40 rows x 100 columns

sub DrawText( _
    sKey as string, _
    iWhich as integer _
    )
   
    Dim iObject As Integer
    Dim iX As Integer
    Dim iY As Integer
   
    Color cWhite
    PrintAt 1, 1, "Simple 2D vector graphics test"
   
    Color cYellow
    PrintAt 3, 1, "Press 1-6 to select active object."
    PrintAt 4, 1, "Arrow keys move active object."
   
    iY = 6
    For iObject = LBound(m_arrObject) To UBound(m_arrObject)
        If m_arrObject(iObject).IsEnabled = TRUE Then
            Color cCyan
        Else
            Color cGray
        End If
        PrintAt iY, 1, "" + _
            "obj #" + cstr$(iObject) + _
            "(" + cstr$(m_arrObject(iObject).x) + "," + cstr$(m_arrObject(iObject).y) + ")" + _
            "(" + cstr$(m_arrObject(iObject).dx) + "," + cstr$(m_arrObject(iObject).dy) + ")" + _
            "(" + cstr$(m_arrObject(iObject).cx) + "," + cstr$(m_arrObject(iObject).cy) + ")" + _
            ""
        iY = iY + 1
    Next iObject

    ' SHOW INPUT
    'if m_bDebug=TRUE then
    Color cLime
    PrintAt 20, 1, "Controls   : " + RightPadString$(sKey, 10, " ") + "   "
       
    Color cWhite
    PrintAt 21, 1, "Object #   : " + cstr$(iWhich)
    'end if
   
    ' SHOW COORDINATES
   
   
End Sub ' DrawText

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN GENERAL PURPOSE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' /////////////////////////////////////////////////////////////////////////////

Function cstr$ (myValue)
    'cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
    cstr$ = _Trim$(Str$(myValue))
End Function ' cstr$

' /////////////////////////////////////////////////////////////////////////////
' Hack function, to be replaced with something better

Function DblToInt% (dblOld As Double)
    Dim dblNew As Double
    Dim sValue As String
    Dim iPos As Integer

    dblNew = RoundDouble#(dblOld, 0)
    'sValue = _Trim$(Str$(dblNew))

    sValue = DblToStr$(dblNew)

    'iPos = InStr(1, sValue, ".")
    'If iPos > 0 Then
    '    DblToInt% = Val(Left$(sValue, iPos - 1))
    'Else
    '    DblToInt% = Val(sValue)
    'End If

    DblToInt% = Val(sValue)
End Function ' DblToInt%

' /////////////////////////////////////////////////////////////////////////////
' Scientific notation - QB64 Wiki
' https://www.qb64.org/wiki/Scientific_notation

' Example: A string function that displays extremely small or large exponential decimal values.

Function DblToStr$ (n#)
    Dim result$: result$ = ""
    Dim value$
    Dim Xpos%
    Dim expo%
    Dim sign$
    Dim valu$
    Dim dot%
    Dim L%
    Dim add$
    Dim min$
    Dim DP$
    Dim n%
   
    value$ = UCase$(LTrim$(Str$(n#)))
    Xpos% = InStr(value$, "D") + InStr(value$, "E") ' only D or E can be present
    If Xpos% Then
        expo% = Val(Mid$(value$, Xpos% + 1))
        If Val(value$) < 0 Then
            sign$ = "-"
            valu$ = Mid$(value$, 2, Xpos% - 2)
        Else
            valu$ = Mid$(value$, 1, Xpos% - 1)
        End If
        dot% = InStr(valu$, ".")
        L% = Len(valu$)
        If expo% > 0 Then
            add$ = String$(expo% - (L% - dot%), "0")
        End If
        If expo% < 0 Then
            min$ = String$(Abs(expo%) - (dot% - 1), "0")
            DP$ = "."
        End If
        For n% = 1 To L%
            If Mid$(valu$, n%, 1) <> "." Then
                num$ = num$ + Mid$(valu$, n%, 1)
            End If
        Next n%
        result$ = _Trim$(sign$ + DP$ + min$ + num$ + add$)
    Else
        result$ = value$
    End If
   
    DblToStr$ = result$
End Function ' DblToStr$

' /////////////////////////////////////////////////////////////////////////////

Function DblRoundedToStr$ (dblValue As Double, intNumPlaces As Integer)
    Dim dblNew As Double
    dblNew = RoundDouble#(dblValue, intNumPlaces)
    DblRoundedToStr$ = DblToStr$(dblNew)
End Function ' DblRoundedToStr$

' /////////////////////////////////////////////////////////////////////////////

Function DoubleABS# (dblValue As Double)
    If Sgn(dblValue) = -1 Then
        DoubleABS# = 0 - dblValue
    Else
        DoubleABS# = dblValue
    End If
End Function ' DoubleABS#

' /////////////////////////////////////////////////////////////////////////////
' Scientific notation - QB64 Wiki
' https://www.qb64.org/wiki/Scientific_notation

' Example: A string function that displays extremely small or large exponential decimal values.

Function FloatToStr$ (n##)
    value$ = UCase$(LTrim$(Str$(n##)))
    Xpos% = InStr(value$, "D") + InStr(value$, "E") 'only D or E can be present
    If Xpos% Then
        expo% = Val(Mid$(value$, Xpos% + 1))
        If Val(value$) < 0 Then
            sign$ = "-"
            valu$ = Mid$(value$, 2, Xpos% - 2)
        Else
            valu$ = Mid$(value$, 1, Xpos% - 1)
        End If
        dot% = InStr(valu$, ".")
        L% = Len(valu$)
        If expo% > 0 Then
            add$ = String$(expo% - (L% - dot%), "0")
        End If
        If expo% < 0 Then
            min$ = String$(Abs(expo%) - (dot% - 1), "0")
            DP$ = "."
        End If
        For n = 1 To L%
            If Mid$(valu$, n, 1) <> "." Then
                num$ = num$ + Mid$(valu$, n, 1)
            End If
        Next n
    Else
        FloatToStr$ = value$
        Exit Function
    End If
    FloatToStr$ = _Trim$(sign$ + DP$ + min$ + num$ + add$)
End Function ' FloatToStr$

' /////////////////////////////////////////////////////////////////////////////
' By sMcNeill from https://www.qb64.org/forum/index.php?topic=896.0

Function IsNum% (text$)
    Dim a$
    Dim b$
    a$ = _Trim$(text$)
    b$ = _Trim$(Str$(Val(text$)))
    If a$ = b$ Then
        IsNum% = TRUE
    Else
        IsNum% = FALSE
    End If
End Function ' IsNum%

' /////////////////////////////////////////////////////////////////////////////
' Split and join strings
' https://www.qb64.org/forum/index.php?topic=1073.0

'Combine all elements of in$() into a single string with delimiter$ separating the elements.

Function join$ (in$(), delimiter$)
    Dim result$
    Dim i As Long
    result$ = in$(LBound(in$))
    For i = LBound(in$) + 1 To UBound(in$)
        result$ = result$ + delimiter$ + in$(i)
    Next i
    join$ = result$
End Function ' join$

' /////////////////////////////////////////////////////////////////////////////

Function LeftPadString$ (myString$, toWidth%, padChar$)
    LeftPadString$ = Right$(String$(toWidth%, padChar$) + myString$, toWidth%)
End Function ' LeftPadString$

' /////////////////////////////////////////////////////////////////////////////
' ABS was returning strange values with type LONG
' so I created this which does not.

Function LongABS& (lngValue As Long)
    If Sgn(lngValue) = -1 Then
        LongABS& = 0 - lngValue
    Else
        LongABS& = lngValue
    End If
End Function ' LongABS&

' /////////////////////////////////////////////////////////////////////////////
' iRow% and iCol% are 0-based in this version

Sub PrintAt (iRow%, iCol%, sText$)
    '_PrintString (iCol% * 8, iRow% * 16), sText$
    _PrintString (iCol% * 8, iRow% * 16), sText$
    '_PrintString (iCol%, iRow%), sText$
End Sub ' PrintAt

' /////////////////////////////////////////////////////////////////////////////
' Generate random value between Min and Max.

Function RandomNumber% (Min%, Max%)
    Dim NumSpread%

    ' SET RANDOM SEED
    'Randomize ' Initialize random-number generator.
    Randomize Timer

    ' GET RANDOM # Min%-Max%
    'RandomNumber = Int((Max * Rnd) + Min) ' generate number

    NumSpread% = (Max% - Min%) + 1

    RandomNumber% = Int(Rnd * NumSpread%) + Min% ' GET RANDOM # BETWEEN Max% AND Min%

End Function ' RandomNumber%

' /////////////////////////////////////////////////////////////////////////////

Function RightPadString$ (myString$, toWidth%, padChar$)
    RightPadString$ = Left$(myString$ + String$(toWidth%, padChar$), toWidth%)
End Function ' RightPadString$

' /////////////////////////////////////////////////////////////////////////////
' https://www.qb64.org/forum/index.php?topic=3605.0
' Quote from: SMcNeill on Today at 03:53:48 PM
'
' Sometimes, you guys make things entirely too  complicated.
' There ya go!  Three functions to either round naturally,
' always round down, or always round up, to whatever number of digits you desire.
' EDIT:  Modified to add another option to round scientific,
' since you had it's description included in your example.

' Receives + returns _FLOAT myVar## (-1.18E-4932 to +1.18E+4932)

' =============================================================================
' ROUNDING FUNCTIONS FOR TYPE _FLOAT

Function Round## (num##, digits%)
    Round## = Int(num## * 10 ^ digits% + .5) / 10 ^ digits%
End Function

Function RoundUp## (num##, digits%)
    RoundUp## = _Ceil(num## * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundDown## (num##, digits%)
    RoundDown## = Int(num## * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundScientific## (num##, digits%)
    RoundScientific## = _Round(num## * 10 ^ digits%) / 10 ^ digits%
End Function

' =============================================================================
' ROUNDING FUNCTIONS FOR TYPE DOUBLE

Function RoundDouble# (num#, digits%)
    RoundDouble# = Int(num# * 10 ^ digits% + .5) / 10 ^ digits%
End Function

Function RoundUpDouble# (num#, digits%)
    RoundUpDouble# = _Ceil(num# * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundDownDouble# (num#, digits%)
    RoundDownDouble# = Int(num# * 10 ^ digits%) / 10 ^ digits%
End Function

Function RoundScientificDouble# (num#, digits%)
    RoundScientificDouble# = _Round(num# * 10 ^ digits%) / 10 ^ digits%
End Function

' /////////////////////////////////////////////////////////////////////////////

Function SmallestOf3% (i1%, i2%, i3%)
    Dim iMin%
    iMin% = i1%
    If i2% < iMin% Then iMin% = i2%
    If i3% < iMin% Then iMin% = i3%
    SmallestOf3% = iMin%
End Function ' SmallestOf3

' /////////////////////////////////////////////////////////////////////////////
' Split and join strings
' https://www.qb64.org/forum/index.php?topic=1073.0
'
' FROM luke, QB64 Developer
' Date: February 15, 2019, 04:11:07 AM
'
' Given a string of words separated by spaces (or any other character),
' splits it into an array of the words. I've no doubt many people have
' written a version of this over the years and no doubt there's a million
' ways to do it, but I thought I'd put mine here so we have at least one
' version. There's also a join function that does the opposite
' array -> single string.
'
' Code is hopefully reasonably self explanatory with comments and a little demo.
' Note, this is akin to Python/JavaScript split/join, PHP explode/implode.

'Split in$ into pieces, chopping at every occurrence of delimiter$. Multiple consecutive occurrences
'of delimiter$ are treated as a single instance. The chopped pieces are stored in result$().
'
'delimiter$ must be one character long.
'result$() must have been REDIMmed previously.

' Modified to handle multi-character delimiters

Sub split (in$, delimiter$, result$())
    Dim start As Integer
    Dim finish As Integer
    Dim iDelimLen As Integer
    ReDim result$(-1)

    iDelimLen = Len(delimiter$)

    start = 1
    Do
        'While Mid$(in$, start, 1) = delimiter$
        While Mid$(in$, start, iDelimLen) = delimiter$
            'start = start + 1
            start = start + iDelimLen
            If start > Len(in$) Then
                Exit Sub
            End If
        Wend
        finish = InStr(start, in$, delimiter$)
        If finish = 0 Then
            finish = Len(in$) + 1
        End If

        ReDim _Preserve result$(0 To UBound(result$) + 1)

        result$(UBound(result$)) = Mid$(in$, start, finish - start)
        start = finish + 1
    Loop While start <= Len(in$)
End Sub ' split

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END GENERAL PURPOSE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN COLOR FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Function cRed~& ()
    cRed = _RGB32(255, 0, 0)
End Function

Function cOrangeRed~& ()
    cOrangeRed = _RGB32(255, 69, 0)
End Function ' cOrangeRed~&

Function cDarkOrange~& ()
    cDarkOrange = _RGB32(255, 140, 0)
End Function ' cDarkOrange~&

Function cOrange~& ()
    cOrange = _RGB32(255, 165, 0)
End Function ' cOrange~&

Function cGold~& ()
    cGold = _RGB32(255, 215, 0)
End Function ' cGold~&

Function cYellow~& ()
    cYellow = _RGB32(255, 255, 0)
End Function ' cYellow~&

' LONG-HAIRED FRIENDS OF JESUS OR NOT,
' THIS IS NOT YELLOW ENOUGH (TOO CLOSE TO LIME)
' TO USE FOR OUR COMPLEX RAINBOW SEQUENCE:
Function cChartreuse~& ()
    cChartreuse = _RGB32(127, 255, 0)
End Function ' cChartreuse~&

' WE SUBSTITUTE THIS CSS3 COLOR FOR INBETWEEN LIME AND YELLOW:
Function cOliveDrab1~& ()
    cOliveDrab1 = _RGB32(192, 255, 62)
End Function ' cOliveDrab1~&

Function cLime~& ()
    cLime = _RGB32(0, 255, 0)
End Function ' cLime~&

Function cMediumSpringGreen~& ()
    cMediumSpringGreen = _RGB32(0, 250, 154)
End Function ' cMediumSpringGreen~&

' ADDED THIS FOR THE GAUGE COLOR:
Function cSpringGreen~& ()
    cSpringGreen = _RGB32(0, 255, 160)
End Function ' cSpringGreen~&

Function cCyan~& ()
    cCyan = _RGB32(0, 255, 255)
End Function ' cCyan~&

Function cDeepSkyBlue~& ()
    cDeepSkyBlue = _RGB32(0, 191, 255)
End Function ' cDeepSkyBlue~&

Function cDodgerBlue~& ()
    cDodgerBlue = _RGB32(30, 144, 255)
End Function ' cDodgerBlue~&

Function cSeaBlue~& ()
    cSeaBlue = _RGB32(0, 64, 255)
End Function ' cSeaBlue~&

Function cBlue~& ()
    cBlue = _RGB32(0, 0, 255)
End Function ' cBlue~&

Function cBluePurple~& ()
    cBluePurple = _RGB32(64, 0, 255)
End Function ' cBluePurple~&

Function cDeepPurple~& ()
    cDeepPurple = _RGB32(96, 0, 255)
End Function ' cDeepPurple~&

Function cPurple~& ()
    cPurple = _RGB32(128, 0, 255)
End Function ' cPurple~&

Function cPurpleRed~& ()
    cPurpleRed = _RGB32(128, 0, 192)
End Function ' cPurpleRed~&

Function cDarkRed~& ()
    cDarkRed = _RGB32(160, 0, 64)
End Function ' cDarkRed~&

Function cBrickRed~& ()
    cBrickRed = _RGB32(192, 0, 32)
End Function ' cBrickRed~&

Function cDarkGreen~& ()
    cDarkGreen = _RGB32(0, 100, 0)
End Function ' cDarkGreen~&

Function cGreen~& ()
    cGreen = _RGB32(0, 128, 0)
End Function ' cGreen~&

Function cOliveDrab~& ()
    cOliveDrab = _RGB32(107, 142, 35)
End Function ' cOliveDrab~&

Function cLightPink~& ()
    cLightPink = _RGB32(255, 182, 193)
End Function ' cLightPink~&

Function cHotPink~& ()
    cHotPink = _RGB32(255, 105, 180)
End Function ' cHotPink~&

Function cDeepPink~& ()
    cDeepPink = _RGB32(255, 20, 147)
End Function ' cDeepPink~&

Function cMagenta~& ()
    cMagenta = _RGB32(255, 0, 255)
End Function ' cMagenta~&

Function cBlack~& ()
    cBlack = _RGB32(0, 0, 0)
End Function ' cBlack~&

Function cDimGray~& ()
    cDimGray = _RGB32(105, 105, 105)
End Function ' cDimGray~&

Function cGray~& ()
    cGray = _RGB32(128, 128, 128)
End Function ' cGray~&

Function cDarkGray~& ()
    cDarkGray = _RGB32(169, 169, 169)
End Function ' cDarkGray~&

Function cSilver~& ()
    cSilver = _RGB32(192, 192, 192)
End Function ' cSilver~&

Function cLightGray~& ()
    cLightGray = _RGB32(211, 211, 211)
End Function ' cLightGray~&

Function cGainsboro~& ()
    cGainsboro = _RGB32(220, 220, 220)
End Function ' cGainsboro~&

Function cWhiteSmoke~& ()
    cWhiteSmoke = _RGB32(245, 245, 245)
End Function ' cWhiteSmoke~&

Function cWhite~& ()
    cWhite = _RGB32(255, 255, 255)
    'cWhite = _RGB32(254, 254, 254)
End Function ' cWhite~&

Function cDarkBrown~& ()
    cDarkBrown = _RGB32(128, 64, 0)
End Function ' cDarkBrown~&

Function cLightBrown~& ()
    cLightBrown = _RGB32(196, 96, 0)
End Function ' cLightBrown~&

Function cKhaki~& ()
    cKhaki = _RGB32(240, 230, 140)
End Function ' cKhaki~&

Function cEmpty~& ()
    'cEmpty~& = -1
    cEmpty = _RGB32(0, 0, 0, 0)
End Function ' cEmpty~&

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END COLOR FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ################################################################################################################################################################
' BEGIN KEYBOARD CODE FUNCTIONS
' NOTE: ALL CODES ARE FOR _BUTTON, EXCEPT:
' cF10 (_KEYDOWN)
' cAltLeft (_KEYHIT)
' cAltRight (_KEYHIT)
' cPrintScreen (_KEYHIT) <- may slow down pc?
' cPauseBreak (_KEYHIT) <- may not work?
' ################################################################################################################################################################

Function KeyCode_Escape% ()
    KeyCode_Escape% = 2
End Function

Function KeyCode_F1% ()
    KeyCode_F1% = 60
End Function

Function KeyCode_F2% ()
    KeyCode_F2% = 61
End Function

Function KeyCode_F3% ()
    KeyCode_F3% = 62
End Function

Function KeyCode_F4% ()
    KeyCode_F4% = 63
End Function

Function KeyCode_F5% ()
    KeyCode_F5% = 64
End Function

Function KeyCode_F6% ()
    KeyCode_F6% = 65
End Function

Function KeyCode_F7% ()
    KeyCode_F7% = 66
End Function

Function KeyCode_F8% ()
    KeyCode_F8% = 67
End Function

Function KeyCode_F9% ()
    KeyCode_F9% = 68
End Function

'_KEYDOWN CODE, NOT _BUTTON CODE
Function KeyCode_F10% ()
    KeyCode_F10% = 17408
End Function

Function KeyCode_F11% ()
    KeyCode_F11% = 88
End Function

Function KeyCode_F12% ()
    KeyCode_F12% = 89
End Function

'_KEYHIT CODE, NOT _BUTTON CODE
Function KeyCode_PrintScreen% ()
    KeyCode_PrintScreen% = -44
End Function

Function KeyCode_ScrollLock% ()
    KeyCode_ScrollLock% = 71
End Function

'_KEYHIT CODE, NOT _BUTTON CODE
Function KeyCode_PauseBreak% ()
    KeyCode_PauseBreak% = 31053
End Function

Function KeyCode_Tilde% ()
    KeyCode_Tilde% = 42
End Function

Function KeyCode_1% ()
    KeyCode_1% = 3
End Function

Function KeyCode_2% ()
    KeyCode_2% = 4
End Function

Function KeyCode_3% ()
    KeyCode_3% = 5
End Function

Function KeyCode_4% ()
    KeyCode_4% = 6
End Function

Function KeyCode_5% ()
    KeyCode_5% = 7
End Function

Function KeyCode_6% ()
    KeyCode_6% = 8
End Function

Function KeyCode_7% ()
    KeyCode_7% = 9
End Function

Function KeyCode_8% ()
    KeyCode_8% = 10
End Function

Function KeyCode_9% ()
    KeyCode_9% = 11
End Function

Function KeyCode_0% ()
    KeyCode_0% = 12
End Function

Function KeyCode_Minus% ()
    KeyCode_Minus% = 13
End Function

Function KeyCode_Equal% ()
    KeyCode_Equal% = 14
End Function

Function KeyCode_BkSp% ()
    KeyCode_BkSp% = 15
End Function

Function KeyCode_Ins% ()
    KeyCode_Ins% = 339
End Function

Function KeyCode_Home% ()
    KeyCode_Home% = 328
End Function

Function KeyCode_PgUp% ()
    KeyCode_PgUp% = 330
End Function

Function KeyCode_Del% ()
    KeyCode_Del% = 340
End Function

Function KeyCode_End% ()
    KeyCode_End% = 336
End Function

Function KeyCode_PgDn% ()
    KeyCode_PgDn% = 338
End Function

Function KeyCode_NumLock% ()
    KeyCode_NumLock% = 326
End Function

Function KeyCode_KeypadSlash% ()
    KeyCode_KeypadSlash% = 310
End Function

Function KeyCode_KeypadMultiply% ()
    KeyCode_KeypadMultiply% = 56
End Function

Function KeyCode_KeypadMinus% ()
    KeyCode_KeypadMinus% = 75
End Function

Function KeyCode_Keypad7Home% ()
    KeyCode_Keypad7Home% = 72
End Function

Function KeyCode_Keypad8Up% ()
    KeyCode_Keypad8Up% = 73
End Function

Function KeyCode_Keypad9PgUp% ()
    KeyCode_Keypad9PgUp% = 74
End Function

Function KeyCode_KeypadPlus% ()
    KeyCode_KeypadPlus% = 79
End Function

Function KeyCode_Keypad4Left% ()
    KeyCode_Keypad4Left% = 76
End Function

Function KeyCode_Keypad5% ()
    KeyCode_Keypad5% = 77
End Function

Function KeyCode_Keypad6Right% ()
    KeyCode_Keypad6Right% = 78
End Function

Function KeyCode_Keypad1End% ()
    KeyCode_Keypad1End% = 80
End Function

Function KeyCode_Keypad2Down% ()
    KeyCode_Keypad2Down% = 81
End Function

Function KeyCode_Keypad3PgDn% ()
    KeyCode_Keypad3PgDn% = 82
End Function

Function KeyCode_KeypadEnter% ()
    KeyCode_KeypadEnter% = 285
End Function

Function KeyCode_Keypad0Ins% ()
    KeyCode_Keypad0Ins% = 83
End Function

Function KeyCode_KeypadPeriodDel% ()
    KeyCode_KeypadPeriodDel% = 84
End Function

Function KeyCode_Tab% ()
    KeyCode_Tab% = 16
End Function

Function KeyCode_Q% ()
    KeyCode_Q% = 17
End Function

Function KeyCode_W% ()
    KeyCode_W% = 18
End Function

Function KeyCode_E% ()
    KeyCode_E% = 19
End Function

Function KeyCode_R% ()
    KeyCode_R% = 20
End Function

Function KeyCode_T% ()
    KeyCode_T% = 21
End Function

Function KeyCode_Y% ()
    KeyCode_Y% = 22
End Function

Function KeyCode_U% ()
    KeyCode_U% = 23
End Function

Function KeyCode_I% ()
    KeyCode_I% = 24
End Function

Function KeyCode_O% ()
    KeyCode_O% = 25
End Function

Function KeyCode_P% ()
    KeyCode_P% = 26
End Function

Function KeyCode_BracketLeft% ()
    KeyCode_BracketLeft% = 27
End Function

Function KeyCode_BracketRight% ()
    KeyCode_BracketRight% = 28
End Function

Function KeyCode_Backslash% ()
    KeyCode_Backslash% = 44
End Function

Function KeyCode_CapsLock% ()
    KeyCode_CapsLock% = 59
End Function

Function KeyCode_A% ()
    KeyCode_A% = 31
End Function

Function KeyCode_S% ()
    KeyCode_S% = 32
End Function

Function KeyCode_D% ()
    KeyCode_D% = 33
End Function

Function KeyCode_F% ()
    KeyCode_F% = 34
End Function

Function KeyCode_G% ()
    KeyCode_G% = 35
End Function

Function KeyCode_H% ()
    KeyCode_H% = 36
End Function

Function KeyCode_J% ()
    KeyCode_J% = 37
End Function

Function KeyCode_K% ()
    KeyCode_K% = 38
End Function

Function KeyCode_L% ()
    KeyCode_L% = 39
End Function

Function KeyCode_Semicolon% ()
    KeyCode_Semicolon% = 40
End Function

Function KeyCode_Apostrophe% ()
    KeyCode_Apostrophe% = 41
End Function

Function KeyCode_Enter% ()
    KeyCode_Enter% = 29
End Function

Function KeyCode_ShiftLeft% ()
    KeyCode_ShiftLeft% = 43
End Function

Function KeyCode_Z% ()
    KeyCode_Z% = 45
End Function

Function KeyCode_X% ()
    KeyCode_X% = 46
End Function

Function KeyCode_C% ()
    KeyCode_C% = 47
End Function

Function KeyCode_V% ()
    KeyCode_V% = 48
End Function

Function KeyCode_B% ()
    KeyCode_B% = 49
End Function

Function KeyCode_N% ()
    KeyCode_N% = 50
End Function

Function KeyCode_M% ()
    KeyCode_M% = 51
End Function

Function KeyCode_Comma% ()
    KeyCode_Comma% = 52
End Function

Function KeyCode_Period% ()
    KeyCode_Period% = 53
End Function

Function KeyCode_Slash% ()
    KeyCode_Slash% = 54
End Function

Function KeyCode_ShiftRight% ()
    KeyCode_ShiftRight% = 55
End Function

Function KeyCode_Up% ()
    KeyCode_Up% = 329
End Function

Function KeyCode_Left% ()
    KeyCode_Left% = 332
End Function

Function KeyCode_Down% ()
    KeyCode_Down% = 337
End Function

Function KeyCode_Right% ()
    KeyCode_Right% = 334
End Function

Function KeyCode_CtrlLeft% ()
    KeyCode_CtrlLeft% = 30
End Function

Function KeyCode_WinLeft% ()
    KeyCode_WinLeft% = 348
End Function

' _KEYHIT CODE NOT _BUTTON CODE
Function KeyCode_AltLeft% ()
    KeyCode_AltLeft% = -30764
End Function

Function KeyCode_Spacebar% ()
    KeyCode_Spacebar% = 58
End Function

' _KEYHIT CODE NOT _BUTTON CODE
Function KeyCode_AltRight% ()
    KeyCode_AltRight% = -30765
End Function

Function KeyCode_WinRight% ()
    KeyCode_WinRight% = 349
End Function

Function KeyCode_Menu% ()
    KeyCode_Menu% = 350
End Function

Function KeyCode_CtrlRight% ()
    KeyCode_CtrlRight% = 286
End Function

' ################################################################################################################################################################
' END KEYBOARD CODE FUNCTIONS
' ################################################################################################################################################################

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN DEBUGGING ROUTINES #DEBUGGING
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub DebugPrint (MyString As String)
    If m_bDebug = TRUE Then
        '_Echo MyString

        ReDim arrLines(-1) As String
        Dim iLoop As Integer
        split MyString, Chr$(13), arrLines()
        For iLoop = LBound(arrLines) To UBound(arrLines)
            _Echo arrLines(iLoop)
        Next iLoop
    End If
End Sub ' DebugPrint

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END DEBUGGING ROUTINES @DEBUGGING
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ################################################################################################################################################################
' #REFERENCE

' =============================================================================
' SOME USEFUL STUFF FOR REFERENCE:

' Type Name               Type suffix symbol   Minimum value                  Maximum value                Size in Bytes
' ---------------------   ------------------   ----------------------------   --------------------------   -------------
' _BIT                    `                    -1                             0                            1/8
' _BIT * n                `n                   -128                           127                          n/8
' _UNSIGNED _BIT          ~`                   0                              1                            1/8
' _BYTE                   %%                   -128                           127                          1
' _UNSIGNED _BYTE         ~%%                  0                              255                          1
' INTEGER                 %                    -32,768                        32,767                       2
' _UNSIGNED INTEGER       ~%                   0                              65,535                       2
' LONG                    &                    -2,147,483,648                 2,147,483,647                4
' _UNSIGNED LONG          ~&                   0                              4,294,967,295                4
' _INTEGER64              &&                   -9,223,372,036,854,775,808     9,223,372,036,854,775,807    8
' _UNSIGNED _INTEGER64    ~&&                  0                              18,446,744,073,709,551,615   8
' SINGLE                  ! or none            -2.802597E-45                  +3.402823E+38                4
' DOUBLE                  #                    -4.490656458412465E-324        +1.797693134862310E+308      8
' _FLOAT                  ##                   -1.18E-4932                    +1.18E+4932                  32(10 used)
' _OFFSET                 %&                   -9,223,372,036,854,775,808     9,223,372,036,854,775,807    Use LEN
' _UNSIGNED _OFFSET       ~%&                  0                              18,446,744,073,709,551,615   Use LEN
' _MEM                    none                 combined memory variable type  N/A                          Use LEN

' div: int1% = num1% \ den1%
' mod: rem1% = num1% MOD den1%

Print this item

Lightbulb I love the jaggies!
Posted by: mnrvovrfc - 10-26-2022, 03:17 PM - Forum: Utilities - Replies (10)

I created a sub that has too many parameters but could fake the block graphic characters drawn by ancient computers such as the TRS-80 Model III. I have found a bug while composing this on Linux.

Code: (Select All)
option _explicit
dim as integer i, x, y, re, be, ge, scw, sch, saiz

scw = 1152
sch = 672
screen _newimage(scw, sch, 32)
saiz = 48
re = 96
ge = re
be = re
'for i = 128 to 191
'    block i - 128, saiz, 2, 3, x, y, _rgb(255, 255, 255)
'    x = x + saiz
'    if x >= 800 then
'        x = 0
'        y = y + saiz
'    end if
'next
'goto pend
saiz = 12
for i = 0 to 4095
    block i, saiz, 3, 4, x, y, _rgb(re, ge, be)
    x = x + saiz
    if x >= scw then
        x = 0
        y = y + saiz
        if y >= sch then exit for
        ge = ge + 32
        if ge > 255 then ge = 96: be = be + 12
    end if
next
pend:
sleep
system

''num = fake character code (bits will be checked)
''siz = point size of the whole "rectangle"
''wd = number of pixels across
''ht = number of pixels vertically
''xx, yy = coordinates of top-left corner (desired to avoid this and "co")
''co = 32-bit color value
''eg. TRS-80 monochrome graphics, wd = 2 and ht = 3, graphics 128 x 48
''for Tandy Coco as well "num" must start at zero but graphics chars started at CHR$(128)
sub block (num as _unsigned integer, siz as integer, wd as integer, ht as integer, xx as single, yy as single, co as long)
    static as integer x, y, k
    static as _byte p
    static as long m
    static as single w, h
    w = siz / wd
    h = siz / ht
    p = 0
    for y = 0 to ht - 1
        for x = 0 to wd - 1
            m = 2 ^ p
            if num and m then
                line(xx + x * w, yy + y * h)-step(w, h), co, bf
            end if
            p = p + 1
        next
    next
end sub

The colors are a vain attempt to see the influence of the pixel rows more clearly. This should have range checking. This wasn't tested under "VIEW" and "WINDOW" setting.

Composed this on Fedora 36 MATE. (Yeah got stuck yesterday waiting for 37 to discover they postponed it for another week!)
This is the bug:

On a laptop or other screen with 768 pixels vertically, try changing "sch" to a value higher than 672, compile and run. The top part of the picture is scrolled off as if "PRINT" were used without semicolon near the bottom of the screen. This is seen more obviously if the commented parts were the demonstration, which draws much-larger pixel blocks. This drove me crazy for about half an hour and while I was getting the 3x4-pixel thing straightened out.

My laptop has only 768 pixels vertically. With "task bar" enabled the area is reduced to 720 or less, however that "task bar" has no influence on the user program's window. Maybe somebody with a larger viewport hardware could handle a larger size, but this bug should happen when the vertical dimension is quite near the maximum.

Print this item

  Curious. Do we still have a way to change the date and time?
Posted by: Pete - 10-25-2022, 01:29 AM - Forum: General Discussion - Replies (4)

In QuickBASIC we could manipulate the time and date of the computer.

TIME$ = "06:30:00"
DATE$ = "10/20/2020"

I see QB64 currently supports only using those two statements to get the computer time and date, and no longer to set the time and date. Do we have a Windows API call that can manipulate the computer clocks available?

Pete

Print this item

  TCP/IP Example Demo for LOCAL HOST/CLIENT Applications
Posted by: Pete - 10-24-2022, 07:30 PM - Forum: Works in Progress - Replies (20)

We had a discussion about using _CLIPBOARD to deliver info from one running QB64 app to another. Spriggsy brought up the point that method is frowned upon by M$, which recommends using a TCP/IP routine to pass the info.

So I decided to post a way to communicate back and forth between two QB64 programs.

Notes: You will probably need to tell Windows Defender to okay running these apps, as Defender checks for exe files of this nature.

How to use...

1) Copy/Paste the first program to your QB64 IDE.

2) Open a second IDE and copy/paste the second program.

3) Name and save the second program as; Pete2.bas.

4) Compile Pete2.bas or just run Pete2.bas and close it.

5) Go back to the first IDE, and select "Run" (You don't need to name this app. Untitled works just fine.)

What next? Well, the first program will SHELL open Pete.exe. Now you will have two windows opened. Click the first window, and INPUT 1, 2, or 3 at the prompt. After you hit Enter, you will see your choice appear in the second window as either A, B, C, or if you goofed up it will tell you. The second window sends a message back that it completed the task so the first window can loop back to the INPUT statement. Just close them out with the mouse when you are finished.

Code: (Select All)
_SCREENMOVE 0, 0 ' Set up this host window to the left of your desktop.
WIDTH 60, 25
DO
    CLS
    DO UNTIL x ' Stay in loop until window determines if it is the host or client window.
        x = _OPENCLIENT("TCP/IP:1234:localhost") ' Used to establish a TCP/IP routine.
        IF x = 0 THEN
            x = _OPENHOST("TCP/IP:1234") ' Note the host and clinet must have the same 1234 I.D. number.
            a$ = "Opening as host." ' x channel is now open and this window becomes the host.
        ELSE
            a$ = "Opening as client." ' Should not go here for this demo.
        END IF
        PRINT a$
    LOOP

    IF initiate = 0 THEN ' This only needs to be performed once, to open the client window.
        SHELL _HIDE "start pete2.exe" ' Open the client window.
        initiate = -1 ' Switches this block statement off for all subsequent loops.
    END IF

    IF z = 0 THEN ' Initiates an open channel number when zero.
        DO
            z = _OPENCONNECTION(x) ' Checks if host is available to transfer data.
        LOOP UNTIL z
        PRINT "Connection established."
    END IF

    LOCATE 3, 1 ' Okay, time to input something on the host that will be communicated to the client.
    INPUT "Input a number for letter of the alphabet 1, 2, or 3: "; choice
    _KEYCLEAR

    PUT #z, , choice ' Input is now entered into TCP/IP routine.

    DO
        GET #z, , a
    LOOP UNTIL a = -1 ' -1 is the return code from the client we set as: task_complete = -1
    PUT #z, , a ' Now put our -1 value back into the routine. Failure to do so would result in the client not waiting in the GET #x DO/LOOP.
    CLS
LOOP

Save this one as: Pete2.bas and compile it to Pete2.exe.
Code: (Select All)
_SCREENMOVE 600, 0 ' Set up this client window next to your host window.
WIDTH 50, 25
x = _OPENCLIENT("TCP/IP:1234:localhost") ' Used to establish a TCP/IP routine.
PRINT "Opened as client.": PRINT
DO UNTIL x = 0 ' Prevents running if this app is opened without using host.
    DO
        _LIMIT 30
        GET #x, , receive ' Waits until it receives data input from the host.
    LOOP UNTIL receive > 0

    PRINT "You chose the letter: ";

    SELECT CASE receive
        CASE 1
            PRINT "A"
        CASE 2
            PRINT "B"
        CASE 3
            PRINT "C"
        CASE ELSE
            PRINT "Wrong input!"
    END SELECT
    PRINT

    task_complete = -1 ' Send back a task completed message to the host.
    PUT #x, , task_complete
LOOP


@Spriggsy

Please have a look. I'd like to see if there is anything you would like to comment on, add or optimize. What I'm shooting for is making another example entry in our wiki to expand on the use of these QB64 available communication functions.

Pete

Print this item

  like Alice in wonderland
Posted by: MasterGy - 10-23-2022, 06:51 PM - Forum: MasterGy - Replies (6)

What does a mouse see? What does an elephant see? Perhaps the larger the animal, the higher it sees the world. The horizon increases with increasing altitude. What is huge for a small animal is small for a large animal. The small animal is slow compared to the ground, but normal speed compared to its own world. Although this is what the big animal feels, only the other way around. I wanted to convey the transition between the two perspectives.

Find an image with a size of about 2000x2000 pixels and try it! Depth data comes from grayscale.



download with sourcecode
https://drive.google.com/file/d/1r3UZ3gp...sp=sharing

Print this item