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

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 714
» Latest member: HenryG
» Forum threads: 3,569
» Forum posts: 31,908

Full Statistics

Latest Threads
4x4 Square Elimination Pu...
Forum: bplus
Last Post: bplus
3 hours ago
» Replies: 12
» Views: 405
Container Data Structure
Forum: Utilities
Last Post: bplus
3 hours ago
» Replies: 3
» Views: 112
Accretion Disk
Forum: Programs
Last Post: bplus
3 hours ago
» Replies: 11
» Views: 279
QB64PE v 4.4.0
Forum: Announcements
Last Post: Unseen Machine
11 hours ago
» Replies: 7
» Views: 656
QBJS v0.10.0 - Release
Forum: QBJS, BAM, and Other BASICs
Last Post: Unseen Machine
11 hours ago
» Replies: 13
» Views: 1,289
Arrays inside Types?
Forum: General Discussion
Last Post: hsiangch_ong
Today, 03:24 AM
» Replies: 47
» Views: 1,402
Has anybody experience wi...
Forum: Help Me!
Last Post: Rudy M
Yesterday, 08:47 AM
» Replies: 31
» Views: 1,936
Sorting numbers - FiliSor...
Forum: Utilities
Last Post: PhilOfPerth
03-11-2026, 12:48 AM
» Replies: 11
» Views: 337
Quick Sort for variable l...
Forum: Utilities
Last Post: SMcNeill
03-10-2026, 03:14 PM
» Replies: 3
» Views: 89
Ready for Easter!
Forum: Holiday Code
Last Post: bplus
03-10-2026, 12:15 PM
» Replies: 0
» Views: 58

 
  Flaming Text (let's make it a challenge)
Posted by: SMcNeill - 01-30-2026, 08:36 PM - Forum: Works in Progress - Replies (7)

Code: (Select All)
Type FlameParticle
    x As Single
    y As Single
    dx As Single
    dy As Single
    life As Integer
    maxlife As Integer
End Type

Const MAXP = 800
Dim Shared FP(MAXP) As FlameParticle

Sub SpawnFlame (x As Single, y As Single, explode)
    Dim i As Long
    For i = 1 To MAXP
        If FP(i).life <= 0 Then
            FP(i).x = x + Rnd * 4 - 2
            FP(i).y = y + Rnd * 2
            FP(i).dx = (Rnd * 1.2) - 0.6
            FP(i).dy = -(1 + Rnd * 1.5)
            FP(i).maxlife = 20 + Int(Rnd * 20)
            FP(i).life = FP(i).maxlife
            If explode = 0 Then Exit Sub
        End If
    Next
End Sub

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

Sub FireText (txt$, x As Long, y As Long, fnt As Long)
    Dim c As _Unsigned Long, i As Long, flicker As Integer
    Dim As Single emitY, t

    flicker = Int(Rnd * 8)
    _Font fnt

    ' --- Outer red glow ---
    Color _RGB(255, 40, 0), 0
    _PrintString (x - 3 - flicker, y + 3), txt$
    _PrintString (x + 3 + flicker, y - 3), txt$

    ' --- Mid orange glow ---
    Color _RGB(255, 120, 0), 0
    _PrintString (x - 2 - flicker / 2, y + 1), txt$
    _PrintString (x + 2 + flicker / 2, y - 1), txt$

    ' --- Inner yellow glow ---
    Color _RGB(255, 200, 0), 0
    _PrintString (x - 1 - flicker / 4, y), txt$
    _PrintString (x + 1 + flicker / 4, y), txt$

    ' --- Bright core ---
    Color _RGB(255, 255, 120), 0
    _PrintString (x, y), txt$

    ' --- Spawn flame particles above the text ---
    Dim tw As Long
    tw = _PrintWidth(txt$)

    For i = 1 To MAXP ' number of flames per frame
        emitY = (y - _FontHeight / 4) + Rnd * (1.25 * _FontHeight)
        SpawnFlame x + Rnd * tw, emitY, 0
        If i Mod 20 = 0 Then 'I don't want as many little firework style flame explosions
            emitY = (y - _FontHeight / 4) + Rnd * (.5 * _FontHeight)
            SpawnFlame x + Rnd * tw, emitY, -1
        End If
    Next

    For i = 1 To MAXP
        If FP(i).life > 0 Then
            FP(i).x = FP(i).x + FP(i).dx
            FP(i).y = FP(i).y + FP(i).dy
            FP(i).life = FP(i).life - 1
        End If
    Next

    For i = 1 To MAXP
        If FP(i).life > 0 Then
            t = FP(i).life / FP(i).maxlife
            c = _RGB(255 * t, 120 * t, 20 * t) ' Flame color gradient: yellow ? orange ? red ? dark
            Line (FP(i).x, FP(i).y)-Step(2, 3), c, BF
        End If
    Next
End Sub
'===========================================================
Screen _NewImage(800, 600, 32)

fnt = _LoadFont("arial.ttf", 64, "BOLD")
If fnt = 0 Then Print "Font load failed": End

Randomize Timer

Do
    Cls
    FireText "STEVE IS AMAZING!", 100, 300, fnt
    _Display
    _Limit 60
Loop Until _KeyHit
System
So I was playing around with trying to produce some sort of flaming text using particles and such.  What I've came up with is the above.  It's... not bad, but quite the "flame" I was looking for.

Still, it's a place to start with, and since you guys like various challenges and such, here's one for you:  Make your own flaming text routine.  Let's see what you guys can come up with.  I've always been one who liked to do various things with text (I have rainbow text routines, and circle text, and rotating text, and scaling text, and faux-3d text, and lots of others), so I figured "Why not shoot for something with a flame style effect?"

Here's my go at that attempt.  Let's see what you guys can come up with.  Everybody needs a nice flaming text routine -- if just for a title screen or something sometime!  Let's go guys!  Show me your best (and worst so I don't feel so bad).

@Pete is disqualified, as I know his version already:

Code: (Select All)
SCREEN 0
PRINT "My text is";
COLOR 20
PRINT " FLAMING ";
COLOR 7
PRINT "hot."

Pete loses before he's even began!  He's the worst, so none of the rest of you have any pressure at all to do better than he has!  Big Grin

Print this item

  Fireworks by Fellippe Heitor
Posted by: Magdha - 01-30-2026, 10:03 AM - Forum: In-Form - No Replies

   

The program uses the following InForm objects:
Form
PictureBox
Label
TRackBar
Checkbox
TextBox


Unzip the file and extract the folder into your PEQB64 directory.  In the IDE make sure that you have the Run Option “Save EXE in source folder” checked.

.zip   Fireworks2.zip (Size: 477.09 KB / Downloads: 7)

Code: (Select All)
': Program by Fellippe Heitor
': This program uses
': This program uses
': InForm-PE for QB64-PE - v1.5.8 based upon InForm by Fellippe Heitor
': Copyright (c) 2025 QB64 Phoenix Edition Team
': https://github.com/QB64-Phoenix-Edition/InForm-PE
'-----------------------------------------------------------

'Improved fireworks:
'    - Particles now leave a trail behind
'    - Round explosions (sin/cos been used...)
'    - Explosion sound effect.

OPTION _EXPLICIT

TYPE Vector
    x AS SINGLE
    y AS SINGLE
END TYPE

TYPE Particle
    Pos AS Vector
    Vel AS Vector
    Acc AS Vector
    Visible AS _BYTE
    Exploded AS _BYTE
    ExplosionStep AS _BYTE
    ExplosionMax AS _BYTE
    Color AS _UNSIGNED LONG
    Size AS _BYTE
END TYPE

REDIM SHARED Firework(1 TO 1) AS Particle
REDIM SHARED Boom(1 TO UBOUND(Firework) * 2, 1) AS Particle
DIM SHARED Trail(1 TO 20000) AS Particle

DIM SHARED StartPointLimit AS SINGLE, InitialVel AS SINGLE
DIM SHARED Gravity AS Vector, Pause AS _BYTE, distant AS LONG

InitialVel = -30
Gravity.y = .8
distant = _SNDOPEN("distant.wav")

RANDOMIZE TIMER

': Controls' IDs: ------------------------------------------------------------------
DIM SHARED BabyYoureAFirework AS LONG
DIM SHARED Canvas AS LONG
DIM SHARED MaxFireworksLB AS LONG
DIM SHARED MaxFireworksTrackBar AS LONG
DIM SHARED MaxParticlesLB AS LONG
DIM SHARED MaxParticlesTrackBar AS LONG
DIM SHARED ShowTextCB AS LONG
DIM SHARED YourTextHereTB AS LONG
DIM SHARED HappyNewYearLB AS LONG

': External modules: ---------------------------------------------------------------
'$INCLUDE:'InForm\InForm.bi'
'$INCLUDE:'InForm\xp.uitheme'
'$INCLUDE:'Fireworks.frm'


': Event procedures: ---------------------------------------------------------------
SUB __UI_BeforeInit

END SUB

SUB __UI_OnLoad
    _TITLE "Baby, you're a firework"
    StartPointLimit = Control(Canvas).Height / 3
    Control(MaxFireworksTrackBar).Value = 20
    Control(MaxParticlesTrackBar).Value = 150
    ToolTip(MaxFireworksTrackBar) = "20"
    ToolTip(MaxParticlesTrackBar) = "150"
    REDIM _PRESERVE Firework(1 TO Control(MaxFireworksTrackBar).Value) AS Particle
    REDIM _PRESERVE Boom(1 TO UBOUND(Firework) * 2, Control(MaxParticlesTrackBar).Value) AS Particle
