遊戲開發日誌:水晶守護者

crystal-guardian-draft
《Crystal Guardian》Design Draft

這是《Crystal Guardian》的遊戲設計草稿。

其實大約在四個月前,我就已經完成了遊戲的基礎設計,本來想要在 NDS 平台上嘗試製作這款小小的遊戲原型,不過後來因為被其他有趣的事情吸引,再加上我一直找不到能夠在 Homebrew 套件上執行 Lua 的方法,所以也就沒有往 NDS 的方向繼續發展下去了。直到兩個月前,在玩過「咕世界」並且讀了「How to Prototype a Game in Under 7 Days」一文之後,內心深處那股「無論如何都想要做遊戲」的雄雄烈火,又再度燃燒了起來!

一開始在做遊戲設計的靈感發想時,對於目前網路上各種動作過關類型的小遊戲,可以看到大多數作品都是以「攻擊」、「毀滅」或者「破壞」當作遊戲的主要題材與樂趣元素。而我想要嘗試的,則是完全相反的方向。我反問自己:「有沒有可能以『保護』或者『防衛』的概念,做為遊戲的主要機制?」

當然,現在有許許多多 Tower Defence 類型的遊戲,但是我想做的並不是這種玩法的遊戲。我想做的遊戲,設計概念與核心機制的出發點在於「防護」(Defence),或許是保護金銀財寶、捍衛重要的東西或者心愛的人,無論那是什麼,我認為世界上總有些值得我們守護的人、事、物以及價值。而至於遊戲的操作方式,我想嘗試的方向,是一個不用動腦思考,只需要不停移動並且點擊滑鼠就能夠進行的遊戲。

按照遊戲原型開發文章裡的做法,我原先預估的開發時程為 10 天整。直到正式開始動工之後,馬上就發現每天的開發時間,實在是超級無敵不夠用,才剛做出了點東西就花費掉一整個晚上,依照這樣的進度,10 天左右肯定無法完成遊戲,於是決定將開發時程延長為 14 天。結果,最終在燃燒小宇宙與睡眠時間的狂暴化狀態下,還是延遲了 2 天,整整用了 16 天才完成這款小遊戲

雖然遊戲的核心機制很早就已經建立完畢,但是 Game Theme(遊戲題材)卻一直處於懸而未決的狀態。原因是「遊戲題材」與「遊戲素材」具有非常高的相依性,在找不到美術設計者合作,我自己也不會畫圖的情形下,想要對遊戲題材拍板定案,實在是一項相當困難而又不切實際的想法。

以後見之明來看,如果當初能夠使用 Flash 做為製作工具的話,應該可以節省不少開發基礎遊戲元件所花費的時間。但是我對 Flash 的熟悉度,差不多停留在讓矩形移動與變大變小的程度而已,所以最終還是毫無懸念地決定使用我最熟悉的 C++ 與 Lua 製作遊戲。

而這次開發的成果,並不是完全從零到有產生出來的。我原先已經有一個小小的遊戲程式框架 (Framework),曾用來製作過一個 2D 遊戲的半成品,其中的功能只有非常基本的 Graphics、Audio、Input、Script 與 Debug 功能。於是我就以這個 Framework 做為出發點,義無反顧地展開了這趟遊戲開發的奇妙旅程

過程中,我將每一天的進度都大致記錄了下來。以下就是這段時間裡,每天所做的開發日誌筆記:

Day 1

  • 簡單扼要地在 Lua 端確立了程式的主流程。當程式啟動初始化完畢後,程式的控制權,包含 Update、Render 以及偵測視窗訊息與鍵盤滑鼠狀態在內,全權交由 Lua 端掌控。只要控制權一回到 C++ 端,就要清理資源然後準備結束程式了。
  • 在既有的程式碼中,只能夠顯示單一的 Sprite 物件,這樣可不行哪。以 Sprite 為基礎,開始打造 CompositeSprite,可以組合任意多個 Sprite 做為一個完整的物件個體。(結果最後並沒有使用到這個功能)
  • 原先在 Framework 中的 Input 系統只有二元狀態 On 或 Off 的 Polling 模式,對於開發除錯來說實在很不方便,所以決定先在 Lua 裡弄個簡易的 Event-based 模式,讓我在每次按下鍵盤或滑鼠按鈕時,只會送出一次事件訊息。
  • 在網路上亂逛,意外找到《太空戰士》系列作品的 Sprite Sheet,品質看起來很不錯,是不是可以考慮拿來做為遊戲的素材?

