Pour ce qui est des trois classes de bases (Player, MovingObject et NonMovableObject), oui (en veillant à le placer dans des fichiers séparés, de manière à ne pas imposer la connaissance des deux autres lorsque tu a besoin d'une classe de base particulière)
Par contre, pour les classes dérivées (Gamer ( = toi), Ennemy ( == un "mechant" personnage), Bullet ( == un boulet de canon, héritant de ... MovingObject) ou Interruptor (== un interrupteur, héritant de NonMovableObject), seule les fonctions virtuelles ( doCollide( ... ) ) devront être déclarées et définies.
Oui, c'est bien de lui que je parle :dOk tu doit parler de ce code:
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
18
19
20
21 class CollisionDetector { public: /* j'aime les template pour éviter de devoir réécrire * vingt fois la même chose :D template <typename FirstType, SecondType> static void detect(FirstType * one, SecondType * second) { /*logique de détection de collision */ /* logique de sélection de priorité */ sendCollision(mostPriorItem, secondPriorItem); } private: template <typename FirstType, SecondType> void sendCollision(FirstType * mostPriorItem, SecondType * secondPriorItem) { Colllision * col = CollisionFactory::createCollection(mostPriorItem, secondPRior); col->transmit(); } };
L'idée d'une factory (d'une fabrique, en francais) est de déléguer et de centraliser en un point unique la création d'objets polymorphes ( comme les différents types de collisions) de manière à éviter autant que possible que d'autres objets n'aillent les créer de manière anarchique.Je remarque que tu utilise une Factory. Je ne sais pas exactement ce que c'est (j'avais trouver un lien sur developpez qui l'expliquait un peu), aurais-tu quelque lien qui explique comment c'est fait et à quoi cela sert ?
Il faut comprendre que le gros de la gestion de la collision sera déjà dévolu au CollisionDetector (c'est lui qui devra la détruire quand elle sera devenue inutile, c'est lui qui décidera de quant en créer une, et c'est lui enfin qui invoquera la fonction collide des deux éléments qui sont rentrés en collision).
Cela fait déjà beaucoup pour une seule classe, d'autant plus qu'il doit donc avoir une connaissance de l'ensemble des éléments (quels qu'en soient le type) qui sont affichés, afin de pouvoir, justement, calculer si collision il y a
Le but de la fabrique est de prendre en charge le choix du type de collision à créer et la création effective.
Il faut comprendre aussi que, comme nous sommes dans une logique d'héritage (que ce soit pour les collisions ou pour les autres hiérarchies) à but polymorphe (l'idée est de pouvoir gérer les différents éléments de chaque hiérarchie en les faisant passer comme étant du type de leur classe de base, sans avoir à s'inquiéter de leur type réel), tous les types que tu pourrais créer au départ de ces classes de base on une sémantique d'entité (cf la FAQ pour plus d'infos sur ce qu'on entend par là) et qu'il ne devraient donc pas être susceptibles d'être copiés ni affecté (seule l'utilisation de références et de pointeurs sur les objets existants devrait être admise ailleurs qu'au sein de la fabrique.
Le gros avantage de travailler de la sorte, c'est que, si un jour tu souhaites rajouter un type (on a parlé des "FlyingEnnemy" et des "FlyingObject"), le seul endroit que tu devras modifier (ou peu s'en faut) sera... la fabrique (de MovableObject ou de Player, ici), parce que c'est le seul endroit où l'on aura effectivement besoin de connaitre le type réel (partout ailleurs, les objets seront traités comme des "Player" ou comme des MovableObject, sans s'inquiéter de savoir si ce sont des boulet de canon, des oiseaux ou des dragons
)
Ouupss, j'ai oublié de fermer mes commentairesDe plus, est-ce que c'est la fonction qui teste s'il y a une collision qui doit appeler la fonction sendCollision ?je vais corriger mon code
Pour l'instant je crois que je vais y allez avec l'enumeration, faute de meilleur idée. Si tu a une meilleur idée, n'hésite pas à la poster.
Alors, je dois crée une fonction pour chaque réaction ? Exemple: Ennemis.ReactJumping(), Ennemis.ReactAttacking(), etc. ???
Qu'est-ce que je passerai en paramètre à cette fonction ?
c'est une fonction statique (car elle doit etre accessible sans qu'il n'existe forcément d'instance particulière de CollisionDetector), que j'ai rendue template pour m'éviter d'avoir à réécrire le code pour l'ensemble des possibilités (après tout, ce qui importe, c'est que deux "choses" entre en collision) et que je remets ici:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 template <typename FirstType, SecondType> static void detect(FirstType * one, SecondType * second) { /*logique de détection de collision */ /* logique de sélection de priorité */ sendCollision(mostPriorItem, secondPriorItem); }C'est ma faute, je me suis arrêté à l'aspect "collision", mais, en gros, tu peux avoir (à peu près) cinq grosse réactions face à un objet mobile:En faite je parlai plus dans le sens de si je suis dans la classe personnage et que je suis dans la fonction :
Si l'objet reçu en paramètre est un MovingObject, Comment savoir!!! tout ce que tu as à faire, c'est réagir à la touch si ce MovingObject est un ennemi et pouvoir utiliser les fonctions spécifiques au ennemis par exemple ? Puisque si je comprend bien les seuls fonctions que MovingObject a son les DoColide, donc s'ils sont des Ennemis, je n'ai pas accès au fonction des ennemis.
Code : Sélectionner tout - Visualiser dans une fenêtre à part virtual void doCollide(CollisionPlayerMovingObject &)
- essayer de le retenir
- essayer de grimper dessus
- essayer de l'agripper
- essayer de sauter au dessus
- essayer de passer en dessous
Mais ces réactions seront commandées par... la touche enfoncée au moment de la collision,en ce qui te concerne du moins, par une logique et des algorithmes adaptés pour les autres types, voire, avoir des réactions tout à fait différentes
(un objet immobile a peu de chance d'essayer de te sauter dessus
)
Comme nous sommes dans un système d'interaction, un objet mobile va... réagir à chacune de ces tentative (grâce à des fonctions comme Climbed, jumpedOver, catched() ou passedUnder, par exemple)
Ces fonctions suivraient le même principe que collide et doCollide() (comprend : invoqueraient une fonction virtuelle privée à redéfinir si la réaction "par défaut" ne convient pas).
Tu n'aurais donc même pas à savoir que l'objet mobile que tu essaye d'attraper est un ennemi... sa réaction lorsque tu tenteras de le faire te le fera bien sentir(parce que, pas de bol, essayer d'attraper un ennemi à mains nues fera que cet ennemi te tuera, ou qu'il ne réagira pas à cette tentative, mais que sa réaction à une collision avec toi (qui arrivera juste après) le fera
)
L'idée de base est, vraiment, de faire en sorte que chaque type d'objet ne connaisse qu'un minimum de types différents et aussi génériques que possible (les classes de base de nos quatre hiérarchies expliquées dans ma première intervention + les différents type réels de collision).
C'est le polymorphisme en réaction à une tentative donnée de ta part (ou en réaction à la collision avec toi) qui te permettra de faire qu'un objet immobile commence à descendre (parce que ton poids le pousse vers le bas), éclate (parce que tu lui a donné un coup de tête) te tue (parce que tu es face à un ennemi avec des picots) ou que justement cet ennemi meure (parce qu'il sera entré en collision avec... une carapace de tortue que tu lui auras jeté)![]()
Partager