2017年2月19日 星期日

多人連線版本的吃金幣的人

吃金幣的人是對基因算法的一個研究和實驗,主要是資料及算法上的研究和測試。後來使用good的繪圖能力把它圖形化,同時測試及擴展good的整合能力。現在再進一步把它和網路底層作結合,建立一個新的實驗平台,命名為nature online。


和good一樣建立no的目的是為了創造一個可以讓我平常利用空間時間來作研發和實驗的平台。no整合了所有到目前為止所作的小實驗和研究。主要的目標是研究分散式網路遊戲的架構及模擬生態系統。

目前具備的功能:
- 分散式的網路伺服器架構,後端使用mysql。
- 使用2張測試地圖,隨時可以任意切換至任意地圖任意位置。
- 地圖物件目前有二種:tree/bug。
- tree物件應用生命遊戲規則生成及更新。
- bug物件應用基因算法活動食物為tree物件。
- 自動同步client可見視野內的內容。
-使用good為client成象引擎。

下階段的目標是持續底層研發及增加更多種類的物件。

;=========================

以下二件事是需要特別記錄的。

A.
首先tree物件的更新決定以生命遊戲的規則來作更新及生成,規則沒什麼問題,問題是數量和速度。如果是像good內建的life範例,那相當於16x16的地圖格子大小,總數也才256格,每次更新時全訠256格都掃一次也沒什麼問題。不過當地圖變成像no那樣是500x500或更大時,問題就出來了。每次要掃那麼多的格子,速度就成為一個問題了,而且server每次更新不只是要更新tree物件而己,還有其它工作要作。

一個簡單的解決方法是只檢查需要檢查的格子。

1,記錄目前有那些存活的格子
2,根據存活的格子推算有那些格子在下一世代可能產生狀態變化,可能有狀態變化的格子也就是存活的格子的周圍8個空格子
3,下一世代只需計算(目前存活格子+可能產生狀態變化的格子),其它的格子都可以忽略不看

假設目前存活的格子是10000個,這10000個格子周圍總共30000個空格子,那麼下一世代只需計算40000個格子,而不是全部250000個格子。數量大大的減少了!

B.
bug物件是以基因算法為基礎來製作。和吃金幣的人一樣,假設基因的編碼是根據上下左右中5個格子(環境變數)共3種不同狀態,基因長度為243。現在的問題是,假設過了一段時間之後,要改變編碼需要檢查的格子數或狀態數,這樣一來原本之前花時間演化出來的基因就會無效。因為新舊編碼方法不同產生的基因長度是不同的,二者無法一一對應。雖然舊的編碼方式的基因可以作為新編碼方式基因的一個子集合被包含,但是存取的方法必須改變,否則無法相容。

一個簡單的解決方法是另外維護一個編碼對照表,這樣即使基因的長度擴充了,舊的基因的位置還是不變可以向下相容。

1,建立<狀態編碼,基因位置>對照表
2,分別處理二種不同的擴充基因的狀況
  * 檢查格子數擴充
  * 檢查狀態數擴充


討論檢查格子數擴充的狀況。



0   0 [0]   0 [0 0]     idx0
1   0 [1]   0 [0 1]     idx1
     1  0     0 [1 0]     idx2
     1  1     0 [1 1]     idx3
                1  0 0       idx4
                1  0 1       idx5
                1  1 0       idx6
                1  1 1       idx7


假設現在只看一個格子且狀態只有0和1二種,如最上表最左行所示,基因長度為2,基因的索引位置為0和1。現在新增一個格子,每個格子一樣有二種狀態,基因長度變為4(2^2)。請看上表中間的部份,列出4種可能的狀態編碼,中括號標出來的[0]和[1]為一個格子的狀況的可能編碼,這是需要在基因擴充時保持不變且向下相容的部份。同樣的再增加一個格子,總共可能的編碼變為3^2=8。如上表右側部份列出所有可能編碼,中括號標示出來的部份[00][01][10]及[11]是必須保持不變向下相容的。

討論檢查狀態數擴充的狀況。



0 0   [0 0]   [0 0]    idx0
         0 1     [0 1]   idx1
         1 0      0 2     idx2
         1 1    [1 0]    idx3
                  [1 1]    idx4
                   1 2      idx5
                   2 0      idx6
                   2 1      idx7
                   2 2      idx8


如上表所示,類似於討論檢查格子數擴充的狀況所說明的,每增加一個新的狀態時,需要保持不變且向下相容的編碼規則會有些不同。不像上面增加檢查格子時舊的部份維持在上半部,新增的部份在下部份。每增加一個新的狀態時,舊的編碼和新的編碼會互相交錯,但還是可以看出其中的規則。

依據以上二個不同狀況變更編碼擴充基因時變更維護的<狀態編碼,基因位置>對照表,這樣就可以繼續套用原來己花時間演化出來的基因而不必全部打掉重來。


2017年2月1日 星期三

Good Game Editor 1.6

* 新增Graphics.DrawText。
* 新增Graphics.SetAnchor。
* 關卡編輯器(LevelEditor)中物件左上角顥示狀態圖標:IsVisible,RepX,RepY,HasScript,ImageMissing。
* 支援一次新增多個貼圖資源(New Texture)。
* 新增播放目前選取關卡(Play This Level)功能。
* 關卡編輯器(LevelEditor)中物件支援階層關係編輯。
* 關卡編輯器(LevelEditor)新增編輯Dummy物件。


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


Related Posts Plugin for WordPress, Blogger...