2011年3月6日 星期日

絕地-眾神之詛咒-2.研發瓶頸及突破

這兩篇絕地-眾神之詛咒的文章 2008/11 在 ChinaAVG 所發表的回憶錄, 當初花了很多時間寫的, 現在把文章貼回自己的 Blog 灌水, 主要是想用 Google 的 Blog 來備份文章.
--------------------------------------------------------------------------------------


本篇會講到在 絕地-眾神之詛咒 研發途中所遇到的難題以及技術上所發生的問題, 並且想辦法去解決它, 另外還會說明當時使用的一些工具及程式技巧, 可能會很偏向程式方面.

這些技術上的問題和現在來比似乎有點跟不上時代, 不過就在那個時期裡卻也是解決問題的方法, 若要以現在的技術再來處理相同的問題則會顯得相當容易, 無奈當時網路不發達, 製作遊戲的一些 Know How 也很缺乏, 因此很多東西都是慢慢摸索而來, 現在看了也許會為之一笑, 不過在當時可說是費盡所有的心思才有的成果.

先說說絕地所使用的程式語言吧, 最早開始全部都是使用組合語言, 因為我是學組合語言出身的, 第一套(也是前一套)遊戲也是全部使用組合語言撰寫; 絕地在後來才改用 Borland C 混合組合語言 (那時候才開始學習 C 語言), 不過因為 EMS 記憶體存取太過麻煩, 最後才又改用那時的當紅炸子雞 Watcom C (DOS4GW真是好物!!), 使用 Watcom C 後因為他的最化佳已經非常好了, 所以只有少部份的地方才要繼續使用組合語言, 比如繪圖相關, 與硬體溝通, 解壓縮...等等.

每個遊戲在製作時都會為遊戲量身訂做許多的工具, 絕地當然也不例外, 初期每個工具都是各自獨立, 一直到快接近中期才將所有的工具整合在一起. 現在看起來是不怎麼樣, 不過在 DOS 時代裡一款工具所有的東西都要自己 DIY 才行, 很麻煩的, 和現在 Windows 的環境真的不能比.



(圖: 整合後的工具主選單)


抓圖工具 :


絕地中所有的圖形都是經過抓圖工具抓下後轉檔過, 因為美術給的圖都是一大張, 所以就要把他們分別抓成一小張, 以上圖為例就是一個小女孩的部份動作圖.





這個抓圖有一個方便的功能, 以上圖為例, 要抓小女孩 20號的圖形時, 只要用滑鼠拖拉一個大概的矩形之後, 工具就會過濾透明色, 然後把矩形一直縮小, 一直縮到有抓到非透明色為止, 然後該框框就是圖形真正存檔的大小, 如此一來就不必把眼睛貼在螢幕前一個點一個點慢慢的去對準. 上圖小女孩頭頂上的號碼就是圖形要存檔時的流水號. 透明色可依不同的圖設定, 有吸管可以直接在底圖上吸取顏色, 不用在色盤裡找.


動作編輯器 :
當角色的圖抓完後, 就把該角色的所有的圖形串成一個檔, 然後就會依這個檔去編輯該角色的動作, 而流水號就是識別該圖形之用, 本來是有打算做個串檔的圖形用流灠的方式選擇, 因為時間因素就沒加入.

動作檔會存入一些播放角色應該要有的資訊, 如圖形代號(流水號), 座標...等等,
每個角色都只有一個串好的圖檔, 動作檔則有很多個, 不同的動作檔則有各自的檔案, 如走路, 說話...等等.

如下圖, 就是編輯一個小女孩的動作連續圖, 其中畫面中央的十字線是定位點, 這定位點也就是在遊戲中角色的中心點, 所有角色的圖形都是以這個中心點去做秀圖的偏移; 在工具中, 這定位點可以隨意調整位置以方便編輯.







絕地做完後接著要做下一個案子, 下圖就是新案子的動作編輯器, 檔案格式延續絕地的使用, 不過畫面由 320x200 提升為 640x480, 所以就順便把工具全部改寫.






場景編輯器 :
當絕地做完後我才想到, 似乎忘了寫場景編輯器, 所以絕地是沒有場景編輯器的.....每次想到這件事都會很...囧...., 所以場景上的前景座標都是先在抓圖工具上記下座標, 然後寫死在程式裡的, 就連事件觸發座標也是, 我真的覺得我當時很呆, 怎麼會漏了這工具, 然後居然也沒想到要做...

---- 我 --- 是 --- 分 --- 隔 --- 線 ---

還有一些其它的工作, 如批次轉檔, 串檔...等等, 不過因為沒圖形化所以就不多做介紹, 下面開始就來說明一下在絕地中所使用到的各種技術, 以及當時碰到的一些難題. 而所有的問題都有一個共同點, 就是程式的效能問題, 要讓遊戲能夠跑的順暢, 畫面的禎數 (Frames Per Second) 要有一定的水準才行, 因為 286 CPU真的不快, 所以每個 CPU指令的時間都要能省則省.


前景與背景 :
第一個面臨到的就是前景與前景之間、前景與角色之間的秀圖順序關係, 因為當時沒有場景編輯器 (腦殘...), 再加上美術給的前景圖很狀觀, 所以有花了一點時間解決這問題, 最後是用圖形的最底部 Y 座標做排序來決定秀圖的優先順序 (即圖層).





















0號色壓縮 :
後來因為場景越來越複雜, 前景也越來越多, 因此畫面的禎數有些降低, 覺得這樣不行要想辦法解決才行; 巧的是當時因為興趣關係所以就有在研究 3D 繪圖 (純軟體 3D, 那時候還沒有 3D 加速卡), 就在看到三角形的填充與紋理貼圖的時候, 我的頭頂上忽然亮起了一顆電燈泡!!

兩條任意夾角的直線所形成三角區塊, 可以使用水平填充法來達到快速填滿兩條線所產生的區塊, 2D 的前景也差不多如此, 就像三角形的某個角一樣透空, 如果用這水平填充法來填充有顏色的前景應該就會很快, 就這樣, 絕地的 0號色壓縮法就此誕生, 而且效果出奇的好, 也想盡辦法來讓資料達到最小化, 並且速度最大化;

這 0號色壓縮在絕地發售一年後也有在國外做遊戲的書籍上看到類似的技巧, 也許絕地不算是首創, 但也至少算是跟得上時代吧. 呵~

這技巧為效能帶來了突飛猛進的提升, 所以那時候就和美術說前景不用切的太細, 效能的問題我已解決, 前景可以不用切割的那麼辛苦...等等, 結果...美術的前景就越畫越多, 而且越來越大塊, 其中有個場景最誇張, 實在是太難忘了..., 如下圖.










說真的, 當時看到這樣的圖我都傻掉了, 不過這不能怪美術,  因為沒有企劃規劃, 所以絕地的場景完全是由美術 Free Style 創作, 背景 (其實可以再切小張一點) + 2 大前景 + 一小前景 + 天空 + 流動的雲....., 0號色壓縮就算再強, 這樣的玩法也受不了, 所以這場景在有 0號色壓縮的情況下還是會有點遲頓, 最後的結果是, 0號色壓縮秀圖的程式碼全部改用組合語言撰寫才解決了這問題.

為了讓0號色壓縮的效能更好, 0號色壓縮的秀圖還分了有裁剪與沒裁剪兩種.


文字的編碼 :
前一篇提到絕地要打國際市場, 所以在文字上必須要能夠符合各國不同語言的需求. 那時候 Unicode 的技術還並不成熟, 所以不同的國家語言就必須要使用專屬的編碼方式, 再加上每種語言的字型大小, 斷行方式等等都不一樣, 而且文字與場景相疊時, 為了能看得清楚因此還必須描邊, 光是描邊一個文字就要再多畫四次, 然後還有文字對位, 對齊畫面邊緣...等等, 如此一來光是畫文字就會耗費不少的效能, 而且可能還要依不同的語言做調整, 經過深思熟慮之後, 最後決定所有的文字都使用圖形的方式呈現.

為此還寫了一個工具, 就是將文字檔的文字, 依不同的編碼將文字轉換成圖形, 並且可以依需求做不同的控制, 如大小, 描邊等等, 然後再使用抓圖工具抓取成 0號色壓縮的圖形.





起初中英文版是使用抓圖工具方式將一句句文字使用手工的方式抓圖, 後來因為文字量很大, 就特地寫了一個專門自動抓圖的工具, 在轉換文字檔成圖形時, 一段文字就轉成一張圖形, 然後再使用自動抓圖的工具自動抓取並轉檔, 這些工作後來使用批次檔的方式將程序自動化.


