有關服務器屬性系統的思考

腦袋有點凌亂,需要整理


有關遊戲屬性與存儲方式



遊戲屬性可以分成2類:靜態屬性、動態屬性
1.靜態屬性:該屬性對於屬性所屬的對象是不會隨着遊戲進行而變化的
2.動態屬性:該屬性在遊戲的進行過程中會進行變化。動態屬性又可以分成2個子屬性。基礎屬性、衍生屬性
a.基礎屬性:就是該屬性的具體數值不能通過其他屬性計算而得
b.衍生屬性:該屬性的具體數值通過其他屬性就可以計算而得

舉例說明:
客戶端可以看到的力量隨着等級變化而不同,同時可以通過分配額外的點數對於當前的力量進行加成。這裏的力量就有着3個屬性。
不同等級的力量值:靜態屬性
當前力量:基礎屬性
力量和其他屬性計算出來的攻擊力:衍生屬性


屬性的存儲:
靜態屬性:配置文件
基礎屬性:數據庫
衍生屬性:初始化通過靜態數據和基礎數據計算而得。內存中存在

1.屬性中存在各種不同狀態下使用不同屬性作爲實際有效屬性的情況。導致客戶端和服務器寫相同的邏輯代碼去使得邏輯生效。
服務器可以在屬性下發前進行邏輯判定。映射實際有效的屬性。
通過屬性進行是否可見的默認設定,決定實際需要下發的屬性。則實際僅僅下發客戶端有效屬性。

2.其實屬性在實際存儲過程中不需要區分基礎屬性和衍生屬性。因爲處理流程上是完全一樣的。都是僅僅需要Get、Modify、Set、OnPropertyChange 3.個操作
但是需要特別獨立出來靜態屬性。因爲靜態屬性是不會變化的。不需要同步。

4.不同類型屬性之間的區別在於承載屬性的內容不同以及OnPropertyChange的後續處理不同。Get、Modify、Set的邏輯應該是完全相同的。所以應該是這麼一個關係。
class PropertyControllerInterface
{
public:
virtual void OnPropertyChange(_U16 iPropId, _S32 iOld, _S32 iNew) = 0;
virtual _S32 GetProperty(_U16 iPropId) = 0;
virtual bool ModifyProperty(_U16 iPropId, ModifyData modifyData) = 0;
virtual bool SetBaseProperty(_U16 iPropId, _S32 iBase) = 0;
}

class PropertyBase
{
public:
_S32 GetPropertyInternal(_U16 iPropId);
bool ModifyPropertyInternal(_U16 iPropId, ModifyData modifyData);
bool SetBasePropertyInternal(_U16 iPropId, _S32 iBase);


protected:
_U16 m_iPropIdBegin;
_U16 m_iPropIdEnd;
_S32* m_pProperty;
PropertyControllerInterface* m_pController;
}

class PropertyWarshipBase : class PropertyBase
{
public:
PropertyWarship()
{
m_pProperty = m_arPropertyData;
m_iPropIdBegin = XXBegin;
m_iPropIdEnd = XXEnd;
}

private:
_S32 m_arPropertyData[XX];
}


class PropertySubmarineExt : class PropertyBase
{
public:
PropertyWarship()
{
m_pProperty = m_arPropertyData;
m_iPropIdBegin = XXBegin;
m_iPropIdEnd = XXEnd;
}

private:
_S32 m_arPropertyData[XX];
}

class SRoomWarship : public PropertyControllerInterface
{
public:
PropertyWarship();
virtual ~PropertyWarship();


public:
virtual void OnPropertyChange(_U16 iPropId, _S32 iOld, _S32 iNew) = 0;
virtual _S32 GetProperty(_U16 iPropId) = 0;
virtual bool ModifyProperty(_U16 iPropId, ModifyData modifyData) = 0;
virtual bool SetBaseProperty(_U16 iPropId, _S32 iBase) = 0;

public:
_S32 m_arProperty;
}

4. 屬性系統設計方案比較
屬性系統功能比較簡單,涉及存儲、修改、同步三個方面。
存儲是基礎,方案也比較多。主要從擴展性、穩定性、性能(空間、時間)及方面考慮
a. 擴展性最好的,完全配置可驅動,性能最差。所有屬性都是一個存儲對象,所有個體都可以由任意可配置個屬性組合。
class PropNode
{
public:
_U16 iPropid;
_S32 iPropVal;
ModifyProperty modifyData;
}

