游戏中的对象资源信息管理
首先要說明的是資源格式。資源格式一般存放如下格式
?
資源
?|
?--- part0
?|
?----part1
?|
?----part2
?|
?...
?
一個很好的例子就是模型信息文件,在一個模型信息文件中,存放了整個物體的所有部分,每一個部分又是單獨的信息。這樣做的目的在于游戲中的換裝。
還有一個例子就是特效文件,比如將一個門派的技能做為一個特效文件,而這個特效文件中包含了所有技能的技能特效。又或者說,當我們要實現不同等級的技能有不同特效的時候,就可以將一個技能做一個特效文件,而特效文件中存放的則是不同的等級的特效。
?
接下來就是要說明邏輯和渲染部分的劃分。有些游戲是直接將渲染和邏輯嵌在一起的。這樣做我覺得非常不好,不便于后期擴充。加上渲染部分的東西在邏輯里亂飛,也會干擾清析度。并且,你不能假設所有寫邏輯的同伴都喜歡和圖形沾親帶故的。因為有必要將渲染部分和邏輯劃分開來。
一種常見的分法就是將渲染部分交給場景管理器,而由場景管理器引出一個場景對象。好比Ogre中的Entity 這個Entity是掛接在場景切點上的。 在這個Entity中,就包含了我們需要顯示和繪制的東西,如模型,特效,位置,材質等等東西。邏輯在使用的時候,只需讓邏輯對象派生(Class導出方式),或者嵌入(導出接口方式)這個場景對象,即可實現信息的共享。我采用的是接口導出方式。
?
class ISceneObject;
class CGameObject
{
...
? ISceneObject *mSceneObject;
};
?
劃分情況就是如此了。那我們如何與場景對象接口通信呢。場景對象接口需要提供一些什么操作呢? 那些改變基礎屬性的,
?
如位置,方向,大小,移動,控制動畫等都是很直觀的。 那我們如何改變一個場景對象的渲染信息? 改變這些渲染信息的時候,又應該以什么樣的方式來進行?
在此我們想到,邏輯中,一個對象都有他自身的各種屬性,如果這個對象需要被渲染,肯定也需要一些渲染信息,如采用什么哪些模型的part,模型上有哪些特效等。 直接的方案就是按照上面講的資源劃分方式提供如下信息表。
struct SRenderInfo
{
? TCHAR[64] szResFile;//存儲信息的文件名
? TCHAR[64] szResName;//信息文件中的資源名
};
?
那么,當我們想要為場景中的一個人物增加一件裝備的時候,我們就可以像這樣提供一個接口。ISceneObject::AddPart(const
?
TCHAR* modelInfoFile,const TCHAR* partName)=0;
?
而假設現在我有一個“肩膀”,肩膀是“天尊套裝”中的“肩膀”。那么這個裝備的SRenderInfo mRenderInfo結構的值是{_TEXT("天尊套裝"),_TEXT("肩膀")} 我們調用mSceneObject->AddPart(mRenderInfo->szResFile,mRenderInfo->szResName);便可以修改一個模型的肩膀,外部并不用關心這個模型的任何渲染過程。
?
那我們要增加一個特效呢? 要知道,特效是隨時都在調用的,當你釋放一個技能的時候,特效被增加,當你技能放完了,特效又會被刪除。 (有個例外的情況就是光環類技能,這種技能的特效是會隨著技能的關閉才刪除的)。 總的來說,我們就需要ISceneObject::AddEffect(const TCHAR* effectFile,const TCHAR* effectName)=0;接口。
?
那我們或許會想做些優化,比如當我穿戴同樣的裝備的時候,就可以不用再調用AddPart了。嗯,或許你會說這種東西用不著優化,那好吧。那特效呢? 成十成百的人放特效的時候,如果他們都總是按著一個技能不停的放。你覺得會不會有必要呢?
?
減少了特效的切換,減少了許多API的調用,模型不用重新計算他的特效信息,不需要重新掛接。 或許,可以用字符串比較的方式來斷定。比如們可以在AddEffect內部檢查是不是已經有相同的特效存在了,是不是在同一位置。。這樣我們就可以不用做更多的工作。當然,這樣是可以的。 而外部呢,你有信息在字符串亂飛的同時保證所有東西都正確嗎?
其實上面的解釋都不足以讓我搬出下面的東西,但是有時候它會讓程序寫著簡單。
想像一下,在配置文件中, 我們總是會給資源一個索引,然后才是他真正的內容。我們很少看到一個東西用字符串來索引的,當然,也有,我沒有說沒有。我們是不是可以試著將所有信息存放起來,然后用一個索引來索引它們呢? 比如現在有50個玩家出現在你的周圍,而他們穿的裝備中有50%是共同的,如果我們采用剛剛的方式,就會出現許多個sizeof(TCHAR)*64*2.并且,裝備模版,特效模版的信息
?
如果沒有和他們放一起,會是多么復雜的一件事。 但是,如果通過索引的話,僅僅是一個16位索引,就可以解決問題。其實我們一開始就可以這樣做,除了模型顯示信息外,還有一些基礎信息都是共同的,這就是我們經常提到的裝備模版。 當我們采用索引后,一切就變得簡單了。 用索引索引出這些信息,再傳給場景對象,看起來多么容易的一件事啊。
?
其實我現在不是這樣做的,我是在場景管理內部做了一個資源信息表,這個表不管其它的,只負責資源ID,資源文件和資源部分的對應關系。 而場景管理是不會加載任何的資源信息的。 因為我根本不知道一個游戲的資源配置文件會寫成什么樣,會用什么寫(XML? INI,EXCEL?)。于是,對外提供了一個注冊這些資源信息到內部的接口。而當我們上面的接口則變成了
ISceneObject::AddPart(int resId);
ISceneObject::AddEffect(int resId);
看到了嗎? 我并沒有用modelId,和effectId.說明什么呢,說明所有資源采用的是統一編號。 這樣做貌似不太好。但這樣在場景管理中就不再需要維護多種資源的資源表了。而上面這兩個函數的實現,則是根據資源索引取得資源信息,然后就可以正式進行操作了。
?
或許,我們可以把這個映射交給寫邏輯的人處理,只是不知道他們愿不愿意。
之所以寫出來,是因為我在猶豫,到底哪種方案更好,或者有沒有更好的方案來解決這個事情。。。。
轉載于:https://www.cnblogs.com/qilinzi/archive/2010/07/12/1940478.html
總結
以上是生活随笔為你收集整理的游戏中的对象资源信息管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FastReport4.6程序员手册_翻
- 下一篇: 使用Log Explorer恢复数据