2008年12月29日 星期一

The Bucket List

前幾天看了一部片子,片名是 "The Bucket List",意思是死前的願望,中文把片名翻譯做「一路玩到掛」,很聳動,但是我覺得很糟糕,所以,還是用英文片名來記錄這部片子。

bucketlist

傑克尼克遜演的是一個億萬富翁,艾德華柯爾,事業很大,擁有好幾家醫院。摩根費里曼演的是一位汽車技工,卡特錢伯斯,雖然是個藍領黑手,但是知識淵博。

這兩人的相遇,是在癌症病房裡,兩人同住在一間病房中,就在艾德華擁有的醫院。

卡特曾經擁有很多夢想,卻因為生活現實無法實現。艾德華則是沒有夢想,只知道經營龐大的事業。兩人同住一間病房,相處久了自然發展出一些友誼。

就在一天,當兩人知道自己的生命已經來日無多,準備面對死亡時,卡特寫下了"The Bucket List",像是"大笑到流淚", "開古董跑車", "登喜馬拉雅山看景觀"這些人生願望。平常遊戲人間的艾德華,也寫下了"高空跳傘", "刺青", "親吻一個全世界最漂亮的女孩"的願望。

卡特問說,「這個願望你要怎麼達成?」

艾德華說,「找很多漂亮的女孩來各親一下。」

於是兩個只剩下六個月生命的病友,結伴旅遊,在生命的最後的一年半載,為自己而活,實現他們最後的人生願望去。

兩人四處旅遊,埃及金字塔、中國長城、泰姬瑪哈陵都走了一遭。唯獨喜馬拉雅山山頂因為天候的關係而放棄。

電影海報中的兩人笑得很燦爛,不光是因為實現了願望與夢想,也因為在這旅程中找回了一生中最快樂的時光。

卡特回到了家人的身邊,回到了平凡的生活,在平凡的家庭中拾回了他的快樂與人生。

艾德華幾經掙扎,也終於與久未聯絡的女兒見上面,擁抱親吻了第一次見到的外孫女,親吻了一個「全世界最漂亮的女孩」。

電影的結局,也是最後一個願望。

兩人的骨灰共同放在了喜馬拉雅山的山頂。

2008年12月24日 星期三

魔鬼終結者

767_200803100423125irul

昨天晚上開始,電視播放魔鬼終結者的電視影集。

故事是從電影第二集之後開始,莎拉康納解決了終結者,同時天網的設計者(我真的忘了他叫什麼名字啦,只記得是一個黑人演的)也自我犧牲了之後,過了幾年平靜的生活,莎拉還嫁了人。

然後故事繼續。電影第三集告訴我們,天網還是會存在,所以天網派了其他的終結者前來,繼續殺掉約翰康納的任務。未來的約翰康納也不甘示弱,派了一個少女外型的機器人保鑣回到過去保護他自己。

(我覺得這樣真好,如果是我,我也會派個美女來,而不是像阿諾的那種肌肉男....)

昨天看了兩集,還滿好看。

只不過我有一事不明,電影的第二集,終結者不是已經進化到液態金屬機械人了,為什麼後來派的還是像阿諾那種型號的機械人啊? 天網也是越來越退步了喔?

啊....電視影集成本比較小咩....

抓了幾張海報圖片當作紀念....

 

148ad319442cb7 148ad3411459d1

2008年12月17日 星期三

遊戲中的特效系統

在過去,我們將遊戲中的特效,分為兩種類型。一種我們稱之為「模型特效」,基本上它就是個美術製作出來的3D模型,只是我們將它用為特效物件上。另外一種,就是「粒子系統」所呈現出來的特效。

particlesgs

過去我們在設計的時候,「粒子系統特效」交給誰來設計製作,一直是一個很困擾的問題。粒子系統沒有一個固定的3D模型,只有一堆的運算參數。程式設計師根據這些參數,去計算每個粒子隨著時間的變化,所以裡面牽涉到不少的數學運算。

程式設計師非常清楚這些參數在數學上的意義,也明瞭調整這些參數對粒子系統的影響,所以,似乎交給我們來設計各式各樣的粒子特效是個不錯的主意。

但這樣一來,這個特效就很可能不好看。例如上面那張單調的煙火特效。畢竟,程式設計師並不是美術設計師。

可是交給美術設計師來製作設計的話,我們要做的第一件事,並不是設計一個很好用的粒子系統編輯器工具,而是 -- 教他們「數學」。

不要鬧了。

所以,有一段時間,我們的粒子系統特效一直是程式設計師在製作。不過,只是做些小特效,比較炫麗、華麗的魔法招式特效,還是交給美術設計,用模型特效來做。

最近我們發現,我們的美術設計師在3dsMax這些建模工具裡,也能夠把粒子系統摸索得很熟練,呵,這是個好機會,讓我們脫離設計難看的粒子特效的好機會。

於是我們做了一些研究,修改3dsMax exporter plugin,將美術在3dsMax中設計的粒子系統輸出,取得一些參數,然後運用這些參數,在遊戲中想辦法模擬出3dsMax的粒子運算。

這麼一來,所有的魔法招式特效,都可以交給美術設計師來製作設計,甚至於,還能夠設計一個華麗的模型特效,再搭配一些粒子特效做點綴。遊戲中的特效就會變得很吸引人。

==============================================

其實,遊戲中還有第三種類型的特殊效果,是運用「Shader」所做出來的效果,例如場景光暈、光線的散射、折射、反射等等。還有像底下這張圖,在「魔獸世界」裡,掛點以後所看到的畫面。

