IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Jeu de labyrinthe, plusieurs questions sans réponse.


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut Jeu de labyrinthe, plusieurs questions sans réponse.
    Bonjour, je débute en C++ et, avec le livre le Guide Complet C++, j'ai créé un jeu de labyrinthe avec hiérarchie de classe, des ennemis et plusieurs map...

    Je suis sous Visual C, voici le liens de projet:
    https://rapidshare.com/files/2694081315/LabyC++.zip

    Le programme ouvre un document texte, composé de 0 et de 1 (0=mur et 1=couloir). Avec quelque autre caractère (j=position de départ du joueur, w= arrivée, s=sortie (car il y a plusieurs map relié entre elle), v= EnnemiVert, r=EnnemiRouge, f=EnnemiFolow).
    Ne répondre qu'a une seul de mes question m'aiderais vachement.
    Tout le projet est sur le liens et vous pouvez déjà tester.

    J'utilise la bibliothèque glut/GL

    Pour le déplacement des ennemi vert/rouge/bleu:

    AU début, un algorithme défini la direction haut/bas/gauche/droite. Puis si il prend a droite, il continue a droite jusqu'au moment ou il y a un mur, puis l'algorithme aléatoire reprend...

    Première chose: si l'on ne met qu'un ennemi, pas de problème, mais si on en met plusieurs, si il y en a un qui est contre un mur, il déclenche l'algotithme aléatoire pour TOUT les ennemis... je voudrai que chaque ennemi se déplace individuellement...

    Deuxième chose: je voudrai que, si l'ennemi avance vers le bas, s'il rencontre un mur, il vérifie d'abord s'il peu aller a droite ou a gauche, si il peux, il va au hasard a droite/gauche, sinon, il repart d'ou il vient.

    Troisième chose: je voudrai que la manière de déplacement que je viens de dire ne marche qu'avec EnnemiVert et EnnemiFolow

    En effet EnnemiRouge se duplique, et pour ne pas compliquer le joueur, cet ennemi ne devrai pas se déplacer beaucoup en parcourant les couloirs ,se déplacer tout le temps aléatoirement évite qu'ils se déplacent trop.


    Quatrième chose: Pour EnnemiFolow maintenant, comme son nom mal orthographié l'indique , s'il est à la portée de vu du joueur (si il est sur la même ligne ou colonne, et qu'il n'y a aucun mur entre le joueur et EnnemiFolow, celui ci fonce vers le joueur en accélérant, et en émettant un son:
    - je sais comment parcourir un fichier, donc le test "si joueur et ennemiFolow" est sur même ligne/colonne c'est bon, mais en plus, vérifier si il y a un mur entre les deux... ça je vois pas...

    - comment accélérer l'ennemi ? (je pourrai, au lieu de varié PosC ou PosL de 2 au lieu de 1, mais alors je ne sais pas comment vérifier s'il y a un mur a plus d'une case de l'ennemie).

    - comment émettre un son ? autre que "\a" ? j'ai un fichier .wav emettant un son approprié, comment l'ouvrir lorsque EnnemiFolow fonce sur le joueur ?


    Voila... ça fait beaucoup de chose, je sais :/ mais je suis débutant et, malgré mes essais je n'arrive a rien...



    Merci.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Hello,

    Citation Envoyé par Hedg-Hop Voir le message
    Bonjour, je débute en C++ et, avec le livre le Guide Complet C++, j'ai créé un jeu de labyrinthe avec hiérarchie de classe, des ennemis et plusieurs map... Je suis sous Visual C
    Je ne sais pas si c'est un exemple tiré du livre ou si tu as tout écrit toi-même depuis zéro mais félicitations : en ajoutant simplement « #include <cstdlib> » et la fonction « glutInit() », j'ai été en mesure de compiler directement ton programme sous Linux, et il marche !

    Ça aide pour le déboguage. :-)


    AU début, un algorithme défini la direction haut/bas/gauche/droite. Puis si il prend a droite, il continue a droite jusqu'au moment ou il y a un mur, puis l'algorithme aléatoire reprend...

    Première chose: si l'on ne met qu'un ennemi, pas de problème, mais si on en met plusieurs, si il y en a un qui est contre un mur, il déclenche l'algotithme aléatoire pour TOUT les ennemis... je voudrai que chaque ennemi se déplace individuellement...
    Tu utilises une variable nommée « impossible » pour savoir si tu peux ou non effectuer le déplacement, mais cette variable est une variable globale. Tous tes sprites lisent donc la même. Il aurait fallu que « impossible » soit une donnée membre de chaque instance, au même titre que PosC et PosL.

    Deuxième chose: je voudrai que, si l'ennemi avance vers le bas, s'il rencontre un mur, il vérifie d'abord s'il peu aller a droite ou a gauche, si il peux, il va au hasard a droite/gauche, sinon, il repart d'ou il vient.
    Si ton ennemi est dans une impasse, il n'y a qu'une seule voie possible. Celle-là même par où il est arrivé. Donc, dans le fonctionnement actuel, ça devrait déjà fonctionner ainsi. Au pire, il fait du surplace pendant un instant le temps de tomber sur la bonne voie.

    Troisième chose: je voudrai que la manière de déplacement que je viens de dire ne marche qu'avec EnnemiVert et EnnemiFolow

    En effet EnnemiRouge se duplique, et pour ne pas compliquer le joueur, cet ennemi ne devrai pas se déplacer beaucoup en parcourant les couloirs ,se déplacer tout le temps aléatoirement évite qu'ils se déplacent trop.
    Pour cela, il te suffit de surcharger « DeplacementAuto() » pour la classe EnnemiRouge. Après examen, il semble que tu l'aies déjà fait, et que tu rappelles naturellement la fonction-membre de la classe de base.

    Il suffit donc d'y rajouter une clause qui titre systématiquement une nouvelle direction à chaque appel. Tu peux aussi, comme tu l'as fait à côté pour la duplication des ennemis rouges, ajouter une probabilité, de manière à ce que l'ennemi en question conserve quand même sa direction pendant une durée minimum.

    Au passage, l'idée de dupliquer les ennemis rouges est une bonne idée mais telle que tu l'as implémentée, tu risques d'avoir une progression exponentielle du nombre de tes ennemis.

    Quatrième chose: Pour EnnemiFolow maintenant, comme son nom mal orthographié l'indique , s'il est à la portée de vu du joueur (si il est sur la même ligne ou colonne, et qu'il n'y a aucun mur entre le joueur et EnnemiFolow, celui ci fonce vers le joueur en accélérant, et en émettant un son:
    - je sais comment parcourir un fichier, donc le test "si joueur et ennemiFolow" est sur même ligne/colonne c'est bon, mais en plus, vérifier si il y a un mur entre les deux... ça je vois pas...
    Je n'ai pas encore été voir comment tu gères ta grille mais je suppose (et j'espère) que tu la lis en mémoire au départ et une fois pour toutes. De là, si tu sais vérifier s'il y a un mur à proximité d'un personnage, qu'est-ce qui t'empêche de vérifier si il y en a un autre un cran plus loin, puis deux, puis trois, etc. ?

    Pour éviter de consommer inutilement des ressources, tu commences effectivement par vérifier si le joueur et l'ennemi se trouve sur la même ligne ou la même colonne, comme tu l'as dit et, le cas échéant, tu explores case par case l'espace qui les sépare et tu t'arrêtes dès que tu rencontres la première case.

    - comment accélérer l'ennemi ? (je pourrai, au lieu de varié PosC ou PosL de 2 au lieu de 1, mais alors je ne sais pas comment vérifier s'il y a un mur a plus d'une case de l'ennemie).
    Il n'y a pas trente-six manières de le faire : soit tu vérifies deux cases au lieu d'une à chaque fois, soit tu accélères la boucle principale et tu ne rafraîchis les autres ennemis qu'une fois sur deux.

    - comment émettre un son ? autre que "\a" ? j'ai un fichier .wav emettant un son approprié, comment l'ouvrir lorsque EnnemiFolow fonce sur le joueur ?
    Il te faut une autre bibliothèque : OpenAL, par exemple.

    Voila... ça fait beaucoup de chose, je sais :/ mais je suis débutant et, malgré mes essais je n'arrive a rien... Merci.
    Tu as un programme qui marche, c'est déjà beaucoup !
    Bon courage.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Merci Obsidian de ta réponse tardive ! ^^ (non pas tardive parce que tu as été lent a répondre mais parce que c'est la nuit )

    Je programmerais ça demain, je suis sur que ça me sera d'une grande aide.

    Info: Le livre me fait créé le labyrinthe pas à pas simple. Avec ce que j'ai appris j'ai rajouté la quadruple map relié entre elles... j'ai créé beaucoup d'ajustement, comme le déplacement des ennemis, création d'un troisième ennemi etc...

    Tu utilises une variable nommée « impossible » pour savoir si tu peux ou non effectuer le déplacement, mais cette variable est une variable globale. Tous tes sprites lisent donc la même. Il aurait fallu que « impossible » soit une donnée membre de chaque instance, au même titre que PosC et PosL.
    Je n'y avais pas pensé ! merci
    EDIT: une donnée membre CAD ? int impossible(0); dans ennemiBase.h ?Après ça cause ds problèmes dans ennemiBase.cpp...
    Et pour PosC et PosL.. ils sont membre protégé de PersonnageBase.h.. donc normalement on peut les utiliser par les class membre non ?

    Si ton ennemi est dans une impasse, il n'y a qu'une seule voie possible. Celle-là même par où il est arrivé. Donc, dans le fonctionnement actuel, ça devrait déjà fonctionner ainsi. Au pire, il fait du surplace pendant un instant le temps de tomber sur la bonne voie.
    Non tu n'as pas compris:
    Si l'ennemi va par exemple vers le bas, et que il arrive à un mur, imaginons qu'il a le choix entre 3 direction: droite/gauche, et haut(là où il est venu)
    Je voudrai que l'ennemi test d'abord avec l'algorithme droite/gauche. (et pas la d'ou il est venu).
    SI bien sur il est dans une impasse, alors il revient sur ses pas.


    (EnemiRouge) Il suffit donc d'y rajouter une clause qui titre systématiquement une nouvelle direction à chaque appel
    Je voudrai que pour cet ennemi, a chaque déplacement seul ce switch soit appelé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int hasard rand()%4
    switch(hasard)
    {...} // fait bouger EnnemiRouge completement aléatoirement
    Mais ce switch est dans EnemiBase.cpp, mère de EnnemiRouge, en plus il est dans un if et... je ne sais même plus comment j'ai réussi j'ai beaucoup soufert pour que tout marche et je ne vois vraiment pas comment faire.


    Au passage, l'idée de dupliquer les ennemis rouges est une bonne idée mais telle que tu l'as implémentée, tu risques d'avoir une progression exponentielle du nombre de tes ennemis.
    C'est fait pour ! pour que le joueur termine le niveau le plus rapidement possible !
    PS: comme c'est une quadruple map, le passage d'une map a l'autre repositionne tout les ennemis a leur places du début. Je sais c'est pas très réaliste mais, ça permet de gerer le nombre. et, je ne sais plus ce que j'avais mis comme temps pour la duplication, mais maintenant j'ai mis 1 chance/450 toute les 500 milisec par ennemiRouge.


    EDIT: Pour ennemiFolow, j'ai pensé a faire ça:
    rajouter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void SuivreJoueur(); // dans EnemiFolow.h
    rajouter dans EnnemiFolow.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void EnnemiFolow::SuivreJoueur()
    {
          if(Matrice[monJoueur.GetPosC()] []  == Matrice[ENNEMI_FOLOW] []  ||      Matrice [] [monJoueur.GetPosL()]  == Matrice[] [ENNEMI_FOLOW])
           {
                   /* par contre la je ne vois pas faire... "si '0' est entre 'monJoueur' et 'EnnemiFolow' */
            }
    }
    Et apparemment... mon premier if est incorect

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Hello,

    Citation Envoyé par Hedg-Hop Voir le message
    Je n'y avais pas pensé ! merci
    EDIT: une donnée membre CAD ? int impossible(0); dans ennemiBase.h ?Après ça cause ds problèmes dans ennemiBase.cpp...
    Tout d'abord, c'est une bonne chose d'avoir essayé une fois les variables globales pour voir comment elles fonctionnent et utiliser « extern » mais, désormais, il faudra t'en passer définitivement, sauf cas extrêmement particulier (que je ne saurais même pas te détailler à brûle-pourpoint). Voici en partie pourquoi :
    http://www.developpez.net/forums/d93...c/#post5271611

    Sinon, pour le reste, il faut que tu remettes les choses à plat, et éventuellement les réécrives au propre. Le fait de tourner à gauche ou à droite, et de se déplacer vers n'importe lequel des quatre points cardinaux est complètement indépendant, en soi, de la notion de classe et des différentes entités que tu as définies.

    Il faut donc prendre dix minutes pour y réfléchir en dehors de tout le reste et, de là, écrire une méthode propre qui sera utilisée ensuite partout dans ton programme.

    D'abord, tu suis quatre directions potentielles, qui peuvent donc être codées sur exactement deux bits, ce qui te permet d'utiliser les opérateurs logiques comme le modulo, ce qui a quelques avantages : un « & 3 » sera donc équivalent à un « % 4 » lorsque tes nombres sont positifs et dans le cas de « (0 - 1) & 3 », tu remonterais à « 3 » au lieu d'obtenir « -1 ».

    Ensuite, tu peux par exemple prendre le nord comme point de repère puis tourner vers la droite, ce qui donnerait : 1→nord ; 2→est ; 3→sud ; 4→ouest. L'avantage est que la congruence apportée par ton modulo suit le même mouvement circulaire. Tant et si bien que si tu stockes ta direction actuelle dans un entier « d », alors l'expression « (d+1) & 3 » correspondra toujours à un virage à droite, quelque soit ta direction initiale, et « (d-1) & 3 » à un virage à gauche. On comprend également que c'est purement algorithmique et que ce n'est pas lié en soi au C ou au C++.

    Puis, comme chaque ennemi doit suivre sa direction courante jusqu'à ce qu'il rencontre un obstacle, cela veut dire qu'à la base, chaque ennemi a une direction propre. Il faut donc ajouter « int direction » aux données membres de « EnnemiBase », voire même « PersonnageBase ».

    Écris ensuite des méthodes dérivées comme « CaseNord() », « CaseEst() », « CaseSud() », « CaseOuest() » pour récupérer le contenu de la cellule adjacente au personnage de façon absolue et « CaseDevant() », «CaseADroite() », « CaseDerriere() », « CaseAGauche() » pour le faire de manière relative à la direction courante de ton personnage.

    Tu peux également choisir d'écrire une seule méthode pour chaque version et passer la direction en argument : « CaseAbsolue(int d); » et « CaseRelative(int d); ».

    Une fois que tu disposes de ces outils, il est très facile de prendre une décision :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        if (CaseGauche()!=1 && CaseDroite()!=1) DemiTour

    EDIT: Pour ennemiFolow, j'ai pensé a faire ça:
    rajouter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void SuivreJoueur(); // dans EnemiFolow.h
    rajouter dans EnnemiFolow.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void EnnemiFolow::SuivreJoueur()
    {
          if(Matrice[monJoueur.GetPosC()] []  == Matrice[ENNEMI_FOLOW] []  ||      Matrice [] [monJoueur.GetPosL()]  == Matrice[] [ENNEMI_FOLOW])
           {
                   /* par contre la je ne vois pas faire... "si '0' est entre 'monJoueur' et 'EnnemiFolow' */
            }
    }
    Et apparemment... mon premier if est incorect
    En effet, cette expression ne veut rien dire. « ENNEMI_FOLLOW » est censé n'être qu'un code pour vérifier si le contenu d'une case est un ennemi suiveur, mais tu t'en sers comme indice de ligne ou de colonne. En outre, tu peux utiliser des crochets vides dans certains cas seulement lors des déclarations, mais pas à l'évaluation.

    À la place, il faut comparer les deux instances de tes personnages, et vérifier si leurs colonnes respectives sont égales, sinon leurs lignes (si les unes et les autres sont égales entre elles au même moment, ça veut dire que l'ennemi est à la même position que le joueur et qu'il y a donc collision).

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        if (monJoueur.GetPosC() == ennemi.GetPosC() || monJoueur.GetPosL() == ennemi.GetPosL())
        {}

    Ensuite, il n'y a pas de manière rapide de vérifier ce que tu veux savoir. L'ennemi n'a le joueur en vue que s'il n'y a aucun obstacle entre les deux. Il faut donc écrire une boucle « for » qui coure de C1 à C2 (respectivement L1 ou L2), où C1 est la plus petite des deux colonnes (entre celle du joueur et celle de l'ennemi) plus une unité, pour commencer après le personnage, et C2 la plus grande moins une unité, pour finir avant l'autre (ou la même chose avec les lignes, le cas échéant) et, à chaque tour, tu examines la case correspondante de la matrice. Dès que tu trouves quelque chose qui diffère de « 1 », le test a échoué et ce n'est plus la peine d'aller plus loin. Si, en revanche, la boucle est allée jusqu'à son terme (et donc que l'indice de boucle est supérieur ou égal à C2), alors le « couloir » est bien vide entre les deux personnages et ton ennemi a le joueur en vue.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Salut.

    Pour la variable impossible: si je supprime de main.cpp et que je let met dans EnnemiBase.h, en tant que membre publique, ça me met erreur...

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    ajouter « int direction » aux données membres de « EnnemiBase
    je met dans les membres public d'EnnemiBase.h c'est bien ça ?


    Écris ensuite des méthodes dérivées comme « CaseNord() », « CaseEst() », « CaseSud() », « CaseOuest() » pour récupérer le contenu de la cellule adjacente au personnage de façon absolue et « CaseDevant() »,
    Méthode dérivée ? je comprend pas dsl... récupérer le contenue des cellule adjacente des ennemis... je ne vois pas...

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Jsuis crevé de chercher, j'ai essayé toute la journée.. j'ai essayé d'enlever "EnnemiBase" pour créé 4 class distinct "Joueur", "EnnemiVert", "EnnemiRouge", "EnnemiFolow" filles de Personnage base, pour que chaqu'une des classe gère Déplacement auto, mais ça me causais d'autant plus de problème...

    Pour ennemiFolow: le if ne fonctionne pas non plus: GetPosC/L erreur doit avoir class/struct/union..., "ennemi" erreur... En plus j'ai essayé le bibliothèqye audio mais j'ai pas réussi, sauvegarder les score si le laby est terminé en notant le temps de jeu sur un fichier ça non plus j'y arrive pas...


    Je vais laisser tomber pour le moment... j'en peux plus a vrai dire... 12h non stop avec des chaque fois des erreur de compilation.. merci beaucoup de tes réponses et du temps passé pour mon ptit programme. J’apprécie.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Hedg-Hop Voir le message
    Pour la variable impossible: si je supprime de main.cpp et que je let met dans EnnemiBase.h, en tant que membre publique, ça me met erreur...
    Mets-la dans « PersonnageBase » à la place.

    Citation Envoyé par Hedg-Hop Voir le message
    je met dans les membres public d'EnnemiBase.h c'est bien ça ?
    Non, « int direction; » tout court. C'est une variable.

    Si tu conçois de mettre PosC et PosL en tant que variables protégées de tes personnages pour savoir où ils sont, qu'est-ce qui te dérange dans le fait d'y ajouter en plus le cap courant de ces personnages ?

    récupérer le contenue des cellule adjacente des ennemis... je ne vois pas...
    Comprendre par là : « récupérer le contenu de la case juste à côté ».

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Hedg-Hop Voir le message
    Jsuis crevé de chercher, j'ai essayé toute la journée.. j'ai essayé d'enlever "EnnemiBase" pour créé 4 class distinct "Joueur", "EnnemiVert", "EnnemiRouge", "EnnemiFolow" filles de Personnage base, pour que chaqu'une des classe gère Déplacement auto, mais ça me causais d'autant plus de problème...

    Je vais laisser tomber pour le moment... j'en peux plus a vrai dire... 12h non stop avec des chaque fois des erreur de compilation.. merci beaucoup de tes réponses et du temps passé pour mon ptit programme. J’apprécie.
    Félicitations, tu viens d'obtenir le grade 1 de la fonction de programmeur ! :-)

    Tout le monde est passé par là : tu vas plancher pendant deux heures sur un problème en fin de journée sans arriver à trouver la solution et, après une bonne nuit de sommeil, tu vas le résoudre en dix minutes le lendemain à tête reposée. Et les temps que je te donne ici sont réels !

    Non seulement tu as récupéré de l'énergie psychique à ce moment, mais tu as également pris le recul nécessaire pour apercevoir ce qu'il te manquait.

  10. #10
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut Finish
    Salut ! J'ai arrêté de chercher des truck que je n'avais pas encore appris, j'ai fini mon programme et je vais continuer mon apprentissage.

    Tient, voici mon projet complet, si tu veux l'essayer ^^:
    https://rapidshare.com/files/398494363/LabyC+++.zip

    J'ai même créé une sauvegarde des scores, avec le temps passé dans le niveau :p
    Allez une dernière chose que je voudrai savoir:
    ça sauvegarde les scores dans un document textes, mais a chaque fois que je rejoue, ça efface les donné et réécrit par dessus : j'aurais voulus que ça écrive une ligne en dessous (et j'ai fais des recherche, essayé le ios::app mais nothing.)
    (j'aurais voulu mettre, les scores dans un document lisible SEULEMENT par le programme, car un document texte, c'est facile a modifier de l'extérieur mais apperemment c'est trop compliqué... x) (pour moi)

    Bref, juste le truck du ios:app et je passerais a... un jeu de morpion ! avec une autre bibliothèque, meilleur que ce vieux glut.... dans le livre c'est seulement Joueur contre joueur, et il y a un ans quand je programmais sur calculette j'avais créé un morpion contre une IA impossible a battre... Je sens que jvais me poser encore plein de problème en me lançant la dedant x)

    Donc, merci et surement a bientôt :]

  11. #11
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Salut, j'ai rajouté une dernière modification:
    j'ai fais en sorte que si l'on est touché, on perd une vie, on supprime l'ennemi qui nous a touché, et on continue de jouer.

    Bref, comment supprimer l'ennemi ?

    Je suis dans EnnemiBase.cpp:

    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
     
    extern void SuprimerEnnemi(int colonne, int ligne);
     
    //...//
     
    void EnnemiBase::TestColision()
    {
         if(PosC == monJoueur.GetPosC() && PosL == monJoueur.GetPosL())
         {
               vie--;
               SupprimerEnnemi(PosC, PosL); // appel de la fonction
     
         }
     
     
    }
    Ensuite, dans la fonction main:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void SuprimerEnnemi(int Colonne, int Ligne)
    {
          // Je met quoi ici ????
    }
    voila, merci...

  12. #12
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Il vaut mieux faire d'abord un test qui recherche la présence d'un ennemi à la position donnée et qui retourne un pointeur sur celui-ci ou NULL s'il ne trouve rien.
    Ensuite soit tu fait un simple delete, le destructeurs se chargeant lui-même d'enlever le mobs de tous les listes/tableaux et autres.
    Soit tu appelles une méthode de destruction qui devra à sa fin détruire l'objet mobs.

  13. #13
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    if(PosC == monJoueur.GetPosC() && PosL == monJoueur.GetPosL())
    {
    dans ce test, PosC et PosL sont la position de l'ennemi dans la matrice.

    Le problème c'est que je ne vois pas quoi écrire dans la fonction SuprimerEnnemi de main.cpp:

    En effet, j'utilise des hiérarchies, et il y a 3 type d'ennemi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    enum TYPE_ENNEMI
    {
         MOBS_1,
         MOBS_2,
         MOBS_3
    }
    Je te montre ma fonction ajouterEnnemi (qui place les ennemi dans le jeu au début lors de l'ouverture du jeu):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void AjouterEnnemi(TYPE_ENNEMI type, int Colonne, int Ligne)  
    {
    EnnemiBase* Pointeur = NULL; // pointeur sur EnnemiBase
    switch(type)
    {
          case MOBS_1: Pointeur = new Mobs1();
          //...//
    }
    //définit la position de l'ennemi créé
    Pointeur->SetPosC(Colonne);
    Pointeur->SetPosL(Ligne);
    Pointeur->SetSuivantPremierEnnemi
    premierEnnemi = Pointeur;
    }
    Voila, mais pour supprimer l'enemi je vois pas de quel manière e dois m'y prendre avec les 3 type d'ennemi et tout...

  14. #14
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Tous les ennemis doivent hériter d'une même classe ennemis.
    Tu met le destructeur en virtual et delete supprimera ton ennemis quel qu'il soit.

    Le fait d'utiliser un switch pour créer ton ennemis n'est à mon sens pas super.
    L'utilisation d'un tableau de pointeur de fonctions me semble plus approprié :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    typedef EnnemiBase * (*FctCreateEnnemi)(int Colonne, int Ligne);
     
    EnnemiBase * CreateEnnemi1(int Colonne, int Ligne)
    {
                 TypeEnnemi1 * x = new TypeEnnemi(Colonne, Ligne);
                 return x;
    }
     
    FctCreateEnnemi[] = {&CreateEnnemi1, &CreateEnnemi2};
     
     
    enum TYPE_ENNEMI
    {
         MOBS_1,
         MOBS_2,
         MOBS_3,
         MOBS_MAX
    }
    void AjouterEnnemi(TYPE_ENNEMI type, int Colonne, int Ligne)  
    {
       if(type > MOBS_MAX || type < 0)
                   ;//erreur
    EnnemiBase* Pointeur = CreateEnnemi[type](Colonne, Ligne);
    }
     
    void SupprimerEnnemi(int Colonne, int Ligne)
    {
              delete getEnnemi(colonne, ligne);
    }
     
    inline EnnemiBase * getEnnemi(int colonne, int ligne)
    {
            return tableau[colonne][ligne];//ou autre
    }
    Par contre, les majuscules en début de nom sont généralement réservée aux nom de classes, les variables, attributs, fonctions et méthodes commencent généralement par une minuscule.

    Tu n'es aussi pas obligé de créer une classe par mobs, tu peux aussi utiliser des design pattern politique.

  15. #15
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Il vaut mieux faire d'abord un test qui recherche la présence d'un ennemi à la position donnée et qui retourne un pointeur sur celui-ci ou NULL s'il ne trouve rien.
    Ensuite soit tu fait un simple delete, le destructeurs se chargeant lui-même d'enlever le mobs de tous les listes/tableaux et autres.
    Soit tu appelles une méthode de destruction qui devra à sa fin détruire l'objet mobs.
    Ce n'est pas forcément la méthode la plus efficace dans le cas qui nous intéresse, car il faut rescanner l'ensemble des ennemis à chaque pas pour vérifier ce fait. Étant donné qu'on les passe déjà tous en revue pour mettre à jour leur propre position et que, d'un autre côté, il n'y a qu'un seul joueur, il est plus intéressant de vérifier si, au moment de la mise à jour d'un ennemi, celui-ci n'atteint pas la position du joueur.

    Citation Envoyé par Hedg-Hop Voir le message
    Salut, j'ai rajouté une dernière modification:
    j'ai fais en sorte que si l'on est touché, on perd une vie, on supprime l'ennemi qui nous a touché, et on continue de jouer.

    Bref, comment supprimer l'ennemi ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void SuprimerEnnemi(int Colonne, int Ligne)
    {
          // Je met quoi ici ????
    }
    Étant donné que tu as créé l'ennemi avec new, il faut le supprimer avec delete et laisser le constructeur faire le ménage.

    Pour le reste, c'est une question de conception. Il faut donc remonter le fil de tes pensées, jusqu'à leur origine : tu es capable de gérer tes ennemis car tu les répertories tous dans une liste. Où se trouve cette liste ? C'est en fait une composante intrinsèque des ennemis eux-mêmes puisque chacun d'eux possède un champ suivant pour référencer le prochain. Tu as donc créé une liste chaînée.

    Comment retire-t-on un élément d'une liste chaînée ? En faisant pointer le maillon précédent directement sur le suivant (plutôt que sur soi-même), puis en libérant la ressource.

    Problème : quand tu examines un ennemi, tu peux te référer au maillon suivant (via le champ Suivant) mais pas au précédent, dont tu ignores l'identité, voire même l'existence si ton maillon est le premier de la chaîne.

    De là : trois solutions :

    • Soit tu ajoutes et maintiens un champ « Precedent » en plus de « Suivant », et tu formes donc une « liste doublement chaînée » ;
    • Soit tu maintiens, dans la boucle où tu passes en revue chaque ennemi, un pointeur vers l'ennemi du tour de boucle précédent. Ça te permet d'éviter d'avoir à le stocker de façon permanente pour rien. C'est la solution que je te préconise dans l'immédiat ;
    • Soit tu gères la liste en dehors de ta classe Ennemi (solution la plus propre) et tu utilises un container quelconque pour tenir la liste des pointeurs new que tu as défini. On purrait penser à un tableau style C par exemple, mais le plus indiqué en réalité consiste à utiliser les conteneurs de la STL, par exemple une liste « std::list<> ». Cela demande un tout petit peu d'apprentissage mais c'est le plus propre à long terme.

  16. #16
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Merci de vos conseil ! Je m'en suis sortie et j'ai terminé mon programme.
    Le système de vie fonctionne a merveille.

    Cependant: si le joueur à au début 5 vie:
    quand il se fait touché, le programme fait 5 bip (avec "\a"), puis s'il à 4 vie le programme émet 4 bip etc... c'est une façon de connaitre le nombre de vie qu'il nous reste.

    Y aurait-il plutôt un moyen d'afficher en petit par exemple en haut a droite le nombre de vie, ainsi même le temps dans la fenêtre ?
    (pas dans la fenêtre DOS, mais dans la fenêtre du labyrinthe)

    Avec glut je craint que ça ne soit pas possible, mais je demande on sais jamais

    Merci encore !

  17. #17
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    L'affichage de texte revient à afficher des images.

    Je n'ai jamais utilisé glut, il se peut qu'il ne gère pas les .ttf mais tu peux toujours créer tes propres images contenants des chiffres et les afficher par-dessus l'image de ta map.

  18. #18
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Tu peux essayer glutBitmapCharacter(), mais il faut initialiser une fonte au préalable.

  19. #19
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Qu'est-ce qu'une fonte ?

  20. #20
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par Hedg-Hop Voir le message
    Qu'est-ce qu'une fonte ?
    Une police de caractères.

    Et dans le cas présent, ça veut dire qu'il faut que tu la déclares d'une certaine façon à OpenGL. Je ne sais pas par cœur comment, donc je te laisse regarder la doc pour voir comment on fait. :-)

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. PyGame, quelques questions sans réponses
    Par Ziranium dans le forum Programmation multimédia/Jeux
    Réponses: 6
    Dernier message: 27/04/2011, 19h33
  2. Plusieurs questions sans réponses
    Par laposte dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 11/06/2010, 16h40
  3. questions sans réponses
    Par miroush dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 08/03/2010, 13h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo