伯乐共勉

讨论。NET专区
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
图形
从一个游戏开发者的观点来看,对图形的支持是一个操作系统的重要特征。Symbian操作系统提供了广阔的图形API,这一章,我们来关注一下游戏中有用的API。

图形体系的简介
Symbian操作系统的图形支持在系统图形设备接口(GDI)中详细说明。GDI定义了简单的显屏方法并且提供了显文本,离散形状和位图的函数。所有的 系统图形组件基本上都依靠像在Graphics Components of Symbian OS中所看到的GDI。这些组件将在以后的章节中详细讨论。

在Symbian操作系统中显屏是用graphics contexts和graphics devices实现的。GDI提供了抽象的graphics contexts类,CGraphicsContext,是所有graphics contexts的基类。它定义了显屏的设置,像笔和刷的风格,提供了程序使用GDI图形功能的函数。实际的显屏使用graphics context中定义的设置由graphics device实现。所有的设备类的基类是CGraphicsDevice,它来明确指定显屏的设备属性。Class Hierarchies of Graphics Contexts and Graphics Devices说明了graphics contexts和graphics devices的类层次结构。

具体的context和device类在BITGDI中实现,它是屏幕和位图用的图形组件,是高度优化的提供快速显屏的汇编程序代码。BITGDI实现图像的光栅处理和渲染,它支持屏上和屏下位图。

显屏基础
控制器显屏—包括CCoeControl,是最基础的控制器类,程序视图也是控制器—由CWindowGc提供的方法来完成。

CWindowGc可以通过CCoecontrol::SystemGc来获取,通过CEikonEnv::Static()->SystemGc ()在controls context外获取CWindowGc是可行的。但是通常情况下显屏还是在controls context内部实现。

得到屏幕的属性,像显示模式,需要使用CWsScreenDevice提供的方法。可以通过CWindowGc:evice来获取。

每一个从CCoeControl继承的控制器都包含实现控制器显屏的Draw方法,下面的例子给出了CWindowGc的Draw方法的使用:
void CMyGameView:raw( const TRect& /*aRect*/ ) const
   {
   // Get the system graphics context
   CWindowGc& gc = SystemGc();
   // Set drawing settings
   gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
   gc.SetBrushColor( KRgbRed );
   // Draw
   gc.DrawLine( TPoint(10,10), TPoint(30,10) );
   }
Draw的TRect参数定义了需要刷新的屏幕区域(实际上,由于剪辑你并不能画在区域之外)。通常,由于整个控制器刷屏非常简单并且在大多数情况下特别是游戏中非常快,给定矩形区域就被忽略了。

Draw方法由程序框架来调用,不能直接调用。Draw被调用,当:
        一个窗口被创建。
        其它的窗口内容不正确的地方(例如,由于窗口重叠)。
        CCoeControl:rawNow或者CCoeControl::DrawDeferred被调用。DrawNow立即激活显屏。而DrawDeferred只是标记不正确的区域,由窗口服务器最后完成刷屏。

在游戏中,由很短时间间隔的计时器更新的屏幕的地方,需要调用DrawDeferred方法来刷屏。DrawDeferred允许例如用户输入被完全处理然后再刷屏,因为刷屏时间的优先级比较低。

不能认为在每次DrawDeferred被调用的时候程序框架都会调用Draw方法。可以多次调用DrawDeferred,但是每次刷屏都去调用 DrawDeferred是不必要的,因为DrawDeferred只是标记不正确的控制区域,在系统初始化之前并发调用DrawDeferred是没有 效果的。这必须在设计Draw方法的内容时加以考虑,例如,游戏的计算不能够分到Draw方法和计时器调用SrawDeferred两部分里。通常的用法 是,计时器计算,Draw方法只是显示目前游戏的状态(不仅是因为刷屏问题,也是为了清晰划分和代码的可读性)。

也可以不用draw事件来进行控制器显屏,但是就要做些另外的步骤了(这些是在程序框架调用Draw方法时自动完成的):
        用CWindowGc::Activate激活graphics context。
        用RWindow::BeginRedraw通知窗口服务显屏。
        控制器显屏。
        用RWindow::EndRedraw通知窗口服务显屏完成。
        用CWindowGc::Deactivate取消对graphics context的激活。

下面的例子说明了前面方法的使用:
void CMyGameView::MyDrawMethod()
   {
   // Get the system graphics context
   CWindowGc& gc = SystemGc();

   // Begin drawing
   gc.Activate(Window());
   // Window().Invalidate(); // for backed-up windows
   Window().BeginRedraw();

   // Set drawing settings
   gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
   gc.SetBrushColor( KRgbRed );
   // Draw
   gc.DrawLine( TPoint(10,10), TPoint(30,10) );

   // End drawing
   Window().EndRedraw();
   gc.Deactivate();
   }