亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

基于Nokia S60的游戲開發之四

2019-11-18 19:39:57
字體:
來源:轉載
供稿:網友

  應用程序在屏幕上的描畫一般是使用CWsScreenDevice圖形設備來完成,與CWindowGc圖形上下文相關聯。CONE提供了一個CWindowGc實例作為描畫控件的標準圖形上下文。它被CCoeEnv創建并且可以使用CCoeControls::SystemGc方法訪問。CWindowGc的描畫方法在客戶端窗口服務器緩沖區上進行緩沖。

  描畫要么是一個系統初始事務要么是一個應用程序初始事務。系統初始描畫在窗口創建的時候被觸發,或者當窗口內容因為窗口重疊而失效的時候被觸發。對于后一種情況,窗口服務器為每個窗口保持一個無效的區域。如果一個窗口需要重畫,窗口服務器發送一個重畫事件到擁有無效窗口的應用程序中。CONE然后使用無效區域來建立需要被重畫的控件,并且調用它們的Draw方法。這就是為什么每個控件都應該實現Draw方法來重畫它們自己。CCoeControl中的Draw的默認為控件為空。下面的代碼說明了Draw方法的示例:

void CExampleControl::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) );

  Draw方法的TRect參數指明了需要重畫的無效區域。然而大多數控件忽略矩形,由于它非常簡單并且重新描畫整個控件也不是非常慢。

  當一個應用程序的數據或者狀態改變的時候,需要應用程序初始化描畫,并且屏幕需要更新。CCoeControl提供非虛擬DrawNow方法,指明控件將要描畫的窗口服務器,調用控件的Draw方法,最后指明完成描畫的窗口服務器。CCoeControl還提供了DrawDeferred方法,使窗口無效并且在窗口服務器中觸發一個新的重畫事件。這兩個方法之間的差異是DrawNow強制控件立即重畫自己,而DrawDeferred導致一個重畫事件將使用低優先級操作。由于CONE使用比重畫事件更優先的級別處理用戶輸入事件,所以任何未定的用戶輸入事件都將首先處理。但由于需要重畫整個控件,故都是很繁重的操作,通常只有改變的部分需要重畫,這可以使用下面的代碼做到:

