發表文章

目前顯示的是 3月, 2010的文章

我的小遊戲

圖片
之前提過,我平均每年至少會作個一款小遊戲(不管是新開發或重製),這些小遊戲會開放免費下載。到目前為止已經推出12款了,其中7款Windows遊戲,2款Symbian遊戲,1款J2ME遊戲和1款WindowsMobile遊戲。 開發這些遊戲除了自己好玩外,也是練功的好題目。所以可以發現到,這幾個小遊戲裡面,有好幾款其實只是不同平台的移植(同平台上用不同方式實作練習就不提)。透過這種方式我能接觸並學習到不同平台的開發,同時也能加強跨平台的經驗也訓練小技巧,一舉數得。 會把它開放到 網站 上,只不過是基於獨樂樂不如眾樂樂的簡單想法,有沒有獲得迴響其實也沒所謂。至少每當看著首頁那一堆自己的作品,只有一個爽字能夠形容! (PS:這些遊戲有差不多一半都是WindowsGDI程式...所以效能難免有時不理想,不過那不是重點) ; 25940m (by good) 25940p 實驗中國象棋 (WindowsMobile,240x320) 實驗中國象棋 (Symbian s60, 176x208) 單人撲克101 小香咪咪方塊 小香咪咪方塊 (J2ME1.0) 867 ( upup 原型) 鋤草機 ( 說明 ) 拼吐 ( 說明 ) 傷心掃雷 (Symbian s60, 176x208) Paint by Numbers 2005 ( 說明 )

C++編譯時期靜態多型在遊戲中的應用

上次談到 C++編譯時期靜態多型 的原理,這次要介紹C++編譯期靜態多型要如何應用在遊戲中。雖然這篇文章主要是在談C++編譯期靜態多型的應用,不過其中也牽涉到跨平台的程式設計,所以也順便作點和跨平台程式設計的介紹。 跨平台程式本身不難,困難點在於如何把和平台有關的部份和平台無關的部份切割開,只要作到這點剩下來的就沒什麼難的了。至於要怎樣才能作的好跨平台程式設計並不是在這邊三言二語就能講的清楚。 總之記住儘可能的把平台有關和無關的部份分離,以及儘可能的使用標準的程式庫。例如std::string就是C++標準和平台無關,CreateWindow就是和Windows平台相關的API。 ;;; 如果我們是以C++物件導向來作遊戲程式設計,我們可能會有個上層的CGameApp類別,其它還有遊戲物件如CGameObj等類別。 ; 範例1 class CGameObj { }; class CGameApp { public: CGameMgr<CGameObj> mObjMgr; }; 在範例1中,CGameApp管理所有遊戲物件。這邊我們先不管CGameMgr<>是什麼東西,實際上在本例中我們也不需要去知道。 因為CGameApp是整個遊戲程式的核心,它除了管理所有遊戲物件(CGameObj)外,同時也管理所有其它和遊戲相關的物件或資源或者說狀態(State)。 ; 範例2 class CGameApp { public: CGameDB mGameDB; CGameMgr<CGameObj> mObjMgr; }; 如範例2中的mGameDB,是和遊戲會使用到的資料庫。現在問題來了,如果CGameObj的實體物件需要存取mGameDB怎麼辨。一個簡單的方法就是讓CGameObj內涵一個mGameDB的參考,我們可以在建立一個CGameObj物件時把它傳入CGameObj的constructor。 不過這樣作另一個問題又來了。在CGameApp內不一定只會有一個像mGameDB這樣的東西,通常還會有其它資料是其它物件需要存取的。如果全都傳到物件內,那肯定不是一個好辨法。 有一個更好的解決辨法,那就是把所有資料都集中在一起管理,把它變成一個 singleton ,讓所有物件都能存取到它,也就能存取到所有資料。為了簡單起見,我們讓

最簡單的單元測試工具 - CppUnitLite

測試驅動開發(Test Driven Development, TDD) 在 敏捷開發流程(Agile Process) 中扮演了一個很重要的角色,不過本文的重點在於TDD,不談Agile,實際上我也不懂,不懂的東西我也不談。 第一次接觸TDD,是在開發 JSR-184 時。在你的JSR(Java Specification Requests)實作和VM整合之前,VM Vendor會要求你的實作至少要通過TCK(Technology Compatibility Kit)。TCK是透過 JCP(Java Community Process) 取得,目的是用來驗證某JSR的實作品是否符合規範。實際上TCK就是一組使用JavaTest harness的測試包,包含了各種用來測試JSR的單元測試(Unit Test)。 以TCK for JSR-184來說,總共包含了161個測試項目,每一個測試項目裡面又再包含了2至10個子測試項目,而每一個子測試項目裡面又有不定數量的更小的測試。JavaTest是個自動化測試的環境,只要載入JSR-184的測試包,設定好環境之後就可以執行自動測試,然後看看結果如何。 JavaTest的測試都是Java寫的,雖然是Java新手,但是當時在發開發的過程中也能感受到TDD的威力。舉個簡單的例子:對於像我這樣不懂3D的人來說,還可以開發3D引擎,你說利不利害。我只需要想盡辨法讓測試能過關就行了,很多細節其實也不懂。這樣說雖然是比較誇張點,但我想要表達的是,TDD果然是神。 ; 話說回來,C/C++是我使用最多的程式語言,所以我如果也要使用TDD的話,就需要找一套支援C/C++的TDD程式工具。因為我沒那麼聰明,所以都只挑簡單易用的,最後終於讓我找到了 CppUnitLite 這個工具。實際上是在閱讀< 修改代碼的藝術 >這本書時,從中學到的,CppUnitLite是作者設計實作的一套短小精幹的UnitTest工具,簡單易用。 這本書的內容我全部忘光光了,但我學會了使用CppUnitLite就算是值回票價了。現在底下內容要作個簡單的介紹,看看如何撰寫單元測試。 ; 下載 後解開檔案,我們只需要將om/CppUnitLite裡的檔案加到我們自己的專案就可以了,om/CppUnitLite裡的Cpp和CppUnitLite資料夾不用管它。

手工打造算式計算機

前面已經對 (E)BNF表示式 作過一個簡介,現在要來看看怎麼樣實作一個可以處理簡單的整數四則運算的Parser。因為我們的重點將放在Parser的語法器(syntax analyser)上,所以忽略字彙剖析器(lexical scanner)不談,雖然一個Parser是由這二部份構成。 ; 許多Parser或Compiler相關的書籍資料上,都會拿簡單的算式計算機作為範例,可以找的到算式計算機的EBNF表示式,底下我們直接引用: expression = term ('+' term | '-' term)* term = factor ('*' factor | '/' factor)* factor = integer | group group = '(' expression ')' 上面的語法可以使用來解析如下的算式: 1+2-3*4 5*(6-(7+8)/9) ; 那麼要如何實作出能夠解析符合我們定義好的規則語法的資料的剖析器呢? 一個剖析器的轉換工作主要分成二個部份:將讀入的資料串流分解為有意義的小單位 token,及處理這些token間的關係。將資料串流分解成小單位 token的工作我們不多作說明。我們現在直接假設我們已經能夠得到分解完畢的 token了,接下來的工作就是分析這些 token之間的關係,檢查它們是否符合我們定義的規則語法。 作法相當的直接。首先,我們從資料串流中獲取一個token,接著檢查這個token是否符合我們正在檢查的語法的第一個符號,如果比對結果是符合的話,那麼我們就把當前的 token 給丟棄並再讀入下一個token,接著再繼續拿這個token和規則的下一個符號作比對。在比對規則時,如果中間遇到了非終端符號,則這個非終端符號會再展開。一直重複這個動作直到讀完所有資料為止,比對的程序才結束。 拿我們定義的group規則來作說明,以下為虛擬碼。 // 檢查當前的token是否是我們所期望匹配的符號 void match(token) {   if (current_token == token)     current_token = get_next_token(); // 如果匹配成功則再讀入下一個符號   else     e