Database Hot Loader 二部曲:Using VSTO and Lua

接續前篇文章的簡短介紹,本文將開始使用 VSTO 與 Lua 語言實作 DHL 系統。首先,定義 DHL 系統的開發環境以及執行環境:

Database Hot Loader 系統

  • 程式開發環境:Visual Studio 2005 Team Suite
  • 使用者執行環境:Office 2003

為了使 Office 2003 達成轉換資料格式的任務,必須仰賴 VSTO 所提供的擴充功能。Visual Studio Tools for Office (簡稱為 VSTO)的作用,簡單來說就是讓程式設計者能夠在 Office 應用程式中,使用 .NET 撰寫附加的擴充元件,使一般的文件檔案,也能夠具備客製化的特殊功能。另外,微軟 .NET 平台的優勢,就是能夠使用 .NET 家族中的任何一種語言來撰寫程式,在此我選擇 C# 做為開發 DHL 系統的語言。

只要使用 VSTO,幾乎就能夠達成一切 Winform 可以做到的事情。在活頁簿上放個按鈕元件?沒問題;另外產生一個全新的 Winform?小意思;在 Excel 的主選單上增加自訂項目?一片蛋糕。總是覺得 Office 應用程式某些地方用得不夠順手嗎?有了 VSTO 以後,就可以幫助我們達成自己動手撰寫擴充功能的願望。

在前篇文章中,曾特別提到需要使用 Visual Studio 2005 的 Team Suite 版本,原因在於 DHL 系統必須使用 VSTO 的「文件層級」(document-level) 擴充程式,而在 Visual Studio 的眾多版本中,只有 Team Suite 版本能夠開發文件層級的擴充程式,一般程式設計者常用的 Professional 版本則只能夠開發 VSTO 的「應用程式層級」(application-level) 擴充程式。關於文件層級與應用程式層級的介紹,請參考「Visual Studio Tools for Office 」中文線上文件裡的詳細說明。

Continue reading “Database Hot Loader 二部曲:Using VSTO and Lua”

登泰山而小天下:Boost C++ Libraries 初體驗

說來有些慚愧,一直以 C++ 語言做為謀生工具的我,在使用了多年的 C++ 程式語言之後,最近終於與聞名遐邇的開源專案 Boost C++ Libraries(簡稱為 Boost)進行了第一次的親密接觸。在本文裡,將參照 Boost 官網的「Getting Started on Windows」文章,於 Windows 作業系統以及 Visual Studio 2005 程式編譯器的環境下,詳細介紹安裝及建置 Boost 的步驟,並且在最後使用 Boost.Thread 函式庫做為測試範例。

從前就常聽到其他人談論著 Boost 的優點,但是只要知道其中由上千個標頭檔以及數十個函式庫所組成,而且還需要以繁複的步驟手動建立函式庫的 .lib 檔案,很容易就會使初學者望而卻步。對於用慣了程式整合開發環境以及現成函式庫的我來說,Boost 簡直就像是一座美麗動人但又戒備森嚴的堡壘般令人不敢輕易接近。多年以後的現在,總算是鼓起了勇氣重新面對 Boost。花了些時間閱讀文件,然後按照指示一步步完成安裝建置之後,發現原來這些步驟比起從前已經簡化許多,函式庫的使用也不如想像中的困難!

One of the reasons for boost’s success has been the cross-pollination of ideas between diverse library projects.

Boost 是由一群功能獨立的函式庫所組合而成的集合體,其中涵蓋了許多熱門而經常使用的函式庫,以及比較冷門的特殊功能作用函式庫。所有的函式庫都包含在名為 boost 的 namespace 中,不僅能夠使各函式庫維持一致的使用風格,同時也得以避免命名衝突的問題。如官網中的 FAQ 所述,Boost 的成功正是由於不同功能函式庫之間的「交叉授粉」(cross-pollination) 作用所致;雖然其中多數函式庫都能夠分開獨立使用,但正是由於函式庫之間相互支援的功能以及介面,才使得 Boost 的開發者社群與使用者社群能夠蓬勃發展且欣欣向榮。

