Yampa
Yampa copied to clipboard
Sampling frequency of mouse motion events
Hey guys, is there a way to control the frequency at which mouse motion is being sampled in Yampa or Bear River?
It feels like the event stream is too dense, when I move the mouse and I could easily have less events, as the app is reacting to the relative mouse motion.
Just to clarify: when I rotate the camera with the keyboard cursor keys, it behaves as expected, but when I move the mouse, it almost feels like the app is trying to react too detailed to every position change of the mouse motion, it feels like it's lagging trying to process too many samples.
Does it sound familiar? Can I fix it by controlling the sampling frequency?
Cheers, Vlad
Yampa/bearriver provides no native way to set the frequency at which the network or branches of the network is run as far as I know, unless you just make the thread running reactimate sleep. My solution to this problem of having different update rates at different parts of the application would be to simply have a set network update rate (200 FPS usually) using the thread sleep method (sleep $ timePassed - frameDelta
) and then creating a switch that recursively switches into something like iPre noEvent >>> myFun
so that every second input gets ignored. However this is pretty ugly since it wont work the same if the update rate changes because then the updates would be happening less often so to skip 2 updates then would take a different amount of time than before. Maybe there is a better solution to this in yampa/BR? The real solution to this problem however is what rhine is doing with clocks
But I think the better alternative in your specific case is to just outside of the FRP network accumulate the mouse events and then eventually send them in as a single event containing the accumulated mouse events every 0.0166 milliseconds or so.
Thanks for the reply, @walseb . Do you, maybe, have an example that does something similar for a reference?
Here's how I get the relative mouse motion events:
nextAppInput :: AppInput -> SDL.EventPayload -> AppInput
-- | mouse movement/position
nextAppInput inp (SDL.MouseMotionEvent ev) =
inp { ...
, inpMousePos = (fromIntegral x, fromIntegral y)
, inpMouseRelPos = (fromIntegral x', fromIntegral y') }
where (P (V2 x y )) = SDL.mouseMotionEventPos ev
( (V2 x' y')) = SDL.mouseMotionEventRelMotion ev
The AppInput
is passed along to the Game
inside the topmost SF as
parseWinInput :: SF WinInput AppInput
parseWinInput = accumHoldBy nextAppInput initAppInput
animate
window
(parseWinInput >>> (mainGame game &&& handleExit))
It looks like iPre f >>>...
does the trick though:
mouseRelPos :: SF AppInput (Double,Double)
mouseRelPos = iPre initAppInput >>> arr inpMouseRelPos -- <- this seems to fix it
Thanks!
Using iPre like that should only delay it by the initial tick though, not every other tick Try this mess I made instead:
runSFEveryOtherTick :: SF a (Event b) -> SF a (Event b)
runSFEveryOtherTick sf =
dSwitch
(constant noEvent &&& constant (Event ()))
(const $ dSwitch
(sf &&& constant (Event ()))
(const $ runSFEveryOther sf))
Maybe it will just hang, I haven't tried it myself, but it does compile so there is hope
I was thinking about this today and my solution wont work if the SF you pass in stores data because the argument SF isn't actually modified. For that to work you would probably have to unMSF
the SF
, so that it's run forcefully and then pass the new SF back again to runSFEveryOtherTick
. But since you are just using a normal function that you lift into a SF that shouldn't be a problem
There seems to be a solution in the comments with iPre
, and there's been no activity in this issue for years. Closing.