class PropBase
{
public:
_S32 GetPropertyInternal(_U16 iPropId);
bool ModifyPropertyInternal(_U16 iPropId, ModifyData modifyData);
bool SetBasePropertyInternal(_U16 iPropId, _S32 iBase);


protected:
Map<_U16, PropNode*> m_mapProp;
PropertyControllerInterface* m_pController;
}

class PropWarship : public PropBase
{
public:
PropWarship()
{
m_mapProp.insert(pair(XXid, pNode*)); 
}
}

class PropSubmarine : public PropWarship
{
}

b. 擴展性需要代碼配合的。屬性組合已經優化。根據不同對象屬性分段、組合。
每個對象需要特殊代碼進行實際修改接口的書寫。
class PropertyBase
{
public:
_S32 GetPropertyInternal(_U16 iPropId);
bool ModifyPropertyInternal(_U16 iPropId, ModifyData modifyData);
bool SetBasePropertyInternal(_U16 iPropId, _S32 iBase);


protected:
_U16 m_iPropIdBegin;
_U16 m_iPropIdEnd;
_S32* m_pProperty;
PropertyControllerInterface* m_pController;
}

class PropertyWarshipBase : class PropertyBase
{
public:
PropertyWarship()
{
m_pProperty = m_arPropertyData;
m_iPropIdBegin = XXBegin;
m_iPropIdEnd = XXEnd;
}

private:
_S32 m_arPropertyData[XX];
}


class PropertySubmarineExt : class PropertyBase
{
public:
PropertyWarship()
{
m_pProperty = m_arPropertyData;
m_iPropIdBegin = XXBegin;
m_iPropIdEnd = XXEnd;
}

private:
_S32 m_arPropertyData[XX];
}

class SRoomWarship : public PropertyControllerInterface
{
public:
PropertyWarship();
virtual ~PropertyWarship();


public:
virtual void OnPropertyChange(_U16 iPropId, _S32 iOld, _S32 iNew) = 0;
virtual _S32 GetProperty(_U16 iPropId) =
virtual bool ModifyProperty(_U16 iPropId, ModifyData modifyData) = 0;
virtual bool SetBaseProperty(_U16 iPropId, _S32 iBase) = 0;

public:
_S32 m_arProperty;
}

c.合併子類屬性。父類具有所有屬性,只是沒有效果。
對象最少,性能最好,但是空間使用最浪費。

class PropertyBase
{
public:
_S32 GetPropertyInternal(_U16 iPropId);
bool ModifyPropertyInternal(_U16 iPropId, ModifyData modifyData);
bool SetBasePropertyInternal(_U16 iPropId, _S32 iBase);


protected:
_U16 m_iPropIdBegin;
_U16 m_iPropIdEnd;
_S32* m_pProperty;
PropertyControllerInterface* m_pController;
}

class PropertyWarshipBase : class PropertyBase
{
public:
PropertyWarship()
{
m_pProperty = m_arPropertyData;
m_iPropIdBegin = XXBegin;
m_iPropIdEnd = XXEnd;
}

private:
_S32 m_arPropertyData[XX]; // 包括Warship,Submarine, CA
}


Modify這裏基本上都是Interface接口實現。改變自身屬性就可以了。但是艦船上需要增加一個額外的接口,以通過該接口實現修改說有部位的屬性。
virtual void OnPropertyChange(_U16 iPropId, _S32 iOld, _S32 iNew) = 0;
virtual _S32 GetProperty(_U16 iPropId) = 0;
virtual bool ModifyProperty(_U16 iPropId, ModifyData modifyData) = 0;
virtual bool SetBaseProperty(_U16 iPropId, _S32 iBase) = 0;
virtual bool ModifyProperty(EffectType, PartType, _U16 iPropId, ModifyData modifyData) = 0;

對於修改處理則主要是兩方面問題:
a. 進行屬性修改後的邏輯處理: 比如物理庫的的參數設定,屬性映射處理
需要考慮屬性邏輯關係,比如潛水艇的水面最大速度、水下一層最大速度和水下二層速度與當前最大速度
b. 進行與客戶端同步
進行屬性同步過濾

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章