Если игра предполагает отображение на экране множества различных движущихся объектов, которые нужно часто обновлять, буфер клиентской части экрана может быть заполнен, прежде чем все объекты успеют обновиться. В результате пользователь увидит мерцание на экране телефона. Подобные нежелательные эффекты могут возникнуть и в случае, если вид, на формирование которого уходит много времени, рисуется прежде чем завершилось его обновление. Эти проблемы легко решаются с помощью двойной буферизации. Создается вспомогательный буфер, в который производится рисование. После того как сцена в полностью сформирована, его содержание переносится на экран. Использование двойной буферизации особенно актуально для игр.

Рассмотрим порядок использования внеэкранного буфера:

  1. Создайте новое изображение, соответвующее по размеру Виду (Это можно сделать, например, с помощью ConstructL.). Если подразумевается, что на экране будет отображаться большое количество игровых объектов, то цветовая палитра буфера должна быть такой же, как у объектов (картинок). Если объектов мало, то лучше сделать палитру буфера совпадающей с палитрой Вида. В идеале палитры игровых объектов, Вида и внеэкранного буфера должны совпадать. Это позволит обойтись без преобразования палитры, что положительно скажется на скорости игры.
  2. Создайте устройство изображения и графический контекст для созданного буферного изображения. Это необходимо, поскольку после создания контекста для изображения, с ним можно работать точно так же как с графическим контекстом Вида.
  3. Каждый раз, когда необходимо обновить содержание экрана, сначала производится рисование во внеэкранный буфер. Когда сцена в буфере полностью сформирована, вызываются методы Вида DrawNow или DrawDeferred. Метод DrawDeferred является безопасным.
  4. Метод Draw Вида просто копирует содержание внеэкранного буфера в Вид (в передний буфер).

Ниже приведен пример:

void CMyGameView::ConstructL(const TRect& aRect)
{
.
.
.
// Создаем новое изображение совпадающее
// по размеру и цветовой палитре м экраном
TDisplayMode displayMode= CEikonEnv::Static()->
ScreenDevice()->DisplayMode();
iBackBufferBitmap=new(ELeave) CFbsBitmap();
User::LeaveIfError(iBackBufferBitmap->
Create(Rect().Size(), displayMode));
// Создаем устройство изображения
iBackBufferDevice= CFbsBitmapDevice::NewL(iBackBufferBitmap);
// Создаем графический контекст для буферного изображения
User::LeaveIfError(iBackBufferDevice.CreateContext(
iBackBufferGc));
}
 
CMyGameView::~CMyGameView()
{
delete iBackBufferGc;
delete iBackBufferDevice;
delete iBackBufferBitmap;
}
 
// Вызываем таймер для периодического обновления экрана
// Все отображение производится во внеэкранный буфер.
void CMyGameView::UpdateDisplay()
{
// Рисуем фон
iBackBufferGc->BitBlt(TPoint(0,0), iMyBackgroundBitmap);
// Рисуем еще что-нибудь
.
.
.
// После того как все что нужно перенесено в буфер, обновлякм Вид
DrawDeferred();
}
 
void CMyGameView::Draw(const TRect&/*aRect*/)const
{
CWindowGc& gc= SystemGc();
// Просто переносим содержание буфера в Вид
gc.BitBlt(Rect().iTl, iBackBufferBitmap);
}

Перевод:aRix




Наши соцсети

Подписаться Facebook Подписаться Вконтакте Подписаться Twitter Подписаться Google Подписаться Telegram

Популярное

Ссылки

Новости [1] [2] [3]... Android/ iOS/ J2ME[1] [2] [3]) Android / Архив

Рейтинг@Mail.ru Яндекс.Метрика
MobiLab.ru © 2005-2018
При использовании материалов сайта ссылка на www.mobilab.ru обязательна