Day 2

  • 製作 Animation 系統。以前有使用 Lua 寫過相同的東西,所以翻出舊作的 Source 來看。「寫得真糟,當初怎麼會這樣想又這樣寫呢?」費了些功夫,翻修製作出新的 AnimatedSprite 元件。當然動畫資料的定義,也全部都使用 Lua 完成。
  • 現在可以載入多張獨立的圖片播放動畫,但是網路上找到的 Sprite Sheet 通常都是一整張圖片的連續畫格,如果還得自己動手裁切,未免也太費力了點。所以只好再製作 AnimatedSprite 的第二種模式,讓它能夠讀入單張圖片來播放動畫。
  • 套用《太空戰士》的 Sprite Sheet,測試 AnimatedSprite 元件的功能無誤。好,就決定偷這些圖來用!
  • 重新組織 Lua 端的檔案結構。

Day 3

  • 給點回應吧!實現簡單的矩形與圓形碰撞檢測。有了 Pick 元件後,才能夠知道滑鼠到底有沒有點選到 Sprite。
  • 創造簡易的 State Machine 元件來搭配角色的 Animation 系統,目前只有 idle 與 move 兩種狀態。
  • 放上數個不同圖片的角色,於遊戲視窗中隨機遊走。顯示結果怎麼全部的角色圖片都相同?
  • 第一次臭蟲大魔頭來襲:是之前的 AnimatedSprite 功能有誤嗎?還是哪個部分的功能有所疏忽?經過了一番奮戰並且用掉好幾罐「補血瓶(小)」之後,才發現原來我誤用了 Lua 物件導向設計的觀念!

下列程式碼是錯誤的用法:

    local o = self:Instance();
    o.m_Transform = transform;
    o.m_Texture = texture;
    o.m_Sprite = sprite;
    

下列程式碼才是正確的版本:

    local o = self:Instance
    {
        o.m_Transform = transform,
        o.m_Texture = texture,
        o.m_Sprite = sprite,
    };
    

修改完成後,終於還給每個角色他們原來的真面目了!

Day 4

  • 開始加入先前已設計完成的 Game Level 結構,可使用 Lua 檔案很便利地定義每一個關卡敵人的出現時間、類型、數量與方位。
  • 簡便地使用 function 與 if-else 切換不同的 Game Stage。目前初步規劃,共有 Initialize、In Game、Between Level 與 Game Set 四個 Stage。(決策錯誤)

Day 5

  • 建立玩家角色的各種狀態:idle、move、attack、powerup 以及 dead。滑鼠點擊後,玩家角色會移動至滑鼠位置,如果角色正在進行攻擊動作則無法移動。過程很順利。
  • 創建敵人的 dead 與 dig(偷取水晶)狀態,包含先前的 idle 與 move 在內,終於完成了第一個完整的 AI 流程。不過敵人還是只會在場景上到處亂逛。

Day 6

  • 開始著手製作原先規劃的數種 AI 型態:預設的一路走到底 AI、亂亂走 AI,還有走一走會停下來的 AI。

Day 7

  • 為了讓 Release Build 的建置程序更加自動化與直覺化(簡單說就是我懶得做一大堆複製貼上的動作),所以用 Lua 弄了個 Prebuild 程序。將指定的純文字格式 Lua 檔案,全部寫入一個新的檔案中,完畢之後執行 luac 編譯成 binary 格式。最後,把執行命令加在 Project 的 Post-Build Event 中,搞定!

Day 8

  • 開始寫 Gameplay 流程的部分,包括 Stage 與 Stage 之間的銜接,Game Over 與全破關的條件判斷。程式碼逐漸有越來越混亂的感覺……

Day 9

  • 到目前為止,遊戲中還沒有出現任何文字。所幸 Framework 中已有繪製 TrueType Font 的功能,直接拉進 Lua 使用。測試無誤。