Continue reading “登泰山而小天下:Boost C++ Libraries 初體驗”

Database Hot Loader 首部曲:Introduction

mana-energy-potion「我有一個夢想,期望有天我們能夠免於調校遊戲資料數據的苦痛。」馬丁路德博士夢想,是人人生而平等並且免於種族歧視的迫害。而我的夢想,沒有這麼崇高偉大,只是希望能夠幫助團隊成員改善遊戲的開發流程。

每次當我看到遊戲企畫者,為了調整遊戲中的各種數據,而必須不斷重複一連串繁瑣而且漫長的操作程序,就替他們感到很辛苦。為了測試資料數據的正確性,首先要在 Microsoft Office Excel 上輸入資料內容,存檔後匯出,接著以外部工具將文字檔轉換為遊戲自訂的檔案格式,把檔案置入遊戲目錄中,最後再開啟遊戲,等待遊戲程式以及遊戲資料載入完成,然後檢視執行的結果。

「咦,食人怪的偵察範圍太遠,而火球魔法的距離太近了些。」於是按下離開遊戲的快速鍵,然後在 Excel 表格中修改相對應的數據後,再次存檔匯出,再次以外部工具轉換為遊戲自訂的檔案格式,再次把檔案置入遊戲目錄中,然後再次開啟遊戲,再次等待遊戲程式與遊戲資料載入完成。

(圖片來源:www.play-gadgets.com)

除非企畫設計者擁有強大的靈動感知能力,能夠精準地預測出合適的遊戲數值,否則總是需要不斷地嘗試錯誤並且經歷許多修改程序,才能夠將遊戲數據調校到完美平衡的狀態。不停地、不停地、不停地重開遊戲,幾乎是每位遊戲企畫設計者都曾經歷過的處境。在遊戲專案開發初期時,可能還感受不到特別的困擾之處;然而當專案到了後期階段,遊戲中的美術素材動輒佔有成千上百 MB 的份量,所以每次開啟遊戲都必須要等待漫長的遊戲初始化載入時間,甚至只是修改單一一個欄位的數據,同樣難以免於遊戲重開的等待過程。

有沒有可能改善這種狀況,減少重新開啟遊戲程式的頻率?有沒有可能在不需要重新啟動遊戲程式的情況下,讓企畫設計者能夠即時調整遊戲的資料庫數據?

Continue reading “Database Hot Loader 首部曲:Introduction”

Prototype:物件原型複製者

prototype-uml在物件導向生成設計模式的範疇中,除了之前曾經介紹過的 Facory Method 以及 Abstract Factory 兩項工廠類型的模式以外,本文將繼續介紹另一項在遊戲程式領域中,經常受到廣泛使用的 Prototype 設計模式。

Prototype,原意為原型或雛形,與工廠模式接收到使用者命令之後即時生產物件的方式不同,在 Prototype 模式中,我們需要先打造出物件的原型樣版,待鑄模程序完成以後,接下來就能夠輕易地以此原型複製產生出全新的物件。複製,也可以是一種生成物件的方法。如 UML 圖所示,在 Prototype 設計模式中,定義了三個參與角色:

  • Prototype:宣告自我複製的介面。
  • ConcretePrototype:具體實作出自我複製的操作。
  • Client:叫原型個體自我複製一份,以生出新的物件。

按照上述的責任關係,程式系統的使用者 Client 只需要指涉到基礎的 Prototype 介面,就能夠以此 Prototype 介面所宣告的 Clone() 方法,複製出類別的物件成品;而 ConcretePrototype 們衍生自 Prototype 介面,是 Client 進行 Operation() 方法後將會獲得的實際成品,所以必須一肩扛起實作 Clone() 內容細節的重責大任。

Continue reading “Prototype:物件原型複製者”

物件導向設計新思維:深入Policy-Based Class Design新大陸

自前一篇「物件導向設計新思維:探索Policy-Based Class Design新視界」發佈以來,已經過了很長的一段時間。在這篇千呼萬喚始出來的續集裡,將會進一步深入探索 Policy-Based Class Design 背後的設計概念與理論,以及在實作層面上經常會遭遇到的問題;最後,以一個遊戲系統中常見的音源引擎 (Audio Engine) 類別設計為範例,做為本文的片尾曲目。

記得曾經有人問過比爾蓋茲,如果有天他被迫一人獨自在荒島上生活,身旁只有一樣物品陪伴的話,最想要什麼東西?他的回答是:「一部電腦與編譯器。」許多程式設計者心裡所嚮往的美好世界,就是那種無拘無束、無邊無際的自由;好像只要手指還能夠活動、頭腦還能夠寫程式,天底下就沒有辦不到事情!只是,有時候這種無限度的自由,反而會對程式系統造成負面的影響。

《C++ 設計新思維》(Modern C++ Design) 書中的第一章,就對於程式系統的設計就開宗明義地闡述:

理想上,一個良好設計應該在編譯期強制表現出大部分 constraint(約束條件、規範)。

身為一位程式設計者,或多或少都有把自己的程式碼交給其他程式設計者使用的經驗,相對於「程式撰寫者」來說,所謂的「程式使用者」,就是那些使用你所撰寫的程式碼的人。就像是遊戲程式中經常使用的 DirectX、OpenGL 或者 .NET Framework 以及遊戲函式庫與引擎等等,我們都是身為「程式使用者」的身份。

Continue reading “物件導向設計新思維:深入Policy-Based Class Design新大陸”

初探Nintendo DS程式開發與設計(四):做個拼貼藝術大師

由之前一系列的三篇文章中,已經一步步地瞭解了如何在 NDS 平台上使用 Framebuffer 背景模式、Bitmap 背景模式,以及 Sprite 物件功能,接著本篇將再次深入與遊戲製作息息相關的背景顯示功能,介紹在真實的遊戲程式應用中,更加實用的圖塊背景 (Tiled Background) 模式

前情提要

由於硬體架構上的先天限制,在 NDS 平台中,沒有如同個人電腦平台上的全彩 (32 bits) 或高彩 (24 bits) 顯示模式可以使用;在這個小小的掌上世界中,所有的繪圖物件只能夠使用 16 bits、8 bits 或 4 bits 的色彩顯示模式。而如前篇文章的內容所提,Sprite 物件能夠使用 16 色 (4 bits) 與 256 色 (8 bits) 兩種模式,對於背景圖件來說亦然如此。在 Sprite 的功能中,可以選擇使用 OBJCOLOR_16 或 OBJCOLOR_256 這兩項色彩模式,而在背景圖件中,也有相對應於 16 色與 256 色模式的 BG_COLOR_16 與 BG_COLOR_256 定義。

瞭解了色彩模式的種類之後,就可以開始進入圖塊 (Tile) 的世界了。很久很久以前,在那個電腦記憶體仍然十分珍貴而稀少的年代裡,多數的家用遊樂器主機,都只配備著非常有限的記憶體容量。而對於掌上型主機來說,記憶體的限制則更為顯著。因此,我們無法使用多張高解析度的點陣圖 (Bitmap) 做為遊戲中的背景圖片,所以在 NDS 上存在著一種特別的繪圖顯示模式,能夠以一組相同大小的圖塊,拼貼組合成為完整的遊戲背景圖片。因此,遊戲開發者就可以利用類似磁磚拼貼的方式,由有限數量的小型圖塊,組合出變化多端的大型圖片。

Continue reading “初探Nintendo DS程式開發與設計(四):做個拼貼藝術大師”

初探Nintendo DS程式開發與設計(三):二維世界小精靈

延續前篇文章中所介紹的 Bitmap 背景圖件顯示功能後,本篇開始進入 2D 圖件 (Sprite) 的二維世界。所謂的 Sprite,原意是指「調皮搗蛋的小精靈」,但是在電腦繪圖與遊戲程式的領域中,Sprite 一詞則被用來當作二維繪圖物件的代名詞:

Sprite is the term used to describe a 2D graphics with a number of related functions.

nds-dev-sprite從前,在那個只有 X 軸與 Y 軸的平面世界中,Sprite 物件就是一切事物的根基,能夠用來表示角色人物、怪物敵人以及武器裝備等許多不同的遊戲物件。Sprite 可以只是一張單純的靜態圖片,也可以由數張圖片組合成為動畫的形式。簡單來講,Sprite 不過是一張可以移動與旋轉的 2D 貼圖罷了。

以 DirectX 為例,在 D3D 中已經包含了 Sprite 的物件功能,能夠使用 LPD3DXSPRITE 與 D3DXSprite() 輕易地創建出 Sprite 物件。即使目前許多平台上的遊戲,都已經趨向全 3D 型態的呈現方式,但是如果能夠應用得宜的話,傳統的 Sprite 物件繪圖模式仍然有很多的可能性存在。例如著名的線上遊戲《仙境傳說》,就是以 2D Sprite 人物,搭配 3D 型態場景的絕佳實例。

如果之前有接觸過 GBA 程式開發與設計知識的讀者,應該能夠很容易發現 NDS 平台與 GBA 平台的硬體架構與核心功能,其實擁有許多的相同之處。任天堂公司保留了原本設計良好的 GBA 架構,然後更進一步延伸,加入了 3D 繪圖、觸控操作、雙處理器引擎等等進階的硬體架構與功能。但是在 2D 繪圖的處理層面,仍然沿襲 GBA 平台的各種設定以及使用方法。而 Sprite 的許多定義與操作行為,也都是由 GBA 時代流傳下來的概念,因此在 NDS 平台上,Sprite 同樣佔了舉足輕重的關鍵地位。

Continue reading “初探Nintendo DS程式開發與設計(三):二維世界小精靈”

向食人魔怪說嗨:與OGRE的第一類接觸

OGRE最近花費了大把的時間,努力地學習如何與 OGRE 這隻聲名遠播的巨獸成為好麻吉。至目前為止,總算是能夠稱得上稍微和它混熟了一點。關於 OGRE,這裡提出幾點我的學習筆記、目前觀察到的個性特質,以及與它相處的心得感想。

首先,對於稍具經驗的程式設計者來說,見到 OGRE 的第一眼印象,應該莫過於各種設計模式 (Design Pattern) 的廣泛使用了。在 OGRE 的架構設計與系統實作層面中,使用了 Abstract FactoryFactory MethodSingletonIteratorObserver 以及 Manager 等等許多著名的設計模式。說實在的,我還是頭一次看到這麼多不同種類的設計模式,能夠同時應用在一個遊戲繪圖引擎之中,正好能夠與以前所學的理論知識相互印證,學習起來非常爽快也很感動,真是令我大開眼界、大呼過癮!

而其中,最顯而易見的設計模式就是 SingletonManager 的結合使用。OGRE 利用這兩項模式的組合,製造出了一位一位各有擅場的「專業經理人」,使各個子系統所負的權責,都能夠劃分的非常清楚仔細。另外,利用 Observer 的概念,讓使用者能夠繼承 FrameListener 類別,自行定義進行繪圖程序前後的相關處理程序,也是一個非常優秀的設計模式應用實例。

回想自己當初剛進入業界時,在沒有任何人使用這些設計模式的情況下,額外看了許多書籍網站的資料,最後終於利用 Singleton 與 Manager 模式實作出幾項遊戲專案的子系統組件。結果深入認識了 OGRE 以後,才發現原來這些觀念已經如此廣泛地運用在遊戲引擎的設計架構之中。正所謂「他山之石,可以攻錯」,對於程式設計者來說,吸收新知以及學習別人的長處,的確是十分關鍵而不可或缺的能力啊。

Continue reading “向食人魔怪說嗨:與OGRE的第一類接觸”

初探Nintendo DS程式開發與設計(二)

