Topic was automatically imported from the old Question2Answer platform.
Asked By
Sersch
I need to detect if the mouse has stopped moving in an FPS game.
I’m capturing the cursor by using Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED).
Because of that I have to use event.relative to detect relative mouse movement, like this:
if event is InputEventMouseMotion:
var mouse_motion = event.relative
However, the mouse_motion variable will never be (0,0), because the value is no longer updated when the mouse stops moving. This is intended behaviour, but doesn’t really help.
Is there a way to detect if the mouse has stopped moving? I could use a short timer that resets every time the mouse moves, but that feels like a workaround.
I assume you want to know if it’s stopped moving for some minimal amount of time. In that case, I don’t know how you can avoid some sort of time element in the solution.
Whether that’s a timer (as you mentioned), or tracking an accumulateddelta in _process, or something else, I think you have to somehow involve time.
Perhaps you could remember the most recent set of mouse coords, and, if they’re (reasonably) the same at some point in the future, the mouse hasn’t moved. How far into the future, and how you elect to track that time, is up to you I guess…
maybe the “no time” element he’s looking for is just “asap” kinda thing so on the next pass check if it’s been updated or the same (same = no movement)
Kalmier | 2020-02-14 17:38
Maybe, but making the check between two consecutive frames is likely too fast, and would not reliably detect what would typically be perceived as a “no motion” state.
jgodfrey | 2020-02-14 18:02
Thank you for your answer. The first frame without mouse movement would be desired in my case, but it doesn’t have to be that accurate, so a few more frames wil do too. I’ve settled for the Timer solution.
There’s a Timer now with a very short duration of 0.05sec that gets restarted every time the mouse is moved and automatically runs out after the mouse movement has stopped.
Reviving a dead post just in case someone comes across this and wants a better answer.
The trick is to simply reset the mouse_motion variable (or whatever you chose to name it) when you’re done using it for that frame.
So using op’s code, once you’ve actually used the mouse_motion variable to move the camera or whatever it is you’re using it for
mouse_motion = Vector2.ZERO
That way, if on the next frame there is no mouse movement, mouse_motion will already be equal to zero.
Can you clarify what you mean by ''reset the variable when you’re done using it for that frame"?
Assuming it’s called from within _input() (as per the OP’s code), where would it fit?
I tried:
_input(event): If InputEventMouseMotion: var mouse_motion = event.relative function(mouse_motion) mouse motion = Vector2.ZERO
Thanks!
mstfacmly | 2021-03-17 14:05
I think this is the right answer, better than the time based suggestion.
InputEventMouseMotion only get fired when the mouse actually moves, so you won’t ever get one in _input() with a relative or speed of Vector2.ZERO when the mouse stops.
Instead you want to reset any mouse movement “state” you are (setting in _input()) in _process() which will get called every frame.
What I did is created a singleton that handles mouse motion and resets the values in the next frame if there was no input.
Put it in AutoLoad and you’ll be able to get proper mouse data. The values are also become available from _process() and _physics_process() like