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

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 555
» Latest member: BrentonRef
» Forum threads: 3,042
» Forum posts: 27,860

Full Statistics

Latest Threads
how to get a file's modif...
Forum: Help Me!
Last Post: eoredson
1 hour ago
» Replies: 35
» Views: 2,264
Extended Input
Forum: SMcNeill
Last Post: SMcNeill
3 hours ago
» Replies: 0
» Views: 5
KeyBoard Library
Forum: SMcNeill
Last Post: SMcNeill
3 hours ago
» Replies: 0
» Views: 12
InForm-PE
Forum: a740g
Last Post: bobalooie
5 hours ago
» Replies: 83
» Views: 10,805
Exiting FOR NEXT, maybe a...
Forum: General Discussion
Last Post: Circlotron
6 hours ago
» Replies: 4
» Views: 52
WINDOWS Set DPI Awareness
Forum: SMcNeill
Last Post: SMcNeill
7 hours ago
» Replies: 4
» Views: 58
an "overloaded subroutine...
Forum: Programs
Last Post: mdijkens
Yesterday, 04:34 PM
» Replies: 9
» Views: 108
A more complete instructi...
Forum: General Discussion
Last Post: James D Jarvis
Yesterday, 03:16 PM
» Replies: 2
» Views: 69
Speed
Forum: Help Me!
Last Post: TempodiBasic
Yesterday, 06:39 AM
» Replies: 7
» Views: 170
1990's 3D Doom-Like Walls...
Forum: Programs
Last Post: SierraKen
Yesterday, 01:20 AM
» Replies: 14
» Views: 1,274

 
  Extended Input
Posted by: SMcNeill - 3 hours ago - Forum: SMcNeill - No Replies

Code: (Select All)
ExtendedInput "What is your name: ", nam$
Print nam$
ExtendedInput "{F8.2}Enter a number (limited to 8 digits and 2 decimal places): ", num$
Print Val(num$)
ExtendedInput "{UIL05}Enter a five digit pin: ", pin$
Print Val(pin$)
ExtendedInput "{UIL05P}Enter a five digit secret pin: ", secret$
Print Val(secret$)
Print
Print "And so on!"
Print "Note that you can also use arrow keys to edit input, or CTRL-V to paste into the input, or hide the input prompt and answer, or lots of options!"