wow_dead

這類型的特殊效果,就真的必須由程式設計師來設計了。

2008年12月11日 星期四

場景管理與通道

遊戲中,隨著劇情跟內容的進行,遊戲場景也會一場一場的變化。遊戲場景大大小小不同,龐大的遊戲場景,可能會有數千個物件在其中,而在網路遊戲的場景中,除了物件之外,可能還會有數百個玩家在其中。

但是我們視野所見的範圍,只是龐大場景中的一角,我們所見到的物件或是玩家,也只是附近的一小撮而已。數字上來說,可能只有十幾二十個物件、七八個玩家,相較於整個場景,只是一小部分。其他大部分場景中的物件與玩家,不管他們發生了什麼事,都是千里之外的事情,我們看不見,也不需要知道。

所以,我們需要場景管理(Scene Management)。

場景管理的最大用處,是能夠用很快的方式,找出視野範圍內的物件,也就是我們需要關心的物件。一般來說,會先將一個場景空間分割成小區塊,把每個物件放在它隸屬的小區塊中,然後再用一個樹狀結構將區塊組織起來,像是二元空間分割(Binary Space Partition, BSP)、四元樹、八元樹等等。

接下來的動作就是,我們可以知道視點在哪個區塊中,視野包括了哪些區塊,然後就只需要處理這些區塊中的物件就好。

通道(Portal)系統則是另一個在場景管理中的工具。

我們在場景裡有一棟房子,我們站在房子外的時候,房子內發生了什麼事,我們是不需要知道的,同樣的,在房子內的人,也看不到房子外。只有門打開的時候,透過大門,房子內外的人可以彼此看見。這個大門,就是所謂的「通道」。

房子是場景中的一個封閉空間,也是一個獨立的區塊,我們站在房子外,除非透過「通道」,否則看不見房子內部。也因為這樣,只有在「通道」進入我們的視野內的時候,我們才需要處理房子內的人和物。

這麼一來,繪圖效能與計算效率都可以提昇。

請看取自「魔獸世界」的這張圖。我站在旅館的外面,左邊站了一個衛兵,右邊有另一個女性NPC,當然旅館內的物件跟NPC是看不見的。這個旅館的造型設計也是完全為了通道而設計的,門口進去一點點,就橫著一道牆,所以我們就算是這樣面對著門口,也還是看不到裡面的狀況。

WoWScrnShot_121008_214101 

第二張圖,是在旅館內,身後站了兩個女NPC。我們看不到外面。

WoWScrnShot_121008_214255

我在這兩個情形下,抓了兩張線框模式的圖。

WoWScrnShot_121008_214116

WoWScrnShot_121008_214301

線框模式下,看得很清楚,在旅館外面的時候,旅館內的NPC,完全沒處理。在旅館內的時候,更簡略了,連外面的場景都沒處理。

2008年12月3日 星期三

感謝艾達瑪指揮官、感謝六號複製人

如果你手邊也有「魔獸世界--巫妖王之怒」的說明書,請翻到最後,工作人員名單的部分。

前幾天,隨手亂翻的時候,突然在工作人員名單裡看到這麼一個人:

瘋狂科學家 Joe Rumsey

呵......Blizzard又開始搞怪了。

網路上查了查,原來這位仁兄是魔獸世界的伺服器主程式。

繼續往後面看,後面有一些工作人員寫的感謝狀,感謝爸爸媽媽啦,感謝家人啦,感謝雙胞胎女兒啦,感謝女朋友啦......

有一個感謝的是,"My Moon Pie"。

感謝一個派要幹嘛?

然後又看到,

Admiral William Adama

MV5BMTUzNTUxODA4NV5BMl5BanBnXkFtZTcwODQwNTE2MQ@@._V1._SX100_SY133_

Number Six

200px-Number_Six_Tricia_Helfer

我說,感謝這兩個人要幹什麼呀?

感謝艾達瑪指揮官也就算了,感謝六號複製人要做什麼? 難道這遊戲也跟塞隆人有關係?

還有人感謝的是別人家的廚房,"Cho’s Kitchen"。這擺明就是常常去搭伙。

還有人感謝的是這個人,"Cao Cao",KOEI出的三國志在還沒中文化之前,這兩個字就是「曹操」。

我意猶未盡,把前一個資料片「燃燒的遠征」說明書拿出來翻,也有搞笑的感謝狀。

“Paul Young”

“The Korean BBQ crew” (常常吃韓國燒烤就對了)

“i and o” (這絕對是程式設計師寫的)

“Every Gnome I’ve ever killed” (這...)

================= 感謝分隔線 ================

最近我們也在想感言要怎麼寫,我想,我還是老老實實的感謝父母親對我這個不務正業的兒子的支持吧!

2008年12月1日 星期一

CSI在我面前採指紋!!

其實這是在家裡遭竊之後,不得不然的苦中作樂跟自我安慰。

前幾天晚上,回家的時候發現門打不開,當時還想說可能是鎖壞了。找了鎖匠來,鎖匠卻說,這是被反鎖了。

反鎖? 怎麼可能? 沒人在裡面啊....

百分之八十的機率就是遭竊了。

開門之後,家裡一團混亂。兩個鎖匠還拿了「傢私」防身才進門。竊賊當然是已經不在了。

拜CSI影集之賜,我們沒有馬上清點失物,而是保留犯罪現場完整,趕快報警。

