以前和同事逛書店的時候,看到了一本收錄100個單人紙牌的遊戲書。那時候就和同事半開玩笑的說,把這本書買回去再把裡面的遊戲一個一個實作出來當作是練功吧。後來有一天我真的去把這本書給買了回來,然後每天早上上班之前,利用最多30分鐘的時間一邊啃著麵包一邊實作紙牌遊戲。那陣子每天我至少可以實作一個單人紙牌遊戲,最多的時候一天可以實作4個...不過一直實作作到33個的時候我停手了...
最近心血來潮想說把它移植上android,所以再拿出來檢視一下。原本這是一個windows的應用程式,當初實作的時候沒有特別考慮太多跨平台,把source拿來看了後大概規劃一下怎麼改就動手了,斷斷續續花了一周時間。
Android版本單人撲克101
下面大概對過程作個記錄。
;
每一個紙牌遊戲都是繼承自CardGame這個類別。下面列出主要和平台有關係的介面,也是移植的時候需要改版的地方。
如上和平台有關的介面有二個,一個和畫圖有關係,另一個和輸入有關係。
1,首先我另外建立了CardGameRenderer這個類別,將畫圖這件事情獨立出來。如下所示。
最近心血來潮想說把它移植上android,所以再拿出來檢視一下。原本這是一個windows的應用程式,當初實作的時候沒有特別考慮太多跨平台,把source拿來看了後大概規劃一下怎麼改就動手了,斷斷續續花了一周時間。
Android版本單人撲克101
下面大概對過程作個記錄。
;
每一個紙牌遊戲都是繼承自CardGame這個類別。下面列出主要和平台有關係的介面,也是移植的時候需要改版的地方。
class CardGame
{
public:
virtual void DrawGame(CDCHandle dc, RECT const& rcClient) const;
virtual bool OnMouseDown(CPoint point, RECT const& rcClient);
virtual bool OnMouseMove(CPoint point, RECT const& rcClient);
virtual bool OnMouseUp(CPoint point, RECT const& rcClient);
void DrawCard(CDCHandle dc, int x, int y, int card) const;
void DrawCover(CDCHandle dc, int x, int y) const;
void DrawEmptyCard(CDCHandle dc, int x, int y) const;
void EraseBkgnd(CDCHandle dc, RECT const& rcClient) const;
};
1,首先我另外建立了CardGameRenderer這個類別,將畫圖這件事情獨立出來。如下所示。
class CardGameRenderer
{
public:
RECT rcClient;
virtual void DrawCard(int x, int y, int card) {}
virtual void DrawCover(int x, int y) {}
virtual void DrawEmptyCard(int x, int y) {}
virtual void EraseBkgnd() {}
};
畫圖抽出來後,CardGame的DrawGame就可以改成如下的樣子。
virtual void DrawGame(CardGameRenderer &g) const;
然後再新建一個windows版本的CardGameRenderer將原來和windows有關係的畫圖程式碼封包起來,如下。
class CardGameDCRenderer : public cgo::CardGameRenderer
{
public:
CDCHandle dc;
...
};
這樣子畫圖部份就可以作到跨平台了。
2,再來是輸入的改版。因為原來輸入的介面就己經抽出來為OnMouseDown/OnMouseMove.OnMouseUp這三個介面,其實就己經算是把輸入的介面抽象化了,只不過這三個介面的參數需要作一下調整,因為CPoint和RECT是windows平台的定義。這次用自定義的POINT_t和RECT_t取代,改成如下。
virtual bool OnMouseDown(POINT_t point, RECT_t const& rcClient);
virtual bool OnMouseMove(POINT_t point, RECT_t const& rcClient);
virtual bool OnMouseUp(POINT_t point, RECT_t const& rcClient);
這樣子就完成了跨平台的改版,再來就是android的移植。
3,第一步先試試把jni lib建出來。同樣的我另外建一個for android的CardGameRenderer來作畫圖,如下。
class AndroidCardGameRenderer : public cgo::CardGameRenderer
{
public:
std::vectormDrawList;
};
這次我建了一個AndroidCardGameRenderer 繼承CardGameRenderer。請注意那個mDrawList,這個list的用意是打算將畫圖的幾個操作:DrawCard/DrawCover/DrawEmptyCard/EraseBkgnd封裝到一串畫圖動作列表,之後再傳到android activity那邊用android的方式一次把遊戲畫面畫出來。
jni lib的介面分別建立對應CardGame的API,包含畫圖和輸入,還有NewGame等。
4,jni lib建出來後就是建一個android activity來處理真正的畫圖和輸入。這裡主要就是上面提到的DrawList的處理,如下所示。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int drawList[] = JniLib.drawGame();
for (int i = 0; i < drawList.length; i++) {
switch (drawList[i])
{
case 0: // erase bk.
break;
case 1: // empty
break;
case 2: // cover
break;
case 3: // card
break;
}
}
}
其它的就沒什麼特別的了。對source有興趣的人自己下載來看看吧。
留言
張貼留言