2016年11月20日 星期日

PIN2 - 拼圖


<Android下載>

這是很久前的一個小遊戲練習,主要目的是作為一個新的實作框架的練習。成像的部份最早是用GDI,後來改成OpenGL,現在又把它拿出來改成使用good。基本上這是個純C++的程式,LUA只佔用來作初始化的5行程式碼。

2016年11月4日 星期五

Good Game Editor 1.5

  • 新增Good.GenTextObj

    samples下提供的Util.GenStrObj是透過bitmap font建立TEXBG子物件。而Good.GenTextObj則是透過系統繪字功能,動態產生每一個字元的文字貼圖,再由文字貼圖生成TEXBG子物件。因為GenTextObj輸入的字串格式是utf8,所以支援多語文字。相同字元編碼指定不同文字大小時,會產生不同大小的字元貼圖。目前支援的平台為windows及android。
  • Create Package時若資源項目不存在則顯示警告訊息並允許輸出檔案。
  • 關卡編輯器(LevelEditor)不可見物件左上角標示一不可見物件圖標。
  • 新增範例text(字圖及系統字)。
  • 合併繪圖DrawCalls大幅提升繪圖效能。more...
  • 修正繪製範圍外的貼圖物件的錯誤。
  • Cache動態載入的Good Package。
  • 修正刪除正開啟的資源時造成的程式崩潰。
  • Util新增SetTextObjColor及GetTextObjWidth。
  • 關卡編輯器(LevelEditor)新增右鍵點選物件切換資源選擇。
  • 新增Good.GetAlpha及Good.SetAlpha(此功能包含於Util)。
  • 新增Graphics.GetAntiAliasGraphics.SetAntiAlias用於控制系統字反鋸齒。

2016年10月14日 星期五

吃金幣的人(Coin Eater)

這是把之前作的基因算法實驗裡的吃金幣的人遊戲化的一個小作品。



下載 (src)

;

這個遊戲比較特別的地方是,這是第一個發佈的遊戲裡面不是全用LUA實作的。實作是一半使用C++另一半使用LUA,C++這邊主要實作比較需要效能的算術邏輯,LUA這邊主要處理成像和UI。

2016年9月16日 星期五

最佳化繪圖管線批次繪製物件(Batch Sprite)

最開始的時候,good的繪圖管線為了簡化設計和實作,物件在繪製時是一個一個畫。每個物件都是以一個glDrawArray畫出來,也就是說花費一個draw call畫出來。

一開始針對繪圖最佳化的規劃除了貼圖合併之外,另一個主要的功能是批次繪製功能作最佳化。現在終於實作了這個功能,可以大幅減少draw calls。

原來繪製物件的方式是透過glVertexPointer傳入長寬各為1的單位矩形,再使用glDrawArray畫出物件。底下是簡單的記錄,一步步將原本的繪製物件的管線轉換為批次繪圖方式。

1,第一步就是先把glTranslate、glScale及glRotate等方法替換掉。首先弄個可以計算4*4矩陣的工具,把這些方法都透過矩陣運算,得到一個轉換矩陣。再使用glLoadMatrix載入這個自行計算得到的轉換矩陣,然後看看是不是結果和原來一樣,如果和原來的結果是一樣的話,表示這個轉換矩陣的計算是正確的。

使用glLoadMatrix載入轉換矩陣時,如果結果不對,可以試試對轉換矩陣作一次transpose轉換,看是不是因為使用的矩陣定義和OpenGL相反。

2,第二步要利用上面求出且驗證正確的轉換矩陣,來再進一步替換掉glLoadMatrix。也就是將傳入glVertexPointer的矩形的4個點,用轉換矩陣轉換成最終結果的座標,並且不需要使用glLoadMatrix將轉換矩陣傳遞給OpenGL,因為我們已經自己作了座標的轉換。再來驗證看看結果是否正確,沒有問的話就可以進入到下一步。