波麗士大人幾分鐘之內就趕到了,不過是個菜到不能再菜的菜鳥警察。他看了看現場,打電話請鑑識組的學長過來採證。

等這個CSI就等很久了,菜鳥警察臉色越來越尷尬。

CSI學長一直不來,菜鳥波麗士就一直被我們小老百姓逼問。

「是不是我們這個案子太小不想辦啊? 」

「是不是我們小老百姓沒背景沒關係不想辦啊?」

小警察也被逼得一直道歉,一直幫學長找藉口。

終於,將近一個小時之後,CSI來了。

台北市整個行政區,只有一個CSI在值班,前面的案子還沒弄完,所以才會讓我們等這麼久。

如果是真的,警察的人力就真的是少得太過分了。

(我家的案子還沒弄完,CSI就又接到一通車禍現場要去採證的電話了)

首先呢,CSI先把犯罪現場拍照,每個房間的凌亂樣子都拍了下來,還有疑似竊賊的出入口。然後在房裡找了一些可以採指紋的東西。

採指紋必須是表面光滑的物品,而且這個用來採指紋的粉末,是洗不掉的有毒重金屬。所以傢俱是不能拿來採指紋的,只能找一些可以丟掉的東西來做。

採證之前,還要請住戶簽個同意書。

所以說,CSI影集都在亂演。最好是什麼亂七八糟的東西都能採指紋。

那個CSI刑警說,可以是可以啦,但是要送到美國的高檔實驗室去做,這費用,誰出啊?

小老百姓就還是算了吧。

最後呢,找了幾個東西來採指紋,就在我家裡當場做。

CSI影集看那麼久,這下真的看到CSI就在我面前採指紋......

還有點興奮哩,真是奇怪的心態。

CSI大人弄了幾分鐘,最後只發現「編織物」的紋路(大人說,這樣講就夠專業),就是戴著一般的那種棉布工作手套的紋路。

CSI大人說得很酸,現在應該沒有那種偷東西還不知道要戴著手套的竊賊了吧!

其實我們也知道,不過該報警,該採證的還是要做,搞不好碰到個一時疏忽,忘了戴手套的竊賊也說不定。

2008年11月27日 星期四

莫戈莫戈大王

我在北風凍原的簡易機場上。

有個地精告訴我,「這是最怪的事,德魯伊,有個魚人在請求我們的幫助!」


「他被稱為莫戈莫戈大王,冬鰭魚人的頭目。看來似乎他和他的人民被趕出來了,他們想要有人來保住他們的村落。」

我心想,「魚人頭目? 魚人什麼時候變成NPC了啊? 你確定是那種成天哇嗚哇嗚亂叫的魚人嗎?」

地精沒作聲了,我招喚出我的座騎霜紋豹,偷看了一下攻略上的座標,跑過去冬鰭魚人的避居地。

OMG!!

91088 91089

「這....這就是魚人大王??」

我忍住笑,開始跟莫戈莫戈大王閒聊。

原來大王不是魚人,是愛好自然的塞納里奧遠征隊的一員,原本穿上這身打扮是為了要就近研究魚人生態的,卻沒想到碰上了冬鰭魚人遭逢大難,一時心軟伸出援手,就這樣被奉為大王了。

我轉到大王身後,「大王!您的愛心內褲露出來了啦!」

EPC2

大王說,冬鰭魚人的洞窟被一隻龍蝦人克拉希穆司占領了,有一部分的冬鰭魚人也因為龍蝦人的邪惡魔法而發狂。大王教了我魚人的語言(不就是哇嗚哇嗚的亂叫嗎?),派我衝進洞窟解救被俘虜的小魚人。

有經驗值跟裝備可拿,那還有什麼猶豫的?

花了幾分鐘,小魚人救出來了,大王又跟我說了件秘密。

「我有件羞於承認的事:我被勒索了!」

「最好是啦!」我嘀咕著。

「姆姆戈莫同意替我清理一些物品,並找到了我的備用魚人服裝。他威脅要將我的真面目揭穿給其它魚人知道。」

我傻眼了。

「我不需要跟你解釋這會是一場多嚴重的混亂吧!」大王咕噥了一聲,「除此之外,我有個計畫得要把那套服裝拿回來。」

「然後?」

「拜託,請你前往避居地另一頭的北邊找姆姆戈莫,並答應他的要求,不管是什麼樣的要求。」

我想問,「為什麼要我去?」不過為了經驗值,還是走了一趟。反正沒幾步路。

往北走了幾步,看到這個一臉卑鄙樣的姆姆戈莫。

92276

「噢,你一定就是人稱莫戈莫戈大王僕人的那個人吧。我猜是那個夜精靈派你來安撫我的?」

「我才不是什麼僕人,有什麼事就快說吧!」

我被姆姆戈莫使喚去殺了一隻大虎鯨,交換回了莫戈莫戈大王的備用服裝。

姆姆戈莫還不忘記威脅兩句,「很好,只要你們的國王繼續協助我們對抗敵人,他的秘密就不會有洩漏的危險。」

我啐了他一聲,把備用服裝拿回給莫戈莫戈大王。

「該是結束這種違反自然情況的時候了。」 大王說道,「為了讓冬鰭魚人能夠有個未來,克拉希穆司必須死!」

「我要你帶著我的備用魚人服裝,以投降當藉口混入冬鰭洞窟。拿著白旗,魚人就不會攻擊你。」

「要我詐降? 一路殺進洞裡不就得了? 士可殺不可辱啊!」

