Series60游戏设计参考(二)

 

6、Graphics
6.1 Graphics Architecture Overview
SymbianOS的图形支持在系统的图形设备接口(GDI)指定。GDI定义了最低层的绘制功能并提供了绘制文本、分形和位图的函数。系统中所有的图形组件都依靠GDI,这点我们可以从下图(Figure 1)中看出。


SymbianOS中,绘制是通过graphics contexts和graphics devices来完成的,这里GDI提供了一个抽象的graphics context类,CGraphicsContext,它是所有graphics contexts的基类。它定义了drawing settings,象pen和brush style,并提供了方法给应用程序以使用GDI的图形功能。而实际的绘制是在graphics device中完成的,其基类为CGraphicsDevice,which specifies the attributes of a device the drawing is assigned to.如下图所示(Figure 2),它演示了从graphics contexts和graphics devices中继承的类。


这些具体的context和device类都是在BITGDI中完成的,which is a screen and bitmap-speicific graphics component.它在汇编级进行过高度优化,可以保证很快的图形绘制。The BITGDI implements rasterizing and rendering of images and it supports drawing in on- and off-screen bitmaps.

6.2 Drawing Basics
我们可以使用CWindowGc提供的方法来绘制控件,控件的基类为CCoeControl,而应用程序的view也是一个控件。CWindowGc可以通过访问CCoeControl::SystemGc来得到。它也可以使用外部控件的CWindowGc??通过调用CEikkonEnv::Static()->SystemGc(),but usually drawing should be done within the controls context.

为了得到屏幕的属性,如显示模式,可以通过调用CWsScreenDevice的功能函数来获得,它可以通过访问CWindowGc::Device来获得。

每个从CCoeControl派生的控件都有一个Draw方法。它可以完成控件的绘制,下面的代码做了演示:
void CMyGameView::Draw(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));


这里的TRect参数定义了可以进行绘制的有效区域,the given rectangle is ignored due to the fact that it is much simpler and in most cases, especially in games, faster to redraw the whole control.

Draw方法是被framework所调用的,你不能直接调用它,那在什么情况下会调用这个Draw那:
(1)创建一个窗口时
(2)当其他事件发生时窗口的内容变的无效(如有了重载的窗口)
(3)CCoeControl::DrawNow或CCoeControl::DrawDeferred可以直接调用它。DrawNow直接进行绘制,而DrawDeferred则仅仅标记control区域为无效,最后由window server来完成重绘。

在游戏中,屏幕通常在短时间内就会得到更新,因此最好使用DrawDeferred方法来重绘屏幕,它允许,如,用户的输入得到适当的处理,因为redraw event在一个较低的优先级。

你要知道的是,在每次调用DrawDeferred后并不能立即调用Draw方法,因为多个DrawDeferred的执行过程是这样的,首个DrawDeferred调用后如果系统还没有重绘的话,那后继的DrawDeferred是无效的。这就要注意了。

我们也可以不经过draw event而绘制一个控件,但这需要额外的步骤(而这些步骤本来是由框架调用Draw方法时自动完成的):
1. Activate the graphics context with CWindowGc::Activate.
2. Notify the window server about the drawing with RWindow::BeginRedraw.
3. Draw on the control.
4. Notify the window server when drawing is finished with RWindow::EndRedraw.
Deactivate graphics context with CWindowGc::Deactivate.

下面的代码指示了上面的步骤
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();


6.3 Text and Fonts
实际上每个游戏中设计者都需要在屏幕上显示文字,在游戏中,字体通常要被设定和游戏风格想匹配,SymbianOS中提供了一组标准的字体,也可以生成并使用你自己的位图字体。在系统中每种字体只能有一个实例存在,并且在系统所有的线程中共享。这样可以节约内存。

要使用一个特定的字体绘制文本,你必须:
1. Construct a CFont object by querying a font with the given parameters from the screen device (CGraphicsDevice::GetNearestFontInTwips).

2. Before drawing text, set the graphics context’s font to a constructed one. (CWindowGc::UseFont)

3. When the font is no longer needed, it can be released with CGraphicsDevice::ReleaseFont. Before releasing the font, it must be released from the graphics context (CWindowGc::DiscardFont).

下面的代码生成了一个新的字体,绘制了文本,并释放了该字体:
void CMyGameView::Draw( const TRect& /*aRect*/ ) const

  CWindowGc& gc = SystemGc();
  // Get smallest possible arial font
  _LIT(KMyFontName,"Arial");
  CFont* myFont;
  TFontSpec myFontSpec(KMyFontName,1);
  CGraphicsDevice* screenDevice = iCoeEnv->ScreenDevice();
  screenDevice->GetNearestFontInTwips(myFont,myFontSpec);
  // Use new font
  gc.UseFont(myFont);
  // Draw some text
  _LIT(KMyText,"My text");
  gc.DrawText(KMyText, TPoint(40, 40) );
  // Discard and release the font
  gc.DiscardFont();
  screenDevice->ReleaseFont(myFont);


实际上一般是在ConstructL中生成font,而在destructor中释放。

