LibGDX: How to get exact touch time?

Viewed 44

Is it somehow possible in LibGDX to get exact touch time (~1 ms accuracy)?

InputProcessor.touchDown is only called at beginning of the frame (or at the end of the frame?) so it only has 16.7 ms accuracy if the frame rate is 60 fps. That is, I only know during which frame the touch happened, but not if it happened 0 or 15 ms after the render() was called, which makes a huge difference in reaction-based games.

Gdx.input.getCurrentEventTime() is not any more accurate.

If this is not possible with LibGDX tools, is there any (easy) hack for capturing the touch event on OS (Android) level to just check the time and then let LibGDX handle it normally?

1 Answers

I looked closely at the libGDX source code and you can see here that it grabs the time stamp from a libGDX TouchEvent class. And you can see here that it uses the time at the moment it's synchronizing touch events as the timestamp placed into TouchEvent, rather than the time reported by Android's MotionEvent class.

So what I would suggest is cloning (copy-pasting) the libGDX AndroidTouchHandler class to create your own class and modifying it so instead of passing the timeStamp variable to the postTouchEvent method, pass event.getEventTime() instead for ACTION_DOWN events.

Then clone the DefaultAndroidInput class, changing nothing but the touchHandler variable to be your cloned class type, and instantiate that instead in the constructor.

So now this version of AndroidInput will report the actual Android MotionEvent's time in Gdx.input.getCurrentEventTime(). True, it will only report the time for the last motion event that occurred before the current animation frame, but presumably it would be very rare or maybe impossible to receive more than one touch down event in a frame. Keep in mind, it will be reporting the time based on system uptime instead of whatever System.nanoTime is relative to.

Then to use this alternative version of AndroidInput, you override createInput() in your game launcher activity class and return an instance of your own class instead.

Disclaimer: I have not tested any of this, and I don't know how accurately Android reports time in the MotionEvent class.

[If you need to handle multiple touches per frame, this gets more complicated. I think you'd need to create an interface in your core module that has a callback that can report multiple touch events with individual timestamps, then implement that in your AndroidInput implementation class, and then back in core you could cast Gdx.input to this interface so you could get at that data.]

Related