nds-dev-bitmap自從年代久遠的「初探Nintendo DS程式開發與設計(一)」問世以後,經過了漫長的兩個月等待,新的續篇終於不負眾望地(?)火熱出爐囉!這篇文章將進入 Nintendo DS 的內心世界,深入探索它在樸實外表下所隱藏的強大能力。然後,同樣地以一個簡單的範例介紹基礎的背景圖件顯示功能。

首先要瞭解的是 DS 的硬體架構。

DS 是一個擁有雙中央處理器 (CPU) 的系統,兩個處理器分別是 ARM 9 以及 ARM 7;ARM 9 是一個 32-bits 架構 66 MHhz 速度的處理器,而 ARM 7 是一個 32-bits 架構 33 MHhz 速度的處理器。DS 擁有 4 MB 的主記憶體容量,總計 656 KB 的顯示記憶體容量,以及數個大小不等的快取記憶體;詳細的內容配置,請參照這張 DS 的記憶體架構圖。除了核心架構以外,當然還有音效硬體、麥克風、觸控螢幕、主機按鍵、GBA 卡匣槽,以及 Wi-Fi 網路的支援能力。

不同於 PC 平台上動輒成千上百的記憶體容量,整個 DS 的主記憶體只有 4 MB 的大小,而相當重要的顯示記憶體更是只有 656 KB 的容量;因此,在 DS 上對於任何資源的配置行為,都需要精打細算地評估考量。ARM 9 與 ARM 7 都能夠自由存取主記憶體,而主記憶體通常會用來存放 ARM 9 所使用的遊戲執行檔,以及與遊戲相關的實體檔案。至於 ARM 7 的執行檔,雖然也能夠放在主記憶體中,但是為了效能上的考量,devkitPro 預設的行為會將執行檔放在快取記憶體 IWRAM 之中。另外,DS 的觸控螢幕輸入功能,是交由 ARM 7 所處理的;在 libnds 的預設執行檔中,ARM 7 會在每次主迴圈更新時,讀取觸控螢幕的相關資料,並且將這些資料存入 ARM 9 也能夠讀取的地方。

Continue reading “初探Nintendo DS程式開發與設計(二)”

物件導向設計新思維:探索Policy-Based Class Design新視界

Policy-Based Class Design 到底是什麼樣的東西?又能夠用來解決什麼樣的問題?本文將由一個在程式專案中常見的現實案例,帶領讀者進入 Policy-Based Class Design 的全新思維領域。

學習一項新的思維方法或實作技術,最容易的方法就是從需求面出發。所以在介紹 Policy-Based Design 之前,先來看看一個現實中經常會遇到的程式設計案例:假設在處理 Input/Output 功能的系統層,原來存在著 BinaryReader 與 BinaryWriter 兩個類別,分別用來讀取以及寫入二進位制的資料串流。

現在,在新的專案項目中,我們希望能夠利用這兩個既存的 IO 類別,但是又不希望將檔案的讀取與寫入動作,分成 BinaryReader 與 BinaryWriter 兩個不同的類別進行處理。因此,程式設計者需要設計一個新的 IO 管理者類別,將原有的讀取與寫入功能合併在一起,以達到集中操作以及檔案資源管理的功用。

而為了盡量減少對既存程式碼的修改,其中一種設計方法是使新的 IOManager 類別,同時繼承自 BinaryReader 與 BinaryWriter 類別,然後藉由虛擬函式的宣告,修改專案所需的行為程序:

class IOManager
    :
    public BinaryReader,
    public BinaryWriter
{
public:
    virtual void Read(); // 覆寫自 BinaryReader
    virtual void Write(); // 覆寫自 BinaryWriter
}

這樣設計的方法確實能夠在不修改原有類別的前提下,達到 IO 系統介面集中的目的。程式系統的撰寫者無須再同時照料 BinaryReader 與 BinaryWriter 兩個類別,只要一個 IOManager 類別就能夠處理 IO 層面的功能操作。

Continue reading “物件導向設計新思維:探索Policy-Based Class Design新視界”