TFontSpec指定了font的属性:
(1)Height of the font
(2)Typeface(TTypeFace); for example, “Roman”, “Courier”. Each typeface has symbol, serif and proportional attributes.
Font style (TFontStyle); posture (italic), weight (bold) and print position (subscript, superscript.)
(3)Font style (TFontStyle); posture (italic), weight (bold) and print position (subscript, superscript.)

当询问关于一个字体的属性时,将返回和给定属性最为接近的那个字体。

CEikonEnv也有一组函数可以获得该环境中具体字体的信息,如CEikonEnv::TitleFont就返回了title font。要找到字体库中可用的字体,那可以使用CGraphicsDevice::NumTypeFaces获得字体的数目,然后再用CGraphicsDevice::TypeFaceSupport获得具体字体的信息。

void CMyGameView::ListMyFontsL()

  // Find out the number of typefaces
  TInt iNumTypefaces = iCoeEnv->ScreenDevice()->NumTypefaces();
  // Show name of each available font
  TBuf<64> myFontName;
  TBuf<128> text;
  for(TInt t = 0; t < iNumTypefaces; t++)
 {
   // Get font name
   TTypefaceSupport myTypefaceSupport;
   iCoeEnv->ScreenDevice()->TypefaceSupport(myTypefaceSupport, t);
   myFontName = myTypefaceSupport.iTypeface.iName.Des();
   _LIT(KMyText, "Font %d/%d:");
   text.Format(KMyText, t, iNumTypefaces);
   iEikonEnv->InfoWinL(text, myFontName);
  }


在游戏中有时候是需要生成一个特定字体的,特定字体的绘制程序为,将位图中代表各个字的image传输到屏幕上,这是个有效而快速的方法,这样你可以现实各种字体:)不过在完成时要花费时间。

你也可以生成一个新的SymbianOS字体,这样就可以使用现存的字体和图形APIs了,要生成这样的字体,你应该:
(1)生成一个font definition file;如MyFont.gd
(2)生成Adobe BDF(Bitmap Distribution Format) font bitmaps,如,MyFont.bdf
(3)Add required, Symbian OS specific properties to the BDF file if they are missing.
(4)使用fnttran工具来生成symbian系统字体存储文件,如,MyFont.gdr.(如fnttran MyFont.bdf MyFont.gd MyFont.gdr)
(5)拷贝生成的字体文件,MyFont.gdr到/system/fonts文件中(我们可以把文件放在pkg中来生成安装文件),而对模拟器来说只要拷贝该文件到fonts目录即可。

字体定义文件(MyFont.gd)可能看起来如下:
Typeface tf_MyFont
  Name "My Font" Proportional
  FontBitmaps
   MyFont // Name of the font in BDF file
  EndFontBitmaps
EndTypeface

FontStoreFile
  CollectionUid 123456789 // Uid of the font; must be unique
  KPixelAspectRatio 1000
  CopyrightInfo
   "MyCopyrightInfo"
  EndCopyrightInfo
  Typefaces
   tf_MyFont
  EndTypefaces
EndFontStoreFile

当使用BDF格式时,各种实用函数都可以用来生成该字体。BDF文件通过Windows bitmaps或特定字体编辑工具来生成,或者自己手动来生成这个文件。因为基本说来它是一个文本文件,不过要手动来做的话很费事。

When the BDF file is created, it usually requires a few modifications. These properties must exist in the BDF file (between STARTPROPERTIES and ENDPROPERTIES statements):
Uid uid (not the same as CollectionUid.)
MaxNormalWidth width.
MaxConsecutiveFillChars max.
Bold [1/0].
Italic [1/0].
FONTASCENT ascent.
FONTDESCENT descent.

Typically Uid and MaxNormalWidth properties are missing from the BDF file. fnttran will notify you if some of the values are missing.

一切就绪后,我们可以这样来使用新字体:
CFont* CMyGameView::GetMyOwnFont()

  _LIT(KMyFontName,"MyFont");
  CFont* myFont;
  TFontSpec myFontSpec(KMyFontName,1);
  CGraphicsDevice* screenDevice = iCoeEnv->ScreenDevice();
  screenDevice->GetNearestFontInTwips(myFont,myFontSpec);
  return myFont;

字体文件可以拷贝到任何盘下(C:/system/fonts, E:/system/fonts),而设备则需要一个soft reboot才能使用它们。也可以动态的来安装字体,使用CWsScreenDevice::AddFile,这样就可以防止重启的需要。

6.4 Bitmaps
在SymbianOS中,使用位图的首选方法是生成MBM(multi-Bitmap文件),然后可以在运行时来访问位图。MBM可以在一个单独的文件中包含多个给定的位图。An MBM can either be a file store or a ROM image type. The ROM image MBM is not compressed and thus accessing the MBM does not consume RAM. File store MBMs are compressed (by default), and accessing the file store MBMs consumes memory due to the needed decompression. The default type of MBMs is file store.

MBMs可以使用位图转换工具bmconv来生成。可以直接从命令行运行,也可以放在工程文件mmp中。在工程文件中,格式应如下:
// MyGame.mmp
START BITMAP MyGame.mbm
HEADER
TARGETPATH ../../../../wins/c/system/apps/MyGame
SOURCEPATH ../MyBitmaps
// color-depth source-bitmap
SOURCE c12 image1.bmp
SOURCE c12 image2.bmp
SOURCE c12 image3.bmp
END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值