Mouse Help Needed
#21
Of course, if one is only avoiding subs, the code would work just the same cut and pasted in the appropriate place, then substitute the mousebutton ID for 'var'. The only real point of the sub is to reduce typing redundancy, and the fact that QB64 is fast enough that the nested loop will probably work faster than any delay that would accommodate human fingers.



I typically use Clear_MB # in anything that uses Steve's MBS function. My typical main program input loop looks like the following. I find it easy peasy, and I should probably put it in an include library. It works like a charm and I never have "click through" problems.



(Note: the Clear_MB number is the mouse button number, not necessarily what MBS returns)




Code: (Select All)
DO 'main program display loop
    in% = 0
    DO 'input loop
        ky$ = INKEY$
        ms% = MBS
        IF ms% AND 1 THEN
            Clear_MB 1
            'Do left mouse initiated stuff
            in% = -1
        END IF
        IF ms% AND 2 THEN
            Clear_MB 2
            'Do right mouse initiated stuff
            in% = -1
        END IF
        IF ms% AND 4 THEN
            Clear_MB 3
            'Do center mouse initiated stuff
            in% = -1
        END IF
        'etc.
        'etc
        'do inkey stuff, blank the ky$, then set in% = -1
        '_LIMIT as necessary
    LOOP UNTIL in%
    'do general display update stuff
    '_DISPLAY if required
LOOP UNTIL done 'whatever done entails


SUB Clear_MB (var AS INTEGER)
    DO UNTIL NOT _MOUSEBUTTON(var)
        WHILE _MOUSEINPUT: WEND
    LOOP
END SUB 'Clear_MB


FUNCTION MBS% 'Mouse Button Status  Author: Steve McNeill
    STATIC StartTimer AS _FLOAT
    STATIC ButtonDown AS INTEGER
    STATIC ClickCount AS INTEGER
    CONST ClickLimit## = 0.2 'Less than 1/4th of a second to down, up a key to count as a CLICK.
    '                          Down longer counts as a HOLD event.
    SHARED Mouse_StartX, Mouse_StartY, Mouse_EndX, Mouse_EndY
    WHILE _MOUSEINPUT 'Remark out this block, if mouse main input/clear is going to be handled manually in main program.
        SELECT CASE SGN(_MOUSEWHEEL)
            CASE 1: tempMBS = tempMBS OR 512
            CASE -1: tempMBS = tempMBS OR 1024
        END SELECT
    WEND

    IF _MOUSEBUTTON(1) THEN tempMBS = tempMBS OR 1
    IF _MOUSEBUTTON(2) THEN tempMBS = tempMBS OR 2
    IF _MOUSEBUTTON(3) THEN tempMBS = tempMBS OR 4

    IF StartTimer = 0 THEN
        IF _MOUSEBUTTON(1) THEN 'If a button is pressed, start the timer to see what it does (click or hold)
            ButtonDown = 1: StartTimer = TIMER(0.01)
            Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
        ELSEIF _MOUSEBUTTON(2) THEN
            ButtonDown = 2: StartTimer = TIMER(0.01)
            Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
        ELSEIF _MOUSEBUTTON(3) THEN
            ButtonDown = 3: StartTimer = TIMER(0.01)
            Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
        END IF
    ELSE
        BD = ButtonDown MOD 3
        IF BD = 0 THEN BD = 3
        IF TIMER(0.01) - StartTimer <= ClickLimit THEN 'Button was down, then up, within time limit.  It's a click
            IF _MOUSEBUTTON(BD) = 0 THEN tempMBS = 4 * 2 ^ ButtonDown: ButtonDown = 0: StartTimer = 0
        ELSE
            IF _MOUSEBUTTON(BD) = 0 THEN 'hold event has now ended
                tempMBS = 0: ButtonDown = 0: StartTimer = 0
                Mouse_EndX = _MOUSEX: Mouse_EndY = _MOUSEY
            ELSE 'We've now started the hold event
                tempMBS = tempMBS OR 32 * 2 ^ ButtonDown
            END IF
        END IF
    END IF
    MBS% = tempMBS
END FUNCTION 'MBS%
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#22
That's interesting OldMoses, I added a PRINT "Mouse Button Pressed" right before the main loop ends. I saved this code in case I need it sometime, thanks!
Reply
#23
Wow B+! I just added that SUB you just mentioned from OldMoses and your code to operate it replacing the _DELAYS and it works really good now! I'm going to think about adding something else before I make the next post on the main forum thread. I did post a version 1 or 2 days ago but this game is grabbing me to add more. Smile
Reply
#24
This is somewhat off topic, but thought you might be interested.

Although you have the mouse sliders working well, I thought I'd introduce you to a little function that I learned a while back, which I think you will love. I think it was Fellippe that introduced me to the map! function. I use it for all sorts of conversions to translate screen positions to desired data ranges, but you'll find it useful for all sorts of things.



When you collect the mouse data for power and angle you're doing the following two computations:

vel = (mx - 60) / 200 * 100 ' converts place in box to 0 to 100

and

a = (mx - 60) / 200 * 90 ' converts place in box to 0 to 90

Here, you're essentially doing the map function manually.



Substituting the map! function, they become:

vel = map!( mx, 60, 260, 0, 100)

and

a = map!( mx, 60, 260, 0, 90)



No less typing of code, but you can shunt the math to the function and all you have to know is the input value from (in this case) mx, the left to right box limits and the desired range you want those limits translated to. In this way you don't have to reinvent the wheel for each different car.



It will even reverse engineer the LINE statement from:

LINE (61, 41)-(mx, 69), _RGB32(255, 0, 1), BF

to

LINE (61, 41)-(map!( vel, 0, 100, 60, 260), 69), _RGB32(255, 0, 1), BF ' returns mx from vel



Which, in this case, doesn't really do anything in your favor, but just illustrates how it will work in either direction.

Then you can place the following in the SUB/FUNCTION section of your code:



Code: (Select All)
FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
    map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
END FUNCTION 'map!




Happy coding!
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#25
Heh, heh that was me doing the calc, I've done it so many times by hand I don't need Map! but yes! very handy for those who haven't had the practice!

Thumbs up for mention of such a useful tool !


Hey too many !'s ? Never!

I think instead of map it might be called Interpolate but that's probably scary term.

map! (locate) this value = value! is between low = minRange and high = maxRange,
as what value = map!'s return is between thisLow = newMinRange and thisHigh= newMaxRange?
b = b + ...
Reply
#26
What's most amazing about map! is how you can reverse the ranges.
If you want a high value from a lower display position:
vel = map!( mx, 60, 260, 100, 0) 'just flip the last two terms.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#27
And you can probably use it for mouse position in a Windowed Screen if you forget Pmap keyword.
b = b + ...
Reply
#28
(05-04-2022, 05:12 PM)bplus Wrote: And you can probably use it for mouse position in a Windowed Screen if you forget Pmap keyword.

That's probably the foremost reason I use map! rather than the PMAP command. I find it more intuitive because I can never remember which of the second function parameters (0-3) controls which translation of axis & direction.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply




Users browsing this thread: 3 Guest(s)