Bonjour chers amis z'et amies!
J'arrive en cette belle journée ensoleillée de fin Aout avec un problème pour vous! Oui! Rien que pour vous! (Bon ok, surtout pour moi. :] )
Problème que voici :
Mise en situation :
Je développe en ce moment un shoot'em up vertical tout à fait oldschool. J'ai mon vaisseau qui balance plein de jolie tirs sur plein d'ennemis qui font boom§
J'ai modélisé ça avec un ensemble de classe que voici :
GameObject :
la classe la plus basique pour mes objets. Elle contient l'image qui représente mes objets sur l'écran de jeu, les positions x et y sur mon plan 2D et une durée de vie. (Elle contient en réalité bien plus, mais je donne les donnée membres qui nous intéresse pour simplifier. =p)
Ennemy :
Les ennemis du jeu, qui héritent de GameObject. Ils ont comme donnée membre supplémentaire des points de vie.
PlayerShot :
Les tirs du joueur, qui héritent eux aussi de GameObject et ont comme donnée membre un bool "has_hit" pour savoir si le tir à touché un ennemy ou non.
Pour schématiser, ça se présente comme ça :
Lorsque le jeu tourne, chaque objet est créé à un instant précis : soit suivant un script qui les ajoute à la scène, soit via certains événements, comme l'appui sur la touche de tirs pour les tirs du joueur, la destruction d'un ennemi pour les explosions et les éventuels bonus à ramasser.
Tout ce qui vie fini par mourir.
C'est vrai ici aussi, sinon je mon jeu va calculer les déplacements de tous les objets du niveau, ce qui va demander énormément de mémoire et faire inutilement ramer l'application. Je dois donc les détruire.
La destruction des objets est gérée par ma plus grosse classe : la classe du niveau (nommée Stage, vu que dans les shoot'em up on parle souvent de stage =p). J'ai donc fait une fonction pour que mes objets puisse dire à mon niveau si ils sont encore utiles ou bon pour la casse.
J'ai donc rajouté une fonction EOL() pour "fin de vie" à chacun de mes objets. Je l'ai faite virtuelle pour bénéficier de l'héritage :
On complique le truc :
Voila j'ai donc mes objets qui peuvent être effacés. Mais ça ne suffit pas!
En avançant dans ma réflexion, je me suis rendu compte que les conditions pour effacer un objet peuvent être différentes pour chaque instances d'objet.
Par exemple : certains GameObject sont effacé lorsqu'ils sortes de l'écran de jeu. D'autres lorsqu'ils arrivent en fin de vie uniquement (car ils sont immobiles et ne sortirons jamais de l'écran), d'autres encore qui disparaissent lorsque l'animation de leur image (composée parfois de plusieurs sprites) se termine.
Je me retrouve donc avec plusieurs conditions différentes, que j'ai besoin de prendre en compte individuellement ou a plusieurs... Et ça complique encore car je n'en ai plus besoin seulement par objet, mais par instances d'objet!
Je dois donc trouver un moyen de dire à mes instances d'objet de quelle manière ils vont être détruits. J'ai donc cherché un peu, j'ai eu l'idée des pointeurs sur fonction. Vite fais, comme ça, ça paraissait génial.
Hop je m'exécute. Je rajoute à mon GameObject un pointeur sur fonction, et ce pointeur sera utilisé par ma fonction EOL() pour renvoyer le bool qui convient, et j'y fais un constructeur approprié pour assigner quelque chose à mon pointeur:
Bon, c'est là que les problèmes commence : comment préparer mes fonctions de condition?
Elles doivent pouvoir accéder aux donnée membre de l'objet auquel elles sont appliquées, alors je les fourres connement dans la classe sur laquelle elles doivent faire des vérification.
Aller j'en fais 4 :
2 pour le GameObject -> OutOfScreen() pour ceux qui sortent de l'écran, et NoMoreLife() pour ceux qui arrivent en fin de vie.
1 pour l'Ennemy -> IsDestroyed() pour les ennemis dont la vie arrive à 0 ou en dessous.
1 pour le shot -> HasHit() pour les tirs qui ont touché un ennemi et ont laissé leur impact.
Et puis on essaye !
Jme créé un ptit objet et j'y colle la fonction que je veux :
J'y test... BAH CA COMPILE PAS§§
Code : 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 #include "Ennemy.h" #include "PlayerShot.h" int main{ // On se fait un ptit ennemy qui meur simplement par destruction objects.push_back(new Ennemy(&Ennemy::IsDestroyed()); // On s'en fait un invincible qui meur en sortant de l'écran objects.push_back(new Ennemy(&GameObject::OutOfScreen()); // Hop pour la forme on fait un PlayerShot objects.push_back(new PlayerShot(&PlayerShot::HasHit()); return EXIT_SUCCESS; }
Bon je demande à un pote qui s'y connais mieux que moi, il me dis c'est pas possible, t''instancies pas tes fonction.
Bon alors il m'embarque sur une solution qui passe par des foncteur, mais j'y comprend pas plus que ça, puis il me parle d'héritage multiple, mais là c'est lui qui s'y perd.Envoyé par moi
Je me tourne donc vers TOI cher ami qui a eu le malheur de cliquer sur ce post! Connais-tu une solution à mon problème?
Pour résumer, je cherche à trouver une solution pour :
- Assigner une fonction pour la suppression de mes objet à chaque instance d'objet
- Les fonctions doivent avoir accès d'une manière ou d'une autre aux données membres nécessaire de mes objets. (soit directement, soit par accèsseur)
- Les fonctions doivent reconnaitre si il s'agit d'un GameObject, un Ennemy ou un PlayerShot afin d'accéder à la bonne donnée membre.
- Et la cerise sur le gâteau, je dois pouvoir assigner la méthode de suppression de l'objet via son constructeur.
Ca peut être par un pointeur de fonction, des foncteur, héritage multiple, ça peut être quelques chose de plus simple, de plus compliqué, peut m'importe mais j'aimerai quelques chose de plus élégant que de poser une énumération et faire un grooooos switch.
Et bien sur je reste disponible si vous voulez plus d'info ou avez des questions sur mon problème. =p
Partager