Почему сенсорные события уничтожают мою частоту кадров в Android?

Я разрабатываю игру для Android. Он прошел много, но работает достаточно гладко. Это, конечно, пока пользователь не коснется экрана.

Пока они касаются его, onTouchEvent вызывается (с action = ACTION_MOVE, x = 0 и y = 0) примерно один раз каждые десять миллисекунд при том, что кажется довольно высоким приоритетом, поскольку он полностью уничтожает частоту кадров, Как только осязание заканчивается, частота кадров возвращается в хорошее состояние.

Я пробовал

  • имеющий onTouchEvent ввод ввода для игры как обычно
  • onTouchEvent возвращает true прямо
  • не реализовано onTouchEvent

Проблема сохраняется во всех трех ситуациях.

Кто-нибудь сталкивался с этим? Есть ли способ уменьшить скорость, с которой генерируются события ACTION_MOVE, или гарантировать, что они генерируются только при фактическом перемещении, или использовать метод опроса, который просто получает текущее местоположение касания? Или даже просто способ полностью отключить его?

Ответы

Ответ 1

Read этот поток. В основном вы хотите спать поток событий, так как в противном случае система будет накачать множество событий (между x, y и давлением всегда происходит некоторое движение), которые вам нужно обрабатывать.

Ответ 2

Я пытаюсь следить за всем, что вы, ребята, говорили о чем, но я должен признать, что после нескольких способов реализации что вы предлагаете, я до сих пор не смог добиться каких-либо положительных результатов Результаты. Может ли один из вас предоставить примерный код? В частности, Я хотел бы знать, как начать спускать поток основного/пользовательского интерфейса. Если это применимо к моим играм, было бы неплохо узнать, как установить опробована модель опроса, например Jon.

Вот как выглядит мой код. В потоке пользовательского интерфейса:

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;
}

и в игровом потоке:

void myGame() {
    while (!stopping) {
        // ...

        // Get a touch event:
        synchronized (someObject) {
            someObject.notify();
        }
        Thread.yield();

        // ...
    }
}

Ответ 3

Возможно, несколько очевидное решение, но... вы пробовали только обрабатывать около 1/10 из них? Если вы выполняете обработку, которая запускается каждые 10 мс в потоке пользовательского интерфейса, это, вероятно, замедлит частоту кадров, да. Итак, что, если вы просто аккумулируете счетчик несколько вместо этого и только делаете какую-либо обработку после того, как получилось какой-то минимальный порог?

Ответ 4

Если вам нужно решение без необходимости синхронизировать потоки, я могу порекомендовать использовать интерфейс Handler для отправки события и соответствующих данных с помощью Message/Bundle в поток воспроизведения игры. Обходной путь сна, намеченный здесь, по-прежнему применяется.

Ответ 5

Обычно события имеют свойство timestamp, поэтому его легко вычислить и снизить скорость события.

if (currentEventTimestamp - lastEventTimestamp > 500) { 

    lastEventTimestamp = currentEventTimestamp;

    // do something 

}