2008年9月的員工旅遊。
出發第一天,關西休息站。
嘉義酒廠,啤酒配香腸,錯誤的開始。(豪華晚餐就因為這樣而吃不下....)
遊樂場裡有90%是公司員工,公司員工有80%在遊樂場裡。做這一行的還真是容易預測行蹤。
2008年9月的員工旅遊。
出發第一天,關西休息站。
嘉義酒廠,啤酒配香腸,錯誤的開始。(豪華晚餐就因為這樣而吃不下....)
遊樂場裡有90%是公司員工,公司員工有80%在遊樂場裡。做這一行的還真是容易預測行蹤。
今天做了一件偉大的事--我花了三個小時去排隊看米勒畫展! 三個小時哪! 偉大吧!
畫展本身並不大,展場也很小,畫作據說只有五十一幅,不過,真的很棒。偉大的畫作,值得我花費三個小時去排隊,也值得我忍受展場裡面擁擠的人。
再想一想,如果要去法國看,花的時間可絕對不止三五個小時!
我對這些美術畫作其實並不懂,還好有個語音導覽可以租借,可以讓我從看熱鬧的人升級到看一點門道。所以我才能說,很棒,真的很偉大。
語音導覽是蔣勳老師解說的,我就像是上了一堂課一般,從那個時期的時代背景,巴比松畫派的起源,米勒的簡易生平,畫風演變,然後才到那幾幅知名的『拾穗』、『晚禱』,不但是收益良多,如果再加上自己一點想像力來想像當時的生活與情景,那真的會有一點的感動的。
為什麼以前學校沒有這種課程啊? 還是我根本沒認真上?
請了半天假,排了三小時的隊,腳已經快練成『鐵腿』,但是,一切都值得,不後悔........
這一篇,算是整理我自己的設計思路。
簡單來說,這功能是讀取資料流裡面的資料,然後產生相關的物件,包括遊戲中的物件,以及引擎核心的物件。當然免不了的,是必須放在多執行緒的環境中來進行,我們不能讓遊戲在進行中的時候,還要停下來等待讀取。
我做了個「不正式的」UML順序圖。
幾個主要的步驟是這樣:在讀取之前,先做一些清除物件列表的事情,然後一個一個物件讀取,讀取完了,再對於這些讀取到的物件,連結它們的從屬關係。物件的產生是由物件的Factory函式來負責,Stream讀取了物件的Type Info之後,根據物件的類別呼叫對應的Factory函式。
物件的Factory函式要做幾個工作:產生新物件、將物件加入到Stream的物件列表中、讀取物件的內容資料。
在多執行緒的環境下,這樣的流程是沒有太大問題的,只要負責讀取的Stream不是各個執行緒共用的就好,而實際上也沒有必要這麼做。
但是遊戲中有幾種物件,資料量很大,很佔用記憶體空間,在設計上,我們必須讓這些資料變成共享的資料以節省不必要的記憶體浪費。而這些物件,在上面的流程裡,就會出問題了。
我用兩個不同的Stream,放在不同的執行緒裡,同時讀取一個共享的Object。由於物件的Factory函式中,並不會產生兩個獨立的Object,而是分享同一個Object,所以在讀取物件的內容資料時,就很容易發生資料打架的Race Condition。
為了解決這個問題,我又多開了一個執行緒。姑且叫做「共享資料專用執行緒」。這個執行緒的唯一工作,就是負責讀取這些共享物件的資料內容。執行緒會把工作存放在佇列中,一項一項的依序處理,這樣一來,資料打架的問題就不會再發生了。
當然,除了共享資料的物件之外,其他的物件也可以把讀取工作交辦給這個執行緒來做,不過我並不打算這麼做,因為這些物件並沒有資料打架的問題,沒有必要多花費一道手續跟時間,而且對這個專用執行緒來說,這麼多物件都交給它讀取,太操了...
沒事,寫個書上看來的小Trick。
Windows API有一個 GetLastError()函式,可以取得前一次呼叫API的Error Code,我們用 Visual Studio跑程式的時候,可以在”Watch” 視窗中,輸入 ‘$err,hr’ (錢號err逗號hr),就可以得到當時的error code...
很方便...而且顯示出來的訊息還是中文的...
以下關於Prototype模式的內容,是屬於我的理解,如果你們有不同的想法,歡迎來討論。
上圖是設計模式的書裡頭,Prototype的架構圖。
但是我覺得這是一個容易讓人誤解的架構圖。Prototype的精神不在於架構,而在於方法,也就是那個 Clone 函式。
舉個例子,網路遊戲玩過吧,裡面有很多怪物讓你打死來練功。程式裡面,怪物是怎麼產生的?
Monster* monster=new Monster();
monster->setName("Kill Me");
monster->setHP(100);
monster->setType("Animal");
monster->setPosition(100,100);
monster->setSkill("Flee");
這樣,我們有了一隻HP 100,動物形態,名字叫做"Kill Me",會逃跑的怪物。
那麼,如果在這個場景裡面,要30隻怎麼辦? 用個迴圈,把上面的程式碼重複跑30次。但是這樣做,有點笨又沒效率。
另外一種方法就是,複製這隻怪物。在怪物類別裡增加一個Clone函式,把自己的所有屬性,包括名字,HP,形態,技能等等,都設定給複製出來的新怪物。這樣的動作,都在類別內完成,效率會比較好些,同時對於外部的應用程式來說,只需要呼叫一個 Clone 函式,哪一天如果怪物又多了個新的屬性的時候,外部應用程式是不需要修改的,只需要在怪物的 Clone 函式裡,再加上複製新屬性的程式碼就好。
Monster* Monster::Clone()
{
Monster* clony=new Monster();
clony->m_Name = m_Name;
clony->m_HP = m_HP;
clony->m_Type = m_Type;
clony->m_Position = m_Position;
clony->m_Skill = m_Skill;
return clony;
}
這隻原始的,用來複製的怪物,就是一個 Prototype。
至於最上面的那張圖,我的想法是,我們可以做一個叫做Prototype的抽象類別,裡面只有一個函式 Clone ,需要做複製的類別,可以藉由繼承 Prototype 抽象類別取得共同的介面,然後,當然,還是要實做自己的 Clone 函式。 Prototype 類別可以做為判斷可否複製之用。ConcretePrototype1, ConcretePrototype2 可以是怪物,可以是花草樹木,可以是車子,可以是八竿子打不著的物件類別,它們之所以繼承 Prototype 類別,純粹只是告訴應用程式說 -- 我這個物件是可以複製的。
卸任的阿扁繼續出包。
這幾天,抖出來阿扁他們家在瑞士有好幾億台幣的外匯帳戶。這次阿扁很快,馬上就出來道歉了,說是選舉結餘款。然後又依照慣例斷尾求生,說不關他的事,是家裡人弄的,他後來才知道。不過,這次的尾巴是吳淑珍。
另外一個阿扁的慣例咧,就是再往另外一個政黨身上扯。這次也沒少就是了。
我對這些說法是很懷疑的,邏輯上怎麼講也講不通。如果是光明正大的公共用途,這麼愛台灣的阿扁與阿珍,為什麼要把錢存到國外去? 又為什麼戶頭要開在別人的名下?
不過,這件事對我們來說,是壞事也是好事。
壞事不多說了,一個前任總統被外國扯出洗錢疑雲,已經夠丟人現眼了。好事咧,至少以後沒哪個做官的敢到瑞士洗錢了吧?
hmm......搞不好以後用更高明的手法.......
這次寫的東西是18禁。
前幾天租了一部片子--『Live殺人網站』。我並不愛看恐怖片,只是這部片子的故事很有創意。劇情是,有個極聰明的兇手,設了一個網站, 實況轉播對被害人的虐殺過程,而且,越多人點閱觀賞,被害人就死得越快。
虐殺的手法要講嗎? 喔,好吧。
第一個手法是,將被害人砍幾刀讓他流血,然後注射『抗凝血劑』(這個,我前一陣子才在CSI裡面學到過...),隨著點閱人數越來越多,抗凝血劑就注射越多,被害人因為血液沒法凝固止血,最後變成大量失血而死。
第二個手法,是用很多很多盞高熱量的照明燈,將被害人『曬』死。第三個被害人是FBI的探員,被兇手抓來泡在水缸裡慢慢的加硫酸,越多人看轉播,硫酸加越多...
犯案要有動機。兇手因為自己的父親自殺時,被人拍下了影片在網路上到處流傳,才會想,好,既然你們這麼愛看,就讓你們看個夠!!
虐殺過程是恐怖還加點噁心的,不過最恐怖的還是這個殺人的創意設定。一個被虐殺的影片,實況轉播,如果是你,你會去點閱嗎?
我們在網路上,什麼沒有,閒來無事的朋友最多,心血來潮就流傳一下,一時好奇就去點閱看看,說真的,我一定會收到這樣的轉發,點閱嘛....我看是忍不住,好奇心百分之百會獲勝.....
然後就成了幾十萬個殺人共犯之一.....
想到就心裡發毛...