Posts: 188
Threads: 22
Joined: Mar 2023
Reputation:
12
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?
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
Posts: 2,696
Threads: 327
Joined: Apr 2022
Reputation:
217
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.
Posts: 2,171
Threads: 222
Joined: Apr 2022
Reputation:
103
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.
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(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
Posts: 3,965
Threads: 176
Joined: Apr 2022
Reputation:
219
04-25-2024, 01:42 AM
(This post was last modified: 04-25-2024, 01:44 AM by bplus.)
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 + ...
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(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
Posts: 188
Threads: 22
Joined: Mar 2023
Reputation:
12
Steve and Terry, thank you, but I'm on a Mac, the neglected step-child platform , 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.
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(04-25-2024, 02:16 AM)NakedApe Wrote: Steve and Terry, thank you, but I'm on a Mac, the neglected step-child platform , 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.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 3,965
Threads: 176
Joined: Apr 2022
Reputation:
219
04-25-2024, 11:50 AM
(This post was last modified: 04-25-2024, 12:08 PM by bplus.)
'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 + ...
Posts: 188
Threads: 22
Joined: Mar 2023
Reputation:
12
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.
|