Нужно ли перерисовывать все объекты на холсте в каждом кадре?

Я настраиваю игровой цикл. Цикл настроен на обновление со скоростью 50 кадров в секунду. В настоящее время единственное действие, которое делает приложение, — это рисование координат экрана в ответ на сенсорные события. Первоначально я настроил функцию отрисовки только для отрисовки новых событий касания. Это заставило текст мигать. Несколько событий касания мигают в разное время, что наводит меня на мысль, что Canvas использует несколько страниц за кулисами. Чтобы обойти это, я составил список всех произошедших событий касания и при каждом вызове отрисовки перерисовывал весь список.

Пожалуйста, поправьте меня, если я ошибаюсь, вызовы lockCanvas()/unlockCanvasAndPost() по сути являются свопом обратного буфера. Чтение документации по блокировке и разблокировке звучит так, будто необходимо перерисовывать всю сцену между вызовами, если только вы не используете lockCanvas(Rect dirty). В этом случае область грязного прямоугольника необходимо перерисовать, а внешнюю область сохранить.

Содержимое поверхности никогда не сохраняется между unlockCanvas() и lockCanvas(), по этой причине каждый пиксель в области поверхности должен быть записан. Единственное исключение из этого правила — когда указан грязный прямоугольник, в этом случае не грязные пиксели будут сохранены.

Я знаю, это звучит так, как будто я ответил на свой вопрос, но, согласно документации, Surface никогда не сохраняется между вызовами. Однако это не объясняет поведение моей первой реализации, когда я нажимал на экран, и текст начинал мигать. Поскольку я нарисовал текст только один раз, это будет означать, что мерцание происходит из-за переключения на «бэкбуфер», который не получил вызов drawText(), и исходную поверхность, которая не была уничтожена, но, возможно, это следует учитывать ненадежный.

Итак, вопрос: нужно ли мне перерисовывать все объекты при каждом вызове отрисовки? И если да, нужно ли мне «очищать» холст или, по крайней мере, перерисовывать фоновое изображение?


person Aholio    schedule 07.06.2012    source источник


Ответы (1)


да, если вы не выполняете грязную перерисовку, когда вы определяете область, которую перерисовываете, каждая точка на вашем холсте будет уничтожена.

person Yevgeny Simkin    schedule 07.06.2012
comment
Спасибо за ответ. Есть ли лучшая документация о том, как работает весь этот процесс? Я бы подумал, что если бы поверхность была уничтожена между вызовами, у меня был бы блик, а не мигающий текст, когда был только один вызов drawText(). Таким образом, либо поверхность уничтожается, но воссоздается в том же месте памяти, таким образом, «грязная» память выглядит так, как будто ничего не изменилось; или Surface не уничтожается, но «следует» считаться ненадежным, возможно, потому, что какая-то другая функция может изменить его между вызовами блокировки/разблокировки. Было бы неплохо узнать, как именно это работает. - person Aholio; 08.06.2012
comment
Я не совсем понимаю, что вы пытаетесь сделать, но во всех моих приложениях для рисования вручную я никогда не видел мерцания. Я считаю, что двойная буферизация обрабатывается автоматически (мне, конечно, никогда не приходилось управлять ею вручную). Каждый раз, когда вызывается аннулирование, вызывается обратный вызов onDraw, и холст перерисовывается. Я не могу сказать, что на самом деле делает Surface *... Я никогда не смотрел на базовый код. - person Yevgeny Simkin; 08.06.2012
comment
На данный момент я только пытаюсь лучше понять, что происходит. Теперь я получаю анимацию без мерцания, очищая холст и перерисовывая все. Мне просто было любопытно, почему я получил мерцание от одного вызова отрисовки. Мое первоначальное предположение заключалось в том, что холст был постоянным, поэтому теоретически при блокировке/разблокировке я имел дело с одной и той же поверхностью. Это не так, поэтому блокировка/разблокировка вызывает другую поверхность. Это то, что я собрал до сих пор. Я надеялся найти лучшую документацию по этому поведению помимо моих собственных наблюдений. Спасибо еще раз за помощь - person Aholio; 10.06.2012
comment
Передача dirtyRect приведет к снижению производительности, поскольку необходимо скопировать содержимое из предыдущего буфера. Конечно, хотелось бы, чтобы был способ отключить двойную буферизацию. - person jjxtra; 25.06.2015