「你要不要經驗值啊? 照我說的做。」 大王說道,「你可以在洞窟的西南邊最角落處找到他。一旦你靠得夠近,就解決掉克拉希穆司。」

我照做了。

穿上魚人裝,走向魚人洞窟。還好沒在吃泡麵,不然鐵定會笑著把麵打翻。

這魚人裝走路的樣子太搞笑了吧? 跳起來還會跌倒咧!

(後來才想到,我應該把這件魚人裝留起來的)

我穿著魚人裝,舉著白旗,一路走近龍蝦人。解任務的人很多,地上已經躺了兩隻龍蝦。

沒多久,殺了龍蝦人,我回到莫戈莫戈大王那兒。大王給了我經驗值,也任我選了一件裝備。

「謝謝你所提供的一切幫助。隨著克拉希穆司被擊敗,也許我們可以重新結合剩餘的魚人,封鎖那些洞穴。」

到現在還是為著冬鰭魚人著想,大王真是太偉大了,好感人。

不過沒時間傷感了,我招喚霜紋豹,繼續找經驗值去。

至於莫戈莫戈大王什麼時候才能回到塞納里奧遠征隊,我就不知道了。

============= 回到現實的分隔線 ===============

遊戲,就是要有趣。「魔獸世界」裡的這個任務串,讓我從頭笑到尾。一個很衰的生態觀察員,一個會勒索主人的清潔工,再加上一件很搞笑的服裝,害我笑了一整晚。

2008年11月24日 星期一

今天真是一整個好運到爆

今天是一定要記錄一下的。

SEGA野球這個遊戲,從看了銀狐的介紹以後,就一直玩到現在,算一算好幾個月了,也打了五年十幾個球季。

這遊戲不需要我花很多時間,每天只要抽一抽球員卡,調整一下球員陣容,然後就可以下線,讓球隊在伺服器裡自己去比賽。(非常適合上班族) 戰績好的球隊呢,會從菜鳥聯盟升上小聯盟,再升上大聯盟,戰績不好呢,就會往下降。

我的球隊這幾個月來,始終龜在小聯盟,距離大聯盟總是差一歩,期間還有一次不知道為什麼戰績超爛被降到菜鳥聯盟去。(結果在菜鳥聯盟好威啊,有史以來頭一次拿到聯盟冠軍)

終於,在昨天開始的第六年第三球季,我的球隊升上大聯盟了。(雖然是吊車尾,但也還是升上去了....)

只不過這一升上去,球員太弱的缺點馬上顯現,第一次碰到空間太充裕、球員不夠放....搞得我一開季就三連敗....

今天咧,照慣例又來抽球員。本來只是當做每天的例行公事,一點也沒打算補強球員(也沒什麼球員可補強就是了),但是就在這個時候,棒球之神顯靈了。

噹的一聲,第一張就是傳說版的球員卡,不是郭泰源,不是陳大豐,也不是野茂英雄。不管他。除非給我郭泰源,否則SEGA別想賺我的錢。

然後....

一張Cost 10的球員卡出來了....拉米瑞斯.... (哇..今天真好運..頭一回抽到Cost 10的球員..)

然後....

一張Cost 8的球員卡出來了....赤星憲廣....(不會吧.. 又一張.. 今天是怎樣..)

然後....

一張Cost 6的球員卡出來了....平野惠一....(蝦咪.. 今天會不會太賽了?? 平常抽到Cost 6就已經很滿足了,今天跟著Cost 10, Cost 8的後面出來,是在搞笑吧?)

十張抽完,大滿足!!

這下子,應該可以在大聯盟多撐兩個球季了吧....

2008年11月21日 星期五

遊戲中的腳本語言

這幾年,越來越覺得遊戲內的腳本語言(Script Language)是一個必要的東西。尤其是遊戲越做越大,越做越複雜,沒有個理想的腳本語言實在是沒辦法應付這樣的需求。

在以前那個一切都還很美好的時代,遊戲也很美好,也很簡單,我們不需要太複雜的腳本語言。簡單的一個文字檔,寫下NPC的ID,起點的位置,終點的位置,然後我們就可以控制NPC,讓他在場景裡從這邊晃到那邊,再從那邊晃回來。

沒有人會嫌這隻NPC很單調。

不過時代不同了。

大概在半年多一年以前,我們的遊戲有個需求,我們需要在人物技能的Tool tip上,顯示各種技能在攻擊與防禦上的影響,而這些影響會跟著人物屬性數值變化。遊戲企劃給了一些公式,大概都是把屬性數值拿來加減乘除算一算。

於是我們的程式設計師很認真的開始分析這些公式,希望可以找出規則,產生出個表格,然後用一個函式搞定所有技能影響的計算。

如果你也是這麼想,那就表示你對遊戲企劃的了解還不夠深。

這規則只有神仙才找得出來。

於是我們開始引入腳本語言。

過去我們曾經研究過lua。lua名氣不小,而且自從「魔獸世界」的UI系統與它結合並且利用它發展出一整套的Addons之後,名氣更大。不過,我們選擇的是Squirrel

Squirrel,松鼠。不知道作者為什麼要取這個名字,它的Script檔案,附檔名是nut,就是給松鼠吃的堅果。很幽默。

Squirrel的作者據說是Far Cry這個遊戲的程式設計師,他們在Far Cry這個遊戲中原本是使用lua,所以骨子裡的程式碼是跟lua很像的。

好,回到我們的技能Tool tip。

舉個例子,有一個攻擊技能,會根據人物的力量屬性計算傷害加成,公式是這樣:

傷害加成 = (力量數值) x (技能等級+5) / 100

遊戲程式可以很簡單的把這個公式寫進程式中。但是隔沒幾天,任性的遊戲企劃來改公式了,於是程式設計師把這一小段程式改寫。又過了幾天,覺得這個技能太強了,又改公式,程式設計師又動了一次刀....

然後是無窮迴圈。

把這些公式的計算,開放在腳本語言中做計算,讓企劃可以自行修改,我們就能夠擺脫任性企劃的糾纏。

程式中的寫法當然不同了。

上面的傷害加成公式,是寫在Script中,腳本語言提供一個函式給遊戲程式呼叫,傳回傷害加成計算的結果。

function GetDamageModify()
{
  return PlayerStr() * ( SkillLv() + 5 ) / 100;
}

PlayerStr(), SkillLv()是兩個由遊戲程式提供給腳本語言呼叫的函式,分別會傳回力量屬性數值以及技能等級。

這兩個函式是額外寫的,腳本語言沒有強大到可以直接呼叫遊戲程式中的函式。我們必須將提供給腳本語言呼叫的C/C++函式,用腳本語言所能理解的方式再包裝一次,腳本語言才能使用它們。

這個包裝的過程,lua跟Squirrel叫做Bind。包裝的方法很繁瑣,也不容易理解。所以,有人利用Template寫出一整套的Binding工具程式庫。lua有luabind, Squirrel有sqplus。

RegisterGlobal(SquirrelVM::GetVMPtr(),&GetPlayerStr,_T("PlayerStr"));
RegisterGlobal(SquirrelVM::GetVMPtr(),&GetSkillLevel,_T("SkillLv"));

這兩行是寫在C/C++遊戲程式中,利用sqplus工具,將 C/C++ 的 GetPlayerStr(), GetSkillLevel()兩個函式,登記給腳本語言呼叫,在腳本中的函式名稱分別是 PlayerStr() 與 SkillLv() 。

這樣套入之後,我們與遊戲企劃就開始分工了。程式設計師需要做的,就是定義與實做這些提供給腳本呼叫的函式,至於公式的內容,就讓遊戲企劃自己去處理。

============= 時間的分隔線 ===============

話說,幾個月之後,遊戲製作人決定要重新檢視一遍所有幾十個技能的設定,同時調整所有的計算公式....

程式設計師笑了....

2008年11月7日 星期五

我是傳奇的異塵餘生

fallout-wp8-800x600

200px-Poster_of_I_Am_Legend

有沒有?

兩張圖有同樣的味道喔?

一個人跟一隻狗,走在同樣是廢墟的道路上。背著一把步槍。

看到「異塵餘生3」的這張圖,第一個讓我想到的就是「我是傳奇」這部電影。電影是有點單調沉悶,反倒是電影海報讓我印象深刻。異塵餘生這款遊戲呢,說真的,我不是很喜歡這種帶著恐怖的遊戲,更何況遊戲的戰鬥進行方式還是類似FPS的戰鬥方式。我在FPS連線遊戲中只有一種角色,槍靶子。所以在異塵餘生這個遊戲裡,也是很慘。

我需要Cheat Code…

(圖片取自網站)

2008年11月5日 星期三

全世界最有權力的黑人

art.obama.historical.gi

(圖片取自CNN網站)

雖然嚴格說起來,歐巴馬是混血的非裔美國人第二代,但這依然是歷史性的一刻。不僅僅是美國歷史,也應該是世界歷史中的一筆。

最近在閱讀美國史(中文翻譯啦,英文閱讀能力還沒有這麼高..),我想可能很快就要改版了,要把歐巴馬的這一場歷史意義加進去才行。

曾經在電視上看過一次歐巴馬的演講,非常的撼動人心,尤其是一再強調的一句”Yes, we can.” 連在地球對面,跟這個選舉沒什麼關係的我,都可以感受到震撼。

說實話,無論是演講技巧還是聽眾情緒拿捏的功力,我們台灣的這些人物實在是差太遠了。

一兩百年前,黑人是隸屬於主人的「財產」,是在市場上買賣的「貨物」,現而今,雖然還沒就任,但已經產生了一個即將是全世界最有權力、最有影響力的黑人。

今天,見證到了一個歷史。

2008年10月31日 星期五

程式碼是給人讀的

不是給機器看的。

Code Complete書裡面如是說。

這本書,繁體中文的書名叫做「軟體建構之道」,大陸那邊就照字面翻譯,叫做「代碼大全」。就像電影"The Day After Tomorrow”,一邊是比較有意境的「明天過後」,另一邊是標準翻譯的「後天」。

好,閒話不講。

最近玩了幾天反組譯工具程式,複習組合語言的時候,突然想到這句話。

然後想到我一直把它當作是程式碼的「文言文」的這個語法:

int a1=rand()%20;
int a2;
a2 = (a1>10)? (a1-10):(a1+10);

這段程式,我寧願把它寫的比較「白話」一點:

int a1=rand()%20;
int a2;
if (a1>10)
{
    a2=a1-10;
}
else
{
    a2=a1+10;
}

你說,為什麼一行可以寫完的東西偏偏要改成多了幾行? 我說,因為容易看懂。

另一個原因,容易Trace Bug。第一個code sample裡,你怎麼trace? 怎麼做中斷? 怎麼知道這個條件究竟有沒有成立?

更不要說我常常忘記究竟是問號還是冒號放前面,究竟是 true : false 還是 false : true。