END SUB

SUB __UI_BeforeUpdateDisplay
    STATIC JustExploded AS _BYTE
    STATIC t AS INTEGER, Initial AS _BYTE, InitialX AS INTEGER, lastInitial#

    DIM AS LONG j, i, a
    DIM AS _UNSIGNED LONG thisColor

    BeginDraw Canvas

    IF JustExploded THEN
        JustExploded = False
        CLS , _RGB32(0, 0, 50)
    ELSE
        CLS
    END IF
    IF _CEIL(RND * 20) < 2 OR (Initial = False AND TIMER - lastInitial# > .1) THEN
        'Create a new particle
        FOR j = 1 TO UBOUND(Firework)
            IF Firework(j).Visible = False THEN
                Firework(j).Vel.y = InitialVel
                Firework(j).Vel.x = 3 - _CEIL(RND * 6)
                IF Initial = True THEN
                    Firework(j).Pos.x = _CEIL(RND * Control(Canvas).Width)
                ELSE
                    Firework(j).Pos.x = InitialX * (Control(Canvas).Width / 15)
                    InitialX = InitialX + 1
                    lastInitial# = TIMER
                    IF InitialX > 15 THEN Initial = True
                END IF
                Firework(j).Pos.y = Control(Canvas).Height + _CEIL(RND * StartPointLimit)
                Firework(j).Visible = True
                Firework(j).Exploded = False
                Firework(j).ExplosionStep = 0
                Firework(j).Size = _CEIL(RND * 2)
                IF Firework(j).Size = 1 THEN
                    Firework(j).ExplosionMax = 9 + _CEIL(RND * 41)
                ELSE
                    Firework(j).ExplosionMax = 9 + _CEIL(RND * 71)
                END IF
                Firework(j).ExplosionMax = 20 '0
                EXIT FOR
            END IF
        NEXT j
    END IF

    'Show trail
    FOR i = 1 TO UBOUND(Trail)
        IF NOT Pause THEN Trail(i).Color = Darken(Trail(i).Color, 70)
        IF Trail(i).Size = 1 THEN
            PSET (Trail(i).Pos.x, Trail(i).Pos.y), Trail(i).Color
        ELSE
            PSET (Trail(i).Pos.x, Trail(i).Pos.y), Trail(i).Color
            PSET (Trail(i).Pos.x - 1, Trail(i).Pos.y), Trail(i).Color
            PSET (Trail(i).Pos.x + 1, Trail(i).Pos.y), Trail(i).Color
            PSET (Trail(i).Pos.x, Trail(i).Pos.y - 1), Trail(i).Color
            PSET (Trail(i).Pos.x, Trail(i).Pos.y + 1), Trail(i).Color
        END IF
    NEXT i

    'Update and show particles
    FOR i = 1 TO UBOUND(Firework)
        'Update trail particles

        IF Firework(i).Visible = True AND Firework(i).Exploded = False AND NOT Pause THEN
            t = t + 1: IF t > UBOUND(Trail) THEN t = 1
            Trail(t).Pos.x = Firework(i).Pos.x
            Trail(t).Pos.y = Firework(i).Pos.y
            Trail(t).Color = _RGB32(255, 255, 255)

            'New position
            Firework(i).Vel.y = Firework(i).Vel.y + Gravity.y
            Firework(i).Pos.y = Firework(i).Pos.y + Firework(i).Vel.y
            Firework(i).Pos.x = Firework(i).Pos.x + Firework(i).Vel.x
        END IF

        'Explode the particle if it reaches max height
        IF Firework(i).Vel.y > 0 THEN
            IF Firework(i).Exploded = False THEN
                Firework(i).Exploded = True
                JustExploded = True

                IF Firework(1).Size = 1 THEN
                    IF distant THEN _SNDPLAYCOPY distant, .5
                ELSE
                    IF distant THEN _SNDPLAYCOPY distant, 1
                END IF

                thisColor~& = _RGB32(_CEIL(RND * 255), _CEIL(RND * 255), _CEIL(RND * 255))
                a = 0
                FOR j = 1 TO UBOUND(Boom, 2)
                    Boom(i, j).Pos.x = Firework(i).Pos.x
                    Boom(i, j).Pos.y = Firework(i).Pos.y
                    Boom(i, j).Vel.y = SIN(a) * (RND * 10)
                    Boom(i, j).Vel.x = COS(a) * (RND * 10)
                    a = a + 1
                    Boom(i, j).Color = thisColor~&

                    Boom(i * 2, j).Pos.x = Firework(i).Pos.x + 5
                    Boom(i * 2, j).Pos.y = Firework(i).Pos.y + 5
                    Boom(i * 2, j).Vel.y = Boom(i, j).Vel.y
                    Boom(i * 2, j).Vel.x = Boom(i, j).Vel.x
                    a = a + 1
                    Boom(i * 2, j).Color = thisColor~&
                NEXT
            END IF
        END IF

        'Show particle
        IF Firework(i).Exploded = False THEN
            IF Firework(i).Size = 1 THEN
                PSET (Firework(i).Pos.x, Firework(i).Pos.y), _RGB32(255, 255, 255)
            ELSE
                PSET (Firework(i).Pos.x, Firework(i).Pos.y), _RGB32(255, 255, 255)
                PSET (Firework(i).Pos.x - 1, Firework(i).Pos.y), _RGB32(255, 255, 255)
                PSET (Firework(i).Pos.x + 1, Firework(i).Pos.y), _RGB32(255, 255, 255)
                PSET (Firework(i).Pos.x, Firework(i).Pos.y - 1), _RGB32(255, 255, 255)
                PSET (Firework(i).Pos.x, Firework(i).Pos.y + 1), _RGB32(255, 255, 255)
            END IF
        ELSEIF Firework(i).Visible THEN
            IF NOT Pause THEN Firework(i).ExplosionStep = Firework(i).ExplosionStep + 1
            FOR j = 1 TO UBOUND(Boom, 2)
                IF Firework(i).Size = 1 THEN
                    PSET (Boom(i, j).Pos.x, Boom(i, j).Pos.y), Boom(i, j).Color
                ELSE
                    PSET (Boom(i, j).Pos.x, Boom(i, j).Pos.y), Darken(Boom(i, j).Color, 100 - (Firework(i).ExplosionStep * 100) / Firework(i).ExplosionMax)
                    PSET (Boom(i, j).Pos.x - 1, Boom(i, j).Pos.y), Darken(Boom(i, j).Color, 100 - (Firework(i).ExplosionStep * 100) / Firework(i).ExplosionMax)
                    PSET (Boom(i, j).Pos.x + 1, Boom(i, j).Pos.y), Darken(Boom(i, j).Color, 100 - (Firework(i).ExplosionStep * 100) / Firework(i).ExplosionMax)
                    PSET (Boom(i, j).Pos.x, Boom(i, j).Pos.y - 1), Darken(Boom(i, j).Color, 100 - (Firework(i).ExplosionStep * 100) / Firework(i).ExplosionMax)
                    PSET (Boom(i, j).Pos.x, Boom(i, j).Pos.y + 1), Darken(Boom(i, j).Color, 100 - (Firework(i).ExplosionStep * 100) / Firework(i).ExplosionMax)
                END IF
                IF NOT Pause THEN
                    t = t + 1: IF t > UBOUND(Trail) THEN t = 1
                    Trail(t).Pos.x = Boom(i, j).Pos.x
                    Trail(t).Pos.y = Boom(i, j).Pos.y
                    Trail(t).Size = Boom(i, j).Size
                    Trail(t).Color = Darken(Boom(i, j).Color, 100 - (Firework(i).ExplosionStep * 100) / Firework(i).ExplosionMax)

                    t = t + 1: IF t > UBOUND(Trail) THEN t = 1
                    Trail(t).Pos.x = Boom(i * 2, j).Pos.x
                    Trail(t).Pos.y = Boom(i * 2, j).Pos.y
                    Trail(t).Size = Boom(i * 2, j).Size
                    Trail(t).Color = Darken(Boom(i * 2, j).Color, 150)

                    Boom(i, j).Vel.y = Boom(i, j).Vel.y + Gravity.y / 10
                    Boom(i, j).Pos.x = Boom(i, j).Pos.x + Boom(i, j).Vel.x '+ Firework(i).Vel.x
                    Boom(i, j).Pos.y = Boom(i, j).Pos.y + Boom(i, j).Vel.y
                    Boom(i * 2, j).Vel.y = Boom(i * 2, j).Vel.y + Gravity.y / 10
                    Boom(i * 2, j).Pos.x = Boom(i * 2, j).Pos.x + Boom(i * 2, j).Vel.x '+ Firework(i).Vel.x
                    Boom(i * 2, j).Pos.y = Boom(i * 2, j).Pos.y + Boom(i * 2, j).Vel.y
                END IF
            NEXT
            IF Firework(i).ExplosionStep > Firework(i).ExplosionMax THEN Firework(i).Visible = False
        END IF
    NEXT

    Control(HappyNewYearLB).Hidden = NOT Control(ShowTextCB).Value

    EndDraw Canvas
END SUB

SUB __UI_BeforeUnload

END SUB

SUB __UI_Click (id AS LONG)
    SELECT CASE id
        CASE BabyYoureAFirework

        CASE Canvas
            Pause = NOT Pause
            IF Pause THEN
                Caption(HappyNewYearLB) = "PAUSED"
            ELSE
                Caption(HappyNewYearLB) = Text(YourTextHereTB)
            END IF
        CASE MaxFireworksLB

        CASE MaxFireworksTrackBar

        CASE MaxParticlesLB

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

        CASE HappyNewYearLB

    END SELECT
END SUB

SUB __UI_MouseEnter (id AS LONG)
    SELECT CASE id
        CASE BabyYoureAFirework

        CASE Canvas

        CASE MaxFireworksLB

        CASE MaxFireworksTrackBar

        CASE MaxParticlesLB

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

        CASE HappyNewYearLB

    END SELECT
END SUB

SUB __UI_MouseLeave (id AS LONG)
    SELECT CASE id
        CASE BabyYoureAFirework

        CASE Canvas

        CASE MaxFireworksLB

        CASE MaxFireworksTrackBar

        CASE MaxParticlesLB

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

        CASE HappyNewYearLB

    END SELECT
END SUB

SUB __UI_FocusIn (id AS LONG)
    SELECT CASE id
        CASE MaxFireworksTrackBar

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

    END SELECT
END SUB

SUB __UI_FocusOut (id AS LONG)
    SELECT CASE id
        CASE MaxFireworksTrackBar

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

    END SELECT
END SUB

SUB __UI_MouseDown (id AS LONG)
    SELECT CASE id
        CASE BabyYoureAFirework

        CASE Canvas

        CASE MaxFireworksLB

        CASE MaxFireworksTrackBar

        CASE MaxParticlesLB

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

        CASE HappyNewYearLB

    END SELECT
END SUB

SUB __UI_MouseUp (id AS LONG)
    SELECT CASE id
        CASE BabyYoureAFirework

        CASE Canvas

        CASE MaxFireworksLB

        CASE MaxFireworksTrackBar

        CASE MaxParticlesLB

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

        CASE HappyNewYearLB

    END SELECT
END SUB

SUB __UI_KeyPress (id AS LONG)
    SELECT CASE id
        CASE MaxFireworksTrackBar

        CASE MaxParticlesTrackBar

        CASE ShowTextCB

        CASE YourTextHereTB

    END SELECT
END SUB

SUB __UI_TextChanged (id AS LONG)
    SELECT CASE id
        CASE YourTextHereTB
            Caption(HappyNewYearLB) = Text(YourTextHereTB)
    END SELECT
END SUB

SUB __UI_ValueChanged (id AS LONG)
    Control(id).Value = INT(Control(id).Value)
    SELECT CASE id
        CASE ShowTextCB

        CASE MaxFireworksTrackBar
            REDIM _PRESERVE Firework(1 TO Control(MaxFireworksTrackBar).Value) AS Particle
            ToolTip(id) = STR$(Control(MaxFireworksTrackBar).Value)
        CASE MaxParticlesTrackBar
            REDIM _PRESERVE Boom(1 TO UBOUND(Firework) * 2, Control(MaxParticlesTrackBar).Value) AS Particle
            ToolTip(id) = STR$(Control(MaxParticlesTrackBar).Value)
    END SELECT
END SUB

SUB __UI_FormResized
END SUB

'$INCLUDE:'InForm\InForm.ui'

Print this item

  Monster Truck
Posted by: MasterGy - 01-29-2026, 10:05 PM - Forum: MasterGy - Replies (25)

you can try :o
the handling is simple. everything is written on the screen. Small code, small size.

Car parameters adjustment, real-time terrain-depth adjustment, intelligent camera, etc...

I still have a lot of things to do.
Thank you for trying it, and thank you for writing me opinions, errors, ideas, requests!

Print this item

  Ctrl + and Ctrl -
Posted by: Pete - 01-29-2026, 08:35 PM - Forum: Help Me! - Replies (8)

So far I've managed to avoid using any Win32API calls in my current project. Ah, but now I'm adding a font increase/decrease function and I'm used to using Ctrl + and Ctrl -, in Firefox, to increase and decrease the font size. So I'd like to use the same key combos in QB64, but...

I don't believe GLUT has a way for us to map those combos, so _KeyHit, _Keydown, Inp, Inkey$, etc. don't seem to have a way to make it so. Simply put, when the control key is held down in QB64, the minus and plus keys (along with some others) are not recognized. At least that's been my experience, but maybe I'm missing something here.

Pete

Print this item

  Interweaving SUB and FUNCTION
Posted by: SMcNeill - 01-29-2026, 02:31 PM - Forum: Learning Resources and Archives - Replies (10)

With v 4.4.0, QB64PE has finally adopted to the QB45 style of allowing users to put SUBS and FUNCTIONS anywhere inside their code.

This was something which QB45 and QBASIC always allowed, but the old IDE had a habit of moving subs to their own windows (if you guys remember), and then it saved them at the end of the code.  You'd have to write code in EDIT or notepad or such, and then compile it from the command line so the IDE wouldn't move those subs/functions automagically on you, but it always has been a part of the language itself.  

It's the reason why QB45 allowed you to use a single file for $INCLUDE libraries and not have to split your work into two files to separate into the top and the bottom of the code.  Just one file at the top and you're good to go with $INCLUDE!

But there is something that folks need to be aware of, and keep in mind -- BASIC has certain commands and precompiler commands which run in a simple TOP TO BOTTOM format, so you can't think of it as the SUBs just being moved to the end of the code.

For example, let's take a look at the following code:

Code: (Select All)
Screen _NewImage(800, 600, 32)

DefInt A-Z

foo

Sub foo
    Print Len(default_variable)
    $If YEP Then
        Print "Yep"
    $Else
        Print "Nope"
    $End If
End Sub

Print
Print "And now we change the DEF and $LET precompiler values"

DefLng A-Z
$Let YEP = TRUE

Print "And let's see if anything has changed with how SUB foo behaves"
foo
Print
Print

Print "But let's see how things look after the change, if used in the main code."
Print Len(default_variable)

$If YEP Then
    Print "Yep"
$Else
        Print "Nope"
$End If

If you notice, the DEFINT is a TOP TO BOTTOM command.  So is the $IF and $LET commands.

Even though we change the DEF *after* the sub, it does nothing to change the default variable types inside the sub.

Same with the $LET.  Where the SUB is located in our code, the $LET isn't defined and thus defaults to FALSE.  Even though we set the precompiler variable AFTER the sub, it's not going to have any affect upon the SUB itself -- even if we call the SUB afterwards.

DEF statements, _DEFINE statements, $CHECKING, $IF, $LET and other such commands work on a simple precompiler TOP TO BOTTOM format.  Keep this in mind and don't think that you can $LET a variable after the SUB and have it affect the sub.  It doesn't work like that.

If you're going to create libraries which rely on DEF statements or $IF conditions, the order of which your commands come is very important.

Code: (Select All)
$LET foo = TRUE
$INCLUDE:'My_Lib.BI'

The above would carry the value of *foo* into the library.

Code: (Select All)
$INCLUDE:'My_Lib.BI'
$LET foo = TRUE

Whereas the above here wouldn't.    Make certain you guys don't get confused now that SUBS and such might be earlier in the code or in the libraries.  Program flow is still as important as ever.  It's just that where you place those SUB/FUNCTION statements has now become a lot more flexible than ever before.

Print this item

  QB64PE v 4.4.0
Posted by: SMcNeill - 01-29-2026, 02:09 PM - Forum: Announcements - Replies (7)

https://github.com/QB64-Phoenix-Edition/...tag/v4.4.0

I know it wasn't long ago that we brought you guys version 4.3.0, but we've got you a brand new shiny and nifty new little 4.4 to enjoy!!

v4.4.0 Latest Enhancements

#670 - Allow interleaving SUB/FUNCTIONs with main program, fixing #504 - @flukiluke
This renders the error Statement cannot be placed between SUBs and FUNCTIONs obsolete.
It also makes building libraries easier, as everything (CONST, TYPE, DIM, SUB, FUNCTION) can go into the same file now.

Library Updates
#674 - Miniaudio rolled back to the previous version - @RhoSigma-QB64
This is now the same version we had in QB64-PE v4.2.0, as the updated version in v4.3.0 had issues with music streaming when tailing at the same time (writing more data to the stream while it is playing).

Bug Fixes
#665 - Export As... fixes - @RhoSigma-QB64
Now auto-closing strings at line end if required.
Fixed look-ahead logic to avoid partly name matches causing wrong output.

#666 - Restore IDE behavior when Autobrackets is disabled - @SteveMcNeill
With the change to autobrackets in v4.3.0, the IDE suddenly started to just skip over end bracket type symbols if one were to type them and the next character was an end bracket. This makes sense with the autobracket enabled, but when it's turned off, those keystrokes should be processed as before, without skipping that next character.

#671 - Do not over-apply auto-semicolon insertion, fixing #575 - @flukiluke
String literals in a PRINT statement may be subject to automatic semicolon insert on either side. For instance, PRINT "abc"123, 123"abc" is equivalent to PRINT "abc"; 123, 213; "abc". The logic was not accounting for the possibility of a comparison operator before/after a string literal, and so PRINT "abc" = "def" gets turned into the invalid PRINT "abc"; <>; "def". These operators are now checked for.



This is one of those enhancements which STEVE thinks everyone should grab and enjoy as soon as possible!!  This does one of the things that I personally think we've been needing for a long time now:

It allows library creators to make libraries with just a single $INCLUDE file in them!!

No longer do you need a *.BI file for the top of your library, and a *.BM file for the bottom of your library.  Just one single file is good enough.  Place it at the start of your code and you're golden!!

Note that this also allows you to do some odd looking stuff, which I really don't recommend, but which *is* technically possible.  Notice the following code:

Code: (Select All)
foo

Sub foo
    Print "Hello";
End Sub

Print " World"

See the SUB in the middle of the program there? 

That's actually 100% QB45-compatible code.  It's not something which we supported before, but it WORKS and has worked in QB45 and QBASIC since forever.  This is why QB45 had only one single $INCLUDE, while old versions of QB64 had to be separated into the top and bottom portions of your code base.

In most cases, writing code like this will make things harder for the programmer to understand and follow, and I discourage doing it.

For people writing library style code for use with $INCLUDE, however, this is a great change as you can now put your entire library into a single file and share it, $INCLUDE it, work with it, format it, and all that as just a single file.

I imagine a LOT of libraries are going to start adapting to this new single file format before long, as it's just easier in general for most of the creators to keep up with things, maintain them, and share them, as a single file, so if you like to $INCLUDE others stuff in your code, you'll probably want to grab the latest version here and update without skipping this release.

Print this item

  Estimated Blood-Alcohol Content Calculator by George McGinn
Posted by: Magdha - 01-29-2026, 10:24 AM - Forum: In-Form - Replies (1)

   

The program uses the following InForm objects:
Form
RadioButton
Button
Label
TextBox
ListBox
CheckBox

Unzip the file and extract the folder into your PEQB64 directory.  In the IDE make sure that you have the Run Option “Save EXE in source folder” checked.

.zip   ebacCalculator.zip (Size: 1,006.11 KB / Downloads: 18)

Help File:

.txt   EBACHelp.txt (Size: 4.08 KB / Downloads: 10)

Code: (Select All)
' ebacCalculator.bas    Version 2.0  10/14/2021
'-----------------------------------------------------------------------------------
'      PROGRAM: ebacCalculator.bas
'        AUTHOR: George McGinn
'
'  DATE WRITTEN: 04/01/2021
'      VERSION: 2.0
'      PROJECT: Estimated Blood-Alcohol Content Calculator
'
'  DESCRIPTION: Program shows many of the functions of using InForm while using
'                most of the original code from the Zenity project. This can now
'                run on all systems (Linux, MAC and Windows).
'
' Written by George McGinn
' Copyright (C)2021 by George McGinn - All Rights Reserved
' Version 1.0 - Created 04/01/2021
' Version 2.0 - Created 10/14/2021
'
' CHANGE LOG
'-----------------------------------------------------------------------------------
' 04/01/2021 v1.0  GJM - New Program (TechBASIC and C++ Versions).
' 06/19/2021 v1.5  GJM - Updated to use Zenity and SHELL commands to run on Linux with
'                        a simple GUI.
' 10/14/2021 v2.0  GJM - Updated to use InForm GUI in place of Zenity an SHELL commands.
'                        Can now run on any OS
'-----------------------------------------------------------------------------------
'  Copyright (C)2021 by George McGinn.  All Rights Reserved.
'
' untitled.bas by George McGinn is licensed under a Creative Commons
' Attribution-NonCommercial 4.0 International. (CC BY-NC 4.0)
'
' Full License Link: https://creativecommons.org/licenses/by-.../legalcode
'
'-----------------------------------------------------------------------------------
' PROGRAM NOTES
'
': This program uses
': InForm - GUI library for QB64 - v1.3
': Fellippe Heitor, 2016-2021 - fellippe@qb64.org - @fellippeheitor
': https://github.com/FellippeHeitor/InForm
'-----------------------------------------------------------------------------------

': Controls' IDs: ------------------------------------------------------------------
DIM SHARED maleRB AS LONG
DIM SHARED femaleRB AS LONG
DIM SHARED AgreeCB AS LONG
DIM SHARED AGREEBT AS LONG
DIM SHARED ebacFRM AS LONG
DIM SHARED SexLB AS LONG
DIM SHARED weightLB AS LONG
DIM SHARED nbrdrinksLB AS LONG
DIM SHARED timeLB AS LONG
DIM SHARED EnterInformationLB AS LONG
DIM SHARED WeightTB AS LONG
DIM SHARED nbrDrinksTB AS LONG
DIM SHARED TimeTB AS LONG
DIM SHARED CancelBT AS LONG
DIM SHARED OKBT AS LONG
DIM SHARED HELPBT AS LONG
DIM SHARED QUITBT AS LONG
DIM SHARED displayResults AS LONG
DIM SHARED informationLB AS LONG

': User-defined Variables: ---------------------------------------------------------
DIM SHARED AS STRING HELPFile
DIM SHARED AS INTEGER SOBER, legalToDrive
DIM SHARED AS STRING Sex
DIM SHARED AS DOUBLE A, T
DIM SHARED AS SINGLE B, OZ, Wt, EBAC

DIM SHARED AS STRING helpcontents, prt_text


': External modules: ---------------------------------------------------------------
'$INCLUDE:'InForm\InForm.bi'
'$INCLUDE:'InForm\xp.uitheme'
'$INCLUDE:'ebacCalculator.frm'

': Event procedures: ---------------------------------------------------------------
SUB __UI_BeforeInit

END SUB

SUB __UI_OnLoad

    ' *** Initialize Variables
    A = 0
    Wt = 0
    B = .0
    T = 0: St = 0
    I = 0
    Bdl = 1.055
    OZ = .5
    SOBER = False: legalToDrive = False
    HELPFile = "EBACHelp.txt"
    displayDisclaimer

END SUB

SUB __UI_BeforeUpdateDisplay
    'This event occurs at approximately 60 frames per second.
    'You can change the update frequency by calling SetFrameRate DesiredRate%

END SUB

SUB __UI_BeforeUnload
    'If you set __UI_UnloadSignal = False here you can
    'cancel the user's request to close.

END SUB

SUB __UI_Click (id AS LONG)
    SELECT CASE id
        CASE ebacFRM

        CASE SexLB

        CASE weightLB

        CASE nbrdrinksLB

        CASE timeLB

        CASE EnterInformationLB

        CASE WeightTB

        CASE nbrDrinksTB

        CASE TimeTB

        CASE informationLB

        CASE displayResults

        CASE AgreeCB

        CASE maleRB
            Sex = "M"

        CASE femaleRB
            Sex = "F"

        CASE AGREEBT
            Answer = MessageBox("Do you want to perform another calculation?            ", "", MsgBox_YesNo + MsgBox_Question)
            IF Answer = MsgBox_Yes THEN
                Control(AgreeCB).Value = False
                Control(AGREEBT).Disabled = True
            ELSE
                Answer = MessageBox("Thank You for using EBAC Calculator. Please Don't Drink and Drive.", "", MsgBox_Ok + MsgBox_Information)
                SYSTEM
            END IF

        CASE CancelBT
            ResetForm

        CASE OKBT
            IF Control(maleRB).Value = False AND Control(femaleRB).Value = False THEN
                Answer = MessageBox("Invalid: You must select either M (male) or F (female). Please Correct.", "", MsgBox_Ok + MsgBox_Information)
                EXIT SUB
            END IF
            A = Control(nbrDrinksTB).Value
            Wt = Control(WeightTB).Value
            T = Control(TimeTB).Value
            calcEBAC
            Control(QUITBT).Disabled = True
            ResetList displayResults
            Text(displayResults) = prt_text

        CASE HELPBT
            ResetList displayResults
            IF _FILEEXISTS(HELPFile) THEN
                DIM fh AS LONG
                fh = FREEFILE
                OPEN HELPFile FOR INPUT AS #fh
                DO UNTIL EOF(fh)
                    LINE INPUT #fh, helpcontents
                    AddItem displayResults, helpcontents
                LOOP
                CLOSE #fh
                Control(displayResults).LastVisibleItem = 0
            ELSE
                Answer = MessageBox("HELP File " + HELPFile$ + " Not Found                            ", "", MsgBox_Ok + MsgBox_Question)
                SYSTEM 1
            END IF

        CASE QUITBT
            Answer = MessageBox("Are you sure you want to QUIT?                    ", "", MsgBox_YesNo + MsgBox_Question)
            IF Answer = MsgBox_Yes THEN
                Answer = MessageBox("Thank You for using EBAC Calculator. Please Don't Drink and Drive.", "", MsgBox_Ok + MsgBox_Information)
                SYSTEM
            END IF

    END SELECT
END SUB

SUB __UI_MouseEnter (id AS LONG)
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_MouseLeave (id AS LONG)
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_FocusIn (id AS LONG)
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_FocusOut (id AS LONG)
    'This event occurs right before a control loses focus.
    'To prevent a control from losing focus, set __UI_KeepFocus = True below.
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_MouseDown (id AS LONG)
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_MouseUp (id AS LONG)
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_KeyPress (id AS LONG)
    'When this event is fired, __UI_KeyHit will contain the code of the key hit.
    'You can change it and even cancel it by making it = 0
    SELECT CASE id
        CASE ELSE
    END SELECT
END SUB

SUB __UI_TextChanged (id AS LONG)
    SELECT CASE id

        CASE WeightTB
            Control(AgreeCB).Value = False
            Control(AGREEBT).Disabled = True

        CASE nbrDrinksTB
            Control(AgreeCB).Value = False
            Control(AGREEBT).Disabled = True

        CASE TimeTB
            Control(AgreeCB).Value = False
            Control(AGREEBT).Disabled = True

    END SELECT
END SUB

SUB __UI_ValueChanged (id AS LONG)
    SELECT CASE id

        CASE displayResults

        CASE maleRB
            Control(AgreeCB).Value = False
            Control(AGREEBT).Disabled = True

        CASE femaleRB
            Control(AgreeCB).Value = False
            Control(AGREEBT).Disabled = True

        CASE AgreeCB
            IF Control(AgreeCB).Value = True THEN
                Control(AGREEBT).Disabled = False
                Control(QUITBT).Disabled = False
            ELSE
                Control(AGREEBT).Disabled = True
                Control(QUITBT).Disabled = True
            END IF

    END SELECT
END SUB

SUB __UI_FormResized
END SUB


': User FUNCTIONS/SUBROUTINES: ---------------------------------------------------------------

SUB displayDisclaimer

    '    prt_text = "*** DISCLAIMER ***" + CHR$(10)
    prt_text = "Unless otherwise separately undertaken by the Licensor, to the extent" + CHR$(10)
    prt_text = prt_text + "possible, the Licensor offers the Licensed Material as-is and" + CHR$(10)
    prt_text = prt_text + "as-available, and makes no representations or warranties of any kind" + CHR$(10)
    prt_text = prt_text + "concerning the Licensed Material, whether express, implied, statutory," + CHR$(10)
    prt_text = prt_text + "or other. This includes, without limitation, warranties of title," + CHR$(10)
    prt_text = prt_text + "merchantability, fitness for a particular purpose, non-infringement," + CHR$(10)
    prt_text = prt_text + "absence of latent or other defects, accuracy, or the presence or absence" + CHR$(10)
    prt_text = prt_text + "of errors, whether or not known or discoverable. Where disclaimers of" + CHR$(10)
    prt_text = prt_text + "warranties are not allowed in full or in part, this disclaimer may not" + CHR$(10)
    prt_text = prt_text + "apply to You." + CHR$(10) + CHR$(10)

    prt_text = prt_text + "To the extent possible, in no event will the Licensor be liable to You" + CHR$(10)
    prt_text = prt_text + "on any legal theory (including, without limitation, negligence) or" + CHR$(10)
    prt_text = prt_text + "otherwise for any direct, special, indirect, incidental, consequential," + CHR$(10)
    prt_text = prt_text + "punitive, exemplary, or other losses, costs, expenses, or damages" + CHR$(10)
    prt_text = prt_text + "arising out of this Public License or use of the Licensed Material, even" + CHR$(10)
    prt_text = prt_text + "if the Licensor has been advised of the possibility of such losses," + CHR$(10)
    prt_text = prt_text + "costs, expenses, or damages. Where a limitation of liability is not" + CHR$(10)
    prt_text = prt_text + "allowed in full or in part, this limitation may not apply to You." + CHR$(10) + CHR$(10)

    prt_text = prt_text + "The disclaimer of warranties and limitation of liability provided above" + CHR$(10)
    prt_text = prt_text + "shall be interpreted in a manner that, to the extent possible, most" + CHR$(10)
    prt_text = prt_text + "closely approximates an absolute disclaimer and waiver of all liability." + CHR$(10)

    Answer = MessageBox(prt_text, "*** DISCLAIMER ***", MsgBox_YesNo + MsgBox_Question)
    IF Answer = MsgBox_No THEN
        Answer = MessageBox("Sorry you don't agree. Please Don't Drink and Drive.", "", MsgBox_Ok + MsgBox_Information)
        SYSTEM
    END IF

END SUB


SUB ResetForm
    Control(nbrDrinksTB).Value = 0
    Control(WeightTB).Value = 0
    Control(TimeTB).Value = 0
    Control(AgreeCB).Value = False
    Control(AGREEBT).Disabled = True
    Control(maleRB).Value = False
    Control(femaleRB).Value = False
    ResetList displayResults
    Sex = ""
END SUB


SUB calcEBAC
    '-------------------------------------------------------------
    ' *** Convert Drinks into Fluid Ounces of EtOH (Pure Alcohol).
    ' *** A is number of drinks. 1 drink is about .6 FLoz of alcohol
    FLoz = A * OZ
    legalToDrive = False

    '-----------------------------------------------------
    ' *** Set/calculate EBAC values based on Sex
    SELECT CASE Sex
        CASE "M"
            B = .017
            EBAC = 7.97 * FLoz / Wt - B * T
        CASE "F"
            B = .019
            EBAC = 9.86 * FLoz / Wt - B * T
    END SELECT

    IF EBAC < 0 THEN EBAC = 0

    '----------------------------------------------------------------------------------------------
    ' *** Populate the EBAC string with the EBAC value formatted to 3 decimal places for FORM output
    prt_text = "ESTIMATED BLOOD ALCOHOL CONTENT (EBAC) in g/dL = " + strFormat$(STR$(EBAC), "###.###") + CHR$(10) + CHR$(10)


    '-----------------------------------------------------------------------------------------
    ' *** Based on EBAC range values, populate the FORM output string with the approriate text
    SELECT CASE EBAC
        CASE .500 TO 100.9999
            prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, DEATH LIKELY" + CHR$(10)
            prt_text = prt_text + "Unconsious/coma, unresponsive, high likelihood of death. It is illegal" + CHR$(10) + _
                                  "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
        CASE .400 TO .4999
            prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, DEATH POSSIBLE" + CHR$(10)
            prt_text = prt_text + "Onset of coma, and possible death due to respiratory arrest. It is illegal" + CHR$(10) + _
                                  "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
        CASE .350 TO .3999
            prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, SEVERE ALCOHOL POISONING" + CHR$(10)
            prt_text = prt_text + " Coma is possible. This is the level of surgical anesthesia. It is illegal" + CHR$(10) + _
                                  "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
        CASE .300 TO .3499
            prt_text = prt_text + "*** ALERT: YOU ARE IN A DRUNKEN STUP0R, AT RISK TO PASSING OUT" + CHR$(10)
            prt_text = prt_text + "STUPOR. You have little comprehension of where you are. You may pass out" + CHR$(10) + _
                                  "suddenly and be difficult to awaken. It is illegal to operate a motor" + CHR$(10) + _
                                  "vehicle at this level of intoxication in all states." + CHR$(10)
        CASE .250 TO .2999
            prt_text = prt_text + "*** ALERT: SEVERLY IMPAIRED - DRUNK ENOUGH TO CAUSE SEVERE INJURY/DEATH TO SELF" + CHR$(10)
            prt_text = prt_text + "All mental, physical and sensory functions are severely impaired." + CHR$(10) + _
                                  "Increased risk of asphyxiation from choking on vomit and of seriously injuring" + CHR$(10) + _
                                  "yourself by falls or other accidents. It is illegal to operate a motor" + CHR$(10) + _
                                  "vehicle at this level of intoxication in all states." + CHR$(10)
        CASE .200 TO .2499
            prt_text = prt_text + "YOU ARE EXTREMELY DRUNK" + CHR$(10)
            prt_text = prt_text + "Feeling dazed/confused or otherwise disoriented. May need help to" + CHR$(10) + _
                                  "stand/walk. If you injure yourself you may not feel the pain. Some" + CHR$(10) + _
                                  "people have nausea and vomiting at this level. The gag reflex" + CHR$(10) + _
                                  "is impaired and you can choke if you do vomit. Blackouts are likely" + CHR$(10) + _
                                  "at this level so you may not remember what has happened. It is illegal" + CHR$(10) + _
                                  "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
        CASE .160 TO .1999
            prt_text = prt_text + "YOUR ARE SEVERLY DRUNK - ENOUGH TO BECOME VERY SICK" + CHR$(10)
            prt_text = prt_text + "Dysphoria* predominates, nausea may appear. The drinker has the appearance" + CHR$(10) + _
                                  "of a 'sloppy drunk.' It is illegal to operate a motor vehicle at this level" + CHR$(10) + _
                                  "of intoxication in all states." + CHR$(10) + CHR$(10) + _
                                  "* Dysphoria: An emotional state of anxiety, depression, or unease." + CHR$(10)
        CASE .130 TO .1599
            prt_text = prt_text + "YOU ARE VERY DRUNK - ENOUGH TO LOSE PHYSICAL & MENTAL CONTROL" + CHR$(10)
            prt_text = prt_text + "Gross motor impairment and lack of physical control. Blurred vision and major" + CHR$(10) + _
                                  "loss of balance. Euphoria is reduced and dysphoria* is beginning to appear." + CHR$(10) + _
                                  "Judgment and perception are severely impaired. It is illegal to operate a " + CHR$(10) + _
                                  "motor vehicle at this level of intoxication in all states." + CHR$(10) + CHR$(10)
            prt_text = prt_text + "* Dysphoria: An emotional state of anxiety, depression, or unease." + CHR$(10)
        CASE .100 TO .1299
            prt_text = prt_text + "YOU ARE LEGALLY DRUNK" + CHR$(10)
            prt_text = prt_text + "Significant impairment of motor coordination and loss of good judgment." + CHR$(10) + _
                                  "Speech may be slurred; balance, vision, reaction time and hearing will be" + CHR$(10) + _
                                  "impaired. Euphoria. It is illegal to operate a motor vehicle at this level" + CHR$(10) + _
                                  "of intoxication in all states." + CHR$(10)
        CASE .070 TO .0999
            prt_text = prt_text + "YOU MAY BE LEGALLY DRUNK" + CHR$(10)
            prt_text = prt_text + "Slight impairment of balance, speech, vision, reaction time, and hearing." + CHR$(10) + _
                                  "Euphoria. Judgment and self-control are reduced, and caution, reason and" + CHR$(10) + _
                                  "memory are impaired (in some* states .08 is legally impaired and it is illegal" + CHR$(10) + _
                                  "to drive at this level). You will probably believe that you are functioning" + CHR$(10) + _
                                  "better than you really are." + CHR$(10) + CHR$(10)
            prt_text = prt_text + "(*** As of July, 2004 ALL states had passed .08 BAC Per Se Laws. The final" + CHR$(10) + _
                                  "one took effect in August of 2005.)" + CHR$(10)
        CASE .040 TO .0699
            prt_text = prt_text + "YOU MAY BE LEGALLY BUZZED" + CHR$(10)
            prt_text = prt_text + "Feeling of well-being, relaxation, lower inhibitions, sensation of warmth." + CHR$(10) + _
                                  "Euphoria. Some minor impairment of reasoning and memory, lowering of caution." + CHR$(10) + _
                                  "Your behavior may become exaggerated and emotions intensified (Good emotions" + CHR$(10) + _
                                  "are better, bad emotions are worse)" + CHR$(10)
        CASE .020 TO .0399
            prt_text = prt_text + "YOU MAY BE OK TO DRIVE, BUT IMPAIRMENT BEGINS" + CHR$(10)
            prt_text = prt_text + "No loss of coordination, slight euphoria and loss of shyness. Depressant effects" + CHR$(10) + _
                                  "are not apparent. Mildly relaxed and maybe a little lightheaded." + CHR$(10)
        CASE .000 TO .0199
            prt_text = prt_text + "YOU ARE OK TO DRIVE" + CHR$(10)
    END SELECT

    '-----------------------------------------------------------
    '*** Determine if Drunk (>.08 EBAC) and calculate:
    '***    - When user will be less than .08
    '***    - How long it will take to become completely sober
    IF EBAC > .08 THEN
        SOBER = False
        CEBAC = EBAC
        st = T
        DO UNTIL SOBER = True
            T = T + 1
            IF CEBAC > .0799 THEN I = I + 1

            SELECT CASE Sex
                CASE "M"
                    B = .017
                    CEBAC = 7.97 * FLoz / Wt - B * T
                CASE "F"
                    B = .019
                    CEBAC = 9.86 * FLoz / Wt - B * T
            END SELECT

            IF legalToDrive = False THEN
                IF CEBAC < .08 THEN
                    prt_text = prt_text + CHR$(10) + CHR$(10) + "It will take about " + strFormat$(STR$(I), "##") + " hours from your last drink to be able to drive." + CHR$(10)
                    legalToDrive = True
                END IF
            END IF

            IF CEBAC <= 0 THEN
                prt_text = prt_text + "It will take about " + strFormat$(STR$(T - st), "##") + " hours from your last drink to be completely sober."
                SOBER = True
            END IF
        LOOP
    END IF

END SUB


FUNCTION strFormat$ (text AS STRING, template AS STRING)
    '-----------------------------------------------------------------------------
    ' *** Return a formatted string to a variable
    '
    d = _DEST: s = _SOURCE
    n = _NEWIMAGE(80, 80, 0)
    _DEST n: _SOURCE n
    PRINT USING template; VAL(text)
    FOR i = 1 TO 79
        t$ = t$ + CHR$(SCREEN(1, i))
    NEXT
    IF LEFT$(t$, 1) = "%" THEN t$ = MID$(t$, 2)
    strFormat$ = _TRIM$(t$)
    _DEST d: _SOURCE s
    _FREEIMAGE n
END FUNCTION

'$INCLUDE:'InForm\InForm.ui'

Print this item

  3D Text
Posted by: SMcNeill - 01-29-2026, 02:56 AM - Forum: Works in Progress - Replies (13)

I was hoping to use _MAPTRIANGLE and create a form of 3D text which might end up looking nice and being all rotatable and tiltable and scalable and such.

What I've got is *this* so far:

Code: (Select All)
$Color:32
Screen _NewImage(1024, 768, 32)
font& = _LoadFont("C:\Windows\Fonts\arial.ttf", 48)

Do
    Cls
    Line (512 - 5, 384)-(512 + 5, 384), _RGB(255, 0, 0)
    Line (512, 384 - 5)-(512, 384 + 5), _RGB(255, 0, 0)

    k = _KeyHit
    Select Case k
        Case 18432 'up
            y = y - 1
        Case 20480 'down
            y = y + 1
        Case 19200 'left
            x = x - 1
        Case 19712 'right
            x = x + 1
        Case Asc("A"), Asc("a")
            z = z - 1
        Case Asc("Z"), Asc("z")
            z = z + 1
        Case Asc("R"), Asc("r") 'reset
            x = 0: y = 0: z = 0
        Case 27, 32
            System
    End Select
    Print x, y, z
    Draw3DTextFull "QB64PE 3D!", font&, Yellow, 512, 384, y, x, z, 2, 10, 10, 1
    _Display
Loop
System


Sub Draw3DTextFull (text$, fontHandle&, col~&, x!, y!, rotX!, rotY!, rotZ!, scale!, depth%, dirX!, dirY!)
    Dim img&, w%, h%
    Dim i%

    ' Measure text using the chosen font
    _Font fontHandle&
    w% = _PrintWidth(text$)
    h% = _FontHeight

    ' Render text into image using the SAME font
    img& = _NewImage(w%, h%, 32)
    _Dest img&
    _Font fontHandle& ' <<< CRITICAL FIX
    Cls , _RGBA(0, 0, 0, 0)
    Color col~&, 0
    _PrintString (0, 0), text$
    _Dest 0

    ' Convert angles to radians
    Dim ax!, ay!, az!
    ax! = rotX! * _Pi / 180
    ay! = rotY! * _Pi / 180
    az! = rotZ! * _Pi / 180

    ' Precompute sin/cos
    Dim cx!, sx!, cy!, sy!, cz!, sz!
    cx! = Cos(ax!): sx! = Sin(ax!)
    cy! = Cos(ay!): sy! = Sin(ay!)
    cz! = Cos(az!): sz! = Sin(az!)

    ' Quad centered at origin (unscaled)
    Dim p(3, 2)
    p(0, 0) = -w% / 2: p(0, 1) = -h% / 2: p(0, 2) = 0 ' TL
    p(1, 0) = w% / 2: p(1, 1) = -h% / 2: p(1, 2) = 0 ' TR
    p(2, 0) = -w% / 2: p(2, 1) = h% / 2: p(2, 2) = 0 ' BL
    p(3, 0) = w% / 2: p(3, 1) = h% / 2: p(3, 2) = 0 ' BR

    Dim vx!, vy!, vz!
    Dim rx!, ry!, rz!
    Dim px!(3), py!(3)

    ' Rotate and scale quad
    For i% = 0 To 3
        vx! = p(i%, 0) * scale!
        vy! = p(i%, 1) * scale!
        vz! = p(i%, 2) * scale!

        ' Rotate around X
        ry! = vy! * cx! - vz! * sx!
        rz! = vy! * sx! + vz! * cx!
        vy! = ry!: vz! = rz!

        ' Rotate around Y
        rx! = vx! * cy! + vz! * sy!
        rz! = -vx! * sy! + vz! * cy!
        vx! = rx!: vz! = rz!

        ' Rotate around Z
        rx! = vx! * cz! - vy! * sz!
        ry! = vx! * sz! + vy! * cz!
        vx! = rx!: vy! = ry!

        px!(i%) = vx!
        py!(i%) = vy!
    Next

    ' Recenter quad to (x!, y!)
    Dim cx2!, cy2!
    cx2! = (px!(0) + px!(1) + px!(2) + px!(3)) / 4
    cy2! = (py!(0) + py!(1) + py!(2) + py!(3)) / 4

    Dim shiftX!, shiftY!
    shiftX! = x! - cx2!
    shiftY! = y! - cy2!

    For i% = 0 To 3
        px!(i%) = px!(i%) + shiftX!
        py!(i%) = py!(i%) + shiftY!
    Next

    ' Normalize extrusion direction
    Dim mag!
    mag! = Sqr(dirX! * dirX! + dirY! * dirY!)
    If mag! = 0 Then dirX! = 1: dirY! = 1: mag! = Sqr(2)
    dirX! = dirX! / mag!
    dirY! = dirY! / mag!

    ' Draw extrusion (per-pixel depth)

    For i% = depth% To 1 Step -1
        Dim ex!, ey!
        ex! = dirX! * i%
        ey! = dirY! * i%

        ' Triangle 1
        _MAPTRIANGLE (0, 0)-(w%, 0)-(0, h%), img& TO _
                    (px!(0) + ex!, py!(0) + ey!)- _
                    (px!(1) + ex!, py!(1) + ey!)- _
                    (px!(2) + ex!, py!(2) + ey!)

        ' Triangle 2
        _MAPTRIANGLE (0, h%)-(w%, 0)-(w%, h%), img& TO _
                    (px!(2) + ex!, py!(2) + ey!)- _
                    (px!(1) + ex!, py!(1) + ey!)- _
                    (px!(3) + ex!, py!(3) + ey!)
    Next

    ' Draw front face
    _MAPTRIANGLE (0, 0)-(w%, 0)-(0, h%), img& TO _
                (px!(0), py!(0))-(px!(1), py!(1))-(px!(2), py!(2))

    _MAPTRIANGLE (0, h%)-(w%, 0)-(w%, h%), img& TO _
                (px!(2), py!(2))-(px!(1), py!(1))-(px!(3), py!(3))

    _FreeImage img&
End Sub


You can see where I was hoping to add a depth to my text and have maptriangle make it more of a 3d text, but I haven't got there yet.

BUT at this point I *can* rotate on the X/Y/Z axis with my text!  And I can scale the text!

I just need to sorts out how to make my 2D text look more 3D, and at the moment I'm thunking my head against the keyboard and not getting the effect I was looking for.  Peter, Unseen, MasterGy.... You guys are much better at this 3D stuff than I am.  Any ideas on how to get that depth working with my text here?

Feel free to modify, expand, blow up this code as you will.  I'll keep pondering and working with it, but hopefully one of you guys will have some insight into this.  I remember ages ago that Galleon did a demo of mapping a 2D sprite of mario in a car and making it look pseduo-3d.  Does anyone have that old demo saved anywhere?  It seems to almost be what I'm looking to do here and might be a good place to start on getting to it do that final 3d enhancement.

Print this item

  Filled Arc
Posted by: SMcNeill - 01-28-2026, 02:27 PM - Forum: SMcNeill - Replies (29)

I've been working on filling in some of the missing tools in my draw library and one thing I noticed that I was missing was a really good filled arc routine.   QB64's method was to draw a circle, choose a point inside the arc, and then use PAINT to fill that circle....

and it didn't work as it never seemed to properly close the arcs and then the paint bled out and colored the entire screen.

The CircleFill that I shared and everyone has used for ages and ages works off LINE statements and thus can never bleed outside the circle itself.  It's fast and lovely and nice.

And so, I thought, can I come up with a similar way to do ARCs?  

After a few different tries, this is what I've came up with -- a scanline polygon fill routine for arcs.

Code: (Select All)
$Color:32
Screen _NewImage(1024, 720, 32)

FilledArc 400, 300, 200, 150, 30, _RGB32(0, 180, 255)
Sleep
Cls , Red
FilledArc 400, 300, 200, 0, 360, _RGBA32(125, 0, 180, 255)
Sleep
Cls , White

' Draw a ring arc from 30 to 300, inner radius 100, outer radius 200
FilledRingArc 400, 300, 150, 200, 30, 300, _RGB32(255, 180, 0)
Sleep
' ---------------------------------------------------------
' TEST DRAWING
' ---------------------------------------------------------

Cls

Color _RGB32(255, 255, 255)

Print "Elliptical Arc / Ring Arc Test"
Print "Press any key to exit."

' Pie slice
FilledEllipseArc 250, 250, 200, 120, 20, 200, _RGB32(0, 180, 255)
Print "(1) Filled Elliptical Arc at (250,250)"

' Ring arc
FilledEllipseRingArc 700, 250, 80, 40, 200, 120, 45, 300, _RGB32(255, 150, 0)
Print "(2) Filled Elliptical Ring Arc at (700,250)"

' Another test arc
FilledEllipseArc 250, 300, 150, 250, 270, 360, _RGB32(0, 255, 120)
Print "(3) Tall Elliptical Arc at (250,300)"

' Another ring arc
FilledEllipseRingArc 700, 500, 50, 100, 180, 250, 0, 180, _RGB32(200, 80, 255)
Print "(4) Vertical Ring Arc at (700,500)"

Sleep
End

Sub FilledRingArc (cx As Long, cy As Long, r1 As Long, r2 As Long, a1 As Single, a2 As Single, col As _Unsigned Long)
    ' Draws a filled ring arc (donut slice)
    ' cx, cy  = center
    ' r1      = inner radius
    ' r2      = outer radius
    ' a1, a2  = start/end angles in degrees
    ' col    = fill color

    Const angStep! = 1! ' smaller = smoother arc
    Dim As Single vx(0 To 2000), vy(0 To 2000), interX(0 To 2000)
    Dim As Single angle, x, y, x1, y1, x2, y2, temp
    Dim As Long count, i, j, n, minY, maxY, yScan

    ' Normalize angles
    If a1 < 0 _OrElse a1 > 360 Then a1 = a1 Mod 360
    If a2 < 0 _OrElse a2 > 360 Then a2 = a2 Mod 360
    If a2 < a1 Then a2 = a2 + 360

    ' ---- Outer arc (A1 ? A2) ----
    For angle = a1 To a2 Step angStep
        x = cx + r2 * Cos(_D2R(angle)): y = cy - r2 * Sin(_D2R(angle)): vx(n) = x: vy(n) = y: n = n + 1
    Next

    ' Ensure exact endpoint
    x = cx + r2 * Cos(_D2R(a2)): y = cy - r2 * Sin(_D2R(a2)): vx(n) = x: vy(n) = y: n = n + 1

    ' ---- Inner arc (A2 ? A1, reversed) ----
    For angle = a2 To a1 Step -angStep
        x = cx + r1 * Cos(_D2R(angle)): y = cy - r1 * Sin(_D2R(angle)): vx(n) = x: vy(n) = y: n = n + 1
    Next

    ' Ensure exact endpoint
    x = cx + r1 * Cos(_D2R(a1)): y = cy - r1 * Sin(_D2R(a1)): vx(n) = x: vy(n) = y: n = n + 1

    ' ---- Scanline fill ----
    minY = vy(0): maxY = vy(0)
    For i = 1 To n - 1: maxY = _Max(maxY, vy(i)): minY = _Min(minY, vy(i)): Next

    For yScan = minY To maxY
        count = 0
        ' Find intersections
        For i = 0 To n - 1
            j = (i + 1) Mod n: x1 = vx(i): y1 = vy(i): x2 = vx(j): y2 = vy(j)
            If (y1 <= yScan And y2 > yScan) Or (y2 <= yScan And y1 > yScan) Then
                If y2 <> y1 Then interX(count) = x1 + (yScan - y1) * (x2 - x1) / (y2 - y1): count = count + 1
            End If
        Next
        ' Sort intersections
        For i = 0 To count - 2
            For j = i + 1 To count - 1
                If interX(j) < interX(i) Then Swap interX(i), interX(j)
        Next j, i
        ' Draw spans
        For i = 0 To count - 2 Step 2
            Line (CLng(interX(i)), yScan)-(CLng(interX(i + 1)), yScan), col, BF
        Next
    Next yScan
End Sub




Sub FilledArc (cx As Long, cy As Long, r As Long, a1 As Single, a2 As Single, col As _Unsigned Long)
    $Checking:Off
    ' Filled arc (pie slice) using only LINE (scanline polygon fill)
    ' cx, cy  = center of circle
    ' r      = radius
    ' a1, a2  = start and end angles in degrees (0 = right, 90 = up)
    ' col    = color

    Const angStep! = 1! ' angle step in degrees (smaller = smoother arc)
    Dim As Single vx(0 To 720), vy(0 To 720), angle, x, y
    Dim As Single interX(0 To 720), x1, y1, x2, y2
    Dim As Long i, n, count, yScan, j, k, temp, minY, maxY

    ' Normalize angles
    If a1 < 0 _OrElse a1 > 360 Then a1 = a1 Mod 360
    If a2 < 0 _OrElse a2 > 360 Then a2 = a2 Mod 360
    If a2 < a1 Then a2 = a2 + 360

    ' Build polygon: start at center
    vx(0) = cx: vy(0) = cy: n = 1

    ' Arc edge points
    For angle = a1 To a2 Step angStep 'with a higher anglestep we have a less rounded arc and more of a polygon figure
        x = cx + r * Cos(_D2R(angle)): y = cy - r * Sin(_D2R(angle))
        vx(n) = x: vy(n) = y: n = n + 1
    Next angle

    ' Ensure last point exactly at a2
    x = cx + r * Cos(_D2R(a2)): y = cy - r * Sin(_D2R(a2))
    vx(n) = x: vy(n) = y: n = n + 1

    ' Close polygon back to center
    vx(n) = cx: vy(n) = cy: n = n + 1

    ' --- Scanline fill of polygon ---
    minY = vy(0): maxY = vy(0)
    For i = 1 To n - 1: maxY = _Max(maxY, vy(i)): minY = _Min(minY, vy(i)): Next

    For yScan = minY To maxY
        ' Find intersections of scanline with each edge
        count = 0
        For i = 0 To n - 1
            j = (i + 1) Mod n
            x1 = vx(i): y1 = vy(i): x2 = vx(j): y2 = vy(j)
            ' Check if edge crosses this scanline
            If (y1 <= yScan And y2 > yScan) Or (y2 <= yScan And y1 > yScan) Then
                If y2 <> y1 Then interX(count) = x1 + (yScan - y1) * (x2 - x1) / (y2 - y1): count = count + 1
            End If
        Next
        ' Sort intersections (simple bubble sort; count is small)
        For i = 0 To count - 2
            For j = i + 1 To count - 1
                If interX(j) < interX(i) Then Swap interX(i), interX(j)
        Next j, i

        ' Draw horizontal spans between pairs of intersections
        For i = 0 To count - 2 Step 2
            Line ((interX(i)), yScan)-((interX(i + 1)), yScan), col, BF
        Next
    Next yScan
    $Checking:On
End Sub

Sub FilledEllipseArc (cx As Long, cy As Long, a As Long, b As Long, a1 As Single, a2 As Single, col As _Unsigned Long)
    $Checking:Off

    ' Filled elliptical arc (pie slice) using only LINE
    ' cx, cy = center
    ' a, b = ellipse radii (horizontal, vertical)
    ' a1, a2 = start/end angles in degrees
    ' col = color

    Const angStep! = 1! ' angle step in degrees (smaller = smoother arc)
    Dim As Single vx(0 To 2000), vy(0 To 2000), angle, x, y
    Dim As Single interX(0 To 2000), x1, y1, x2, y2
    Dim As Long i, n, count, yScan, j, k, temp, minY, maxY

    ' Normalize angles
    If a1 < 0 _OrElse a1 > 360 Then a1 = a1 Mod 360
    If a2 < 0 _OrElse a2 > 360 Then a2 = a2 Mod 360
    If a2 < a1 Then a2 = a2 + 360

    ' Build polygon: start at center
    vx(0) = cx: vy(0) = cy: n = 1

    ' Arc edge points
    For angle = a1 To a2 Step angStep 'with a higher anglestep we have a less rounded arc and more of a polygon figure
        x = cx + a * Cos(_D2R(angle)): y = cy - b * Sin(_D2R(angle))
        vx(n) = x: vy(n) = y: n = n + 1
    Next angle

    ' Ensure last point exactly at a2
    x = cx + a * Cos(_D2R(a2)): y = cy - b * Sin(_D2R(a2))
    vx(n) = x: vy(n) = y: n = n + 1

    ' Close polygon back to center
    vx(n) = cx: vy(n) = cy: n = n + 1

    ' --- Scanline fill of polygon ---
    minY = vy(0): maxY = vy(0)
    For i = 1 To n - 1: maxY = _Max(maxY, vy(i)): minY = _Min(minY, vy(i)): Next

    For yScan = minY To maxY
        ' Find intersections of scanline with each edge
        count = 0
        For i = 0 To n - 1
            j = (i + 1) Mod n
            x1 = vx(i): y1 = vy(i): x2 = vx(j): y2 = vy(j)
            ' Check if edge crosses this scanline
            If (y1 <= yScan And y2 > yScan) Or (y2 <= yScan And y1 > yScan) Then
                If y2 <> y1 Then interX(count) = x1 + (yScan - y1) * (x2 - x1) / (y2 - y1): count = count + 1
            End If
        Next
        ' Sort intersections (simple bubble sort; count is small)
        For i = 0 To count - 2
            For j = i + 1 To count - 1
                If interX(j) < interX(i) Then Swap interX(i), interX(j)
        Next j, i

        ' Draw horizontal spans between pairs of intersections
        For i = 0 To count - 2 Step 2
            Line ((interX(i)), yScan)-((interX(i + 1)), yScan), col, BF
        Next
    Next yScan
    $Checking:On
End Sub


' Filled elliptical ring arc using only LINE
' cx, cy  = center
' a1, b1  = inner ellipse radii
' a2, b2  = outer ellipse radii
' ang1, ang2 = start/end angles
' col    = fill color

Sub FilledEllipseRingArc (cx As Long, cy As Long, a1 As Long, b1 As Long, a2 As Long, b2 As Long, ang1 As Single, ang2 As Single, col As _Unsigned Long)

    Const angStep! = 2!

    Dim vx(0 To 4000) As Single
    Dim vy(0 To 4000) As Single
    Dim interX(0 To 4000) As Single
    Dim count As Long
    Dim yScan As Long
    Dim x1 As Single, y1 As Single, x2 As Single, y2 As Single
    Dim j As Long, temp As Single

    Dim minY As Long, maxY As Long
    Dim i As Long

    Dim n As Long
    Dim angle As Single
    Dim x As Single, y As Single

    If ang2 < ang1 Then ang2 = ang2 + 360

    n = 0

    ' ---- Outer ellipse arc (ang1 ? ang2) ----
    For angle = ang1 To ang2 Step angStep
        x = cx + a2 * Cos(angle * _Pi / 180)
        y = cy - b2 * Sin(angle * _Pi / 180)
        vx(n) = x: vy(n) = y: n = n + 1
    Next

    ' Exact endpoint
    x = cx + a2 * Cos(ang2 * _Pi / 180)
    y = cy - b2 * Sin(ang2 * _Pi / 180)
    vx(n) = x: vy(n) = y: n = n + 1

    ' ---- Inner ellipse arc (ang2 ? ang1, reversed) ----
    For angle = ang2 To ang1 Step -angStep
        x = cx + a1 * Cos(angle * _Pi / 180)
        y = cy - b1 * Sin(angle * _Pi / 180)
        vx(n) = x: vy(n) = y: n = n + 1
    Next

    ' Exact endpoint
    x = cx + a1 * Cos(ang1 * _Pi / 180)
    y = cy - b1 * Sin(ang1 * _Pi / 180)
    vx(n) = x: vy(n) = y: n = n + 1

    ' ---- Scanline fill (same as before) ----

    minY = vy(0): maxY = vy(0)
    For i = 1 To n - 1
        If vy(i) < minY Then minY = vy(i)
        If vy(i) > maxY Then maxY = vy(i)
    Next


    For yScan = minY To maxY

        count = 0

        For i = 0 To n - 1
            j = (i + 1) Mod n
            x1 = vx(i): y1 = vy(i)
            x2 = vx(j): y2 = vy(j)

            If (y1 <= yScan And y2 > yScan) Or (y2 <= yScan And y1 > yScan) Then
                If y2 <> y1 Then
                    interX(count) = x1 + (yScan - y1) * (x2 - x1) / (y2 - y1)
                    count = count + 1
                End If
            End If
        Next

        ' Sort intersections
        For i = 0 To count - 2
            For j = i + 1 To count - 1
                If interX(j) < interX(i) Then Swap interX(i), interX(j)
        Next j, i

        ' Draw spans
        For i = 0 To count - 2 Step 2
            Line (CLng(interX(i)), yScan)-(CLng(interX(i + 1)), yScan), col, BF
        Next

    Next yScan
End Sub
It does all the math first and calculates all those points which make up the edges of the circle and the lines of the sides of the arc, and then it draws the lines which makes up the circle.

This seems to work for me, and it seems to work nice and fast enough as to be usable in any program I might have.

You math guru's make take a look at this, go over it with a fine tooth comb like everyone did the CircleFill routine and see what might be improved with it, and share your thoughts with us, if you would.  Without a whole lot of other versions to compare against, I don't know whether to call this really speedy or not.

At the moment, it seems suitable for my personal usage.  I dunno if others have better or faster versions which do the same thing.  If so, please share and let's compare!

(Note that you can really see the polygon code in action if you change the CONST inside the routine.  Heck, there might even be times where you WANT to do so, for some particular reason or the other.  Change it to something like 10! or 20! and then see how our circle looks.  It'll be obvious with those values as to what it's doing for us.  (You can also make the routine *faster* if desired by going with a rougher circle.  Change the value to 2 or 5 and it's not that visually different, but it changes our polygon count by that step.)

CircleFill is nice and fast.  This is my attempt to see if I can do the same style fastness for an ArcFill.  Let me know what you guys think about it.  Wink



EDIT:  Condensed version which wraps all commands to the main routine can be found here: https://qb64phoenix.com/forum/showthread...6#pid39566

I'll leave the original up here so folks can just grab whatever they need from it with each routine holding independent, but I honestly recommend just using the one routine to do it all.  It's all you honestly need now.

Print this item

  QB64PE - AI Steve
Posted by: SMcNeill - 01-27-2026, 06:58 PM - Forum: Works in Progress - Replies (10)

Every so often, Steve likes to just play around and have fun and goof off and see just what oddness he can hack into QB64 from time to time.

This time, I decided that what QB64PE *really, really, REALLY* needs is its own mascot helper -- and who better than.... STEVE??

And so, I sat down and decided to create the latest and greatest and newest and most AWESOMEST version of QB64PE ever!!

BEHOLD!!

I give you all...

QB64PE -- with AI STEVE!!!!

Kids, don't try this at home!  This is the most high powered, redneck hacked, OMG WHAT DID I JUST SEE, version of QB64 to ever exist.  I can just hear @vince falling out of his chair right now.  I just hope he can call 911 before he passes away from the awesomeness that this version brings to us.

The archive below is a fully stand-alone WINDOWS version of QB64PE-AI Steve.  It even has a compiled EXE in it for all you guys to play around with and test out and enjoy!

As for Linux/Mac folks.... umm....  you *might* grab the source file and compile it on your systems.  I dunno exactly how deep the changes go and what all would be required to compile in Linux.  Just point your existing version to the "QB64PE-AI Steve.bas" file in the /source folder here, and then try to compile it and see what blows up.  You may have to move the created EXE to the proper folder afterwards so it finds the internal files and such in the spot where it expects them.

I really don't know what would be required to get this amazing little program to run on Linux.  Probably toss it in a 64-bit WINE version, if one exists?  If not, and you don't feel like experimenting, just skip this and shrug it off as "Crazy Ass Steve is just fooling around again!"

Same for anyone on limited bandwidth.  Don't bother wasting time to grab this, if you're on a limited bandwidth.  This is hacked together, and just me having some fun, with more of a Proof-of-Concept style coding going on here, so I might try some other more complicated stuff later someday with QB64PE.  I know it's buggy and has several little glitches that need addressing, but it's just FUN to mess around with and play with, and if you have the bandwidth and are on Windows, and want to waste a few minutes, feel free to check out my new...
 
QB64PE -- with AI STEVE!!!!



Attached Files
.7z   QB64PE - AI Steve.7z (Size: 101.75 MB / Downloads: 26)
Print this item