2017年10月14日 星期六

在桌機中準備 OpenGL ES 的開發環境

大約在 2013 年中,公司的產品方針由桌機網遊轉變為手遊。由於當時還是採用自製的呈像引擎所以立刻要處理的就是把 Render API 切換為手機上通用的 OpenGL ES 2.0。

雖說手機遊戲最終是運行在手機上,但是為了方便開發和測試,遊戲也必需能在一般的桌機上運行。這一點在現今 Unity 稱霸的時代已經是很基本的需求,但對於當時一切 DIY 的我們來說還算是一項考驗。那時負責呈像的同仁拋出了兩個方案 -- 一是只在手機上使用 OpenGL ES API、桌機環境上維持使用既有的 OpenGL API;二是無論如何都使用 OpenGL ES API,桌機環境上去找 OpenGL ES Emulator 來提供 OpenGL ES 的支持。最後考慮到維護成本採取的是後者,這樣只需要統一維護 OpenGL ES 的部分即可。

Emulator 與 Simulator 傻傻分不清楚

Emulator 跟 Simulator 這兩個詞,Google Translate 給出的中文翻譯都是「模擬器」。然而它們並不是同義詞,至少在資訊工程的領域不是。尤其是每當有新的硬體平台發表時,開發者們都會很關切一件事 -- 它對桌面環境的開發者提供的是「Emulator」還是「Simulator」? ? 這兩者帶開發者的痛苦程度不太相同。

「Emulator」通常意指的是「同質性的模擬」,而「Simulator」則是「表像上的模擬」,通常也暗示者「異質性的模擬」。有同時開發過 Android 與 iOS 平台的朋友們一定都知道是怎麼回事 -- Android 對開發者提供的 Virtual Device 就是「Emulator」,設定 Virtual Device 時可以選擇 ABI,如果選的是 ARM,那 Emulator 中就真的是跑 ARM 的指令集。反觀 iOS 對開發者只有提供「Simulator」,它實際上運行的是 x86 的指令集,跟真實的 iOS 裝置上使用的指令集完全無關,所以稱為「異質性的模擬」。

最近正在進行某 N 社平台的移植工程,該社的開發機供不應求有價無市,除此之外對開發者只提供「Simulator」 -- 而且與實機環境的差異還蠻大的。有感而發。

2017年10月13日 星期五

重拾筆頭

算一算離上次發表文章,竟已有四年半的時間了。回顧這幾年,大部分的時間都耗費在公司手遊的研發上,雖有陸續在日、港、全球上線營運,但成績始終未達預期。產品的細節礙於公司規定是不便多說的。但技術上積累了不少可分享的心得倒是想陸續發上來。

還記得 2012 年我剛從電子業轉換跑道進這行時,面試我的上司問我為什麼要轉行? 我那時候回答他,我認為遊戲產業是「最多種不同面向的技術同時交匯的產業」,所以我覺得這裡的挑戰最多元、身為資工出身的我能貢獻最多,並且也能學到最多東西。四年半之後回顧初衷,還真是一點也不錯,一路走來果真挑戰連連,常常得面臨一關闖不過就要鳥獸散的窘境。雖不敢說對某門技術功力很深,但盡力要求自己各項都要摸要懂,漸漸地也常感受到觸類旁通的領悟。

雖然遊戲開發會粗略分為 Client 與 Server 兩種人員,但小團隊裡通常壁壘不會這麼分明,反而是靠部分通才人員兩邊一起顧。我在開案時最初擔任的是 Server 的架構及開發,最終上架時已經要兼顧一部分 Client 的功能、Client 端第三方 SDK 串接,以及幾乎所有營運後台需要的工具了。試想像還有哪個行業會同時磨練你 3D呈像、美術製程、各種 mobile 平台、Socket Programming、RESTful WEB API、Database (SQL and NoSQL)、雲端平台的背景知識呢? 當時的產品 Client 端甚至還是採用自有的引擎而非 Unity,那陣子承受的壓力與成長幅度都是我人生中的高峰。

很感謝身邊幾位才華洋益的同伴一起打拼,有些驚險關卡想在回想起來還冒冷汗。但受用最多的還是網路上搜尋到的各種技術內容探討、心得分享。這也是我要求自己把心得發佈上來的主因。