資料壓縮與檔案串連 :
在資料的壓縮上也費了一些工夫, 因為絕地的場景, 過場動畫, 文字等等都是圖形, 而且因為當時軟碟版還是主要的市場之一, 另一方面也是為了要縮減讀取硬碟資料的時間, 所以挑選了一個解壓速度快且壓縮率也還不錯的壓縮演算法 (LZSS 演算法), 並且將解壓縮的核心使用組合語言全部改寫, 讓這即時解壓縮的效率更加的好.

另外, 為了有效管理檔案, 也避免開啟檔案過多及過度頻繁因而造成效能上的降低, 還特別寫了一個串檔程式, 將所有的檔案依照需要的分類串連成幾個檔, 不過因為圖形本身就已經有壓縮過, 因此在串連檔案時就不需要另外再壓縮.


路徑搜尋與景深 :
冒險遊戲另一個重要的技術就是路徑搜尋, 當時並沒有所謂的 A* 演算法, 而且市面上有關人工智慧的書籍都過於理論化, 所以路徑搜尋只好靠自己, 當時為了這個也是花了一點時間才解決不會被卡住的路徑搜尋, 使用的方式是障礙法 + 遞迴的方式, 應該是有點類似迷宮鼠的那種方式吧, 不過因為效能問題有費了一些苦心, 如逆向搜尋...等等.

光有路徑搜尋還不夠, 因為絕地的場景是有景深的, 因此人物走到深處時必須要縮小, 為此還寫了一個 0號色壓縮的無段放大縮小功能.





如上圖, 因為絕地沒有場景編輯器, 所以絕地的場景可行走路線是使用圖形的方式來表示. 一張是場景圖, 另一張則是路徑圖; 這路徑圖包含了很多資訊, 除了表示可行走的區域之外, 還包括了滑鼠游標移到畫面邊緣或某個地方時, 滑鼠游標就會變成方向指標或是禁止通行的指標; 另外可行走區域的顏色也表示不同的意義, 比如人物在遠景的縮小比例, 在這個場景路徑圖中還有一種特別的資訊, 當人物走當陽光下時 (路徑圖藍色系區域), 人物還會變亮, 也就是光源及陰影的資訊, 不過有這種光影資訊的場景並不多.






光有這樣還是不夠, 以上圖為例, 這樣的路徑搜尋並不完美, 因為景深所以人物會縮小, 所以當人物變小時, 如果人物走路的步伐 (座標偏移量)沒有隨著比例縮小的話, 人物在畫面上就會呈現劇大的偏移或跳動現象, 因此在路徑搜尋的演算法裡還必須依照現在的座標去找尋路徑的縮放比例, 然後依著比例去縮減移動單位,並且計算下一個路徑的位置;

上面這花園是在絕地中唯一有可能會出現路徑搜尋缺陷的場景, 因為在水池轉角處 (四個角落)的空間不夠, 步伐很不容易踏過去, 因此有可能會造成人物在原地不動, 演算法一修再修也沒辦法, 這也是我唯一沒辦法解決的場景; 這場景當然不是最糟的路徑場景, 某些場景的路徑可以用『細』來形容, 解決方法就是在可以接受的範圍下把路徑加粗.

這個路徑與景深的演算法現在已有更好的方式來解決, 只是當時做遊戲的資訊太稀少, 因此能想到的也只有這個方法而已.

順便一提, 所有的路徑圖都是我自己畫的, 因為只有我知道哪些顏色代表著什麼意義, 我當然是有想過請美術畫, 不過美術的工作量已經很大了, 再加上絕地的美術實在是太 Free Style, 我會怕....


數學與特效 :
絕地裡某些特效用到了數學, 比如說某些場景的畫面扭曲特效是使用三角函數, 還有旋轉...等等, 那些都是即時演算的.

其中最特別的特效應該算是溶合效果 (Dissolve), 所謂的溶合效果就是兩張圖形重疊, 一張圖慢慢的出現, 另一張圖慢慢的消失, 兩張圖還會互相的重疊, 並且還可以同時看見兩張圖以半透明的效果相疊在一起, 這效果以現在的 3D技術可以輕易的實現, 就算是 2D也好, 在 high color(多彩) 或 true color(全彩) 模式下也可以輕易的實現, 因為頂多是把兩個點的 RGB 值套個公式算出一個新的  RGB 值丟進記憶體而已.

