Bonjour à tous,
Dans la construction de mon jeu, j'essaie d'atteindre un degré d'abstraction que je n'arrive pas à obtenir avec mes connaissances. C'est à cause des types de variables en statique dans le code et j'essaie de le rendre dynamique et donc les types sont connus uniquement à l'exécution.
Pour vous expliquer le contexte, c'est des caractéristiques d'entités et j'ai créé une classe caractéristique qui est censé contenir une variable de type dépendant d'un fichier XML, pour que ça soit plus facilement modifiable sans toucher au code à chaque fois. J'ai utilisé boost::any pour l'instant mais je me retrouve bloqué: en ce moment dans mon fichier XML je spécifie le type de variable (ex: unsigned int), je le parse et je fais pleins de if (voir dernier code) pour traiter tous les cas de types (7) dont j'ai besoin pour le moment.
En plus je vais devoir les manipuler (ces variables dynamiques), je vais devoir "additionner" 2 caractéristiques ensemble (pour les niveaux des entités) uniquement si le type concorde (Est-ce que boost::any supporte l'operator+() ?). A noter que le type d'addition est spécifié par le fichier XML. Ensuite je dois pouvoir afficher cette variable dans mon code avec son bon type, pour l'utiliser dans le gameplay (par exemple les HP, la vitesse d'attaque etc... sont des caractéristiques en unsigned int). Voilà la partie du code intéressant
characteristic.h :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Characteristic {
public:
// Constructors
Characteristic(string _charactName, boost::any _val);
~Characteristic();
// Functions
void setUpDownOperators(string _upOper, string _dwOper);
// Operators
Characteristic doOperator(string _currOp, const Characteristic &upgrader);
Characteristic operator+(const Characteristic &upgrader);
Characteristic operator-(const Characteristic &downgrader);
// Getters
unsigned int getUint();
signed int getSint();
float getF();
double getD();
bool getB();
string getStr();
entityRunnerFlags getErf();
entityTowerFlags getEtf();
damageType getDt();
private:
string charactName;
string upOper;
string dwOper;
boost::any val;
}; |
characteristic.cpp :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| // Constructors for each type
Characteristic::Characteristic(string _charactName, boost::any _val) : charactName(_charactName), val(_val) { }
Characteristic::~Characteristic() { }
void Characteristic::setUpDownOperators(string _upOper, string _dwOper) {
upOper = _upOper;
dwOper = _dwOper;
}
// Operators
Characteristic Characteristic::doOperator(string _currOp, const Characteristic &upgrader) {
if (_currOp.empty())
return *this;
if (val.type() != upgrader.val.type())
return *this;
if (_currOp == string("+")) {
val += upgrader.val;
}
else if (_currOp == string("-")) {
val -= upgrader.val;
}
else if (_currOp == string("0")) {
val = upgrader.val;
}
else if (_currOp == string("-1")) {
// Do nothing
}
else {
// Do nothing
}
return *this;
}
Characteristic Characteristic::operator+(const Characteristic &upgrader) {
return doOperator(upOper, upgrader);
}
Characteristic Characteristic::operator-(const Characteristic &downgrader) {
return doOperator(dwOper, downgrader);
}
// Getters
unsigned int Characteristic::getUint() {
return boost::any_cast< unsigned int >(val);
}
signed int Characteristic::getSint() {
return boost::any_cast< signed int >(val);
}
float Characteristic::getF() {
return boost::any_cast< float >(val);
}
double Characteristic::getD() {
return boost::any_cast< double >(val);
}
bool Characteristic::getB() {
return boost::any_cast< bool >(val);
}
string Characteristic::getStr() {
return boost::any_cast< string >(val);
}
entityRunnerFlags Characteristic::getErf() {
return boost::any_cast< entityRunnerFlags >(val);
}
entityTowerFlags Characteristic::getEtf() {
return boost::any_cast< entityTowerFlags >(val);
}
damageType Characteristic::getDt() {
return boost::any_cast< damageType >(val);
} |
un BOUT du .XML (avec les 3 façons d'additionner)
1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8"?>
<EntityCharacteristicsList>
<maxHp type="unsigned int" upgradeOperator="+" downgradeOperator="-">5</maxHp>
<moveRate type="unsigned int" upgradeOperator="-" downgradeOperator="+">0</moveRate>
<text type="string" upgradeOperator="0" downgradeOperator="0">hello</text>
</EntityCharacteristicsList> |
Et pour finir, le chargeur du fichier XML qui est censé après l'avoir chargé être capable de lire la variable sans connaître son type (en le récupérant depuis la classe characteristic par exemple) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| bool loadCharactListFile(string filePath) {
[...]
// partie chargement du XML omise
// Définition: string currType, currName
// Try to convert to the right type
Characteristic *currCharact;
// -- unsigned int
if (currType == string("unsigned int")) {
unsigned int val;
current->GetValue(&val);
currCharact = new Characteristic(currName, val);
}
// -- signed int
else if (currType == string("signed int")) {
signed int val;
current->GetValue(&val);
currCharact = new Characteristic(currName, val);
}
// -- unsigned int - damageType
else if (currType == string("damageType")) {
unsigned int val;
current->GetValue(&val);
currCharact = new Characteristic(currName, convertAttackTypeFile( val ));
}
// -- unsigned int - entityRunnerFlags
else if (currType == string("entityRunnerFlags")) {
unsigned int val;
current->GetValue(&val);
currCharact = new Characteristic(currName, convertRunnerFlagsTypeFile( val ));
}
// -- unsigned int - entityTowerFlags
else if (currType == string("entityTowerFlags")) {
unsigned int val;
current->GetValue(&val);
currCharact = new Characteristic(currName, convertTowerFlagsTypeFile( val ));
}
// -- bool
else if (currType == string("bool")) {
bool val;
current->GetValue(&val);
currCharact = new Characteristic(currName, val);
}
// -- string
else {
string val;
current->GetValue(&val);
currCharact = new Characteristic(currName, val);
}
charactList.push_back( *currCharact );
delete currCharact;
// Try to get operators
try {
string upOper, downOper;
upOper = currEl->GetAttribute("upgradeOperator");
downOper = currEl->GetAttribute("downgradeOperator");
charactList.at(charactList.size() - 1).setUpDownOperators(upOper, downOper);
}
catch (ticpp::Exception& ex) {
cout << "Cannot get "<<child->Value()<<" operators"<<endl;
return false;
}
}
cout << "Test values :"<<endl;
for (unsigned int i = 0; i < charactList.size(); i++) {
try {
cout << "["<<i<<"] "<< charactList.at(i).getEtf() <<endl;
}
catch (boost::bad_any_cast& bac) {
cout << "Bad type given ! ("<<bac.what()<<")"<<endl;
}
}
} |
J'espère que j'ai été suffisamment explicite dans mon problème et je sais que c'est pas toujours aisé de comprendre le code des autres, j'ai fais du mieux que j'ai pu. J'espère que vous pourrez m'aider, merci d'avance !!
Partager