Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
while: wend
#11
No sooner did I post the edit when I tried the opposite:
10 If _MouseInput Then GoTo 10

They both freak'n worked!

Dang It looks like you just have to call _MouseInput, no loop needed! No GOTO needed nutt'n but a mention of _MouseInput!

Code: (Select All)
_Title "Click to draw paths from one click to next" 'b+ 2023-01-03

Do
    z = _MouseInput
    mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
    Locate 1, 1: Print mx, my
    If mb Then
        If lastx <> 0 And lasty <> 0 Then
            Locate my, mx: Print "X";
            If mx > lastx Then
                While lastx < mx
                    lastx = lastx + 1
                    Locate lasty, lastx: Print "X";
                Wend
            Else
                While lastx > mx
                    lastx = lastx - 1
                    Locate lasty, lastx: Print "X";
                Wend
            End If
            If my > lasty Then
                While lasty < my
                    lasty = lasty + 1
                    Locate lasty, lastx: Print "X";
                Wend
            Else
                While lasty > my
                    lasty = lasty - 1
                    Locate lasty, lastx: Print "X";
                Wend
            End If
        End If
        lastx = mx: lasty = my
    End If
Loop
b = b + ...
Reply
#12
(01-04-2023, 01:55 AM)bplus Wrote: No sooner did I post the edit when I tried the opposite:
10 If _MouseInput Then GoTo 10

They both freak'n worked!

Dang It looks like you just have to call _MouseInput, no loop needed! No GOTO needed nutt'n but a mention of _MouseInput!

Code: (Select All)
_Title "Click to draw paths from one click to next" 'b+ 2023-01-03

Do
    z = _MouseInput
    mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
    Locate 1, 1: Print mx, my
    If mb Then
        If lastx <> 0 And lasty <> 0 Then
            Locate my, mx: Print "X";
            If mx > lastx Then
                While lastx < mx
                    lastx = lastx + 1
                    Locate lasty, lastx: Print "X";
                Wend
            Else
                While lastx > mx
                    lastx = lastx - 1
                    Locate lasty, lastx: Print "X";
                Wend
            End If
            If my > lasty Then
                While lasty < my
                    lasty = lasty + 1
                    Locate lasty, lastx: Print "X";
                Wend
            Else
                While lasty > my
                    lasty = lasty - 1
                    Locate lasty, lastx: Print "X";
                Wend
            End If
        End If
        lastx = mx: lasty = my
    End If
Loop

What you have here is bad code.  Let me illustrate why rather simply:

Code: (Select All)
Do
    z = _MouseInput
    If oldX <> _MouseX Or oldY <> _MouseY Then Print _MouseX, _MouseY
    _Limit 60
    oldX = _MouseX: oldY = _MouseY
Loop Until _KeyHit

Drag the mouse around a bit.  Stop dragging.  How long does it take for your program to process all those mouse reports after you've finished moving your mouse??

Now, I know someone will say, "Yeah, but just increase your limit!!"

And SUUUURRREEEE, that might work for this specific example, but start *doing* something.  Write a game.  Deal with refreshing graphics.  Tracking coordinates.  Detecting and dealing with collisions.  Enemy AI...   Your program will naturally start to run fewer and fewer loops per second, as it's got more stuff to do per second.  At what point does your game now run at a FPS (limit) which is too slow to process every mouseinput that your OS generates?  What type of lag are you going to have to try to optimize out of your code elsewhere, just so you can process mousex/y positions that aren't really doing anything at all in your program?

If my program runs at a max 60 FPS, and the mouse reports 120 events per second, then it's going to take 2 seconds to process every second of mouse input!  

That's a seriously laggy game right there!
Reply
#13
Ah I see, with _Limit 60 in loop it behaves quite differently and THEN it does make a difference between

10 If _MouseInput then Goto 10  ' this short circuits hitting _LIMIT in the other part or Loop and slowing things down

and 

10 If Not _MouseInput Then GoTo 10

Fixed for _Limit 60
Code: (Select All)
_Title "Click to draw paths from one click to next" 'b+ 2023-01-03

Do
    10 If _MouseInput Then GoTo 10
    mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
    If mb Then
        If lastx <> 0 And lasty <> 0 Then
            Locate my, mx: Print "X";
            If mx > lastx Then
                While lastx < mx
                    lastx = lastx + 1
                    Locate lasty, lastx: Print "X";
                Wend
            Else
                While lastx > mx
                    lastx = lastx - 1
                    Locate lasty, lastx: Print "X";
                Wend
            End If
            If my > lasty Then
                While lasty < my
                    lasty = lasty + 1
                    Locate lasty, lastx: Print "X";
                Wend
            Else
                While lasty > my
                    lasty = lasty - 1
                    Locate lasty, lastx: Print "X";
                Wend
            End If
        End If
        lastx = mx: lasty = my
    End If
    _Limit 60 ' <<<  to work with limit you need to run _MouseInput in small tight loop
Loop

Thanks Steve
b = b + ...
Reply
#14
Shocked 
Now I'm confused for the first time in 2023.
Reply
#15
(01-04-2023, 04:51 AM)mnrvovrfc Wrote: Now I'm confused for the first time in 2023.

LOL my work is done!

Seriously the lesson is that _MouseInput has to be in it's own tight little loop with no _LIMIT other wise it will use the _Limit in the main loop in which it sits and slow down all the other processing going on.

So, the reason behind the one-line:
While _MouseInput: Wend

or a variation with just a single GoTo
10 If _MouseInput Then Goto 10 ' don't tie up the rest of the loop handling _MouseInput
b = b + ...
Reply
#16
(01-03-2023, 04:07 PM)james2464 Wrote: Thanks james.  You explained it  well enough I belive.  You and SMcNeil made some sense to me.  