可是這樣的效果在 256色的色盤裡就不是那麼容易了 (把其它顏色扣除實際上還不到 256色), 因為 256色色盤是固定的, 所以顏色不是說變就變的, 否則畫面其它的圖形的顏色就會亂掉. RGB 值的範圍是 0~ 255, 所以一共是 256 x 256 x 256 = 1677216 色的變化, 就算以傳統的抖色技術方式來做也不好看, 而且效能又差, 不要忘了, 那時候的 CPU 還很慢.

這個效果本來是另一位程式同事在寫他的案子時所實作出來的, 效果是不錯, 但是效能實在是太差了, 宛如放幻燈片一樣; 不過這效果很炫 (以當時來說), 所以那時我也想把這效果給做進來, 有請教他技術原理, 不過實在是太複雜了, 也太理論化.

那時因為美術同事的關係, 所以我很喜歡和同事看看市面上美術作品的畫冊, 或是美術的相關書籍, 在一個偶然下翻到一頁有關於色彩學理論, 那一頁還有一個色空間的圖形, 燈燈!! 我頭頂的電燈泡又亮了起來!!

沒錯, RGB 若使用三維來表示色空間的話, 就正好形成一個正立方體, 而 256 色就正好散落於這正立方體的各個地方, 因此當你要取得任何一個顏色時只要去尋找最接近 256 色的其中一個顏色即可.

最佳的演算法當然不是即時的去算出哪個 RGB 最接近 256色中的哪一個, 而是使用程式預先算好並建立一個大的表格 (Table), 當 RGB 為多少時, 該表格的欄位值就是 256 色中的某個索引值, 但是這立方體太大,  256 x 256 x 256 = 1677216, 當時 DOS 640k 的記憶體 (當時 1M 的記憶體已普及, 現在是 1G 很普及...) 根本不夠放這個表格, 後來想到把色空間壓縮就好了, 經過多次的試驗之後, 終於找到一個理想值, 就是64 x 64 x 64 = 262144, 顏色的表現不錯, 記憶體也很省, 不過因為壓了 1 / 4, 所以在做溶合時, 兩張圖所算出來的 RGB 最後值就要除以 4, 這樣才能正確的對應到正確的表格中.

這效果被用在很多地方, 如人物的半透明, 人物的光影, 場景煙塵的半透明, 飛翔動畫的溶合效果 (用DosBox 模擬玩時效果會有點不好, 這幕會有點延遲)....等等, 最早的版本在皇宮的地板上及某些場景的水裡都還有用半透明做人物倒影效果, 不過後來因為與前景遮罩關係有點突兀或是不搭調所以就拿掉這效果.


滑鼠游標 :
最早以前的滑鼠游標是使用軟體游標, 所以滑鼠有點不順暢, 那時玩了很多國產遊戲甚至外國遊戲都有這現象, 不過在凱蘭迪亞傳奇裡滑鼠游標卻出奇的順暢, 後來才知道他們使用了硬體滑鼠游標的技術, 找了很多資料後也終於解決這個問題, 不過還是有個小問題無法解決, 所以在遊戲一開始才會有這個畫面提示 (後來想想, 這問題應該很容易解決, 只是當時沒想到)



(圖: 上圖的紅色字 『系統偵測中...請不要移動滑鼠』.....現在看了都會想笑....呵~)


音樂音效 :
音樂音效播放與驅動程式最初也找了很多方案, 不過都不是很好, 後來看到很多外國遊戲都使用一套叫 Miles Sound System, 因此公司才買了這套系統, 並且也用在其它專案中. 這套很好用, 一直到現在都還有人使用, 並且還跨不同的平台. 當時這套系統還支援了我的 GRAVIS ULTRASound  Max (開心).


最後, 再補上一些當初的漏網之圖, 因為一些關係並沒有做進遊戲中.



(圖 : 上面兩張圖是初期版本的開場圖形之一, 後來使用靜態 3D 圖形取代)


P.S. 如果你有玩過絕地, 你有沒有發現 絕地-眾神之詛咒 是使用倒敘法在說故事呢?




(圖 : 上面兩張圖是初期主角進入絕地的最初場景, 由傳送門進入水裡以倒影的方式在水中出現, 水上沒有實體, 後來取消了)


(圖 : 這是當初要做溶合倒影效果的場景之一, 不過因為美術沒有切割桌子當前景, 所以倒影會在桌上, 因此作罷, 這只是取消特效的其中一個原因)
.