敬請期待。

2013年4月8日 星期一

Data Hiding 的兩種作法: Pimpl 與 Pure Virtual Interface

大型的軟體專案在開發前期通常會先將功能較獨立、且共用性高的部分規劃為函式庫。在設計 C/C++ 的函式庫接口時,特別要留意那些要公開給外部使用的 header 檔案。裡面盡可能只包含「要公開的 API 定義」,而將「只有內部才需要」的各種定義或 header 藏起來,以免相依性向外轉嫁到函式庫的使用者。這個動作稱為「Data Hiding」或「Information Hiding」。

舉一個設計不良的例子,假設你要對外公開這個 MyTool 類別,而它的 header 長這樣:

2012年12月18日 星期二

C++ 非靜態成員函式指標語法

C/C++ 語言裡的一個特色是函式 (function) 可視為一級物件 (First-Class Object), 即函數可被當成變數供另一個函數做為參數使用. 對比缺少此特色的語言 (Ex: Java) 來說, 語法上較易表示交付 Callback 或指派 Delegate 等等的應用.

可能是因為 C/C++ 本身的歷史關係, 函數指標的型別宣告方式還蠻艱誨深澀, 基本的全域靜態函式的指標宣告和傳遞可能就能讓許多 Programmer 停下來翻書查語法了. 更別說 C++ 中引入的非靜態成員函式指標語法. 這邊筆記一下網路的參考資料和範例:

2012年11月5日 星期一

Torque3D 引擎提供的實作參考 - 基於 UDP 的網路傳輸層

2011 年的 GDC 年會中, BUNGiE.net 分享了他們在進行 Halo 的遊戲開發時針對一些即時性的網路傳輸議題的處理經驗. 介紹到他們的網路架構時, 較讓我驚訝的是他們採用完全 UDP 的實現. 微軟的 Halo 技術服務頁面也應驗了這一點. 稍一查訪之後發現全 UDP 實作的網路傳輸在遊戲領域中還不算少見, 另一個專門用於遊戲開發的 Raknet 網路函式庫也是採用 UDP 實作 (另提供 TCP wrapper). 在 BUNGiE 分享的投影片內容中, 有提到他們的架構很大程度是延用 1995 年 Tribes 開發團隊同樣是在 GDC 中分享的 "Tribes Networking Model" 中提到的架構. 這篇論文目前還可在網路上找到 (PDF).

2012年10月9日 星期二

使用 Visual Studio Performance Tool 進行 Profiling

要對自己的程式進行優化前, 要先知道實際運行中的時間大都花在哪些函數上. 這時就需要對程式進行 Profiling, 大致如同 MSDN 上這篇廣告文描述的這種過程.

文章裡沒說的是一個小尷尬的現實: Visual Studio 2010 的眾多版本裡, 只有 Premium 和 Ultimate 這兩個版本有內建 Profiler, 免費的 Express 版本自然是沒有. 但付費的 Professional 版本竟然也沒有就不知道作何解釋...

不過微軟倒是有把 Profiling 工具另外打包成一個獨立於 Visual Studio 之外的工具套件, 取名為 Performance Tool, 可以在這裡下載. 透過這個工具套件也一樣可以對程式進行 Profiling, 它最後會產生 Excel 可匯入的 CSV 文件, 也可選擇改為 XML 型式的輸出. 具體使用方式可見這篇文章:

http://codeka.com/blogs/index.php/2009/03/21/got-visual-studio-2008-professional-want

幾點補充:
  1. 原文是針對 Visual Studio 2008 的環境. 但相同內容和步驟在 Visual Studio 2010 中也適用. 只需要將內容中路徑含有 "Microsoft Visual Studio 9.0" 字樣的都改為 "Microsoft Visual Studio 10.0" 即可.
  2. 若是已裝有 Visual Studio 的話, 可直接使用它的 Command Prompt. 就不用自己設定 path.
  3. 建議可直接對 Release 版的程式做 Profiling. Debug 版中由於使用到 Debug CRT 會多做很多事, 出來的 Profiling Report 不儘體積會很龐大, 統計到的函數時間花費也可能失真.