Sub ExtendedInput (prompt$, result$) 'Over Engineered Input
    'limit VALUES:
    '1 = Unsigned
    '2 = Integer
    '4 = Float
    '8 = Who cares. It's handled via internal variables and we don't need to know a type for it.
    'Uses {} at the start of the prompt to limit possible input
    'P = Password
    'U = Unsigned
    'I = Integer
    'F = Float
    'L## = Length of max ##
    'X##, Y## = LOCATE before printing
    'D = Disable paste option
    'V = Move CTRL-V to AFTER paste
    'H = Hide Input after finished.  (Won't leave prompt, or user input on the screen.)

    PCopy 0, 1
    A = _AutoDisplay: X = Pos(0): Y = CsrLin
    OX = X: OY = Y 'original x and y positions
    CP = 0: OldCP = 0 'Cursor Position
    _KeyClear
    length_limit = -1 'unlimited length input, by default

    If Left$(prompt$, 1) = "{" Then 'possible limiter
        i = InStr(prompt$, "}")
        If i Then 'yep, we have something!
            limiter$ = UCase$(Mid$(prompt$, 2, i - 2))
            If InStr(limiter$, "U") Then limit = limit Or 1 'Unsigned
            If InStr(limiter$, "I") Then 'can't limit to BOTH an integer AND a float
                limit = limit Or 2 'Integer
            ElseIf InStr(limiter$, "F") Then
                limit = limit Or 4 'Float
                float_before_limit = KB_GetValue(limiter$, "F")
                float_after_limit = KB_GetValue(Mid$(limiter$, InStr(limiter$, "F") + 1), ".")
            End If
        End If
        If InStr(limiter$, "P") Then password_protected = -1: limit = limit Or 8 'don't show passwords.
        If InStr(limiter$, "L") Then 'Length Limitation
            limit = limit Or 8
            length_limit = KB_GetValue(limiter$, "L")
        End If
        If InStr(limiter$, "X") Then 'X position on screen
            limit = limit Or 8
            X = KB_GetValue(limiter$, "X")
        End If
        If InStr(limiter$, "Y") Then 'Y position on scren
            limit = limit Or 8
            Y = KB_GetValue(limiter$, "Y")
        End If
        If InStr(limiter$, "D") Then disable_paste = -1: limit = limit Or 8 'disable paste
        If InStr(limiter$, "V") Then cursor_after_paste = -1: limit = limit Or 8 'disable paste
        If InStr(limiter$, "H") Then clean_exit = -1: limit = limit Or 8 'hide after finished
    End If
    If limit <> 0 Then prompt$ = Mid$(prompt$, i + 1)


    Do
        PCopy 1, 0
        If _KeyDown(100307) Or _KeyDown(100308) Then AltDown = -1 Else AltDown = 0
        k = _KeyHit
        If AltDown Then
            Select Case k 'ignore all keypresses except ALT-number presses
                Case -57 To -48: AltWasDown = -1: alt$ = alt$ + Chr$(-k)
            End Select
        Else
            Select Case k 'without alt, add any keypresses to our input
                Case 8
                    oldin$ = in$
                    If CP > 0 Then OldCP = CP: CP = CP - 1
                    in$ = Left$(in$, CP) + Mid$(in$, CP + 2) 'backspace to erase input
                Case 9
                    oldin$ = in$
                    in$ = Left$(in$, CP) + Space$(4) + Mid$(in$, CP + 1) 'four spaces for any TAB entered
                    OldCP = CP
                    CP = CP + 4
                Case 32 To 128
                    If _KeyDown(100305) Or _KeyDown(100306) Then
                        If k = 118 Or k = 86 Then
                            If disable_paste = 0 Then
                                oldin$ = in$
                                temp$ = _Clipboard$
                                in$ = Left$(in$, CP) + temp$ + Mid$(in$, CP + 1) 'ctrl-v paste
                                'CTRL-V leaves cursor in position before the paste, without moving it after.
                                'Feel free to modify that behavior here, if you want it to move to after the paste.
                                If cursor_after_paste Then CP = CP + Len(temp$)
                            End If
                        End If
                        If k = 122 Or k = 90 Then Swap in$, oldin$: Swap OldCP, CP 'ctrl-z undo
                    Else
                        check_input:
                        oldin$ = in$
                        If limit And 1 Then 'unsigned
                            If k = 43 Or k = 45 Then _Continue 'remove signs +/-
                        End If
                        If limit And 2 Then 'integer
                            If k = 45 And CP = 0 Then GoTo good_input 'only allow a - sign for the first digit
                            If k < 48 Or k > 57 Then _Continue 'remove anything non-numeric
                        End If
                        If limit And 4 Then 'float
                            If k = 45 And CP = 0 Then GoTo good_input 'only allow a - sign for the first digit
                            If k = 46 And InStr(in$, ".") = 0 Then GoTo good_input 'only one decimal point
                            If k < 48 Or k > 57 Then _Continue 'remove anything non-numeric
                            If Left$(in$, 1) = "-" Then temp$ = Mid$(in$, 2) Else temp$ = in$
                            If InStr(in$, ".") = 0 Or CP < InStr(in$, ".") Then
                                If Len(temp$) < float_before_limit Or float_before_limit = -1 Then
                                    in$ = Left$(in$, CP) + Chr$(k) + Mid$(in$, CP + 1) 'add input to our string
                                    OldCP = CP
                                    CP = CP + 1
                                End If
                            Else
                                temp$ = Mid$(in$, InStr(in$, ".") + 1)
                                If Len(temp$) < float_after_limit Or float_after_limit = -1 Then
                                    in$ = Left$(in$, CP) + Chr$(k) + Mid$(in$, CP + 1) 'add input to our string
                                    OldCP = CP
                                    CP = CP + 1
                                End If
                            End If
                            _Continue
                        End If
                        good_input:
                        If CP < length_limit Or length_limit < 0 Then
                            in$ = Left$(in$, CP) + Chr$(k) + Mid$(in$, CP + 1) 'add input to our string

                            OldCP = CP
                            CP = CP + 1
                        End If
                    End If
                Case 18176 'Home
                    CP = 0
                Case 20224 'End
                    CP = Len(in$)
                Case 21248 'Delete
                    oldin$ = in$
                    in$ = Left$(in$, CP) + Mid$(in$, CP + 2)
                Case 19200 'Left
                    CP = CP - 1
                    If CP < 0 Then CP = 0
                Case 19712 'Right
                    CP = CP + 1
                    If CP > Len(in$) Then CP = Len(in$)
            End Select
        End If
        alt$ = Right$(alt$, 3)
        If AltWasDown = -1 And AltDown = 0 Then
            v = Val(alt$)
            If v >= 0 And v <= 255 Then
                k = v
                alt$ = "": AltWasDown = 0
                GoTo check_input
            End If
        End If
        blink = (blink + 1) Mod 30
        Locate Y, X
        Print prompt$;
        If password_protected Then
            Print String$(Len(Left$(in$, CP)), "*");
            If blink \ 15 Then Print " "; Else Print "_";
            Print String$(Len(Mid$(in$, CP + 1)), "*")
        Else
            Print Left$(in$, CP);
            If blink \ 15 Then Print " "; Else Print "_";
            Print Mid$(in$, CP + 1)
        End If

        _Display
        _Limit 30
    Loop Until k = 13

    PCopy 1, 0
    Locate OY, OX
    If clean_exit = 0 Then
        Locate Y, X
        If password_protected Then
            Print prompt$; String$(Len(in$), "*")
        Else
            Print prompt$; in$
        End If
    End If
    result$ = in$
    If A Then _AutoDisplay
End Sub


Function KB_GetValue (limiter$, what$)
    jstart = InStr(limiter$, what$): j = 0
    If Mid$(limiter$, InStr(limiter$, what$) + 1, 1) = "-" Then
        KB_GetValue = -1 'unlimited
        Exit Function
    End If

    Do
        j = j + 1
        m$ = Mid$(limiter$, jstart + j, 1)
    Loop Until m$ < "0" Or m$ > "9"
    KB_GetValue = Val(Mid$(limiter$, jstart + 1, j - 1))
End Function


And what is *this* over engineered little routine you ask?  Since I just reuploaded my Keyhit Library, I thought I'd take a moment and highlight this little extra tool that goes with it.

This is my ExtendedInput, which works basically like Input but with a ton of built in bells and whistles.  Give it a shot.  Try to disobey what it asks for.  It limits input to floats or integers, or signed or unsigned, or length, or hidden responses.  It can clean up and restore your background after itself.  It has arrow key support.  And paste with CTRL-V.  And undo with CTRL-Z...

And it can do your taxes and kiss your wife at night...

IT'S THAT AMAZING!!

But remember, Steve is even more Amazing!   Big Grin Big Grin Big Grin

Print this item

  KeyBoard Library
Posted by: SMcNeill - 3 hours ago - Forum: SMcNeill - No Replies

This is basically Windows Only.  You can plug it into your Linux/Mac systems, but it simply defaults back to _KEYHIT and does nothing else for you guys.

This library has been around forever and ever now, and is my *most used* personal library of code.  This is *ESSENTIAL* for me, and I could've sworn it was on the forums here, but somehow it doesn't seem to be.  My apologies for anyone who might've made use of this and missed out on it for that oversight.

So, what *is* this?  It's my handy dandy, super dooper, personal replacement for _KEYHIT.

To illustrate its usefulness, let me just pop out the world's simplest little set of code to run with it.  Grab the library, extract it to your QB64PE folder, and copy/paste/compile/run this little code snippet.

Code: (Select All)
'$Include: 'Keyboard Library.bi'
Do
    k1 = _KeyHit: k = KeyHit
    If k <> 0 Then Print k,
    If k1 <> 0 Then Print k1,
    If k _OrElse k1 Then Print
    _Limit 30
Loop
'$Include: 'Keyboard Library.bm'

