|
前言 目前這個引擎只是一個預覽版, 很多功能仍在開發當中 硬件需求: 顯卡支持ShaderModel3.0 作者Blog: http://flohofwoe.blogspot.com 用到的開源工程 為了避免版本之間的不兼容, 已經在SDK中包含 體系結構一覽 - Nebula3 分成三層, 每一層都是建立在另一層之上的:
- 基礎層: 最底層, 提供了一個圖形和音頻之下基本的平臺抽象. 基礎層可以用作任意類型的程序開發平臺, 而不僅僅是實時3D程序.
- 渲染層: 這是中間層, 它在基礎層之上另加了許多特性, 像3D渲染, 音頻, 物理和場景管理等.
- 應用程序層: 這是最高的一層, 提供了一個完整的游戲框架, 這使得開發人員可以集中精力在游戲邏輯上, 而不用對關心各種細節實現.
- Nebula3 會跟Mangalore 合為一個整體, Mangalore的各種子系統會集成到Nebula3的適合它們的層中去.
- Nebula3 比 Nebula2更趨向于使用C++.
- Nebula3通過引用計數和智能指針實現了對象生命周期的管理.
- Nebula3的新對象模型使用一個4 byte的基類來代替Nebula2中70+ bytes的.
- RTTI更高效, 更易用.
- Nebula3仍然不使用C++異常, RTTI和STL(所有這些不是降低性能就是降低便攜性).
- 根據類名來創建對象更快更易用.
- Nebula3 避免使用C Lib, 去除了附加的代碼層.
- Nebula3 使用LUA 代替TCL作為標準的腳本語言(當然也可以增加其它腳本語言的支持)
基礎層 - App 包含各種Application類
- Attr 屬性注冊
- Core Nebula3的對象模型
- Debug 程序內存轉儲和基于HTTP的調試信息(這個真是個好東西, 第一次聽說)
- Http 實現了HTTP服務器和客戶端, 這樣可以在瀏覽器中實時查看調試信息
- IO 輸入輸出系統, 很方便
- Math 基于C++的數學庫, 沒什么特別的
- Memory 實現了定制的內存分配器
- Messaging 消息定義
- Net 最基本的基于TCP協議的C/S架構, 更多的功能會在高層的網絡擴展中給出
- Scripting 腳本系統
- System 硬件平臺和特定操作系統相關的一些特性
- Threading 多線程
- Timing 時間/定時器管理
- Util 工具庫, 包括各種容器, 數據結構, 還有一個強大的string類(拋棄STL吧!)
渲染層 - CoreGraphics 圖形庫核心類
- Frame 基于幀的處理, 如RenderTarget, PostProcess等
- Graphics 一些實體類型定義, 如Camera之類
- Input 輸入設備, 就是鼠標鍵盤手柄…..
- Lighting 光照處理, 包括陰影算法(竟然要SM3.0@_@)
- Models 骨骼模型&粒子系統
- RenderUtil 目前就只有一個Maya的攝像機…..
- Resources 資源管理器
應用程序層 application_win32工程就是一個簡單的游戲, 框架, 但是已經包含了許多特性, 如果物理, 數據庫等. 不過好像還缺少GUI系統. 插件 目前有三個, 基于ODE的物理引擎, 基于SQLite的本地數據庫, 基于nebula2模型的骨骼模型系統 編譯 沒什么好說的, 打開.sln直接編譯就成了, 沒見過這么簡單的開源工程^_^ 就以這個程序做為測試程序的模板吧 1: #include "stdneb.h"
2: #include "core/debug.h"
3: #include "core/coreserver.h"
4: #include "core/sysfunc.h"
5:
6: using namespace Core;
7:
8: void
9: __cdecl main()
10: {
11: Ptr<CoreServer> coreServer = CoreServer::Create();
12: coreServer->SetAppName("Nebula3 Hello World!");
13: coreServer->Open();
14:
15: n_printf("Hello World\n");
16: system("pause");
17:
18: coreServer->Close();
19: coreServer = NULL;
20:
21: Core::SysFunc::Exit(0);
22: }