第二個code sample裡,你就絕對不會誤解我要表達的程式意義,我也絕對不會懷疑我是不是又把 true, false寫反了。

至於給機器看的是什麼? 第一段程式編譯出來的結果是這樣:

; 50   :     a2 = (a1>10)? (a1-10):(a1+10);
  000d7    83 7d fc 0a     cmp     DWORD PTR _a1$[ebp], 10    ; 0000000aH
  000db    7e 0b         jle     SHORT $LN9@wmain
  000dd    8b 55 fc     mov     edx, DWORD PTR _a1$[ebp]
  000e0    83 ea 0a     sub     edx, 10            ; 0000000aH
  000e3    89 55 c4     mov     DWORD PTR tv69[ebp], edx
  000e6    eb 09         jmp     SHORT $LN10@wmain
$LN9@wmain:
  000e8    8b 45 fc     mov     eax, DWORD PTR _a1$[ebp]
  000eb    83 c0 0a     add     eax, 10            ; 0000000aH
  000ee    89 45 c4     mov     DWORD PTR tv69[ebp], eax
$LN10@wmain:
  000f1    8b 4d c4     mov     ecx, DWORD PTR tv69[ebp]
  000f4    89 4d f8     mov     DWORD PTR _a2$[ebp], ecx

 

而第二段程式碼編譯出來的結果,像這樣:

; 50   :     if (a1>10)
  000d7    83 7d fc 0a     cmp     DWORD PTR _a1$[ebp], 10    ; 0000000aH
  000db    7e 0b         jle     SHORT $LN8@wmain
; 51   :     {
; 52   :         a2=a1-10;
  000dd    8b 55 fc     mov     edx, DWORD PTR _a1$[ebp]
  000e0    83 ea 0a     sub     edx, 10            ; 0000000aH
  000e3    89 55 f8     mov     DWORD PTR _a2$[ebp], edx
; 53   :     }
; 54   :     else
  000e6    eb 09         jmp     SHORT $LN7@wmain
$LN8@wmain:
; 55   :     {
; 56   :         a2=a1+10;
  000e8    8b 45 fc     mov     eax, DWORD PTR _a1$[ebp]
  000eb    83 c0 0a     add     eax, 10            ; 0000000aH
  000ee    89 45 f8     mov     DWORD PTR _a2$[ebp], eax
$LN7@wmain:
; 57   :     }

 

仔細看,文言文跟白話文的兩段程式碼,是一樣的作用,所以編譯出來的結果當然也是一樣的。既然是相同的,那為什麼不寫得讓人容易看懂些?

2008年10月26日 星期日

住了一週的小鳥房客

陽台藤蔓上的不知名小鳥,已經待了一星期了。

小鳥每天早出晚歸,生活非常規律。早上不知到幾點離開的,反正是我起床以前。晚上回來,大約就是下午五點至五點半之間。

週末這兩天,趁著天色還沒完全暗下來,總算把小鳥拍了清楚一點。

DSC00313

2008年10月22日 星期三

藤蔓上的小鳥

陽台的九重葛藤蔓上,前天晚上來了隻小鳥。

牠攀在藤蔓上,一動不動,我們也不知道牠究竟怎麼了,不敢驚動牠。

隔天早上,小鳥不見了,看來是飛走了,我們擔心牠受傷還是怎麼的,顯然是白擔心了。

晚上下班,小鳥回來了。

好像是把陽台的藤蔓當成了棲身之所。

我看機會難得,拍了相片。

DSC00311

DSC00312

我知道我需要專業的相機,可以拍夜間特寫,但是光有專業相機,沒有專業技術還是不行,所以還是算了,拿個數位相機,就這麼拍吧。

(偏偏陽台外有一盞亮到不行的大路燈,數位相機的拍攝模式調來調去,好不容易才調出個能夠照出樣子的模式來)

今天早上,小鳥又飛走了,不知道晚上還會不會回來?

2008年10月8日 星期三

Proxy : 不只是設計模式

proxy

Proxy是一種設計模式。Wiki上是這麼說的:

A proxy, in its most general form, is a class functioning as an interface to another thing. The other thing could be anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.

不過今天的內容跟這個沒太多關係。

最近碰到一個狀況。

我們在遊戲場景裡頭產生了很大量的物件,大約五千個吧。由於程式結構的關係,並沒有利用動態的方式管理這些物件,以致這五千個物件使用了很大量的記憶體,必須要想辦法節省下來。

第一個想法當然是把這些物件改成動態管理,需要的生成,不需要的就釋放掉。不過這麼一來,物件生成的順序、物件之間的關聯性、相依性,就造成了很大的困擾。我們必須從核心程式去調整,甚至在資料方面都必須一起修改。怎麼算,都是一個不小的手術,大概是半身麻醉的等級。

就在我塗塗改改,畫著結構設計圖,想著要怎麼調整程式結構的時候,突然間,Proxy出現了。

我將這些物件套用Proxy結構,把物件之間的關聯性和相依性,保留在Proxy物件中,占用比較大量記憶體的資料部分,就改用動態的管理。需要的時候,由Proxy物件來產生,用完了,也從Proxy物件去釋放。至於Proxy物件呢,就像原先的程式結構一樣,遊戲場景裡放了五千個。

於是乎,物件生成的順序不需要調整,物件之間的關聯性、相依性不需要調整,核心程式也不需要動大手術,只需要在這些場景物件上,把Proxy模式導入。

所以Proxy不只是設計模式,它還成了一種改善程式品質的手法。

不過,最後實做的結果又不太一樣了。

