Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Another Mouse Issue?
#1
I'm working on a game, see, and I don't want the player to be able to hold down the fire-button indefinitely (that's cheating!). So I tried setting up a timer that kills the left mouse button after a second and a half. All is cool if the mouse is stationary, but the minute you move the mouse the button resets itself - without the user letting the button up - not cool. Is this a Mac mouse issue, a QB64PE mouse issue or a dumb NakedApe issue?
Is there a better way to do this?     Huh  

Thanks in advance for any insights, Ted

DIM AS _BYTE leftClick, started
DIM startTime AS LONG
SCREEN _NEWIMAGE(800, 600, 32)

DO
    WHILE _MOUSEINPUT
        leftClick = _MOUSEBUTTON(1) '
        mouseX = _MOUSEX
        mouseY = _MOUSEY
    WEND

    IF leftClick THEN

        IF NOT started THEN startTime = TIMER: started = -1

        IF TIMER - startTime > 1.5 THEN '    no holding the button down forever!
            leftClick = 0 '                              kill left click
            started = 0 '                                reset timer
            SOUND 1000, .7 '                         pip
        END IF

        _PRINTSTRING (380, 280), "Button Down"
        _PRINTSTRING (380, 320), STR$(TIMER - startTime)
    END IF

    IF NOT leftClick THEN '                            if buttonUP then reset timer and erase
        CLS
        started = 0
    END IF

LOOP UNTIL _KEYDOWN(27)
SYSTEM
Reply
#2
Mouse your mouse events outside the update loop:

Code: (Select All)
Dim As _Byte leftClick, started
Dim startTime As Long
Screen _NewImage(800, 600, 32)

Do
    While _MouseInput: Wend
    leftClick = _MouseButton(1)
    mouseX = _MouseX
    mouseY = _MouseY

    If leftClick Then

        If Not started Then startTime = Timer: started = -1

        If Timer - startTime > 1.5 Then '    no holding the button down forever!
            leftClick = 0 '                              kill left click
            started = 0 '                                reset timer
            Sound 1000, .7 '                        pip
        End If

        _PrintString (380, 280), "Button Down"
        _PrintString (380, 320), Str$(Timer - startTime)
    End If

    If Not leftClick Then '                            if buttonUP then reset timer and erase
        Cls
        started = 0
    End If
    _Limit 30
Loop Until _KeyDown(27)
System

This fixes any issues on my system.  Honestly, the only thing that needs to go inside that WHILE_WEND loop is your scrollwheel code.
Reply
#3
My mouse routine without double or triple clicks, which I'll probably add tomorrow.

Code: (Select All)
Type mousevar
    mx As Integer ' Row.
    my As Integer ' Column.
    wh As Integer ' Wheel.
    lb As Integer ' Left Button.
    rb As Integer ' Right Button.
    lb_status As Integer ' Left Button Status.
    rb_status As Integer ' Right Button Status.
    CursorStyle As Integer ' 0 Default, 1 Link style. (Hand).
    mousekey As String ' Auto Keyboard Input.
End Type
Dim m As mousevar

Sub mouse (m As mousevar)
    ' Local vars: i%,j%
    Static oldmx As Integer, oldmy As Integer
    If m.wh Then m.wh = 0
    While _MouseInput
        m.wh = m.wh + _MouseWheel
    Wend
    m.mx = _MouseX
    m.my = _MouseY
    m.lb = _MouseButton(1)
    m.rb = _MouseButton(2)
    Select Case m.lb
        Case 0
            Select Case m.lb_status
                Case -2
                    m.lb_status = 0 ' The clicked event and the release triggered any event structured to occur on release.
                Case -1
                    m.lb_status = -2 ' The clicked event triggered any event structured to occur when the button is released.
                Case 0
                    ' Button has not been pressed yet.
                Case 1
                    m.lb_status = -1 ' Rare but button was released before the next required cycle, so cycle is continued here.
                Case 2
                    m.lb_status = 0 ' The drag event is over because the button was released.
            End Select
        Case -1
            Select Case m.lb_status ' Note drag is determined in the text highlighting routine.
                Case -1
                    ' An event occurred and the button is still down.
                    If oldmx <> m.mx Or oldmy <> m.my Then m.lb_status = 2 ' Drag.
                Case 0
                    m.lb_status = 1 ' Left button was just pressed.
                Case 1
                    m.lb_status = -1 ' The button is down and triggered any event structured to occur on initial press.  The status will remain -1 as long as the button is depressed.
            End Select
    End Select
    Select Case m.rb
        Case 0
            Select Case m.rb_status
                Case -2
                    m.rb_status = 0 ' The clicked event and the release triggered any event structured to occur on release.
                Case -1
                    m.rb_status = -2 ' The clicked event triggered any event structured to occur when the button is released.
                Case 0
                    ' Button has not been pressed yet.
                Case 1
                    m.rb_status = -1 ' Rare but button was released before the next required cycle, so cycle is continued here.
                Case 2
                    m.rb_status = 0 ' The drag event is over because the button was released.
            End Select
        Case -1
            Select Case m.rb_status
                Case -1
                    ' An event occurred and the button is still down.
                Case 0
                    m.rb_status = 1 ' button was just pressed.
                Case 1
                    m.rb_status = -1 ' The button is down and triggered any event structured to occur on initial press.  The status will remain -1 as long as the button is depressed.
            End Select
    End Select
    oldmx = m.mx: oldmy = m.my
End Sub

Multiple left clicks an be handled with a timer. Timer starts when the left button is pressed. If the button is released within the time, a flag is set to count 1. If not, no flag. If the flag was set the timer now tracks no-click time. If that set time, say .1 expires, the flag is canceled. The flag can be increased to some max like 3 for a triple click. Of course we could also just count click and release events during a .2-sec period. Get 3 click cycles completed and your triple clicked!

I'll come back and update the code if I do add that to this routine tomorrow. I have a new graphics WP project I'm using this one in, but I haven't added double click to highlight one word or triple click to highlight the line, yet.

Pete
Shoot first and shoot people who ask questions, later.
Reply
#4
(04-25-2024, 01:06 AM)SMcNeill Wrote: Mouse your mouse events outside the update loop:
LOL. Mouse your mouse events, cracked me up. I find myself doing these types of typos all the time.

But Steve is correct, the only thing that should be done within a mouse update loop is gathering scroll wheel events. Here's a demo of that:

Code: (Select All)
SCREEN _NEWIMAGE(800, 600, 32)

radius = 50
DO
    _LIMIT 60
    CLS
    LOCATE 2, 2: PRINT "_MOUSEHWEEL OUTSIDE THE UPDATE LOOP"
    LOCATE 4, 2: PRINT "Use mouse wheel to change size of circle"

    LOCATE 6, 2: PRINT "PRESS ANY KEY TO MOVE _MOUSEWHEEL INSIDE THE LOOP"
    WHILE _MOUSEINPUT: WEND
    radius = radius + _MOUSEWHEEL * 5
    IF radius < 5 THEN radius = 5
    CIRCLE (_MOUSEX, _MOUSEY), radius
    _DISPLAY
LOOP UNTIL INKEY$ <> ""
DO
    _LIMIT 60
    CLS
    LOCATE 2, 2: PRINT "_MOUSEHWEEL NOW INSIDE THE UPDATE LOOP"
    LOCATE 4, 2: PRINT "Use mouse wheel to change size of circle"
    LOCATE 6, 2: PRINT "PRESS ESC TO EXIT"
    WHILE _MOUSEINPUT
        radius = radius + _MOUSEWHEEL * 5
        IF radius < 5 THEN radius = 5
    WEND
    CIRCLE (_MOUSEX, _MOUSEY), radius
    _DISPLAY
LOOP UNTIL _KEYDOWN(27)
SYSTEM
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#5
i approached that problem by timing bullets fired

also you could limit number of bullets, waiting until bullet off screen before reactivating that bullet slot to fire again.
b = b + ...
Reply
#6
(04-25-2024, 01:42 AM)bplus Wrote: i approached that problem by timing bullets fired

also you could limit number of bullets, waiting until bullet off screen before reactivating that bullet slot to fire again.
I use a similar approach. The code below is a snippet from my Widescreen Asteroids game that controls bullet fire. I tend to set up frame counters as timers.

In the second line of code I first check to see if Clock.shipBullet is zero. If it is that means I can fire again. If not toward the end of the snippet you'll see I decrement Clock.shipBullet by one with each passing frame.

The game runs at 60 frames per second and setting Clock.shipBullet to 10 after each bullet fired ensures that the player can fire no more than 6 bullets per second.

Code: (Select All)
        IF Clock.warp = 0 THEN '                                                  warping to next level?
            IF Clock.shipBullet = 0 THEN '                                        no, ready to fire again?
                IF _KEYDOWN(Keys.fire) THEN '                                    yes, fire bullet key pressed?
                    Clock.shipBullet = 10 '                                      yes, set bullet interval
                    c = 0
                    DO '                                                          cycle through bullets
                        IF ShipBullet(c).life = 0 THEN '                          bullet active?

                            '*******************
                            '* Add ship bullet *
                            '*******************

                            '**
                            '** NOTE: player ship bullet lifespan below (70)
                            '**

                            ShipBullet(c).life = 70 '                            set bullet lifespan
                            ShipBullet(c).x = ObjX1(Ship, 0) '                    set bullet X,Y origin
                            ShipBullet(c).y = ObjY1(Ship, 0) '                    (front tip of player ship)

                            '**
                            '** NOTE: player ship bullet speed below (9)
                            '**

                            ShipBullet(c).xv = ObjVectorX(Ship) + 9 * ObjPSine(ObjAngle(Ship)) '  bullet X,Y vectors
                            ShipBullet(c).yv = ObjVectorY(Ship) + 9 * -ObjPCosine(ObjAngle(Ship))
                            PlaySound Sounds.fire, TRUE
                            c = 4
                        END IF
                        c = c + 1
                    LOOP UNTIL c = 5
                END IF
            ELSE
                Clock.shipBullet = Clock.shipBullet - 1 '                        decrement bullet interval timer
            END IF
        END IF
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#7
Steve and Terry, thank you, but I'm on a Mac, the neglected step-child platform Wink , and moving the mouse events outside the update loop is different. Doing your fix, Steve, doesn't solve the problem for me, it just made the timer not work at all 'cept for the beep. Terry, your demo doesn't work on my system either. Pete, thanks, I'll give your sub a try, but I have my doubts. bplus, I'm not using bullets here, just a laser beam to blast away. Terry, I'll try the method from your latest post - cycle counting makes sense.  Thanks, everybody.
Reply
#8
(04-25-2024, 02:16 AM)NakedApe Wrote: Steve and Terry, thank you, but I'm on a Mac, the neglected step-child platform Wink , and moving the mouse events outside the update loop is different. Doing your fix, Steve, doesn't solve the problem for me, it just made the timer not work at all 'cept for the beep. Terry, your demo doesn't work on my system either. Pete, thanks, I'll give your sub a try, but I have my doubts. bplus, I'm not using bullets here, just a laser beam to blast away. Terry, I'll try the method from your latest post - cycle counting makes sense.  Thanks, everybody.
My demo doesn't work on a Mac? That sounds like an issue with QB64pe that needs looking into. Huh
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#9
'bplus, I'm not using bullets here, just a laser beam to blast away.'

semantics: bullet/laser beam, is it a wave or is it a particle? it's both!

just time the 'lastBeam' and don't fire another until > your spec'd time period

how come you aren't giving Terry this bs about bullets, lol

btw i have recently heard nobel prize went to physics that proved it is neither wave nor particle until it is observed, really spooky stuff, then it IS particle referring to double slit experiment with light ie when 'observed' there is no interference pattern. of course i am getting this info from wacky gia you tube???
b = b + ...
Reply
#10
Terry, I think the lack of mouse wheel support on macOS is a known issue, but maybe a740g could comment on that. bplus, you are so right. I fixed the issue without using timers. Cycle counting, which I already used elsewhere in the program, was a simple fix - duh. There's almost always another way to get a job done with QB if you think about it - and get help from the hive mind here.  Smile
Reply




Users browsing this thread: 4 Guest(s)