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)

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



下載

;

這個遊戲比較特別的地方是,這是第一個發佈的遊戲裡面不是全用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 免費下載>>


2016年7月13日 星期三

STGE的技術

很早就計劃要寫個有十個章節的關於stge的一個小品,其中有些內容在之前的文章己發表過,但要整個完成真的很難啊~~

底下是半成品連結

http://www.smallworld.idv.tw/stge/

底下是己完成內容的目錄
;

前言
CHAPTER1 射擊遊戲編年史
CHAPTER2 彈幕幾何
2.1 子彈的種類
2.2 子彈的屬性
2.3 子彈的移動模式
2.4 彈幕的基本樣式
2.5 彈幕的產生
2.6 移動的發射器
CHAPTER3 STGE語言
3.1 程式區塊
3.2 註解
3.3 發射粒子
3.4 移動方向及速度
3.5 時間的控制
3.6 迴圈
3.7 累加速度及累加方向
3.8 綁定程序控制粒子的行為
3.9 再擴充粒子方向及速度指令功能
3.10 瞄準自機
3.11 算式及亂數
3.12 程序的參數
3.13 粒子的生命週期
3.14 方向及速度的狀態變化
3.15 位置的狀態變化
3.16 子程序呼叫
3.17 條件分支
3.18 再談算式
3.19 使用者自訂參數
CHAPTER4 物件管理器
4.1 需求分析
4.2 物件的存取
4.3 配置物件
4.4 釋放物件
4.5 檢驗物件使用狀態
4.6 巡訪容器
4.7 資料結構
4.8 未使用物件串列
4.9 已使用物件串列
4.10 雙向串列
4.11 類別定義
4.12 更多的操作
CHAPTER5 虛擬機器
5.1 內部資料結構
5.2 腳本管理器
5.3 物件管理器
5.4 粒子物件
5.5 動作程序
5.6 算式
5.7 數學模組
CHAPTER6 語法剖析器
6.1 語法剖析器
6.2 EBNF表示式
6.3 算式計算機語法
6.4 遞迴下降分析
6.5 手工打造算式計算機
6.6 lex/yacc
6.7 正規表示式
6.8 使用lex
6.9 使用yacc
6.10 使用lex/yacc實作算式計算機
6.11 Boost Spirit
6.12 內建parser1
6.13 動作程式碼1
6.14 使用Boost Spirit實作算式計算機
6.15 yardparser
6.16 內建parser2
6.17 動作程式碼2
6.18 使用yardparser實作算式計算機
6.19 幾種方法的比較
CHAPTER7 STGE語言剖析器
7.1 語法定義
7.2 以Boost Spirit實作剖析器
CHAPTER8 測試工具
CHAPTER9 狀態堆疊
9.1 需求分析
9.2 函式指標
CHAPTER10 實作射擊遊戲


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...