因為原來的物件裡面,早已經將資料部分分離出來,所以我只是修改了幾行程式碼,改成動態的取得資料以及釋放資料。

搞了半天,如此而已..

2008年10月7日 星期二

程式設計者的笑話

http://www.workjoke.com/programmers-jokes.html

這個網站裡頭,有一些關於電腦、程式以及程式設計者的笑話。會去找這種網站,主要是因為我在GDC的會議上聽了一場演講,演講還沒開始的時候,投影片就先撥放了一頁一頁的笑話,看得是台下數百個身為程式設計師的聽眾個個心有戚戚焉,也就博得了滿堂彩。可惜,雖然後來下載到了演講內容的投影片,但卻只有嚴肅的演講內容。

我不知道那位演講者究竟是哪裡收集來的,那麼多讓人會心一笑的笑話,我也就只好自己Google了。

網站裡頭的笑話,有些落落長可是卻不怎麼好笑的,有些呢,倒是滿經典。像是這個..

- "Have you heard about the object-oriennted way to become wealthy?"
- "No..."
- "Inheritance."

還有..

There are three kinds of lies: Lies, damned lies, and benchmarks.

(所以說,benchmark都不能信任啊..)

The programmer to his son: "Here, I brought you a new basketball."
"Thank you, daddy, but where is the user's guide?"

還有這一句..

Bugs in your software are actually special features.

微軟的名字是哪些字的縮寫?

MICROSOFT: Most Intelligent Customers Realize Our Software Only Fools Teenagers

有一段,標題是Software Development Cycle,雖然也是落落長,但卻是我們的辛酸血淚史..

網頁上你還可以看到一個表格,列出來Drug Dealers與Software Engineers有些什麼不同。Drug Dealers說,"The first one is free.”, Software Engineers說,"Download a free trial version”,是啊是啊,免費試用版就是吸引你上癮的啊!

2008年10月1日 星期三

VC中的系統符號檔

嗯,今天跟大家介紹個工具。

先來一段小程式片段。裡面有一個故意弄的Bug。

HANDLE hFile=CreateFile(…);

CloseHandle(hFile);
CloseHandle(hFile);

我把檔案關了兩次,所以在執行的時候,就會crash,call stack看起來像是底下的圖。

callstack_nosymbol

程式死在kernel32.dll, ntdll.dll 這些系統 dll 裡面,啊..束手無策..

接著我對VC做了點調整,加了些東西,crash 時候的 call stack 變成這樣,

callstack_withsymbol

咦? Kernel32.dll 裡的 CloseHandle() 當掉?

這個調整很簡單,打開 VC選單的Tools->Options,然後照著以下的設定,

vc8_symbol_setting

切換到Debugging裡面的Symbols項目,在symbol file locations填入 http://msdl.microsoft.com/download/symbols,接著在cache目錄的欄位,指定一個要存放pdb檔案的目錄。

設定好了之後,重新開始debug程式。第一次執行程式,會很花時間,因為這個時候,VC需要先下載程式用到的每一個系統dll檔的符號檔 (symbol file, *.pdb),放到設定的cache目錄中。

然後在程式當掉的時候,call stack就會多了這一些資訊。

要把這個功能關掉的話,就在上面的這個設定畫面,把symbol file locations的打勾選項都取消掉,也不要指定cache目錄。(硬碟裡面的檔案都還會留著,下次不用重新下載…)

2008年9月24日 星期三

時間換空間,空間換時間

標題這句話,是程式設計裡頭進行最佳化(Optimize)調整時的最終圭臬。不是唯一的方法,卻是全世界通用、軟硬體通吃的最後一招。

所以寫程式的人都沒什麼才華,弄來弄去,只剩一招。

最佳化調整通常有兩個目的,一個是增加程式的運算效能,另一個就是節省程式的資源使用。我們需要減少運算時間的時候,就用查表的方式、建立快取(Cache)的方式,拿空間換時間;需要節省記憶體空間、硬碟空間的時候,就改存放比較簡單的資料、壓縮過的資料,再花時間用演算法計算。

不過,不管怎麼樣,這都是最後一招。意思是,在我們將能夠調整的都調整過了之後,才能使用它。如果有一個比較快速的演算法可以改善程式的運算效能,我們就還不能使用這最後一招。畢竟這一招是需要付出代價的。

舉個很簡單的例子講。我們需要做一個計算從整數A累加到整數B的函式。看到題目,我們很快的寫了一個迴圈來做累加的計算。然後我們將這個函式做最佳化。不需要查表,不需要快取,不需要任何用空間換時間的方法,只需要一個很簡單的梯形面積公式。Sum = (B+A)*(B-A+1)/2。

好,我知道這個例子很蠢,但是概念很重要。

概念是,有比較好的方法可以改進運算效能、節省資源使用量的時候,千千萬萬不要只會想到時間換空間,空間換時間的最後一招。

我們最近進行了一個最佳化的任務--改善遊戲的資料讀取時間。

一開始,我們將資料讀取的工作修改為交給一個專門的執行緒來做,得到一部份的成果,只是還不夠理想。然後我們進一步的將資料分出優先順序,盡可能的將資料載入的時間點分開來,不要讓很多資料載入的工作集中在同一時間。但是這樣的改善成果也還不夠。

最後,我們發現資料載入的效能瓶頸,是出在將這些讀取得的資料轉換為遊戲內資料的過程,於是就施放大絕--拿空間換時間。我們將資料檔案做修改,改成存放已經轉換過的資料,載入的過程中不再需要做轉換,只需要很單純的將資料讀取到記憶體中就可以。效果很好,達到我們的理想需求,但是代價也很大--檔案容量膨脹了十倍以上。