"ELI5" attempt:


I was confused by this as well.   WHILE _MOUSEINPUT: WEND looked like a single line of code to me.    The : symbol is used to separate lines of code on the same line. 

An example would be...

FOR t = 1 TO 10 : NEXT t


If you forget that and just think of it as two lines...

WHILE _MOUSEINPUT
WEND


Then you can just consider reply #2.   But that was also confusing to me a while ago.   I wondered how this doesn't just loop infinitely.
But it just goes and checks for the latest mouse input and then exits the loop.
Reply
#17
(01-03-2023, 04:07 PM)james2464 Wrote: "ELI5" attempt:


I was confused by this as well.   WHILE _MOUSEINPUT: WEND looked like a single line of code to me.    The : symbol is used to separate lines of code on the same line. 

An example would be...

FOR t = 1 TO 10 : NEXT t


If you forget that and just think of it as two lines...

WHILE _MOUSEINPUT
WEND

Then you can just consider reply #2.   But that was also confusing to me a while ago.   I wondered how this doesn't just loop infinitely.
But it just goes and checks for the latest mouse input and then exits the loop.

It's a little more than just checking for the latest mouse input; it's clearing the mouse buffer itself and updating the mouse commands to the last input recieved.

For example, let's look at something that's easy to visualize and understand, that behaves in exactly the same way.   First, try the code below:

Code: (Select All)
Print "Press a few keys in the next 5 seconds."
_Delay 5
Print "You can stop pressing keys now."
_Delay 1
Print "The keys you pressed while I was paused were:"
Do
    k = _KeyHit
    Print k
Loop Until k = 0

Now, as you can see, even when the program is paused, it still records whatever keys you pressed and saved them in a buffer for you.  The DO..LOOP here runs in a quick loop until it clears out that buffer by reading it once character at a time and printing it to the screen for you.

But what if you didn't want to actually print to the screen?  What if you just wanted to clear that buffer, to reset it for some fresh input.  After all, you might not need to know what the user pressed while the program was paused.

While _KeyHit: Wend

^The above is all you'd need.  It'd read the keyhit buffer, clear it one character at a time, until there wasn't any characters left in it.

And that's basically what While _MouseInput: Wend does.  It reads the mouse buffer, one event at a time, and clears it until there's nothing left in that buffer.  When you exit that loop, _MouseX, _MouseY, and _MouseButton(#) are all whatever the last pass of the mousebuffer had in it.  You're just clearing out all the events which you don't need to process, and dealing with whatever the current event is.

It's that simple.  Wink
Reply
#18
Interesting tip. And so one way you can see which keys have been pressed.  Tongue

Code: (Select All)
Do
  k = _KeyHit
  Print "They pressed the keys: ";
  Print k; " = "; Chr$(Abs(k))
Loop Until k = 0
Reply
#19
(01-03-2023, 06:09 AM)fistfullofnails Wrote: On Terry Ritchie's function/subroutine part of the QB64 tutorial, line 15 of subs.base,  we have:

Code: (Select All)
WHILE _MOUSEINPUT: WEND

The only way I've seen "WHILE" and "WEND" used is at the start and end of a loop, with some instructions  in between, which then ends with 'WEND".
I'm confused on what is exactly going on here.  Can anyone explain like I'm a five year old?

Code: (Select All)
DO
    _LIMIT 60
    WHILE _MOUSEINPUT: WEND
    IF _MOUSEBUTTON(1) THEN DrawStar _MOUSEX, _MOUSEY
    IF _MOUSEBUTTON(2) THEN Directions
    _DISPLAY
LOOP UNTIL _KEYDOWN(27)

Sorry I'm late to the party here. I didn't see this post until now.

As Steve pointed out the mouse commands in QB64 are buffered. It's not very common with today's computers but back in the Windows 3.x and 9x era it was easy to start clicking around the screen and actually get ahead of the program running. However, each mouse click and mouse movement would would eventually get processed. The reason for this is Windows uses a mouse buffer as well so mouse events are not missed.

Most of the time all you need is the latest mouse event which requires the old mouse events to be cleared (especially in fast paced games). This is where this line of code comes in:

WHILE _MOUSEINPUT: WEND

(As someone else pointed out there are actually two lines of code here separated by a colon)

Once that loop completes the next mouse command issued, for instance _MOUSEX, will report the most up to date or current position. It's also a good idea to gather your mouse data directly after issuing this loop otherwise any delay may result in the buffer starting to fill again resulting in mouse events that are a few steps old.

There may be instances where you need to know every single movement and click performed so you don't miss a user's input, such as how I illustrated Windows 3.x and 9x would keep up. This can be done as well. The second piece of code in this section of the tutorial:

https://www.qb64tutorial.com/lesson7#h.9uisxsndidwf

shows how you can gather every mouse event and process them. This is the same concept as the example code Steve showed here to gather keys from the keyboard buffer.

If WHILE ... WEND is not to your liking there are other loops you can use:

DO WHILE _MOUSEINPUT: LOOP

DO: LOOP UNTIL NOT _MOUSEINPUT

DO: LOOP UNTIL _MOUSEINPUT = 0

etc.. In my opinion, WHILE ... WEND is the cleanest method though.
Reply
#20
Hello,
 in theme but on the border...some my questions 

Is the stack of mouse events (click of buttons, position of cursor)  for all OSes or only for Windows?

Do our QB64 friends living in Linux or MacOs  have the same experience of Windows's users?

Is this kind of management of mouse input  universal or typical of C/C++?  (Our BASIC becomes C++ and then machine language!)

Thank you, for reading, for sharing knowledge and be part of this friendship named QB64 community.
Reply




Users browsing this thread: 4 Guest(s)