Why are touch events destroying my Android framerate?
Asked Answered
M

5

15

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

  • having onTouchEvent handle input for the game as usual
  • having onTouchEvent return true straight away
  • not having onTouchEvent implemented at all

The 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?

Might answered 27/4, 2009 at 3:42 Comment(0)
W
14

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.

Wyeth answered 27/4, 2009 at 17:43 Comment(0)
V
1

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();

        // ...
    }
}
Velites answered 1/1, 2010 at 14:32 Comment(0)
J
0

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?

Jennette answered 27/4, 2009 at 13:9 Comment(0)
P
0

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.

Piotrowski answered 14/11, 2011 at 19:20 Comment(0)
P
0

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 

}
Pouch answered 24/11, 2014 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.