問題來了。

這樣的檔案容量大爆炸,會影響到下載檔案的時間與頻寬,還有,搞不好安裝光碟會從一片DVD變成兩片,成本大增。於是我們又想了個辦法調整。

我們將一部份的資料還原成轉換前的比較小的原始資料,然後做了個小程式把轉換資料的工作獨立出來。使用者下載與安裝的是容量小的原始資料,經過轉換程式轉換後,再存放到資料硬碟裡面。這樣,我們又拿時間來換空間,只不過這個時間並不是遊戲進行時的運算時間,而是檔案安裝與更新的時間。遊戲還是保持順暢,安裝與更新嘛…多花一點時間無妨的啦!

2008年9月17日 星期三

Spore : 向沙丘魔堡致敬

39003m

最近一個新上市的遊戲,Spore,很火熱。今天看到新聞說,已經登上全球的賣座冠軍。玩了幾天下來,突然有個想法--這是在向『沙丘魔堡』致敬啊!!

從頭說起。

Spore是製作模擬城市、模擬市民這一系列遊戲的製作人,所帶著的團隊所做的新遊戲。所以多多少少還帶著一些「模擬」系列的玩法與風格。 不過,讓人津津樂道的,是遊戲裡面的幾個可以讓玩家自行發揮創意的編輯器,包括 生物的編輯器、載具的編輯器、建築的編輯器等等。玩家製作出來的東西,可以上傳到伺服器來分享,然後就可能會出現在別的玩家的遊戲中,變成你的盟友或是敵人,呵...

ph_paintph_make

昨天有一篇報導,有很多很棒的作品...

承載所有玩家夢想 各式知名ACG人物於《SPORE》現身

我是沒什麼美術概念的人,所以這東西,基本上沒什麼在玩,不過倒是下載到了其他人所做的東西來欣賞讚嘆一下。

除了這創意編輯器之外,遊戲本身分成幾個階段,從最渺小的一個單細胞生物,發展到生物階段、部落階段、文明階段、最後到太空階段。換句話說,這遊戲,是在模擬一個生物的進化。但是遊戲還是遊戲,生物的進化過程是根本不能模擬的,所以,除了最後的太空階段之外,前面的幾個階段都有過關條件,達到了就可以進入下一階段,一跳就是個幾百萬年的進化....

所以我就像玩一般的遊戲一樣,想辦法過關,花了幾個小時吧,衝到了太空階段。

80021

太空階段就回到「模擬」系列遊戲的概念了--沒有結局。玩家有一個星球,然後要想辦法在宇宙中生存,擴張自己的星際帝國版圖。你可以用軍事力量征服,經濟力量收購,或是用宗教力量感化,也可以就一步一步的,找無人的星球慢慢殖民,慢慢擴張。宇宙有多大,遊戲就有多大.....

到了這裡,我就把這遊戲當做『三國志』在玩了....哈...

殖民星球有幾個要素,
1. 改變星球的氣候與生態
2. 建立殖民地
3. 採集香料換錢

這...只要再加上『沙蟲』,就是『沙丘魔堡』了啊!!

2008年9月13日 星期六

2008 員工旅遊 之五

第四天,該回家了。廬山溫泉-->清境農場-->台北

DSC00213

離開廬山之前,來一張有圖有真相。

DSC00225

綿羊餵食。

DSC00231

喔...這隻毛毛蟲只是要測試新相機的數位變焦效果.....結果焦距好像對準到後面的葉子上了。

DSC00238

清境農場的7-11與Starbucks,以前是全台最高的,現在被阿里山上的打敗。據說,這整個建築都是7-11的...

DSC00245

關西休息站的黃昏。

貼完。

其實每一張照片都有我,相機後面的那個就是....

2008 員工旅遊 之四

第三天的後半段。

DSC00174

森林國家公園裡的樹林。

DSC00179

姐妹潭一隅。

DSC00201

到現在還是不知道為什麼星巴克跟阿里山站會黏在一起.....

DSC00209

這是南投信義鄉農會的一個酒莊,拼經濟的好地方。東西算有點貴了,但是包裝得很有質感,當伴手禮很適合。

DSC00211

呵....很可愛喔?

2008年9月12日 星期五

2008 員工旅遊 之三

第三天,阿里山日出-->廬山泡溫泉 (前半段,日出篇)

DSC00088

『半夜三點』的阿里山車站。(絕對要強調『半夜三點』)

DSC00091

等車中。

DSC00103

觀日平台的人群,時間--四點半。

DSC00121

太陽還躲在山後面,時間--五點。

DSC00143

五點半,還是躲在山後面不給人看。

DSC00147

五點四十,日出前。

DSC00156

五點四十六,終於等到了。(新買的相機效果還算不錯,相機厲害比拍攝技術重要)

DSC00171

這張,有前景、中景、遠景,還有光源....

2008 員工旅遊 之二

員工旅遊第二天,嘉義-->阿里山

DSC00053

現烤蚵。很燙。

DSC00065

沙洲上抓到的笨螃蟹(也不會躲好一點....)

DSC00074

奮起湖街上的7-11,樓下是便當專賣店。

DSC00078

奮起湖火車站。可惜火車頭躲到維修場裡了,沒看見。

DSC00082

古老的鐵道。

DSC00086

阿里山上,全台最高的7-11與Starbucks。