為手頭游戲項目寫編器,關聯編器和游戲中的游戲對象的屬性成了一個不小的問題,經過多經改寫總算有一個相對好點的方案了,如果大家有更好的解決方案,請指點:
myProperty.h
[cpp]
// 王智泉
#ifndef __myProperty__H__
#define __myProperty__H__
#include <string>
#include <vector>
// @注意: 以下的宏只能在CPP文件中使用
/* 定義一個屬性
@param ownerClass: 宿主類
@param propertyName: 屬性名
@param bindVar: 邦定的變量
@param defaultVal: 默認值
@param describe: 描述
**/
// =================================================================
#define myDEF_PROPERTY(ownerClass, propertyName, bindVar, describe)\
class ownerClass##bindVar##Pty : public myProperty\
{\
public:\
ownerClass##bindVar##Pty():myProperty(propertyName, describe){}\
virtual void setter(myPropertySet* owner, const std::string& val)\
{\
str2val(val, &(static_cast<ownerClass*>(owner)->##bindVar));\
}\
virtual std::string getter(const myPropertySet* owner)\
{\
return val2str(static_cast<const ownerClass*>(owner)->##bindVar);\
}\
virtual std::string getValueType(const myPropertySet* owner)\
{\
return getvalType( static_cast<const ownerClass*>(owner)->##bindVar );\
}\
};\
static ownerClass##bindVar##Pty s_pty##ownerClass##bindVar;
// 清空屬性可能的值
#define myClearPropertyPossVals(ownerClass, bindVar)\
s_pty##ownerClass##bindVar._possibleVal.clear();
// 為屬性增加可選的值
#define myAddPropertyPossVal(ownerClass, bindVar, possibleVal)\
s_pty##ownerClass##bindVar._possibleVal.push_back(possibleVal);
/* 注冊屬性
@param ownerClass: 類名
@param propertyName: 屬性名
**/
#define myRegisterProperty(ownerClass, bindVar)\
registerProperty_impl(&s_pty##ownerClass##bindVar);\
s_pty##ownerClass##bindVar._defaultVal = s_pty##ownerClass##bindVar.val2str(bindVar);
// 屬性類
// =====================================================================
class myPropertySet;
class myProperty
{
public:
/* 構造函數
@param name: 屬性名
@param valType: 數據類型
@param describe: 描述
**/
myProperty(const std::string& name, const std::string& describe)
: _name(name)
, _describe(describe)
{}
virtual ~myProperty(){}
/* 設置屬性
@param owner: 該屬性的宿主(myPorpertySet的子類)
@param val: 該屬性對應的值
**/
virtual void setter(myPropertySet* owner, const std::string& val) = 0;
/* 獲得屬性
@param owner: 該屬性的宿主(myPorpertySet的子類)
**/
virtual std::string getter(const myPropertySet* owner) = 0;
/* 獲得屬性的數據類型
@param owner: 宿主
@return: 返回數據類型的名稱(int, float, bool, string, ...)
**/
virtual std::string getValueType(const myPropertySet* owner) = 0;
public:
// 將字符串轉化成其它類型
void str2val(const std::string& str, int* val) { *val = atoi(str.c_str());}
void str2val(const std::string& str, float* val){ *val = (float)atof(str.c_str()); }
void str2val(const std::string& str, bool* val){ *val = str == "TRUE"; }
void str2val(const std::string& str, std::string* val){ *val = str; }
// 獎其它類型轉化成字符串
std::string val2str(int val) {char str[128] = {0}; sprintf(str, "%d", val); return str; }
std::string val2str(float val) {char str[128] = {0}; sprintf(str, "%.2f", val); return str; }
std::string val2str(bool val) { return val ? "TRUE" : "FALSE"; }
std::string val2str(const std::string& val){ return val; }
std::string val2str(double val){ return val2str((float)val); }
// 獲得屬性的數據類型
std::string getvalType(int val) {return "int";}
std::string getvalType(float val) {return "float";}
std::string getvalType(bool val) {return "bool";}
std::string getvalType(std::string val) {return "string";}
public:
std::string _name; // 屬性的名稱
std::string _defaultVal; // 默認值
std::string _describe; // 描述
std::vector<std::string> _possibleVal; // 可用的值
};
#endif
myProperty.cpp
[cpp]
#include "myProperty.h"
myPropertySet.h
[cpp]
// 王智泉
// 屬性集
#ifndef __myPropertySet__H__
#define __myPropertySet__H__
#include <string>
#include <map>
// 關閉自動排序(還未用)
template<class T>
struct DisableCompare
{
bool operator()(const T& lhs, const T& rhs) const
{
return true;
}
bool operator<(const T& rhs) const
{
return true;
}
};
// 屬性集
// ======================================================================
class myProperty;
class myPropertySet
{
public:
typedef std::map<std::string, myProperty*> PropertyList;
myPropertySet(void);
virtual ~myPropertySet(void);
/* 注冊屬性
@param pty: 屬性
**/
void registerProperty_impl(myProperty* pty);
/* 設置屬性
@param name: 屬性名
@param val: 屬性值
**/
void setProperty(const std::string& name, const std::string& val);
/* 獲得屬性值信息
@param name: 屬性名
@return: 返回屬性名對應的值
**/
std::string getProperty(const std::string& name) const;
/* 獲得屬性
@param name: 屬性名
@return: 返回屬性名對應的屬性指針
*/
myProperty* getPropertyPtr(const std::string& name);
/* 獲得指定屬性的數據類型
@param name: 屬性名
@return: 返回指定屬性的數據類型
**/
std::string getPropertyValueType(const std::string& name) const;
public:
PropertyList _ptysList;
};
#endif
myPropertySet.cpp
[cpp]
#include "myPropertySet.h"
#include "myProperty.h"
#include <assert.h>
// ================================================================
myPropertySet::myPropertySet(void)
{
}
// ================================================================
myPropertySet::~myPropertySet(void)
{
}
// ================================================================
void myPropertySet::registerProperty_impl(myProperty * pty)
{
_ptysList[pty->_name] = pty;
}
// ================================================================
void myPropertySet::setProperty(const std::string& name, const std::string& val)
{
myPropertySet::PropertyList::iterator pos = _ptysList.find(name);
if (pos != _ptysList.end())
{
pos->second->setter(this, val);
}
}
// ================================================================
std::string myPropertySet::getProperty(const std::string& name) const
{
myPropertySet::PropertyList::const_iterator pos = _ptysList.find(name);
assert(pos != _ptysList.end());
return pos->second->getter(this);
}
// ================================================================
myProperty* myPropertySet::getPropertyPtr(const std::string& name)
{
myPropertySet::PropertyList::const_iterator pos = _ptysList.find(name);
if (pos != _ptysList.end())
return pos->second;
return NULL;
}
// ================================================================
std::string myPropertySet::getPropertyValueType(const std::string& name) const
{
myPropertySet::PropertyList::const_iterator pos = _ptysList.find(name);
assert(pos != _ptysList.end());
return pos->second->getValueType(this);
}
myMain.cpp
[cpp]
// 王智泉
#include "myPropertySet.h"
#include "myProperty.h"
#include <iostream>
class myTest : public myPropertySet
{
public:
myTest();
int _intVal;
float _floatVal;
std::string _strVal;
bool _boolVal;
};
// 定義屬性
myDEF_PROPERTY(myTest, "IntValue", _intVal, "這是整型");
myDEF_PROPERTY(myTest, "FloatValue", _floatVal, "這是浮點型");
myDEF_PROPERTY(myTest, "StringValue", _strVal, "這是字符串");
myDEF_PROPERTY(myTest, "BOOLValue", _boolVal, "這是布爾型");
myTest::myTest()
{
// 注冊屬性,一定人先調用myDEF_PROPERTY定義對應的屬性
myRegisterProperty(myTest, _intVal);
myRegisterProperty(myTest, _floatVal);
myRegisterProperty(myTest, _strVal);
myRegisterProperty(myTest, _boolVal);
}
int main()
{
myTest test;
test.setProperty("IntValue", "10");
test.setProperty("FloatValue", "10");
test.setProperty("StringValue", "我叫王智泉,哈哈....");
test.setProperty("BOOLValue", "TRUE");
std::cout << "IntValue:" << test._intVal << "\nFloatValue:" << test._floatVal << "\nStringValue:" << test._strVal << "\nBOOLValue:" << test._boolVal << std::endl;
test._intVal = 100;
test._floatVal = 100.0f;
test._strVal = "Are you a programming monkey?";
test._boolVal = false;
std::cout << "\nIntValue:" << test.getProperty("IntValue") << "\nFloatValue:" << test.getProperty("FloatValue") << "\nStringValue:" << test.getProperty("StringValue") << "\nBOOLValue:" << test.getProperty("BOOLValue") << std::endl;
return 0;
}
輸出結果:
IntValue:10
FloatValue:10
StringValue:我叫王智泉,哈哈....
BOOLValue:1
IntValue:100
FloatValue:100.00
StringValue:Are you a programming monkey?
BOOLValue:FALSE