從J2ME學Symbian遊戲開發

火星人 @ 2014-03-10 , reply:0


相信在手機遊戲開發這塊是J2ME的天下,一是因為它簡單容易學,二是因為關於它的資料多.

而J2ME畢竟是運行在Symbian OS的內核之上的,速度慢也是必然的了,更不能忍受的是它把很多與底層的交互封裝了起來,並且不提供讓你訪問.

這對於我這樣喜歡刨根問低的人來說,是實在無法忍受的!

其實真正了解了Symbian OS和相應的Series 60,如果在這個平台上做遊戲開發的話,Series 60並不比J2ME高深多少.因為它提供了一個AppArc,同樣把一些底層的東西封裝了起來,但是至少我們可以有介面可用來訪問低層的東西.

下面我就把最近一段時間的學習總結一下:

(一)關於開發

原本是沒有必要寫這個的,不過看到網上五花八門的工具配置、工具安裝的文章,實在覺得有必要出來澄清一下.

其實,完全沒必要為選擇什麼IDE來煩惱,無論是Moblie Borland C 、VC、VC.NET、CodeWarrior還是Nokia最近力推的Carbide.C ,他們都存在著這樣那樣的問題.沒有一個是的開發工具,series的SDK還為每一種開發工具提供了不同的版本,真是感覺有點"光了屁股系褲腰帶——多那麼一道子".IDE只能用來看源或者寫代碼,真正有用的還是SDK下的command命令行,不要怕麻煩,這些往往是最重要的.

命令也就是常用的那麼幾個:

bldmake bldfiles

abld build wins udeb

epoc

makesis

devices

(二)關於交互

無論做什麼樣的遊戲,都少不了與用戶的交互,而對於手機設備來說.與用戶交互的無非是鍵盤,事件是系統事件的一種,一旦設備鍵盤上的鍵被按下、按住或釋放的時候即會產生按鍵事件.

Symbian的Window通過控制項棧把按鍵事件傳遞到應用程序.然後通過調用控制項的OfferKeyEventL()方法把按鍵事件通知相應的控制項.這和我們在J2ME里通過KeyPressed(int keyCode)把相應的按鍵事件通知相應的Canvas類一樣.

OK,我們現在有了第一個類比的關係:

Symbian的OfferKeyEventL()和J2ME的KeyPressed(int keyCode)

當然,Symbian里這個方法還有一些需要特別說明的不同之處.

Symbian里的控制項棧是一個結構,負責維護控制項.當有按鍵事件發生的時候,這個按鍵事件會從控制項棧的頂部依次傳遞到最底端,直至得到了某個控制項的處理.默認情況下,控制項是不在棧中的,應該使用相應的函數CAknAppUi::AddToStackL()把控制項添加到控制項棧中,使它能夠處理按鍵事件.

這和我們的J2ME里不一樣,J2ME里KeyPressed(int keyCode)是和相應的Canvas里關聯在一起的.試著想象一下,如果從一個From高級UI切換到Canvas的低級UI,是不是需要用Command命令來控制?

然後就可以通過調用控制項的OfferKeyEventL()把按鍵事件傳遞給該控制項.控制項可以自己決定是否處理某個按鍵事件,如果處理事件,則返回值EKeyWasConsumed,否則返回EKeyWasNotConsumed.按鍵事件會按次序傳遞給控制項棧中的每個控制項,直至其中某個控制項返回EKeyWasConsumed或沒有剩餘控制項為止.

OfferKeyEventL()有兩個參數:按鍵事件(const EKeyEvent& aKeyEvent)、按鍵類型(TEventCode aType).前者表明按鍵是哪一個鍵等信息,後者則是一個emnu類型,說明按鍵事件的種類.

和我們在J2ME里不同的是,J2ME里用三個方法來分別表示Pressed、Released、Repeated.而Symbian里用一個emnu類型的參數來說明按鍵事件的種類,分別是:EEventKeyDwon、EEventKey、EEventKeyUp.

用以下代碼來做為事例恐怕更能說明問題:

TKeyReponse CMyControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType){

if(aType == EEventKeyUp){

switch(aKeyEvent.iCode){

case EKeyUpArrow:

//producing

return EKeyWasConsumed;

case EKeyDownArrow:

//producing

return EKeyWasConsumed;

default:

return EKeyWasNotConsumed;

}

}

return EKeyWasNotConsumed;

}

前面我們講到了「按鍵事件」在J2me和Symbian中的類似處理過程,其實這些東西都是一個遊戲里做的處理,無論是在任何平台.那麼在手機遊戲里,菜單也是必不可少的.而在Symbian里是不分什麼高級UI和低級UI的,只有系統控制項和自定義控制項之分.

那麼界面交互部分我們一樣可以和J2ME做個對比:J2ME里的高級UI CommandAction()、 Symbian里的系統控制項 HandleCommandL()、J2ME里的低級UI KeyPressed()和Symbian里的自定義控制項 OfferKeyEventL()

