Posts: 3,965
Threads: 176
Joined: Apr 2022
Reputation:
219
01-04-2023, 01:55 AM
(This post was last modified: 01-04-2023, 01:59 AM by bplus.)
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 + ...
Posts: 2,696
Threads: 327
Joined: Apr 2022
Reputation:
217
(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!
Posts: 3,965
Threads: 176
Joined: Apr 2022
Reputation:
219
01-04-2023, 04:12 AM
(This post was last modified: 01-04-2023, 04:14 AM by bplus.)
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 + ...
Posts: 1,586
Threads: 59
Joined: Jul 2022
Reputation:
52
01-04-2023, 04:51 AM
Now I'm confused for the first time in 2023.
Posts: 3,965
Threads: 176
Joined: Apr 2022
Reputation:
219
01-04-2023, 05:22 PM
(This post was last modified: 01-04-2023, 06:47 PM by bplus.)
(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 + ...
Posts: 11
Threads: 3
Joined: Dec 2022
Reputation:
0
(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.
Posts: 2,696
Threads: 327
Joined: Apr 2022
Reputation:
217
(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.
Posts: 1,002
Threads: 50
Joined: May 2022
Reputation:
27
Interesting tip. And so one way you can see which keys have been pressed.
Code: (Select All) Do
k = _KeyHit
Print "They pressed the keys: ";
Print k; " = "; Chr$(Abs(k))
Loop Until k = 0
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(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.
Posts: 344
Threads: 24
Joined: Jul 2022
Reputation:
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.
|