void CExampleControl::DrawBitmap( const TPoint& aPoint,
const CFbsBitmap* aBitmap )
{
 // Get the system graphics context and control rectangle
 CWindowGc& gc = SystemGc();
 // Establish drawing rectangle
 TRect rect = TRect( aPoint,
 TSize( aBitmap.iWidth, aBitmap.iHeight ) );
 // Activate graphics context
 ActivateGc();
 // Invalidate window
 Window().Invalidate( rect );
 Window().BeginRedraw( rect );
 // Draw a bitmap
 gc.DrawBitmap( aPoint, aBitmap );
 Window().EndRedraw();
 // Deactivate graphics context
 DeactivateGc();

  上面的示例代碼在aPoint參數定義的位置畫一個CFbsBitmap。示例中值得注意的是圖形上下文在使用之前需要激活,在描畫完成之后失活。還有窗口服務器需要取得客戶端即將啟動重畫的信息,這使用BeginRedraw方法來完成。由于窗口服務器只允許一個應用程序在無效區域中描畫,所以需要Invalidate方法。在一個系統初始重畫中,CONE激活圖形上下文并且調用用于應用程序的BeginRedraw方法。如果窗口已經無效了,那么Invalidate方法就不必被調用了--這就是為什么系統初始需要被首先描畫。
  子圖形(精靈)

  子圖形是一個經過蒙板化(Mask)的位圖,可以在應用程序不重畫底層窗口的情況下移動。如果游戲不需要經常更新背景,那么使用子圖形就再好不過了。例如類似于PacMan這樣的游戲,在這種游戲中動畫在一個不能卷軸并且固定的背景上移動。重畫是靠窗口服務器來執行的,替代一個較高優先性的任務。這種游戲要考慮的是平滑的動畫和子圖形的運動。Symbian OS提供兩種不同的子圖形:指針和動畫位圖。圖1說明子圖形類的層次。

圖1說明子圖形類的層次

  RWsSPRiteBase是一個用于子圖形的抽象基本類。它擁有一個或多個包含子圖形的位圖數據的TSpriteMembers。通過指定帶有不同的位圖的多個成員,子圖形就可以活動起來了。TSpriteMember還定義了位圖的蒙板,子圖形中位圖的位置和位圖顯示的時間間隔。RWsSprite是一個用于子圖形的具體的類。除了構造器之外,它只提供一個方法SetPosition,可用于移動子圖形。下面的代碼說明了使用從MBM文件中裝載的位圖創建子圖形的示例。

RWsSprite sprite = RWsSprite( iEikonEnv->Wssession() );
User::LeaveIfError( sprite.Construct( Window(), TPoint(0,0), 0 );
for ( TInt i=0; i < 8; i += 2 )
{
 iMember[i/2].iBitmap = new ( ELeave ) CFbsBitmap();
 User::LeaveIfError( member.iBitmap->Load( KBitmapFile, i, EFalse ) );
 iMember[i/2].iBitmap = new ( ELeave ) CFbsBitmap();
 User::LeaveIfError( member.iMaskBitmap->Load( KBitmapFile, i+1, EFalse ) );
 iMember[i/2].iInvertMask = EFalse;
 iMember[i/2].iOffset = TPoint(0,0);
 iMember[i/2].iInterval = TTimeIntervalMicrosecond32(100000);
 User::LeaveIfError( sprite.AppendMember( iMember[i/2] ) );

  在子圖形成員已經更新并且附加到RWsSprite類之后,子圖形可以通過調用RWsSpriteBase::Activate來激活。在此之后,這個子圖形顯示在屏幕上,并且準備移動。子圖形的內容可以使用RWsSpriteBase:UpdateMember方法來變化。因為CFbsBitmaps還可訪問窗口服務器,所以只有子圖形的位圖句柄被發送到窗口服務器。這使子圖形的位圖的更新相當迅速。當子圖形不再需要的時候,窗口服務器需要調用RWsSpriteBase::Close來釋放資源。但不釋放需要被刪除的客戶端成員數據。RWsPointerCursor是一個用于應用程序創建光標的類。

  雙緩沖

  如果一個游戲的圖形由多個需要被經常更新的運動對象組成,窗口服務器的客戶端緩沖可能被充滿并且可能會在所有對象都更新的時候溢出。用戶可能會發現屏幕出現閃爍。如果一個視圖仍然在更新的時候,可能會出現閃爍或者其他不希望的效果。這些問題的解決方案是雙緩沖,圖形先被畫在一個屏外位圖上,然后被畫到屏幕上作為一個單一窗口服務器操作。尤其是對于那種在一秒鐘內重畫幾次屏幕的游戲,使用屏外位圖可以改善它們的性能。

  一個屏外位圖可以使用位圖化的圖形上下文和圖形設備類來創建:CFbsBitGc和CFbsBitmapDevice。它們使用其他的上下文和設備類來創建和使用。為了獲得額外的性能,位圖自己就應該是一個CWsBitmap位圖。在屏外位圖更新之后,它可以使用正常的窗口服務器的描畫方法畫在窗口中。

  當一個應用程序在一個窗口畫位圖時,它轉化為和窗口相同的顯示模式。這是一個很消耗時間的操作,實質上可能降低描畫的速度。因此把位圖用于動畫的游戲應該在動畫開始之前就完成轉化。轉化可以通過使用一個屏外位圖來執行,如下面的示例方法演示:

CFbsBitmap* CExampleControl::LoadAndConvertBitmapL(
Const TDesC& aFileName, TInt aBitmapId )
{
 // Load the bitmap
 CFbsBitmap* originalBitmap = new ( ELeave ) CFbsBitmap();
 CleanupStack::PushL( originalBitmap );
 User::LeaveIfError( originalBitmap->Load( aFileName, aBitmapId, EFalse ) );
 // Create a new bitmap, graphics device and context
 CFbsBitmap* newBitmap = new ( ELeave ) CFbsBitmap();
 CleanupStack::PushL( newBitmap );
 newBitmap->Create( originalBitmap->SizeInPixels(), Window()->DisplayMode() );
 CFbsBitmapDevice* graphicsDevice = CFbsBitmapDevice::NewL(bitmapConverted );
 CleanupStack::PushL( graphicsDevice );
 CFbsBitGc* graphicsContext;
 User::LeaveIfError( graphicsDevice->CreateContext( graphicsContext ) );
 TPoint zero(0,0);

 // Blit the loaded bitmap to the new bitmap
 bitmapContext->BitBlt( zero, originalBitmap );
 CleanupStack::Pop(3);
 delete bitmapContext;
 delete bitmapDevice;
 delete originalBitmap;
 return newBitmap;

  示例方法使用一個文件名和位圖ID作為參數,并且從一個MBM文件中裝載相應的位圖。如果一個游戲有許多位圖應該轉化,那么應該在游戲或者等級的初始化階段轉化。因此用戶就不會看到這個操作了。
  直接描畫

  使用窗口服務器在屏幕上描畫需要一個上下文轉換,這會減慢描畫速度。為了繞過窗口服務器省去繁瑣的上下文轉換,可以直接訪問屏幕。這被稱作直接描畫。在Symbian OS中有兩種方法來直接在屏幕上描畫。

  CFbsScreenDevice是一個可以被發送到屏幕驅動程序SCDV.DLL的圖形設備。在創建一個CFbsBitGc圖形上下文之后,它能像任何其他的圖形設備一樣使用。然而,可以直接在屏幕上描畫,而不需要使用窗口服務器。直接在屏幕上描畫的另一種方法是從系統中查詢屏幕內存地址。這可以使用UserSrv類來實現:

TPckgBuf<TScreenInfoV01> infoPckg;
TScreenInfoV01& screenInfo = infoPckg();
UserSvr::ScreenInfo(infoPckg);
TUint16* screenMemory = screenInfo.iScreenAddress + 16;

  屏幕內存有一個32字節的頭。

  即使在屏幕內存內寫數據比CFbsScreenDevice稍微快一點,但是功能可能根據硬件和屏幕的設備驅動程序的不同而有差異。在一些基于Symbian OS的終端中,屏幕在內存變化的時候自動從屏幕內存中更新,而在其他的終端中描畫需要明確的激活。屏幕內存地址只對目標硬件有效,因此描畫代碼需要分為硬件和模擬器兩部分。在模擬器環境中,可以描畫到一個屏外位圖中,而不是屏幕內存中,然后使用正常的窗口服務器描畫方法位塊傳送到屏幕上。環境可以通過使用__WINS__定義來檢測出來。

#ifdef __WINS__ // Emulator environment
// Draw to an off-screen bitmap
#else // Hardware environment
// Draw directly to the screen memory
#endif 

  這兩種直接描畫方法的一個共同的問題是窗口服務器不了解描畫,因此它不能通知應用程序是否出現另一個窗口或者窗口組。 即使當應用程序失去焦點的時候得到一個事件,它們也不能停止直接描畫,因為直接描畫實在太快了,并且屏幕內容有可能被弄亂。 這可能發生在玩游戲的時候,突然有電話打進來的情況下。
新近的GT 6.1版本提供了一個應用編程接口用于直接描畫,將能解決前面提到的問題。 這個應用編程接口由兩個類組成:一個MDirectScreenaccess類,提供用于應用程序的回調方法,還有一個CDirectScreenAccess類處理與窗口服務器的通訊。 下面的代碼說明CDirectScreenAccess實例是如何構造的,以及直接描畫支持是如何激活的。

iDrawer = CDirectScreenAccess::NewL(iEikonEnv->WsSession(), *iEikonEnv->ScreenDevice(), Window(), *this);
iEikonEnv->WsSession().Flush();
iDrawer->StartL();
iDrawer->ScreenDevice()->SetAutoUpdate(ETrue); 

  CDirectScreenAccess的NewL方法獲得一個窗口服務器會話、CONE的圖形設備、應用程序窗口和一個到MDirectedScreenAccess導出類的指針作為參數。 在CDirectScreenAccess::StartL被調用來激活直接描畫支持之前,客戶端窗口服務器緩沖應該溢出。 為了能自動更新屏幕,屏幕設備的SetAutoUpdate方法需要使用ETrue參數。 當直接描畫支持激活的時候,CDirectScreenAccess產生一個CFbsBitGc圖形上下文,可以被應用程序用來在屏幕上繪畫。

iDrawer->Gc()->BitBlt( TPoint(0,0), iBitmap ); 

  當另一個窗口出現在應用程序窗口上時,CDirectScreenAccess從窗口服務器取得一個事件來中斷描畫。 CDirectScreenAccess然后調用MDirectScreenAccess派生類的AbortNow方法,這個方法必須被應用程序重載以便中斷描畫。 為了防止屏幕被弄亂,窗口服務器直到中斷描畫事件被處理的時候才畫重疊窗口


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美另类交人妖| 国产精品av在线播放| 国产91精品青草社区| 日韩av中文字幕在线免费观看| 国产欧美中文字幕| 78m国产成人精品视频| 成人性教育视频在线观看| 国产精品黄页免费高清在线观看| 青青草精品毛片| 日本韩国在线不卡| 欧美成aaa人片在线观看蜜臀| 91久久精品国产91性色| 久久精品国产免费观看| 亚洲国产精品va在线观看黑人| 国产精品一区电影| 日韩精品免费观看| 三级精品视频久久久久| 成人黄色激情网| 自拍偷拍亚洲精品| 欧美日韩国产中文字幕| 成人免费高清完整版在线观看| 最近2019中文字幕mv免费看| 久久影院中文字幕| 国产精品视频久久久久| 黄色91在线观看| 国产91精品网站| 国产人妖伪娘一区91| 日韩中文视频免费在线观看| 国产亚洲成av人片在线观看桃| 日韩成人xxxx| 日产日韩在线亚洲欧美| 欧美整片在线观看| 国产精品午夜一区二区欲梦| 国产精品三级美女白浆呻吟| 亚洲日韩中文字幕在线播放| 国产精品aaaa| 欧美丝袜一区二区| 亚洲性av网站| 日本精品va在线观看| 久久久精品国产一区二区| 欧美超级免费视 在线| 国产精品一区二区女厕厕| 精品国产一区二区三区久久久狼| 亚洲专区在线视频| 久久久久久国产精品三级玉女聊斋| 欧美裸体xxxxx| 欧美大成色www永久网站婷| 欧美日韩国产专区| 麻豆国产精品va在线观看不卡| 国产精品狼人色视频一区| 日韩精品在线观看一区二区| 国产日本欧美一区| 国产网站欧美日韩免费精品在线观看| 国产日韩换脸av一区在线观看| 9.1国产丝袜在线观看| 2019中文字幕在线| 欧美高跟鞋交xxxxhd| 国内精品一区二区三区| 国产成人精品999| 亚洲欧洲在线观看| 亚洲第五色综合网| 亚洲无线码在线一区观看| 中国人与牲禽动交精品| 亚洲一区二区三区sesese| 成人在线精品视频| 国产精品mp4| 一区二区三区天堂av| 国产suv精品一区二区| 91经典在线视频| 成人中文字幕在线观看| 日韩成人中文电影| 国产亚洲美女精品久久久| 国产一区欧美二区三区| 欧美另类69精品久久久久9999| 欧美肥臀大乳一区二区免费视频| 九九精品在线视频| 中文字幕久精品免费视频| 国产欧美精品久久久| 亚洲经典中文字幕| 国产精品十八以下禁看| 久久视频在线观看免费| 亚洲免费视频一区二区| 日韩av在线高清| 国产成人精品一区二区| 欧美电影免费观看高清| 久久精品人人做人人爽| 久久久国产一区二区三区| 欧美精品videossex88| 在线亚洲国产精品网| 日韩av在线导航| 欧美电影在线观看| 91社影院在线观看| 久久噜噜噜精品国产亚洲综合| 亚洲国产成人爱av在线播放| 日韩欧美在线观看视频| 亚洲色图激情小说| 亚洲精品久久7777777| 色妞一区二区三区| 亚洲精品美女久久久久| 国产精品白丝av嫩草影院| www.午夜精品| 欧美最猛性xxxxx免费| 国产精品中文字幕久久久| 91在线色戒在线| 成人情趣片在线观看免费| 欧美xxxx做受欧美.88| 国a精品视频大全| 欧美电影在线免费观看网站| 97人人爽人人喊人人模波多| 亚洲伊人一本大道中文字幕| 国产精品日韩欧美综合| 久久91精品国产91久久跳| 欧美乱人伦中文字幕在线| 久久亚洲综合国产精品99麻豆精品福利| 亚洲天堂av在线免费观看| 亚洲天堂网在线观看| 成人做爰www免费看视频网站| 亚洲人在线观看| 欧美性受xxxx白人性爽| 久久久久久成人| 亚洲欧美日韩精品| 亚洲尤物视频网| 姬川优奈aav一区二区| 欧美一级免费看| 欧美视频国产精品| 国产精品一区久久| 久久国产精品久久国产精品| 国产69精品久久久久9999| 国语自产偷拍精品视频偷| 国产精品成人免费电影| 欧美性xxxxx极品| 亚洲深夜福利网站| 91av免费观看91av精品在线| 久久精品青青大伊人av| 成人黄色免费在线观看| 国产国产精品人在线视| 视频一区视频二区国产精品| 狠狠做深爱婷婷久久综合一区| 亚洲精品成人久久久| 亚洲男女自偷自拍图片另类| 91精品国产色综合久久不卡98| 亚洲va久久久噜噜噜久久天堂| 精品视频偷偷看在线观看| 精品亚洲一区二区三区| 97超级碰碰碰| 国产精品www色诱视频| 亚洲人成网站免费播放| 亚洲精品美女在线观看| 国产精品久久激情| 日韩经典中文字幕| 亚洲国产成人久久综合一区| 日韩美女激情视频| 色狠狠av一区二区三区香蕉蜜桃| 中文字幕自拍vr一区二区三区| 91超碰中文字幕久久精品| 欧美一区二区三区免费观看| 一道本无吗dⅴd在线播放一区| 这里只有精品视频| 亚洲国语精品自产拍在线观看| 日韩av电影手机在线观看| 日韩精品久久久久| 91禁外国网站| 欧美激情亚洲综合一区| 久久亚洲精品一区|