(三)系統菜單和J2ME里不一樣的是,Symbian里的系統控制項是通過在資源文件中編輯,在源代碼之外獨立地指定應用程序的可見控制項.在資源中可以定義的系統控制項包括菜單、對話框、列表等.

應用程序框架在應用程序啟動時會打開資源文件,並根據在.rsg中創建的資源標識符,根據需要把各個資源載入到C 代碼中.

這樣的架構有一定的好處就是:資源文件和C 源文件之間可以共享資源文件中定義的數據.

通常在一個後綴名為.hrh的文件中定義命令菜單中使用的標識符.

如下實例摘自SDK自帶的Graphics實例:

#ifndef __GRAPHICS_HRH__
#define __GRAPHICS_HRH__
// Graphics enumerate command codes
enum TGraphicsIds
{
EGaphicsNoOffScreenDemo = 1,
EGaphicsOffScreenDemo,
EGaphicsStopDemo
};
#endif // __GRAPHICS_HRH__

可見資源文件的處理使用的是C的預處理器,以避免多重包含.而.hrh文件也只能包含emnu和預處理語句,其它的C 語法都會導致資源編輯器編輯失敗,這點需要特別注意.

下面是和這個.hrh文件相對應的.rss文件的內容:

NAME GRAP
#include <eikon.rh>
#include <avkon.rh>
#include <avkon.rsg>
#include "Graphics.hrh"

// ---------------------------------------------------------
//
// Define the resource file signature
// This resource should be empty.
//
// ---------------------------------------------------------
//
RESOURCE RSS_SIGNATURE
{
}
// ---------------------------------------------------------
//
// Default Document Name
//
// ---------------------------------------------------------
//
RESOURCE TBUF
{
buf="";
}
// ---------------------------------------------------------
//
// Define default menu and CBA key.
//
// ---------------------------------------------------------
//
RESOURCE EIK_APP_INFO
{
menubar = r_graphics_menubar;
cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;
}

// ---------------------------------------------------------
//
// r_graphics_menubar
// Menubar for Graphics example
//
// ---------------------------------------------------------
//
RESOURCE MENU_BAR r_graphics_menubar
{
titles =
{
MENU_TITLE
{
menu_pane = r_graphics_menu;
}
};
}


// ---------------------------------------------------------
//
// r_graphics_menu
// Menu for "Options"
//
// ---------------------------------------------------------
//
RESOURCE MENU_PANE r_graphics_menu
{
items =
{
MENU_ITEM
{
command = EGaphicsNoOffScreenDemo;
txt = "No off screen bmp";
},
MENU_ITEM
{
command = EGaphicsOffScreenDemo;
txt = "Off screen bmp";
},
MENU_ITEM
{
command = EGaphicsStopDemo;
txt = "Stop Animation";
},
MENU_ITEM
{
command = EAknSoftkeyExit;
txt = "Exit";
}
};
}

下面對這個文件的內容做一些說明

RESOURCE RSS_SIGNATURE
{
}
RESOURCE TBUF
{
buf="";
}

這兩個一般情況下是不允許做改動的,前者是資源的簽名,後者是默認文檔名.

RESOURCE EIK_APP_INFO
{
menubar = r_graphics_menubar;
cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;
}

用來標識菜單和快捷鍵的ID,就是給菜單和相應的快捷鍵起個名字而已,以便於程序後面的使用.

RESOURCE MENU_PANE r_graphics_menu
{
items =
{
MENU_ITEM
{
command = EGaphicsNoOffScreenDemo;
txt = "No off screen bmp";
},
MENU_ITEM
{
command = EGaphicsOffScreenDemo;
txt = "Off screen bmp";
},
MENU_ITEM
{
command = EGaphicsStopDemo;
txt = "Stop Animation";
},
MENU_ITEM
{
command = EAknSoftkeyExit;
txt = "Exit";
}
};
}

這個才是實際定義的菜單的真正內容,也就是我們能在界面上看得到的Menu_Item的標識和內容.

OK了,資源定義已經完成,下面只需要在Ui類的HandleCommandL()方法中針對相應的Command做相應的處理即可.

void CGraphicsAppUi::HandleCommandL(TInt aCommand)
{
switch(aCommand)
{
case EEikCmdExit:
case EAknSoftkeyExit:
Exit();
break;
case EGaphicsNoOffScreenDemo:
iAppView->StartNoOffScreenDemo();
break;
case EGaphicsOffScreenDemo:
iAppView->StartOffScreenDemo();
break;
case EGaphicsStopDemo:
iAppView->StopDemo();
break;
default:
User:anic (_L("Graphics"), EGraphicsBasicUi);
break;
}
}

現在你也學了和J2ME里的高級UI響應相對應的Symbian里的處理方法,現在和用戶交互應該沒問題了.無論是按鍵事件的OfferKeyEventL()方法、還是菜單命令的HandleCommandL()方法.




[火星人 via ] 從J2ME學Symbian遊戲開發已經有62次圍觀

http://www.coctec.com/docs/java/show-post-61885.html