суббота, 10 ноября 2012 г.

Работа над ошибками

Как легко сделать ошибку. И насколько-же сложно потом ее бывает найти и исправить! Если кто-то потрудился запустить мой пример, он мог обратить внимание на его странное поведение, заметное даже на эмуляторе. Кнопки не реагируют на нажатие до тех пор, пока мы не завершим касание. После этого, корректным образом, анимируется нажатие кнопки. Если сделать анимацию посложнее, можно заметить, что в момент касания вся активность приложения приостанавливается, а как только мы отпускаем палец, все продолжается, как ни в чем не бывало.

Я не сразу это заметил, а затем еще дольше искал, в чем ошибка. Ошибка здесь:

void Desktop::update(uint64 timestamp) {
    currentTimestamp = timestamp;
    if (isChanged) {
        getScreenSizes();
    }
    int cnt = touchPad.getTouchCount();
    if (cnt > 0) {
        for (int i = 0; i < MAX_TOUCHES; i++) {
            Touch* t = touchPad.getTouch(i);
            if (t->isActive) {
                int msg = (cnt > 1)?emtMultiTouchUp:emtSingleTouchUp;
                if (t->isMoved) {
                    msg = (cnt > 1)?emtMultiTouchMove:emtSingleTouchMove;
                }
                if (t->isPressed) {
                    msg = (cnt > 1)?emtMultiTouchDown:emtSingleTouchDown;
                }
                if (checkBounce(t->id, msg)) return;
                if (currentScene != NULL) {
                    currentScene->sendMessage(msg | (t->id & emtTouchIdMask), 
                                              t->x, t->y);
                }
            }
        }
    }
    if (isKeyAvailable) {
        s3eKeyboardUpdate();
    }
    if (currentScene != NULL) {
        currentScene->update(timestamp);
    }
}


Как всегда, все произошло из за того, что "хотелось как лучше". Дело в том, что если не предпринимать каких-то дополнительных действий, при нажатии, Touchpad (имеется в виду модуль проекта) посылает целую последовательность событий "нажатие", там где кнопке хватило бы всего одного. В результате, кнопка начинала "дребезжать", быстро нажимаясь и отжимаясь. Чтобы этого избежать, была добавлена функция checkBounce, формирующая правильную последовательность событий, убирая лишние. В процессе поиска ошибки, ее код был перепроверен, наверное, раз десять. А ошибка была совсем не там.

Вот правильный код:

void Desktop::update(uint64 timestamp) {
    currentTimestamp = timestamp;
    if (isChanged) {
        getScreenSizes();
    }
    int cnt = touchPad.getTouchCount();
    if (cnt > 0) {
        for (int i = 0; i < MAX_TOUCHES; i++) {
            Touch* t = touchPad.getTouch(i);
            if (t->isActive) {
                int msg = (cnt > 1)?emtMultiTouchUp:emtSingleTouchUp;
                if (t->isMoved) {
                    msg = (cnt > 1)?emtMultiTouchMove:emtSingleTouchMove;
                }
                if (t->isPressed) {
                    msg = (cnt > 1)?emtMultiTouchDown:emtSingleTouchDown;
                }
                if (!checkBounce(t->id, msg)) {
                   if (currentScene != NULL) {
                       currentScene->sendMessage(msg | (t->id & emtTouchIdMask), 
                                                 t->x, t->y);
                   }
                }
            }
        }
    }
    if (isKeyAvailable) {
        s3eKeyboardUpdate();
    }
    if (currentScene != NULL) {
        currentScene->update(timestamp);
    }
}


Найдите десять отличий ;)

Для тех, кто не следил за циклом статей, как всегда, ссылка на исправленный проект.

P.S. В эти выходные закончился Evaluation период у Мармелада. Я решил его продлить, теперь уже за денежку :) Считаю, что $149 совсем не дорого за такое удовольствие.

Комментариев нет:

Отправить комментарий