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

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

基于Nokia S60的游戲開發之四

2019-11-17 05:50:00
字體:
來源:轉載
供稿:網友
  應用程序在屏幕上的描畫一般是使用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中有兩種方法來直接在屏幕上描畫?! FbsScreenDevice是一個可以被發送到屏幕驅動程序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
成人性生交大片免费看小说| 国产在线观看精品| 91久久久久久久| 中文字幕一区二区精品| 亚洲人成电影在线| 精品国产1区2区| 欧美性资源免费| 欧美国产精品va在线观看| 黄色精品在线看| 狠狠躁夜夜躁人人爽天天天天97| 91精品久久久久久久久久入口| 国产成人综合一区二区三区| 国产主播欧美精品| 亚洲精品视频在线播放| 国产成人精品免费视频| 黑人极品videos精品欧美裸| 97精品久久久| 中文字幕久精品免费视频| 精品国产区一区二区三区在线观看| 久99九色视频在线观看| 97国产在线视频| 亚洲石原莉奈一区二区在线观看| 色婷婷综合成人av| 亚洲理论在线a中文字幕| 久久精品国产亚洲| 福利一区视频在线观看| 国产精品欧美亚洲777777| 97久久精品人人澡人人爽缅北| 亚洲天堂2020| 一区二区三区四区视频| 成人在线一区二区| 成人免费大片黄在线播放| 亚洲黄色有码视频| 国内伊人久久久久久网站视频| 国产成人小视频在线观看| 中文字幕国产亚洲| 国产精品久久av| 国产精品久久久久久久久粉嫩av| 精品国内自产拍在线观看| 欧美二区在线播放| 91欧美精品午夜性色福利在线| 91免费欧美精品| 日韩中文字幕在线看| 亚洲第一偷拍网| 欧美又大粗又爽又黄大片视频| 亚洲综合日韩在线| 亚洲美女性视频| 国产一区二区色| 亚洲欧美日韩一区在线| 亚洲精品永久免费精品| 亚洲国产高潮在线观看| 91香蕉亚洲精品| 91亚洲va在线va天堂va国| 午夜精品久久久久久久99热浪潮| 日韩精品免费在线观看| 欧美高清视频在线| 日韩视频免费大全中文字幕| 九九九热精品免费视频观看网站| 亚洲人成网7777777国产| 欧美精品成人在线| 91久久久久久久久久久久久| 亚洲视频一区二区| 亚洲福利影片在线| 国产成人一区二| 成人亲热视频网站| 欧美美女18p| 日韩在线视频中文字幕| 97成人精品区在线播放| 亚洲人成在线免费观看| 成人日韩在线电影| 日韩精品在线播放| 精品国产一区二区三区久久久狼| 亚洲精品99久久久久中文字幕| 国精产品一区一区三区有限在线| 国产精品69久久久久| 色樱桃影院亚洲精品影院| 51ⅴ精品国产91久久久久久| 91欧美视频网站| 高跟丝袜欧美一区| 91香蕉嫩草影院入口| 亚洲韩国欧洲国产日产av| 日韩亚洲欧美中文高清在线| 日韩欧美在线观看| 亚洲国产欧美一区二区丝袜黑人| 热re91久久精品国99热蜜臀| 亚洲香蕉伊综合在人在线视看| 91在线观看免费高清| 亚洲欧美一区二区三区久久| 国产成人精品免高潮在线观看| 久久久成人的性感天堂| 亚洲国产欧美一区二区丝袜黑人| 亚洲激情国产精品| 日韩中文在线观看| 精品国产成人av| 美女啪啪无遮挡免费久久网站| 狠狠爱在线视频一区| 亚洲免费一级电影| 欧美精品www| 青青草原成人在线视频| 成人激情综合网| 中文字幕亚洲第一| 色婷婷av一区二区三区在线观看| www.xxxx精品| 亚洲免费小视频| 亚洲欧洲激情在线| 日韩在线视频线视频免费网站| 最近2019中文字幕一页二页| 91免费在线视频网站| 欧美日韩日本国产| 中文字幕九色91在线| 激情懂色av一区av二区av| 97精品国产97久久久久久| 国产亚洲欧美日韩一区二区| 国产日韩欧美在线看| 欧美大胆a视频| 性欧美亚洲xxxx乳在线观看| 日韩少妇与小伙激情| 国产视频自拍一区| 亚洲综合自拍一区| 欧美日韩亚洲国产一区| 亚洲精品女av网站| 91久久久国产精品| 国产精品第100页| 久久久久亚洲精品| 亚洲人成电影网站| 丝袜美腿精品国产二区| 2020久久国产精品| 欧美性videos高清精品| 久久亚洲精品一区二区| 国产精品国语对白| 久久精品人人爽| 欧美成人一二三| 久久精品成人一区二区三区| 国产精品视频内| 亚洲国产天堂久久国产91| 亚洲精品美女久久久| 51精品在线观看| 视频一区视频二区国产精品| 国产精品你懂得| 亚洲欧美三级在线| 欧美亚洲国产精品| 国产91成人video| 亚洲精品第一页| 亚洲黄色成人网| 成人亚洲欧美一区二区三区| 国产精品福利在线观看| 麻豆一区二区在线观看| 亚洲一区二区三区xxx视频| 亚洲欧美激情在线视频| 亚洲国产精品悠悠久久琪琪| 欧美色道久久88综合亚洲精品| 精品国产乱码久久久久久婷婷| 亚洲国产三级网| 日韩av电影在线播放| 2019中文字幕免费视频| 亚洲欧洲中文天堂| 国产精品久久激情| 久久久人成影片一区二区三区观看| 国产精品av在线播放| 欧美大片在线看免费观看| 日韩中文字幕免费视频| 欧美成人免费网| 亚洲人成网7777777国产| 亚洲深夜福利网站|