Одним из ключевых моментов с точки зрения разработчика игр является работа с графикой. Symbian OS предоставляет широкий спектр графических API. Ниже будет рассказано о различных API и показано, как нужно работать с графикой.
Поддержка работы с графикой в Simbian OS реализована в графическом интерфейсе устройства (GDI). GDI определяет рисование примитивов, текста, различных форм и рисунков. Все графические компоненты системы в конечном счете опираются на GDI (рис. 1). Представленные на рисунке компоненты будут описаны ниже.
При рисовании в Symbian OS используется графический контекст и графическое устройство. GDI предоставляет абстрактный класс графического контекста (CGraphicsContext), который является базовым для всего графического контекста. Именно в нем определяются такие параметры рисования, как стиль карандаша и кисти, а также методы, позволяющие использовать в приложении возможности GDI. Фактически рисование на экране устройства осуществляется на основании настроек, установленных в графическом контексте. Базовым классом для всех классов устройства является CGraphicsDevice. В нем определены атрибуты устройства. На рисунке 2 показана иерархия классов графического контекста и устройства.
Экземпляры классов контекста и устройства реализованы в BITGDI, который фактически является экраном или графическим компонентом типа рисунок. Его код написан на ассемблере и хорошо оптимизирован, чтобы обеспечить быстрое отображение графики. BITGDI поддерживает работу с растровыми изображениями, а также обеспечивает двойную буферизацию.
Фактически рисование производится с помощью методовCWindowGc. (Включая базовый класс CCoeControl.)
Доступ к CWindowGc можно получить через CCoeControl::SystemGc, или CEikonEnv::Static()->SystemGc(), если вызов осуществляется вне контекста, но этот метод используется редко.
Чтобы получить свойства экрана, например разрешение, необходимо использовать методы класса CWsScreenDevice, доступный через CWindowGc::Device.
Всякий потомок класса CCoeControl имеет метод Draw, с помощью которого осуществляется перерисовка экрана. Следующий пример демонстрирует использования метода Draw и CWindowGc:
void CMyGameView::Draw(const TRect&/*aRect*/)const { // Получаем ссылку на графический контекст CWindowGc& gc= SystemGc(); // Устанавливаем параметры рисования gc.SetBrushStyle( CGraphicsContext::ESolidBrush); gc.SetBrushColor( KRgbRed); // Рисуем линию gc.DrawLine( TPoint(10,10), TPoint(30,10)); }
Параметр TRect метода Draw определяет область, которую необходимо перерисовать (Вы фактически не имеете возможности рисовать вне этой области. Все, что выходит за ее пределы, будет отсекаться.) Обычно эта область игнорируется, поскольку в большинстве случаев, и особенно в играх, быстрее перерисовать весь экран.
Метод Draw вызывается средой. Вы не должны вызывать его напрямую. Draw вызывается когда
В играх, где экран обычно обновляется через конечные интервалы времени, Вы должны использовать метод DrawDeferred. Он позволяет должным образом обрабатывать команды пользователя, поскольку событие перерисовки имеет низкий приоритет.
Вы не можете быть уверены, что метод Draw будет вызывается средой каждый раз при вызове DrawDeferred. Нет никакого смысла в многократном вызове DrawDeferred, поскольку этот метод лишь обозначает область перерисовки, в то время как сама перерисовка инициализируется системой. Вы должны помнить об этом, когда будете проектировать метод Draw. Например, не стоит разделять игровые вычисления на части, вызываемые между методом Draw и вызовом через таймер DrawDeferred. Самым оптимальным способом осуществления вычислений является реализация расчета по таймеру, а Draw просто отображает текущую игровую ситуацию. (Этот подход позволяет избежать проблем с перерисовкой и делает код более читаемым.)
Возможно осуществлять рисование и без вызова события рисования, но это требует дополнительного шага. (Который, впрочем, делается автоматически при вызове средой метода Draw.)
Следующий пример иллюстрирует описанный метод.
void CMyGameView::MyDrawMethod() { // Получаем указатель графического контекста системы CWindowGc& gc= SystemGc(); // Начинаем рисовать gc.Activate(Window()); // Window().Invalidate(); // для скопированного окна Window().BeginRedraw(); // Задаем параметры рисования gc.SetBrushStyle( CGraphicsContext::ESolidBrush); gc.SetBrushColor( KRgbRed); // Рисуем линию gc.DrawLine( TPoint(10,10), TPoint(30,10)); // Завершаем рисование Window().EndRedraw(); gc.Deactivate(); }
Перевод:aRix