Only 9 simple lines of code.  How the heck could this showcase how useful something could possibly be?  All this does is read keyboard input for us and then print the up and down codes related to that input...   YAWWWNNN......

But, humor me and give it a test run.

Press keys.  See how the values match.
Then get creative.  Try some more advanced things, like combo keys.  Try something simple like CTRL-1, or CTRL-2, or CTRL-(any number).  Or CTRL-TAB...   

And then try some three keys combo like CTRL-SHIFT-(any number).

So which is returning proper values for you, and which is missing key up or key down events, or mapping them to god only knows what...



GLUT is screwy.  It doesn't work with a BEEP with extended keypresses.  So, to deal with that, I wrote my own custom keyboard input handling routines.  Big Grin

Of course, I'm a Windows-Only type of programmer and this reverts back to system calls for us, so it's not Linux/Mac suitable.  Just so basic code doesn't break if someone wants to cross-compile, this internally substitutes _KEYHIT for KeyHit (note my routine doesn't have any underscore associated with it), but you lose all the best features with this.

This also has German, Western Europe, and Italian keyboard support provided so you can use it to read from each of those keyboards and not miss any key events.  There's also an over-engineered enhanced INPUT routine packaged in this, but it's more than a little complicated for a new user to sort it.  (But it's rather impressive on what it can do for us, in its own right.)

Kick it around.  Try it out.  This might be what you never knew you needed.  Then again, if you've never been disappointed with _KEYHIT before, then it might not be.  Either way, it's back here on the forums for those who might need to make use of it for their own stuff.  Wink



Attached Files
.7z   Keyboard Library.7z (Size: 8.16 KB / Downloads: 2)
Print this item

  Exiting FOR NEXT, maybe a bug? Version 4.1.0 on Linux
Posted by: Circlotron - Yesterday, 12:49 PM - Forum: General Discussion - Replies (4)

Had a go at calculating some Perfect Numbers. If I EXIT the FOR NEXT and print the number and the sum of it's factors (which should be equal) it works just fine. (After the first four it might take forever because it is a big number.) But if I print the number and the sum of it's factors just before I EXIT the FOR NEXT as well as after then I get several extra unrelated numbers. The line that causes the issue is commented out, but put it in and things go bad. I would have thought that it made no difference except for printing the numbers twice. What's going on? 

Code: (Select All)
ChDir startdir$ + "perfect numbers/"

Dim number As _Integer64
Dim trial As _Integer64
Dim div_total As _Integer64

number = 4 'start even and add 2 per pass
top:
div_total = 0

For trial = 1 To ((number / 2) + 1)
    If number Mod trial = 0 Then div_total = div_total + trial
    'If div_total = number Then Print number, div_total, "x": Exit For
Next trial

If div_total = number Then Print number, div_total
number = number + 2
GoTo top

Print this item

  WINDOWS Set DPI Awareness
Posted by: SMcNeill - Yesterday, 02:34 AM - Forum: SMcNeill - Replies (4)

Code: (Select All)
Declare Dynamic Library "user32"
    Function DPI& Alias SetProcessDpiAwarenessContext (ByVal dpiContext As _Offset)
End Declare
Const UNAWARE = -1, AWARE = -2, PER_MONITOR_AWARE = -3
Const PER_MONITOR_AWARE_V2 = -4, UNAWARE_GDISCALED = -5

_FullScreen

Dim result As Integer
Print _DesktopWidth, _DesktopHeight
Sleep
Print "Setting DPI Awareness Context..."

_FullScreen _Off 'Note if you use _FULLSCREEN, you should turn it OFF before making any change
_Delay .2 'And give it a delay to make certain that it can make that change

result = DPI(AWARE) 'change to setting you like
Print _DesktopWidth, _DesktopHeight
_FullScreen _Stretch
Sleep
System

With the above, a windows user can set DPI Awareness as they wish for their programs.  Note that once Awareness is turned off, the system ignores all other calls so you can't just turn it off and on all willy-nilly.

And what *IS* DPI Awareness?  It's the automatic scaling of a program according to the settings you have in your window display settings.
For example, if you have your system set to 200% scaling, it's going to automatically scale all your programs 200% in size.

For a 3840 x 2160 display, this means that the biggest program screen you can make and view would be 1920 x 1080 as it'd scale 200% to fill the 3840 x 2160 display completely.

So with this, you can set your program to decide if it wants to do that scaling or not.  

If your program is DPI(Aware), it means you're going to do any necessary scaling yourself.
If it's DPI(UnAware), it means you're going to let the system do that automatic scaling.
By monitor is going to depend on your scaling settings on each monitor and where the program is located on the desktop.



Chances are, if you don't know what DPI Awareness is or that Windows automagically resizes and scales things for you, then you won't need to worry about this.  This is mainly something that affects people with scale factors built into their system (like many laptops -- mine defaults to 200% scaling) and if you've never noticed it in the past, then it's probably not something you need to concern yourself about anytime soon.  Wink

Print this item

  an "overloaded subroutine" example
Posted by: James D Jarvis - Yesterday, 12:55 AM - Forum: Programs - Replies (9)

an example of a means to have overloaed subroutines or at least subroutines with a varying range of variables. 
it makes use of a modified version of splitstring that someone else developed that allows the variables to be broken down in the subroutine.

Code: (Select All)
'an example of an overloaded subroutine in QB64
'
'more acurately an example of passing a different range of variables to a sub
'and gettign a different range of results based on those arguments
'
'$Dynamic
Screen _NewImage(500, 240, 256)
Dim Shared klr
Locate 1, 1: Print "A dot      (press Any key) "
overload_example "12"
overload_example "100,100"
Sleep
Locate 1, 1: Print "                            "
Locate 1, 1: Print "Amother dot (press Any key) "
overload_example "50,50,14"
Sleep
Locate 1, 1: Print "                            "
Locate 1, 1: Print "A Filled Box (press Any key)"

overload_example "50,50,100,100,10"
Sleep
Locate 1, 1: Print "                            "
Locate 1, 1: Print "Outlined that box "

overload_example "50,50,100,100"
Sleep
Cls
Locate 1, 1: Print "                            "
Locate 1, 1: Print "The code is an example of passing numerical variables "
overload_example "30,30,110,110,2"
For x = 10 To 40 Step 5
    A$ = _Trim$(Str$(70 - x))
    B$ = _Trim$(Str$(x + 70))
    overload_example A$ + "," + A$ + "," + B$ + "," + B$
Next x

End

' overload_example'
'takesa string with a set of arguments delimited by a comma
'if there is one argument the default color is set
'if there are 2 arguments a pixel is drawn in the deafult color with pset
'if there are 3 arguments a pixel is drawn in a temporary color but the default is not changed
'if there are 4 arguments a Box is drawn  the default color
'if there are 5 arguments a Filled Box is drawn  the temporary color

Sub overload_example (argument$)
    Dim argu$(0)
    SplitString argument$, ",", argu$()
    a_count = UBound(argu$)
    Select Case a_count
        Case 1 'set the defined color for follwoign statements
            klr = Val(argu$(1))
        Case 2 'pset in defined color
            x0 = Val(argu$(1))
            y0 = Val(argu$(2))
            PSet (x0, y0), klr
        Case 3 'pset in temporary color
            x0 = Val(argu$(1))
            y0 = Val(argu$(2))
            tklr = Val(argu$(3))
            PSet (x0, y0), tklr
        Case 4 'draw a box in defined color
            x0 = Val(argu$(1))
            y0 = Val(argu$(2))
            x1 = Val(argu$(3))
            y1 = Val(argu$(4))
            Line (x0, y0)-(x1, y1), klr, B
        Case 5 'draw a filled in temporary color
            x0 = Val(argu$(1))
            y0 = Val(argu$(2))
            x1 = Val(argu$(3))
            y1 = Val(argu$(4))
            tklr = Val(argu$(5))
            Line (x0, y0)-(x1, y1), tklr, BF
    End Select
End Sub
Sub SplitString (inputString$, delimiter$, wordArray$())
    'make sure you have dynamic arrays set up
    wordCount% = 0
    startPos% = 1
    Do
        psn% = InStr(startPos%, inputString$, delimiter$) ' Find the next delimiter
        If psn% = 0 Then
            ' No more delimiters found, this is the last word
            word$ = Mid$(inputString$, startPos%)
            If Len(_Trim$(word$)) > 0 Then ' Check for empty word (e.g., multiple spaces)
                wordCount% = wordCount% + 1
                ReDim _Preserve wordArray$(wordCount%)
                wordArray$(wordCount%) = word$
            End If
            Exit Do ' Exit the loop
        Else
            ' Delimiter found, extract the word
            word$ = Mid$(inputString$, startPos%, psn% - startPos%)
            If Len(_Trim$(word$)) > 0 Then ' Check for empty word (e.g., multiple spaces)
                wordCount% = wordCount% + 1
                ReDim _Preserve wordArray$(wordCount%)
                wordArray$(wordCount%) = word$
            End If
            startPos% = psn% + Len(delimiter$) ' Move the starting position past the delimiter
        End If
    Loop
End Sub

Print this item

  Saving an Inform picturebox.
Posted by: James D Jarvis - 05-07-2025, 06:19 PM - Forum: Help Me! - Replies (4)

This involves using Inform.
I've figured out how to load images generated within the program into picture boxes and edit them but I haven't figured out how to save a picturebox as an image file.

It is possible to have all graphics commands write to a buffer image that is loaded into a picturebox when needed throughout execution of the program, and save that to a file when desired.  But that defeats some of the purpose of using Inform.

Any ideas?

Print this item

  A more complete instructional video
Posted by: James D Jarvis - 05-07-2025, 04:56 PM - Forum: General Discussion - Replies (2)

I whipped up an instructional video for QB64. A simple hello world program with random pixels graphics. It's my first attempt in ages and I certainly learned a few things already. Give it a peek if you want to and probably turn up that speaker volume so you can hear me talk as I type. 

https://youtu.be/nHbUsXhzsjQ?si=lusAg8BlST1sIIC4

Print this item

  CAN someone please get the graphics in this to work?
Posted by: Dragoncat - 05-07-2025, 11:03 AM - Forum: Help Me! - Replies (3)

Code: (Select All)
' QB64 Phoenix Edition Cassette Recorder Simulator with Proper Alpha and Case-Sensitive Variables
DECLARE SUB DrawTapePlayer (LeftReel AS INTEGER, RightReel AS INTEGER, TapeWobble AS INTEGER, TapeType AS INTEGER, Angle AS SINGLE)

' Create high-resolution graphics window
DIM ScreenID AS LONG
ScreenID = _NEWIMAGE(800, 600, 32) ' 800x600 resolution, 32-bit color mode
SCREEN ScreenID
_AUTODISPLAY ' Enables graphics rendering

' Define colors with Alpha Channel (fully opaque)
DIM PlayerColor AS _UNSIGNED LONG
DIM TapeColor AS _UNSIGNED LONG
DIM OxideTapeColor AS _UNSIGNED LONG
DIM RollerColor AS _UNSIGNED LONG

PlayerColor = _RGBA32(50, 50, 50, 255) ' Dark gray for the player casing
TapeColor = _RGBA32(139, 69, 19, 255) ' Standard brown tape
OxideTapeColor = _RGBA32(160, 82, 45, 255) ' Reddish-brown oxide tape
RollerColor = _RGBA32(245, 245, 220, 255) ' Off-white rollers

DIM TapeLength AS INTEGER
DIM SpeedMode AS STRING
DIM TapeType AS INTEGER
DIM LeftReel AS INTEGER
DIM RightReel AS INTEGER
DIM TapeWobble AS INTEGER
DIM KeyPress AS STRING
DIM Angle AS SINGLE

CLS
_PRINTSTRING (50, 50), "Welcome to the QB64 Cassette Recorder Simulator!"
_PRINTSTRING (50, 70), "Press any key to continue..."
DO
    KeyPress = INKEY$
LOOP UNTIL KeyPress <> ""

CLS
_PRINTSTRING (50, 50), "Select Tape Length (10, 15, 30, 45, 60, 90, 120 minutes): "
DO
    KeyPress = INKEY$
    IF KeyPress >= "0" AND KeyPress <= "9" THEN TapeLength = VAL(KeyPress) * 10
LOOP UNTIL TapeLength > 0

_PRINTSTRING (50, 70), "Select Speed Mode (N: Normal, F: Fast, S: Slow, L: Long Play, E: Extra Long Play): "
DO
    KeyPress = INKEY$
    SELECT CASE KeyPress
        CASE "N": SpeedMode = "Normal"
        CASE "F": SpeedMode = "Fast"
        CASE "S": SpeedMode = "Slow"
        CASE "L": SpeedMode = "Long Play"
        CASE "E": SpeedMode = "Extra Long Play"
    END SELECT
LOOP UNTIL SpeedMode <> ""

_PRINTSTRING (50, 90), "Choose Tape Type (1: Standard Brown, 2: Metal Oxide Red-Brown): "
DO
    KeyPress = INKEY$
    IF KeyPress = "1" THEN TapeType = 1
    IF KeyPress = "2" THEN TapeType = 2
LOOP UNTIL TapeType > 0

CLS
_PRINTSTRING (50, 50), "Loading Tape..."
SLEEP 2

' Initial reel sizes
LeftReel = 80
RightReel = 20
TapeWobble = 0
Angle = 0

FOR i = 1 TO TapeLength * 5
    CLS
    DrawTapePlayer LeftReel, RightReel, TapeWobble, TapeType, Angle
    SLEEP 1
   
    ' Simulate tape winding: left reel shrinks, right reel grows
    IF LeftReel > 20 THEN
        LeftReel = LeftReel - 1
        RightReel = RightReel + 1
    END IF
   
    ' Simulate slight tape wobble
    TapeWobble = INT(RND * 4) - 2

    ' Increase rotation angle
    Angle = Angle + 5
    IF Angle >= 360 THEN Angle = 0
NEXT

_PRINTSTRING (50, 550), "Playback Complete!"

SUB DrawTapePlayer (LeftReel AS INTEGER, RightReel AS INTEGER, TapeWobble AS INTEGER, TapeType AS INTEGER, Angle AS SINGLE)
    ' Select tape color
    DIM CurrentTapeColor AS _UNSIGNED LONG
    IF TapeType = 1 THEN
        CurrentTapeColor = TapeColor
    ELSE
        CurrentTapeColor = OxideTapeColor
    END IF

    ' ? **Layer Rendering: Back-to-Front**
   
    ' 1️⃣ Draw **player frame (boxy shape)**
    LINE (100, 100)-(700, 500), PlayerColor, BF

    ' 2️⃣ Draw **rollers (off-white)**, dividing player into thirds
    CIRCLE (250, 150), 10, RollerColor
    PAINT (250, 150), RollerColor, RollerColor

    CIRCLE (550, 150), 10, RollerColor
    PAINT (550, 150), RollerColor, RollerColor

    ' 3️⃣ **Convert polar coordinates to rectilinear** for rotation effect
    DIM X1 AS INTEGER, Y1 AS INTEGER, X2 AS INTEGER, Y2 AS INTEGER
    X1 = 300 + COS(Angle * 3.14159 / 180) * LeftReel
    Y1 = 300 + SIN(Angle * 3.14159 / 180) * LeftReel
    X2 = 500 + COS(Angle * 3.14159 / 180) * RightReel
    Y2 = 300 + SIN(Angle * 3.14159 / 180) * RightReel

    ' 4️⃣ Draw **reels (shrinking/growing with playback)**
    CIRCLE (300, 300), LeftReel, CurrentTapeColor
    PAINT (300, 300), CurrentTapeColor, CurrentTapeColor

    CIRCLE (500, 300), RightReel, CurrentTapeColor
    PAINT (500, 300), CurrentTapeColor, CurrentTapeColor

    ' 5️⃣ Draw **animated tape strip moving through rollers**
    LINE (300, 300)-(250, 150 + TapeWobble), CurrentTapeColor
    LINE (250, 150 + TapeWobble)-(550, 150 + TapeWobble), CurrentTapeColor
    LINE (550, 150 + TapeWobble)-(500, 300), CurrentTapeColor

    ' 6️⃣ **Graphical text overlay at the end** (to avoid interference)
    _PRINTSTRING (50, 520), "Left Reel Size: " + LTRIM$(STR$(LeftReel))
    _PRINTSTRING (450, 520), "Right Reel Size: " + LTRIM$(STR$(RightReel))
END SUB

Print this item

  Astounding (and brief videos) demonstrating Inform
Posted by: James D Jarvis - 05-06-2025, 03:39 PM - Forum: General Discussion - No Replies

Two "astounding" and very brief videos using Inform and QB64-PE.   Finally decided to buckle down and get a decent demo program together using both.

https://youtu.be/TdpYGPMs-HQ?si=TkzLldejugJM-OZZ

https://youtu.be/-PoMNTGH3ZE?si=VJXQOef8Vn_8mZVx

No sound and really brief but I'm making progress in using Inform.

Print this item

  STRING$ empowered with StringPatternFilling
Posted by: TempodiBasic - 05-06-2025, 07:43 AM - Forum: Utilities - Replies (5)

Hi
thanks to Steve I can post this here because I have a STRING$ function that fills fastly a string with a pattern but I have missed the thread about String concatenation and MID$ way  String concatenation thread.
By the way in a speed test this function is faster than MID$ way!
So I share it here.

Code: (Select All)

Dim As Long Scr
Scr = _NewImage(800, 600, 32)
Screen Scr
_ControlChr Off
_Title "FillString: a new STRING$"
Cls , _RGB32(33, 172, 172)
Locate 2, 1: Print "Starting Test :"
S$ = Chr$(0) + Chr$(255) + Chr$(255) + Chr$(255) ' Substring
Fs$ = "" ' FinalString
Size = 800 * 600 * 4 '1.920.000
Print "Fillstring concatenation with 2*n formula"
t1# = Timer(0.001)
Print FillString(Size, S$, Fs$), Size, Len(Fs$)
t2# = Timer(0.001)
Print " Fillstring with MID$"
Fs$ = "" ' FinalString
t3# = Timer(0.001)
Print FillString2(Size, S$, Fs$), Size, Len(Fs$)
t4# = Timer(0.001)
Print "Fillstring concatenation with n+n formula"
Fs$ = "" ' FinalString
t5# = Timer(0.001)
Print SlowFillString(Size, S$, Fs$), Size, Len(Fs$)
t6# = Timer(0.001)

Locate 10, 1
Print Using " Tempo & #.####  #.####  #.#### "; "String = String + String "; (t2# - t1#); t1#; t2#
Print Using " Tempo & #.####  #.####  #.#### "; "MID$ way "; t4# - t3#; t3#; t4#
Print Using " Tempo & #.####  #.####  #.#### "; "String = String + Pattern "; t6# - t5#; t5#; t6#
End

Function FillString (Size As Long, Bases As String, S As String)
    FillString = 0
    S = Bases
    Do
        S = S + S
    Loop Until Len(S) > Size
    S = Left$(S, Size)
    FillString = -1
End Function

Function FillString2 (Size As Long, Bases As String, S As String)
    FillString2 = 0
    Dim posi As Long
    S = Space$(Size)
    posi = 0
    Do
        Mid$(S, posi, 4) = Bases
        posi = posi + 4
    Loop Until posi > Size
    S = Left$(S, Size)
    FillString2 = -1
End Function

Function SlowFillString (Size As Long, Bases As String, S As String)
    SlowFillString = 0
    Dim As Double Starts, Ends
    Dim Counter As Long
    Starts = Timer(.001)
    Ends = 10#
    Counter = 0
    Do
        Counter = Counter + 1
        S = S + Bases
    Loop Until Len(S) > Size Or (Timer(.001) - Starts >= Ends)
    Print , Counter; " cycles", Len(S); " lenght of string vs max size"; Size
    S = Left$(S, Size)
    SlowFillString = -1
End Function

Wellcome feedbacks and improvements of FillString or STRING$pattern (what name is more explicative?),
maybe any other friend of QB64pe wants share something better for performance and or algorythm.
In the other thread there is the screenshot with comparisons and a graphic explanation of why it works well.

Print this item