Day 10

  • POPcade 的音樂音效素材區搜尋資料,找到一個日本的網站 Propan_Mode,裡頭滿滿的都是 MP3 格式的高品質音效與音樂,真是太棒太讚太感動啦!(不過一直沒有找到合適的攻擊音效,囧)
  • 加入播放音樂與音效的功能。製作一個 Radio 元件,用來做為遊戲中的 BGM Player,可把使用者提供的播放清單,依序、隨機或者循環播放。

Day 11

  • 在 Google 打上「Free Font」,從成千上萬個 Font 裡找到幾個還算合用的字型。
  • 用網路上搜尋到的免費軟體,將 MP3 轉換為檔案容量較小的 OGG 格式,將播放音效的程序加入遊戲。

Day 12

  • 用 Photoshop 幫角色圖片進行去背程序。讚!終於不用帶著白色的框框在場景上行走啦。
  • 再度修改 Animation 系統與 AnimatedSprite 元件,現在可以指定動畫中每個畫格的起始位置了。
  • 產出遊戲角色以及水晶的動畫定義檔,對每一個動作的每一個畫格(還好數量很少),Pixel by Pixel 逐一進行微調。

Day 13

  • 測試 AI 系統裡最複雜的「閃避」程序。果然有不少問題,經過整修後得出一個還算可接受的成果。
  • 修改 Framework 的 Debug 功能,可將 Lua 的錯誤訊息以 MessageBox 秀出來並且記錄在 Log 檔中。(為什麼這麼晚才想到可以這樣做? =_=)

Day 14

  • 實作 AI 的 Perk 程序,敵人「格檔」時會無視玩家的攻擊,「反制」時會使玩家在三秒內無法動作。掛上一個額外的盾牌與雙劍小圖示。
  • 加入分數計算以及 Combo 連擊加成的程序。
  • 從以前的作品素材中,拉來幾張背景圖。場景畫面終於脫離了單調無趣的背景色!

Day 15

  • 開始正式製作遊戲關卡。試玩,微調,微調,微調。
  • 找了台沒有安裝 MSVC 的電腦測試,確認遊戲執行檔沒有 DLL 相依性的問題。
  • 第二次臭蟲大魔頭來襲:正當我以為遊戲已經逼近完成之時,突然發現了嚴重的邏輯與流程問題。當敵人奪取水晶之後再被玩家擊倒,敵人的 AI 會產生異常狀態。然後過關條件的判斷也不正確,水晶都被幹光了竟然沒有切換到 Game Over 的 Stage,到底是怎麼回事?

Day 16

  • 重新大整修:首先是敵人連結水晶的部分,寫的方式含糊不清又太多假設條件,造成不正確的執行結果。接著再重新思考敵人的 State 轉換,將原先散落在各個 State 中的邏輯判斷,提煉出來做為獨立的 function。最後,加入一個新的「準備階段」Stage,大幅簡化 Stage 與 Stage 之間的切換流程。
  • 重新調整關卡難度。調整。測試。調整。測試。完成!
  • 打包壓縮,撰寫文章,發佈。(靈魂飄走)

以上就是 16 天以來的開發流程。

雖然我使用 Lua 已經有一段不算短的時間了,但這還是我第一次以 Lua 完成所有的 Gameplay 程式碼。在遊戲的開發流程中,相關於程式設計的部分,只有使用了 5% 左右的時間在修改及新增 C++ 端 Framework 的功能上,其餘 95% 的時間全投注於 Lua 的環境下撰寫程式碼。再者,為了使這些以 Lua 撰寫的遊戲元件能夠繼續在未來的遊戲作品中使用,所以也耗費了不少時間在考量 Reusability(可復用性)的議題。最終,順利地把 Lua 端的程式碼,分成了「遊戲元件」(可復用)以及「Gameplay 相關」(不可復用)兩種不同的用途。

使用 Lua 編寫 Gameplay 程式邏輯的主要優勢在於「速度」。修改,存檔,然後執行,一氣呵成!再也不必因為一點小小的修改,而必須等待漫長的程式碼編譯與函式庫連結時間。但是使用 Lua 也並非全無缺點;在程式碼編輯工具的選擇上,我使用的是 Lua for Windows 套件中的 SciTE 編輯器,雖然 SciTE 具備有基本的編譯與除錯功能,但無法與 C++ 端的程式碼相互連結,所以在 Gameplay 的除錯程序上比較麻煩,還是必須執行 C++ 端的程式執行檔,才能夠找出 Lua 端的錯誤與問題點。

