Reputation: 7931
I'm developing a game for Android. It's got a lot going on but is running reasonably smoothly. That is, of course, until the user touches the screen.
While they're touching it, onTouchEvent
is called (with action = ACTION_MOVE
, x = 0
and y = 0
) roughly once every ten milliseconds at what appears to be a fairly high priority, as it absolutely obliterates the framerate. As soon as the touch ends the framerate returns to its nice state.
I've tried
onTouchEvent
handle input for the game as usualonTouchEvent
return true
straight awayonTouchEvent
implemented at allThe problem persists in all three situations.
Has anyone encountered this? Is there a way to reduce the rate at which ACTION_MOVE
events are generated, or to ensure that they're only generated when there is actual movement, or use a polling method that just gets the current location of the touch? Or even just a way to disable it entirely?
Upvotes: 15
Views: 11997
Reputation: 61
Generally events comes with a timestamp property so it's easy to compute and throttle event rate.
if (currentEventTimestamp - lastEventTimestamp > 500) {
lastEventTimestamp = currentEventTimestamp;
// do something
}
Upvotes: 0
Reputation: 211
If you want a solution without having to deal with synchronizing threads I can recommend using the Handler interface to send the event and relevant data using a Message/Bundle to the game rendering thread. The sleep workaround hinted here still applies.
Upvotes: 0
Reputation: 11
I've been trying to follow everything you guys have been talking about, but I must admit that after trying several ways of implementing what you suggest, I still haven't been able to achieve any positive results. Could one of you provide some example code? Specifically, I'd like to know how to go about making the main/UI thread sleep. If it's applicable to my games, it would also be nice to know how to set up a polling model like Jon implemented.
Here's what my code looks like. On the UI thread:
public boolean onTouchEvent(MotionEvent event) {
// Store event somewhere the game thread can see it:
// ...
synchronized (someObject) {
try {
someObject.wait(1000L);
} catch (InterruptedException e) {
}
}
return true;
}
and on the Game thread:
void myGame() {
while (!stopping) {
// ...
// Get a touch event:
synchronized (someObject) {
someObject.notify();
}
Thread.yield();
// ...
}
}
Upvotes: 1
Reputation: 2145
Read this thread. Basically you want to sleep the event thread since otherwise the system will pump a lot of events (between x,y and pressure there is always some movement going on) that you need to handle.
Upvotes: 14
Reputation: 43117
Perhaps a somewhat obvious solution, but... have you tried only handling about 1/10 of them? If you're doing processing that's triggered every 10ms on the UI thread, that's likely going to slow down the framerate, yes. So what if you just accumulate a counter somewhat instead and only do any processing once that's gotten past some minimal threshold?
Upvotes: 0