3,以上兩個步驟已經將OpendGL轉換矩陣的部份都替換掉,由我們自已的底層計算得到。將來再作進一步最佳化時,還可以把這個預先計算得到的轉換矩陣cache起來,只在狀態變動及需要時再重新計算,如此還可以進一步提高繪圖速度。

接下來就是要將每一個繪製物件的動作儘可能的合併起來批次處理。基本原則是準備大一點的buffer,針對vertex、texture coord及color,分別使用glVertextPointer、glTexCoordPointer及glColorPointer餵給OpendGL,在最後使用glDrawArray繪出時再指定實際繪出的數量即可,這樣就能夠大符減少draw call。

使用glDrawArray批次繪製時發現,結果好像不怎麼正確,物件其中一個點總是會和其它物件的相連。後來發現原來是因為glDrawArray的mode參數是使用GL_TRIANGLE_STRIP,這樣一來會把整個buffer作一大塊連續內容繪出。解決方法是對buffer內容的排列稍作調整,glDrawArray的mode參數改為GL_QUAD,這樣就繪出正確的結果。

最後在移植android時又發現,GL_QUAD這個參數GLES是不支援的。為了解決這個問題,需要將glDrawArray改為glDrawElements並再提供一個index buffer,這樣就可以在手機上正確執行了。



2016年8月12日 星期五

成語四則運算

花了點時間作了這個結合數字成語和四則運算的小遊戲,其中有超過一半的時間都花在收集和整理成語資料上面...

<<Android 下載>>




附上src

PS: dat.h是由idiom_ansi.txt轉換過來的,就當作給對src有興趣的人的人的作業。

2016年8月9日 星期二

Good Game Editor 1.4.4

* 修正貼圖物件在負數Scale時顯示錯誤。
* 修正編輯器開啟舊檔時偶發性當機的問題。
* 修正地圖編輯器(MapEditor)繪製圖格超出地圖範圍時造成當機的問題。
* Good.OBJ更名為Good.SPRITE
* 新增Good.SetName


2016年7月25日 星期一

數獨詳解 - Kill Sudoku Step by Step

用了大約一周的時間把之前的Kill Sudoku改成安卓版。一開始原本是打算把html5版本使用WebView直接作移植,但作了一些測試後發現有些困難,比如說怎麼作就是搞不定讓顯示和內建的Chrome一樣,還有拖曳畫面的效能也和內建的Chrome有很大的差異的問題等等。最後只好選擇用java+jni的方式改版,因為最早的版本原本就是C++,所以java這邊主要的工作只剩UI的處理。

<<Android 免費下載>>  (src)


2016年6月20日 星期一

Char Link

利用前幾天再加上周末二天的瑣碎時間,把link這個範例程式改版製作成一個小品遊戲:CharLink。

<<Android Download>>


附上Source

PS: ar.lua和Util.lua請自行到good的samples目錄底下找。

2016年5月25日 星期三

單人撲克101

以前和同事逛書店的時候,看到了一本收錄100個單人紙牌的遊戲書。那時候就和同事半開玩笑的說,把這本書買回去再把裡面的遊戲一個一個實作出來當作是練功吧。後來有一天我真的去把這本書給買了回來,然後每天早上上班之前,利用最多30分鐘的時間一邊啃著麵包一邊實作紙牌遊戲。那陣子每天我至少可以實作一個單人紙牌遊戲,最多的時候一天可以實作4個...不過一直實作作到33個的時候我停手了...

最近心血來潮想說把它移植上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::vector mDrawList;
};
這次我建了一個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有興趣的人自己下載來看看吧。

2016年4月10日 星期日

Good Game Editor 1.4.3

* 物件屬性檢視器(Property View)的ComboBox改為以關卡編輯器(Level Editor)的物件列表取代。

* 新增Resource.GetFirstLevelId
* 新增Ctrl+F5開始播放資源樹指定關卡。
* 新增Good.GetName
* Good.IsVisible更名為Good.GetVisible
* 新增範例animator(簡易動作系統)。


下載Good Game Editor 1.4.3
下載libgood-1.4.3
下載Good Game Player 1.4.3 Android

Related Posts Plugin for WordPress, Blogger...