另外在撰寫程式的過程中,我有點太過於小看 Stage 切換邏輯判斷的複雜度。一開始在撰寫 Stage 相關的部分時,並沒有設想太多,只使用了最簡單的 function 與 if-else 敘述句來切換不同的 Stage,結果到了最後反而造成不少問題。還是應該打從一開始就把 Stage 的架構與流程控制,寫成一個獨立可重複利用的元件才正確。

而在所有的程式系統與遊戲邏輯中,最複雜的部分應該就是敵人的 AI 程序了。我想達到的目標,是多變且具有擴充性的 AI 模組。為了達成多樣化的 AI 行為,如果只是單純地將 AI 程序分成「直線型」、「隨機型」與「格檔型」等等,其實無法發揮良好的綜效。所以後來我想到了一個做法,就是將 AI 處理程序拆解成三種獨立的邏輯程序,分別是 Path Planner、Tactic Thinker 以及 Perk(特技):

Path Planner

  • 直線
  • 隨機

Tactic Thinker

  • 暫停
  • 閃避

Perk

  • 格檔
  • 反制

分成三種獨立程序之後,我就可以在設計各關卡的敵人類型時,任意組合上述三種 AI 邏輯程序,然後再加上敵人外觀與生命數值的設定,製作出豐富而多樣化的敵人軍團。

在這 16 天的遊戲開發過程中,排除之前預先完成的遊戲設計層面,以程式設計、素材生產與關卡設計三個面向進行評估,程式設計約略佔了 80% 左右的開發時間,而素材生產與關卡設計加起來卻只佔用了 20% 左右的時間。用在關卡設計與素材製作面向上的心力,實在太少太少啦!

總結來說,下一款遊戲作品的改善目標為:

  1. 先搞定 Stage 架構與流程控制元件。
  2. 美術!我需要找到能夠共同合作的美術成員,或者是可以見人的 Better Programmer Art
  3. 花費更少的時間寫程式碼,把更多時間心力投注在關卡設計與素材製作上。
  4. 遊戲必須要更有趣,更具有可玩性。

在遊戲設計的層面上,我還是個十足的嫩咖,但是只要過程好玩,我就會一直一直玩下去! :D

你可能不知道的小秘辛:遊戲本來想取名為 Crystal Defender,後來發現 Square Enix 在 iPhone 上有發佈一款同名作品,所以只好更換名稱為 Crystal Guardian。 XD

你不可不知道的小秘技:如果覺得遊戲太刁難或是滑鼠不夠滑而過不了關,請打開遊戲資料夾中的 GameEnemy.lua 與 GameLevel.lua 檔案,相信各位一定能夠發現戰勝遊戲的很黑暗的招。 :P

