實作Lua Closure二合一洗牌發牌機

dice-triangle
(圖片來源:maniacworld.com)

亂數 (Randomness),是每一位程式設計者們熟悉又親切的好朋友,無論我們開發製作的是哪一種類型的遊戲,亂數機制總是在遊戲設計程序與撰寫程式碼的過程中,扮演著不可或缺的重要角色。亂數最重要的用途,就是提供遊戲世界中必要的「不確定性」,只要能夠將這份「不確定性」的設計機制運用得宜,就可以為玩家們帶來許多驚喜感與樂趣元素。

然而,有許多時候,亂數的產生並不只是使用 rand() 函式般單純容易而已。在某些遊戲機制裡,無邊無際的亂數數值,並不能滿足程式設計者或企畫設計者所想達到的目標——我們需要的是「亂中有序」——能夠在某個限定範圍之內產生亂數。

何謂「亂中有序」?撲克牌遊戲就是一個最好的實例。撲克牌由 4 種花色與 13 種數字,組合成 52 張「牌組」。而「洗牌」(Shuffle) 動作可以定義為:在一組有限的集合元素內,進行亂數排列的程序。只要將牌組洗完之後,就可以按照牌堆的排列順序,開始一張張地進行「發牌」動作了。

對於程式設計者來說,不論是使用哪一種程式語言,要實作出洗牌與發牌的功能都不是件太困難的事情。假設,我們可以使用 Lua 語言來實作洗牌發牌機,是否能夠創造出什麼樣有趣的變化?

Continue reading “實作Lua Closure二合一洗牌發牌機”

遊戲專案的目錄結構規劃

不知道各位如何規劃遊戲專案的目錄結構?各位所使用的是專案管理體系的正規方法,或者只是隨意地將檔案與資料夾散佈在電腦中的各處?在一個遊戲專案的開發過程裡,重要的資產除了程式碼檔案之外,還包括了設計文件、美術素材、音效檔案,以及最終的執行檔等等。該如何妥善管理這些不同類別的項目,以達到良好的成效?在此將以我個人目前使用的方法,提出一套目錄結構的規劃架構,與各位一同進行交流討論。

有些人喜歡將許多各式各樣不同用途的資料夾,直接放置在電腦的「桌面」上,最後經常會使得整個桌布,幾乎被各種不同圖示與資料夾所淹沒。這樣的作法,在一時的使用上或許非常方便,但是如果沒有善加整理歸檔,未來很容易會找不到想尋找的目標文件或檔案。不論是公司的正式專案,或是自己在工作之餘開發的個人專案,都能夠從良好的目錄結構規劃中,得到易於管理與變動的益處。

首先,我習慣在電腦硬碟的作業系統槽(通常是 C 槽)之外,選擇一個空間足夠的磁碟槽,在根目錄下開啟幾個資料夾進行專案的管理:

  • Codespace:專案區,只存放由 CVS 或 SVN 等版本控制系統取出的各項專案。
  • Workspace:工作區,存放各項測試中的程式、待完成的工作項目,以及各種經常需要查閱使用的文件及資源。
  • Temp:暫存區,存放各種暫時物件,包括從網路上下載的安裝檔,以及檔案解壓縮後的資料夾等等。

專案區中的資料,應該經常與版本控制系統保持同步化,盡可能減少修改後的版本存在於自己電腦中的時間。即使個人的工作硬碟不幸遭遇毀損的狀況,也能夠由版本控制系統的伺服器中,重新取回整個專案的資料。而工作區,則用來存放各項試驗中的專案;例如在剛開始接觸 Boost.Pool 函式庫時,我就會在工作區裡開設一個測試資料夾命名為 TestBoostPool 進行各項測試,等到成果達到一定程度後,再將專案提交至版本控制系統以及專案區中存放。最後,在暫存區中的資料,則只是便利暫時性的使用,可以隨時將全部的內容清空刪除。

Continue reading “遊戲專案的目錄結構規劃”

表頭檔要不要?拿速度來換!

本文要提出的內容,是一個非常基礎的程式觀念:表頭檔 (Header Files) 與編譯依存關係的課題。雖然對於許多程式設計者來說,這個觀念技巧應該是相當基本而且必備的基礎知識,但在現實世界中,我卻時常看到許多人忽略了這個問題的重要性,因而造成專案開發流程中的重大災難。

來看看實際的範例。例如在專案中有一個 GameObject 類別,用來實作遊戲物件的相關操作行為:

// @ GameObject.h
#include < string >

class GameObject
{
public:
    int GetType();
    std::string& GetName();

private:
    int m_iType;
    std::string m_kName;
};

有了基礎的遊戲物件類別之後,自然會陸續建構並且實作出其他的類別。當 GameObject 需要使用或包含其他的類別時,可能會在類別中定義一個該類別的成員變數,以結合 GameObject 類別進行更複雜的操作行為。例如,可能會在 GameObject 類別中,加入一個 ComponentA 類別的物件定義遊戲物件的基本組件:

// @ GameObject.h
#include < string >
#include "ComponentA.h"

class GameObject
{
public:
    int GetType();
    std::string& GetName();
    ComponentA& GetComponentA();

private:
    int m_iType;
    std::string m_kName;
    ComponentA m_kCompA;
};

Continue reading “表頭檔要不要?拿速度來換!”

程式碼的版面配置與風格樣式

什麼是程式碼的版面配置 (Layout)風格樣式 (Style)?用一句話簡單說明就是:程式碼呈現出來的樣貌

在程式碼的文字檔案中,除了有意義(或混亂)的程式碼與註解文字之外,佔據其他空間的正是所謂的版面配置元素;也就是程式碼中的空格、空行、斷行、縮排、括弧等元素。 正所謂「人要衣裝,程式要風格」,利用這些版面配置元素將程式碼好好打扮裝飾一番,不僅能夠讓程式碼看起來賞心悅目,使閱讀程式碼的人功力大增,更能夠讓程式碼的邏輯與結構更加清楚顯著地展現出來。可說是一舉數得、好處多多,真是「居家寫 Code,出門上班」的最佳良伴啊~

版面配置是對於程式結構的有用指引線索。良好的配置方案能夠使程式的視覺化結構與邏輯結構相符合,傳達給人類與電腦相同意義的訊息。在此要再次引用《Refactoring》書中所寫的一句經典:

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

在撰寫程式的過程裡,較少部分的工作成效,是為了使得電腦能夠瞭解程式碼;而較多部分的努力,是為了使得其他的人類能夠讀懂程式碼。在這個前提之下,程式碼如果能夠達到良好的視覺化配置,就可以恰如其份地展現出一個程式的邏輯結構。程式碼的配置和風格,不會影響到外在可見的因素,例如執行速度、記憶體使用等等,而是對於易讀性、可修改性有很大的影響。並且必須在程式專案初始建構的時期,就將這個議題納入考量。

Continue reading “程式碼的版面配置與風格樣式”