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 :
Code CPP : Sélectionner tout - Visualiser dans une fenêtre à part
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 :
Code CPP : Sélectionner tout - Visualiser dans une fenêtre à part
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)
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
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) :
Code CPP : Sélectionner tout - Visualiser dans une fenêtre à part
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