23 Replies to “遊戲開發日誌:水晶守護者”

  1. 看了真是令我振奮精神
    很厲害喔
    我之前也常嘗試著自己開發
    只是都死在美術素材不足

    加油吧

  2. 真精采的筆記~~ “我認為世界上總有些值得我們守護的人、事、物以及價值”,不確定半路有沒有看過我以前做的小遊戲,有類似的理念耶,而且也一樣是一直點滑鼠就行。用Flash做小遊戲真的快很多!

    http://blog.xuite.net/laishiekai/Dairy/7617714

    有想過要做2.0版,像是有的牛奶會讓寶寶跑速上升一段時間啦、增加爸爸的招數啦… 可是那個寶寶從遊戲來到我們的真實生活後,我就沒力氣去動flash了… = =

  3. 看這份開發筆記就知道開發過程會發生多少奇奇怪怪的事…如果是合作的話,我想這份筆記應該會再增加個一兩千字吧XD

    不過,我一直以為自製遊戲最缺乏的應該是程式呢…因為我自己是美術,總覺得程式反而難找,可見專業領域的生活圈都挺狹小的,不太認識其它領域的人。

    AI的部份,之前在企劃製作一款梭哈遊戲時遇到了很大的瓶頸,也是一年來第一次接觸實際的AI,所以一整個不曉得怎麼辦…過去都是用簡單的判斷式,但是以博奕來說,這樣又缺乏變化性,所以最後沒有完成Orz

  4. 我欣賞遊戲的構思和實作的完整程度。雖然說是Prototype,郤做得像成品。要學習。

    人家是七整天做一個遊戲吧,十六天工餘時間也不容易,再次佩服半路的勤奮。

    不知道這遊戲大約需要多少行 Lua 代碼實現呢?Framework又有多大呢? 想參考一下。

  5. 一樣身為遊戲人的我
    對你記欣賞又佩服,還有些羨慕,
    目前在公司做一款算是自己喜歡的專案,
    但在公司限制與怪意見就是多…,
    而且還有搞死人不償命的公司文化!

    自己出來搞遊戲的念頭從來沒段過,
    不過我是企劃…自己搞必須有錢..
    不然就是有夥伴>”<
    在不然就是自己要會程式….(自修自修)
    一起加油吧

  6. 哪個筆記很讚,我手邊也有很多這種類似sketch的東西,不過礙於領人薪水,就不能亂分享了~

    很多人想看遊戲製作的過程,這算是一個不錯的小原型:)

  7. @Rich:
    所以說,跟美術做好朋友真的是很重要的事啊。 Q_Q

    等等,不對啊,你明明自己就會畫圖,而且還畫得很好。我想應該是分身乏術而不是素材不足的原因吧? XD

    @lsk:
    有!很久之前在逛你們家部落格的時候,就有玩過《爸爸寶衛戰》,現在才知道原來你們也有類似的想法概念,真是太巧啦~

    「可是那個寶寶從遊戲來到我們的真實生活後,我就沒力氣去動flash了… = =」哈哈哈哈哈,我大笑了。不過我覺得要照顧真實生活中的寶寶,可遠比製作遊戲來得困難太多啦。 ^^

    @Azusa:
    沒錯,如果和其他人合作的話,這份開發日誌應該會更加精彩。你提到了一項事實:「專業領域的生活圈都挺狹小。」我覺得真是一點也沒錯,可能我自己就是這樣吧,實在需要設法改進才行。 Orz

    如果只使用 if-else 或者 switch-case 做 AI 判斷,只要遇到比較複雜的邏輯判斷與狀態變換,寫到最後一定會炸掉。 (無誤)

    @Milo Yip:
    對了,我原來就想寫出來,結果寫著寫著就忘記了。感謝提醒! = =

    • Lua modules/components:約 2000 行
    • Lua gameplay code:約 1500 行
    • Lua game data:約 1300 行
    • C++ Framework:大約有 20 至 30 個類別左右,約 90% 類別裡的程式碼都不超過 200 行,只有 10% 的主要類別比較繁重。

    @橘子:
    謝謝,可以做自己喜歡的專案是很幸福的事情,無論如何也要堅持下去!

    在自己搞之前,我想與其一開始就花錢,倒不如先找到可以一起合作的好麻吉好伙伴才是正途啊~

    @梅添涼:
    公司的東西當然不能分享,不過阿涼應該有一些私人的設計草稿吧?嘿嘿嘿,或許可以考慮拿出來當作教材喔。 = =+

    @zii:
    謝謝,希望能多交流分享。 ^^

    @Percy:
    謝謝,不過只是可玩還不夠好玩,還得繼續加強才行。 ^^

    @Wallace:
    我覺得 Lua 實在是越用越有滋味。別說請教,就相互交流討論吧! :D

    非常感謝各位的熱烈迴響,接下來我要準備好好去度個假了,期望自己過完年回來之後,已經重新補滿了體力與能量。在此先預祝各位牛年快樂,在新的一年裡,每個人都能夠成為工作與專業領域上的牛人! ^_^

  8. 美術啊……,去開拓動漫祭找一個吧

    我在WKY做的dawn2程式目前還是基礎建設的階段,那位美術兼劇本現在也非常沒空,何時能完成很難說
    最近找到了可能合作的作曲者,就等那位夥伴抽空找他們談了
    我覺得自製遊戲最容易缺的是作曲,「四季樂章」這個俱備程式、美術、音樂人才的團隊是很有潛力的

    水晶守護者看了不太有興趣玩,等比較完整的版本出來再看看吧

    @Azusa:
    「可見專業領域的生活圈都挺狹小的」
    頗有同感,學問往往鑽得越深範圍越窄,一些大師的論點通常只在他那個圈子裡有用,拿到其他地方就用不著,所以我不會盡信大師。我比較敬佩能實際做出東西的人
    看到這裡再一次慶幸自己是從遊戲fan site和同人場起家而不是一開始就鑽研技術,不會有鑽牛角尖或領域過窄的問題

  9. @Shark:
    有自信是好事,希望你們的作品早日問世。

    @southp:
    你好,

    真是有夠巧的巧啊~ 現在想起來,還好我當初沒有打算做 Tower Defence 類型的遊戲。 XD

    懂 3D 美術又會程式設計很好!如果可以成為 Technical Artist 就更讚啦(招手)。請不用加大大,稱呼我半路就可以了,謝謝。 ^^

  10. 作得很好呢!!

    只是我沒有滑鼠用筆電玩不了T_T

    GOOD GAME

    不過很好奇是純用win32 api進行貼圖跟撥放音樂
    還是有使用什麼套件??

  11. @shell:
    沒有滑鼠呀……用觸控板玩的話,大概會玩到想翻桌。 XD

    底層是用 DirectDraw 和 DirectSound 來畫圖片和放音樂的。

    感謝支持。 ^^

  12. 看了此篇,也想自己做做看,不過C++不熟。於是再找找Lua是否可以做,還真的找到。Lua SDL(Simple DirectMedia Layer)套件就是開發小遊戲用,但沒有在Lua for Windows套件中。
    另一套LuaAIO(Lua all in one)中有含SDL,這套的函式庫更多,但無editor及debug界面。但對Lua進階user已是夠用。
    看來應是有機會全用Lua來實現類似的小遊戲。

  13. @Wallace:
    SDL 簡單易用,很適合做中小型遊戲!而且有了 Lua binding 會更加便於撰寫 Gameplay 的相關程式碼,我覺得你可以盡量嘗試看看喔~ :D

  14. @yokotachaos:
    原來你是多媒體領域的創作者啊~ 或許以後我們有機會可以合作唷!

    我逛了一下你的網站,提供一點小建議:在任何有背景音樂的 Flash 頁面中,如果能夠提供「開啟或關閉音樂」的選項,以及「調整音量」的選項,對使用者來說會更加易於親近喔。

    謝謝你的來訪。 ^^

  15. 介面做得不錯了耶

    Hey~你在台灣嗎?
    我也對遊戲開發很有興趣,雖然暫時還不能拿來賺錢吃飯
    因為平常很忙,之前只有用Irrlicht做Tetris的經驗
    之後沒做因為找人不收錢做美工很難,而且構想的遊戲要一個人完成可以能好幾年
    這樣太沒意思了,所以到處找人一起做沒錢收的遊戲開發
    我相信集合大家的力量才是王道,如果不嫌棄一起做的話就email給我吧

  16. @Maxi:
    你好,

    我人在台灣沒錯。不過最近我正陷於水深火熱的生活和工作 schedule 中,所以目前沒辦法在工作之外花很長的時間去製作遊戲。要憑一己之力開發遊戲真的十分困難,我想我們可以先聊一聊,交個朋友! :D

    我會再寄信給你,謝謝你的來訪。 :)

  17. 您好:)
    我是來自大陸的開發者,您的blog寫的非常有”活力”,難怪有如此多的fans XD
    看到此篇文章標題的Crystal Defence,我的第一反應就是SE iphone上的那款遊戲 囧
    很期待您的下一篇文章 :D

  18. @九思:
    你好,

    謝謝你的讚賞!我想這裡的讀者應該說不上是 fans 吧。而且比起所謂的擁護者,我更希望能夠聽到各種對於文章內容的討論與感想哩! = =+

    嗯,這款遊戲和 SE 社的 Crystal Defenders 完全沒有關連性喔~ XD

Leave a Reply