最近拿到SpeedTree資料,開始學習,并用到項目里去.
1. 該插件的特點: api無關。它本身只是數據結構和邏輯架構,沒有任何渲染語句子,因此為了把它應用到自己的引擎里,需要為之添加渲染相關的語句。而根據sdk的講解,推薦用戶為之搭建中間架構,用來聯系SPEEDTREE與自己的引擎。這樣做起碼有兩點好處,搭建的中間架構(也推薦別加任何api相關的語句),因此,即使你以后換了api(譬如從gl換成dx),中間架構還是可以繼續沿用的。還有一個好處就是,當speedtree更新版本的時候,你也無須修改你的引擎,而只需要修改相對簡單而且穩定的中間架構。
2. 該插件的具體特性: 注意,下面具體特性分析都是基于SDK里一個叫“DirectX9”的例子進行的,在這個例子里,它給出了最基本的使用方法,同時也向用戶展示了它的基本特性。 A. 樹的基本渲染 通過大場景的測試,DP的個數大致是樹木棵數的兩到三倍。詳細分析下,發現 它一棵樹分三部分繪制:樹干和大樹枝(branches),小樹枝(fronds),樹葉(leaves) Branches:使用模型來繪制 Fronds:使用兩個十字交叉的面模擬小樹枝,為了節省三角形。 Leaves:使用billboard方式繪制,這樣就能產生視覺效果比較好的葉子了。 它這樣劃分是出于以下三方面的考慮:這幾部分的渲染狀態不一樣,動畫的狀態不一樣,做LOD的時候也不一樣。具體看下面的介紹。 B. 樹的陰影系統 它包括兩方面的陰影。首先是樹干上的陰影。其次是整棵樹在地面的投影。 樹干的自陰影(self shadow)是預先生成的,至于生成的算法,可能是可以根據可穿透的光線跟蹤,也可能是結合shadow map的逐象素地生成光照貼圖(把樹干的面都展開后,在對應的地方畫上陰影).有了該光照貼圖,那渲染樹干的時候就可以跟樹干本身的紋理進行混合產生比較真實的效果。 而整棵樹在地面的透影子,則是使用一個矩形畫出來的,陰影貼圖也是預先生成好。渲染的時候浮在地面。 C. 樹的動畫 樹的三部分的動畫狀態都是不一樣的。這對優化有極其重要的作用。風小的時候,或是樹離眼睛比較遠的時候,可以不動樹枝,而只是動樹葉。而具體他們是怎么動的: 樹葉的動畫:就是一個billboard的來回平移以及他本身繞視坐標系統Z軸的轉動。 樹枝的動畫:通過它引擎本身計算出來的矩陣進行動畫。 而至于它具體怎么渲染動畫的,它提供了基于CPU和GPU的方法。 基于CPU的方法是:創建頂點緩沖的時候, 使用D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY標記(這種方法能提高CPU修改和更新該緩沖的速度),渲染的時候實時更新頂點位置。 基于GPU的方法是:通過自定義的頂點shader程序進行,更新動畫的時候,向shader傳遞常量數組。 D. 樹的光照 它可以打開和關閉實時光照,對于實時光照,樹干部分又分兩種情況,對于沒有法線貼圖的樹干,使用per-vertex的光照。而對于有法線貼圖的,則使用per-pixcel光照。至于給不給樹干渲染法線貼圖,則根據具體的程序決定。 而對于樹葉的渲染,因為它是一個billboard,因此也無法通過其法線來計算光照。它其實是根據這個 billboard的位置來確定其亮度的。通過把整棵樹當成一個球來分析,而每個billboard的位置就相當于是球上的一點,結合光的方向,計算出該點的亮度。 E. LOD的特點 其強大的LOD系統,為實現大規模的場景提供了有力的支持。這里的LOD分三方面:頂點的LOD,紋理的LOD,動畫的LOD。 (1) 頂點的LOD:首先是針對樹干,因為這里的樹干是實實在在的模型。至于樹干的建立,它里面是采用貝塞爾曲線來描述整個mesh的,貝塞爾曲線的描述方式無疑給即時高效率的LOD計算提供了可行性。同時這還針對樹枝,遠了之后,小樹枝就不渲染了。到了一定的距離的時候,整棵樹其實就變成一個billboard了。 (2) 紋理的LOD:樹干上在最高精度的時候會有三套紋理:基本紋理,光照貼圖,法線貼圖。隨著LOD的進行,可以依次減去法線貼圖,光照貼圖,最后是本身貼圖,最后只為樹干渲染一種顏色。 (3) 動畫的LOD:現在有三種動畫,大樹枝(模型)的動畫,小樹枝(兩個交叉面)的動畫,以及樹葉的動畫。隨著LOD的進行,依次去掉大樹桿的動畫,小樹桿的動畫,最后是樹葉的動畫。這也是符合視覺效果的。 F. 文件系統 用場景來分析的話,一個場景是.stf文件(Speed Tree Forest).該文件描述了每棵樹的相關屬性。而一棵樹是通過一個.spt(Speed Tree)文件來描述的.用文本編輯器打開,就能看到里面記錄了該樹的所有信息。而該插件為此開發了配套了樹木編輯器材。使用該編輯器,打開.spt文件之后,就可以對該樹進行瀏覽以及編輯。 3.Speedtree使用實踐 它提供給用戶的一個最主要的類就是CSpeedTreeRT.這是一個speedtree對外界的接口,從SpeedTreeRT.h中可以看到,這個類其實是包括了該插件的核心類.因此,我們在使用該插件的時候,其實全都是通過這個接口。 譬如CSpeedTreeRT::SetCamera(eye, viewDir),通知它內部現在的攝像機的信息,然后它內部就根據這些信息計算出正確的billboard. 而如何加載一棵樹呢?使用CSpeedTreeRT::LoadTree(const char *treefile);輸入一個”.spt”文件,然后我們設置光照和風效果的方法如CSpeedTreeRT::SetBranchWindMethod,SetFrondWindMethod,SetBranchLightingMethod,SetLeafLightingMethod, SetLodLimits等,接著執行CSpeedTreeRT::Compute(),然后它里面就開始進行黑盒處理,最后我們就可以獲取其幾何數據(CspeedTreeRT::GetGeometry)進行渲染。獲取之前還可以手動去設置LOD級別CSpeedTreeRT::SetLodLevel,然后你獲取到的就是經過LOD處理的幾何數據。 不過有一點需要要注意的是,speedtree里面用的是右手坐標系(盡管它說可以通過define Y_UP來改變坐標系統,但我沒發現define改了之后有什么變化,很奇怪)。筆者開始的時候完全沒注意到這點,發現搬到自己的架構后,樹全都是橫著的。當時死活發現不了問題,就去旋轉每棵樹。然后又發現那些樹葉也無法正常地旋轉成billboard,又查了很久。后來終于發現,是因為speedtree內部使用右手坐標系進行計算。而我的架構是使用左手,這樣一來,連傳給speedtree camera的數據都要修改了, CSpeedTreeRT::SetCamera(eye, viewDir),其中的eye,eyeDir,都得經過變換再傳進去: float3 viewDir=pCamera->GetViewDir(); float3 eye=pCamera->GetEye(); float afDirection[3]; afDirection[0] = viewDir.x; afDirection[2] = viewDir.y; afDirection[1] = -viewDir.z; CSpeedTreeRT::SetCamera(eye, afDirection); 4.把speedtree加到自己的引擎中去 以上所說的CSpeedTreeRT接口,筆者在使用的時候都是讓一個CSpeedTreeRT對象匯聚到自己設計的一個tree類里。通過這種方式來封裝speedtree,搭建中間架構。CSpeedTreeRT這接口也許多靜態函數,譬如SetCamera,參照它的DEMO, 直接“CSpeedTreeRT::SetCamera(eye, eyeDir);”但要實現完美地跟自己的引擎相結合,也并不是一件容易的事情。主要是,自己的引擎本來就有一套完整的渲染系統,LOD系統,動畫系統,而且跟speedtree的方式也不一樣。一個極端的做法就是,對于SpeedTreeRT,屏蔽其實時計算,而是根據自己引擎的系統計算,這樣的話, 其實是只利用了SpeedTree的數據結果了。而另外一個極端就是,不管 speedtree和自己引擎的關系,只保留簡單的耦合,各自使用各自的系統,只是讓他們的渲染行為(LOD,光照效果等)保持一致性。至于更好的辦法,筆者也是在研討中,我非常希望能跟讀者進行探討,這也是筆者寫本筆記的動機之一。
Game組成員超過Hack組,不過Game的大部分人都不認識,有的甚至沒有聯系過。 我的好友中還有部分Hack沒有聯系上,至少應該還有20名左右吧,實際上加起來應該還比Game組的多。 我的好友中大部分應該是搞過C++或WinSDK編程的,至少是學過編程。 懷念從2000年至今的編程學習生涯,這是第三個QQ了, 最早一個QQ上的人大部分現在都應該是大牛了吧,可惜偶還是小弟,悲哀之。 這么多年過去了,發現自己依舊是那么無知無畏。 人一生所尋找的也許就是腳下的路吧,這樣的人生才會意義。 這樣才過的踏實一點,去年跟一朋友來到福州,來這里做游戲, 等到實際工作中才發現游戲不比傳統軟件行業, 這里的人比傳統軟件行業時的人更有想法,但大部分都不切換實際,甚至弱智。 為一點所謂的利益搞來搞去,其實真正的利益在BOSS那里,因為BOSS付出了。 不付出是得不到回報的,搞來搞去只是在犧牲自己的腦細胞。 不堅持原則,不追求完美,不追求質量,不切合實際,不明確目標。 完美的程序員至少是個政治家,雖然我不完美,但我是政治家,不要和我玩政治。 這里沒有失敗,因為我們只是為BOSS服務的。 損害別人并不能得到什么,因為每個人都選擇的權利,因為和誰玩牌都一樣。 輸掉的只是大家的時間。 
The Release builds include optimizaed code, but with the NiMemory system, NiMetrics, and release mode logging enabled. The Shipping builds do not have these systems enabled. ship 和 release 工程設置基本相同,但沒有NiMemory、NiMetrics、release mode logging.更像是非常穩定之后的版本.
不可否認 選擇做程序員 源于真正意義上的興趣和喜歡 在做程序員的這幾年 我的生活也在一步步的提升 但同樣 不可否認 在我個人眼里 就像選擇其他種類的工作一樣 只是一份職業 一種在社會上存身立足的手段 現在呢 又在想 自己以前想過 大家也時不時的都會想 的問題 那就是 程序員的人生 將如何規劃 在校時 以及 工作后 都曾這么的想過: 做一個IT從業人員 做一個程序員 做上個一二年 然后 向上提升下 做一個項目經理 什么的 再然后 或許 開一家自己的小軟件公司 或許 做一名軟件顧問 再或者 開一個網站 開發一個自己的小軟件 或者 真的不行的 利用做程序員這幾年的積蓄 做一些小買賣 轉行 另謀生計 總之 感覺做程序開發將是人生的一個過渡 可若真的按這種思路一過渡 就將是用我人生的青春年華大好時光的五六年 或者更多時間 遺憾的是 至今 對這種付出后的收獲 我卻沒有把握 曾聽有人言(這一定是國人說的): 一年管理成富翁 三年市場路路通 十年技術一場空 這話每每想來 心里都不免有些低落 低落的不是現在 而是在現在看來 自己一兩年或幾年后的生活 沒有著落 沒有依靠 而那時的自己 或許做了項目經理 薪資在才做程序員的后輩們看來 已很是不低 但卻可能遠遠不夠日常生活的進一步開支 因為我們每個人每時每刻都有讓生活越來越好的念頭和目標 我們不想自己上去了 又下去了 不想自己 由前幾年剛畢業的 藍領代碼工人 好不容易辛苦努力才做到今天的 白領項目經理 接著卻因年事問題 薪資待遇問題 而淪為 房奴 車奴 我們不回避 人生將由 1.幼年-童年-少年-青年 2.成年-壯年 3.老年 這三段的劃分 也不忌諱自己真的有一點老不中用了 但我們不能容忍自己在 從三十歲到五十歲 這段時間里 碌碌無為 而現在 我們站在目前自己做程序員的角度 去看三五年后的而立之年 我們心里沒底 我們站在而立之年的程序員的角度 去看自己30-50的人生成熟和收獲的黃金時期 我們更多的可能看到的是灰暗和苦澀 那么 早知如此 何必當初 想問大家 也是在問自己 一句 程序員的人生 該將如何規劃? ( 希望成功的前輩們 能多多賜教 也希望有同樣思考的同輩們 能說說自己好的想法和規劃 或許 這個問題 不單單是屬于做程序員工作的同行們 也可能是屬于所有現在 沒有自己的事業 正在工作著的 各行各業的同志們 我思 故我在 沒有對明天的思考 明天的我 也許就沒有美好的未來 也許換種環境更好 比如出國 至少不會有職業歧視 至少技術與業務一視同仁 至少會認為每個人的工作同樣重要 ) *注:轉載,部分修改.
由于項目的原由最近接觸了很多優秀的項目,其中包括HTML排版引擎,以下對其做下簡單的介紹和比較. 現在瀏覽器的內核引擎,基本上是三分天下: - Trident: IE 以Trident 作為內核引擎。
- Gecko: Firefox 是基于 Gecko 開發。
- WebKit: Safari, Google Chrome 基于 Webkit 開發。
- Trident
Trident (又稱為MSHTML),是微軟的窗口操作系統(Windows)搭載的網頁瀏覽器—Internet Explorer的排版引擎的名稱,它的第一個版本隨著1997年10月Internet Explorer第四版釋出,之后不斷的加入新的技術并隨著新版本的Internet Explorer釋出。在未來最新的Internet Explorer第七版中,微軟將對Trident排版引擎做了的重大的變動,除了加入新的技術之外,并增加對網頁標準的支持。盡管這些變動已經在相當大的程度上落后了其它的排版引擎,如Gecko、WebCore、KHTML及Presto。 Trident引擎被設計成一個軟件組件(模塊),使得其它軟件開發人員很容易的將網頁瀏覽的功能加到他們自行開發的應用程序里。微軟提出了一個稱為組件對象模型(COM)的軟件接口架構。供其它支持的組件對象模型開發環境的應用程序(如:C++及.NET)存取及編輯網頁。例如,由C++所撰寫的程序可以加入瀏覽器控件里,并透過Trident引擎存取當前顯示在瀏覽器上的網頁內容及網頁的各種元素的值,從瀏覽器控件觸發的事件亦可被程序擷取并進行處理。Trident引擎所提供的所有函式庫可以透過與 mshtml.dll這個檔案的連結而達成撰寫程序時所需要的功能。 除此之外,微軟還有另一個網頁瀏覽器排版引擎,稱為Tasman,它是使用在「Internet Explorer for Mac」的排版引擎。相較于Trident,Tasman引擎對網頁標準有較佳的支持。與普遍的看法相反的是,微軟已經停止了麥金塔計算機版本的 Internet Explorer的開發,但Tasman的開發仍舊持續, 新版本的Tasman引擎仍被應用在一些微軟產品上,如:麥金塔計算機版本的Microsoft Office。 使用Trident引擎的瀏覽器有很多,比如Maxthon,騰訊TT,MyIE等等,但Trident只能應用于Windows平臺. - Gecko
Gecko是套開放源代碼的、以C++編寫的網頁排版引擎。目前為Mozilla家族網頁瀏覽器以及Netscape 6以后版本瀏覽器所使用。這軟件原本是由網景通訊公司開發的,現在則由Mozilla基金會維護。 這套排版引擎提供了一個豐富的程序界面以供互聯網相關的應用程式使用,例如網頁瀏覽器、HTML編輯器、客戶端/服務器等等。雖然最初的主要對象是Mozilla的衍生產品,如Netscape和Mozilla Firefox,現在已有很多其他軟件現在利用這個排版引擎。Gecko是跨平臺的,能在Microsoft Windows、Linux和Mac OS X等主要操作系統上運行。 Gecko是最流行的排版引擎之一,其流行程度僅次于Trident. 使用Gecko引擎的瀏覽器有Firefox, 網景(6至9), SeaMonkey, Camino, Mozilla, Flock, Galeon, K-Meleon, Minimo, Sleipnir, Songbird , XeroBank. -
WebKit WebKit是Mac OS X v10.3及以上版本所包含的軟件框架(對v10.2.7及以上版本也可通過軟件更新獲取)。 同時,WebKit也是Mac OS X的Safari網頁瀏覽器的基礎。WebKit是一個開源項目,包含了來自KDE項目和蘋果公司的一些組件。 目前使用WebKit 引擎的瀏覽器主要有:Safari(apple出品),Midori,chrome(google出品)等。 WebKit擁有清晰的源碼結構、極快的渲染速度。
現代游戲已經不能沒有聲音,所以音頻引擎成為游戲引擎中不可缺少的一部分.這是一篇介紹現代音頻引擎的文章(http://hard.zol.com.cn/labs/2003/0520/60986.shtml).FMOD音頻引擎(http://www.fmod.org)是一個非常不錯的音頻引擎,其使用也比較簡單,下面做一些簡單介紹: 一.基本準備 它是免費的,你可以從它們的主站上下載API等文件.之后,你需要添加頭文件和庫文件,如下(C/C++): fmodvc.lib 用于 Microsoft Visual C++ 和 Codewarrior fmodbc.lib 用于 Borland fmodwc.lib 用于 Watcom fmodcc.lib 用于 LCC-Win32 libfmod.a 用于 MingW and CygWin fmod-3-7.lib 用于 GCC (參考:http://www.gamedev.net/reference/articles/article2098.asp) 之后,只要添加fmod.h頭文件后就可以使用了. 二.開始使用 1.初始化 開始播放聲音前,需要進行初始化,很簡單: FSOUND_Init (44100, 32, 0); 第一個參數是輸出HZ,第二是最大軟件信道數可以不管也不會增加CPU負擔,第三個參數可以設置一些標志可以不設置則賦值為0. 2.基本常識 FMOD將音頻分為聲音(sound)和音樂(music)兩種.前者如:.MOD, .S3M, .XM, .IT, .MID, .RMI, .SGT or .FSB 等,后者如: .WAV, .MP2, .MP3, .OGG or .RAW等.二者使用不同的函數處理.都可以通過采樣后流的方式來處理.不過小文件一般通過采樣方式,它可以多次播放但占用內存.大文件通過流方式,減少內存消耗. 3.播放音樂 首先定義一個FMUSIC_MODULE類型變量來作為文件句柄.然后就可以通過FMUSIC API來實現,如: 裝入文件: handle=FMUSIC_LoadSong("YourFileName"); FMUSIC_PlaySong(handle); 音量控制:FMUSIC_SetMasterVolume (handle, 255);后面的參數在0~255之間,值越大聲音越大. 暫停播放:FMUSIC_SetPaused (handle, true); 重開始:FMUSIC_SetPaused (handle, false); 循環播放:FMUSIC_SetLooping (handle, true); 停止播放:FMUSIC_StopSong (handle); 釋放音頻內存:FMUSIC_FreeSong (handle); 下面是一個命令模式下的例子: #include <conio.h> #include "inc/fmod.h" FMUSIC_MODULE* handle; int main () { // 初始化 FSOUND_Init (44100, 32, 0); // 裝如 handle=FMUSIC_LoadSong ("canyon.mid"); // 只播放一次 // 播放midi文件時請關閉循環播放 FMUSIC_SetLooping (handle, false); //播放 FMUSIC_PlaySong (handle); // 按任一鍵結束 while (!_kbhit()) { } //釋放 FMUSIC_FreeSong (handle); FSOUND_Close(); } 4.播放聲音 4.1 采樣(Sample)方式 先定義FSOUND_SAMPLE類型變量,然后就可以使用FSOUND系列函數來實現,如: 裝如文件: handle=FSOUND_Sample_Load (0,"YourFileName",0,0,0); //除文件名外的參數用于多采樣或其它等 FSOUND_PlaySound (0,handle); 設置音量:FSOUND_SetVolume (handle, 255); 暫聽:FSOUND_SetPaused (handle, true); 重新開始:FSOUND_SetPaused (handle, false); 停止:FSOUND_StopSound (handle); 釋放:FSOUND_Sample_Free (handle); 下面是一個簡單的例子: #include <conio.h> #include "inc/fmod.h" FSOUND_SAMPLE* handle; int main () { // 初始化 FSOUND_Init (44100, 32, 0); // 裝載和播放 handle=FSOUND_Sample_Load (0,"sample.mp3",0, 0, 0); FSOUND_PlaySound (0,handle); // 按任一鍵結束 while (!_kbhit()) { } // 釋放 FSOUND_Sample_Free (handle); FSOUND_Close(); } 4.2 流(stream)方式 先定義一個FSOUND_STREAM 類型變量,然后: 裝入文件: handle=FSOUND_Stream_Open("YourFileName",0, 0, 0); FSOUND_Stream_Play (0,handle); 提示:3.7版本之前的方式是不一樣的. 停止:FSOUND_Stream_Stop (handle); 釋放:FSOUND_Stream_Close(handle); 其它和前面是一樣的.下面是一個簡單的例子: #include <conio.h> #include "inc/fmod.h" FSOUND_STREAM* handle; void main () { //init FMOD sound system FSOUND_Init (44100, 32, 0); //load and play sample handle=FSOUND_Stream_Open("sample.mp3",0, 0, 0); FSOUND_Stream_Play (0,handle); //wait until the users hits a key to end the app while (!_kbhit()) { } //clean up FSOUND_Stream_Close(handle); FSOUND_Close(); } 5.關閉 FSOUND_Close (); 參考: A Quick Guide to FMOD by Joachim Rohde(http://www.gamedev.net/reference/articles/article2098.asp) FMOD wiki(http://www.devmaster.net/wiki/FMod)
看到Fox發表關于 成員函數的消息映射的文章,也忍不住發表的一點自己的觀點,希望對大家有所幫助。 其實也就是COMMAND模式的簡單實現,看代碼吧。 1. XGUIEventHandlerPointer.h
namespace XGUI { class EventHandlerSlot { public: virtual ~EventHandlerSlot() {}; virtual void execute(const EventArgs& args) = 0; virtual void* getClass() = 0; };
template<typename T> class EventHandlerPointer : public EventHandlerSlot { public: typedef void (T::*EventHandler)(const EventArgs&); public: EventHandlerPointer() : d_undefined(true), d_object(NULL) {} EventHandlerPointer(EventHandler func, T* obj) : d_function(func), d_object(obj), d_undefined(false) {} virtual ~EventHandlerPointer() {}
void execute(const EventArgs& args) { if(!d_undefined) (d_object->*d_function)(args); }
void* getClass() { return static_cast<void*>(d_object); }
protected: EventHandler d_function; T* d_object; bool d_undefined; }; }
2. XGUIWidget.h
namespace XGUI { // class Widget { public: template<typename T> void addWidgetEventHandler(WidgetEvent EVENT, void (T::*function)(const EventArgs&), T* obj) { mWidgetEventHandlers[EVENT].push_back(new EventHandlerPointer<T>(function,obj)); } void addWidgetEventHandler(WidgetEvent EVENT, EventHandlerSlot* function) { mWidgetEventHandlers[EVENT].push_back(new EventHandlerPointer<T>(function,obj)); } bool Widget::fireWidgetEvent(WidgetEvent EVENT, EventArgs& args) { // If there are no User defined event handlers we are done. if(mWidgetEventHandlers[EVENT].empty()) return false; // Execute registered handlers std::vector<EventHandlerSlot*>* userEventHandlers = &(mWidgetEventHandlers[EVENT]); for(std::vector<EventHandlerSlot*>::iterator it = userEventHandlers->begin(); it != userEventHandlers->end(); ++it ) (*it)->execute(args); return true; } // . }; }
以上只為部分代碼。
摘要: 作者:炎龍工作室 千里馬肝 版本:v1.0 最后更新日期:2002-3-30 緒言 在游戲中,因為我們是中國人麻,通常都需要顯示漢字,比方說交待劇情。而對于文字的顯示,英文的顯示要較其簡單得多,因為只有26個字母,就算再加一些標點、符號什么的,用一張位圖,就可以足以顯示所有的單詞了,而相關實現技巧,也比較輕松。 而中文的顯示方法,要復雜得許多。記得原來在DOS下,漢字的顯示都是讀的UCDOS的點陣... 閱讀全文
頭文件, 處理憔悴, 編譯器, 報錯如風雪。 是誰混淆基本類, 惹變量是非。 虛基類, 構造輪回, 動態堆, 字符串喚不回。 縱然代碼已經成灰, 內存不滅。 循環如三千東流水, 我嵌套一瓢愛了解, 只戀函數的遞歸。 你發如雪, 定義了離別, 我指針指向了誰, 邀明月, 讓地址皎潔, 愛在數組里傾頹。 你發如雪, 初始化眼淚, 我聯編繼承了誰, 數據醉, 編程的歲月, 我用后悔, 刻電腦崩潰的碑。 啦兒啦 啦兒啦 啦兒啦兒啦 啦兒啦 啦兒啦 啦兒啦兒啦 去約會她斜扎兒馬尾只因為學C++學到了崩潰 http://m.shnenglu.com/Lee/archive/2008/09/17/62108.html
|