Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Page 7 sur 15 PremièrePremière 123456789101112131415 DernièreDernière
Affichage des résultats 181 à 210 sur 448
  1. #181
    L'idée de créer un status "PlayerDead", c'est le genre de choses qu'il faut justement pas faire pour ne pas s'embrouiller

    À ta place je garderais ton idée plus haut : tu créé un objet "PlayerInfos", "PlayerProgression" ou "PlayerStats" (un nom comme ça)

    Tu créé une instance de celle-ci dans ton application principale, et ensuite tu la passes au constructeur de PlayScreen, qui la passe à son tour au constructeur de Player
    (une instance c'est le nom qu'on donne à un objet dont le type est la classe en question)
    Cette "technique" s'appelle de l'injection de dépendance (nom barbare qui désigne un truc très simple)

    Cette classe ("PlayerStats") contient l'XP, les ressources, etc. tout ce qui doit se garder d'une partie à l'autre
    Et la classe Player va lire et mettre à jour PlayerStats plutôt que de tout stocker elle-même
    Rust fanboy

  2. #182
    Citation Envoyé par Tomaka17 Voir le message
    L'idée de créer un status "PlayerDead", c'est le genre de choses qu'il faut justement pas faire pour ne pas s'embrouiller


    Citation Envoyé par Tomaka17 Voir le message
    À ta place je garderais ton idée plus haut : tu créé un objet "PlayerInfos", "PlayerProgression" ou "PlayerStats" (un nom comme ça)

    Tu créé une instance de celle-ci dans ton application principale, et ensuite tu la passes au constructeur de PlayScreen, qui la passe à son tour au constructeur de Player
    (une instance c'est le nom qu'on donne à un objet dont le type est la classe en question)
    Cette "technique" s'appelle de l'injection de dépendance (nom barbare qui désigne un truc très simple)

    Cette classe ("PlayerStats") contient l'XP, les ressources, etc. tout ce qui doit se garder d'une partie à l'autre
    Et la classe Player va lire et mettre à jour PlayerStats plutôt que de tout stocker elle-même
    Cette manière est en effet bien plus élégante je trouve, c'est pour ça que j'avais opté pour cette méthode en premier lieu
    Va maintenant falloir que j'arrive à faire marcher tout ça ! Merci

    ---------- Post added at 15h06 ---------- Previous post was at 13h59 ----------

    Citation Envoyé par Tomaka17 Voir le message
    L'idée de créer un status "PlayerDead", c'est le genre de choses qu'il faut justement pas faire pour ne pas s'embrouiller

    À ta place je garderais ton idée plus haut : tu créé un objet "PlayerInfos", "PlayerProgression" ou "PlayerStats" (un nom comme ça)

    Tu créé une instance de celle-ci dans ton application principale, et ensuite tu la passes au constructeur de PlayScreen, qui la passe à son tour au constructeur de Player
    (une instance c'est le nom qu'on donne à un objet dont le type est la classe en question)
    Cette "technique" s'appelle de l'injection de dépendance (nom barbare qui désigne un truc très simple)

    Cette classe ("PlayerStats") contient l'XP, les ressources, etc. tout ce qui doit se garder d'une partie à l'autre
    Et la classe Player va lire et mettre à jour PlayerStats plutôt que de tout stocker elle-même
    Je comprends pas bien quand tu dis "Tu créé une instance de celle-ci dans ton application principale, et ensuite tu la passes au constructeur de PlayScreen, qui la passe à son tour au constructeur de Player".
    Mon application principale pour moi il me semble que c'est PlayScreen, puisque c'est cette classe qui met à jour tout le monde et affiche tout le monde. Ensuite quand tu dis de passer au constructeur, tu veux dire de mettre en argument du constructeur un truc comme "PlayerProgression playerProgression" pour la classe PlayScreen et Player ?

  3. #183
    Citation Envoyé par Belhoriann Voir le message
    Je comprends pas bien quand tu dis "Tu créé une instance de celle-ci dans ton application principale, et ensuite tu la passes au constructeur de PlayScreen, qui la passe à son tour au constructeur de Player".
    Mon application principale pour moi il me semble que c'est PlayScreen, puisque c'est cette classe qui met à jour tout le monde et affiche tout le monde.
    Ce que tu appelles application principale n'est probablement pas PlayScreen, mais la toute première fonction qui est appelée quand tu exécutes le programme [need plus d'infos, y'a une fonction main en C# ?]. Peut-être celle qui lance le constructeur de PlayScreen.

    Citation Envoyé par Belhoriann Voir le message
    Ensuite quand tu dis de passer au constructeur, tu veux dire de mettre en argument du constructeur un truc comme "PlayerProgression playerProgression" pour la classe PlayScreen et Player ?
    Oui, au moins pour PlayScreen. Et aussi un attribut de type PlayerProgression, que tu initialises dans le constructeur avec ce nouvel argument, pour pouvoir utiliser facilement la nouvelle classe depuis PlayScreen (ex : mise à jour d'un attribut, ou récupération d'un attribut pour affichage).

  4. #184
    Quand tu construits ton PlayScreen en lui donnant un PlayerProgression, c'est comme si tu disais "je créé un objet qui se charge du déroulement du jeu, et je lui demande d'utiliser cet objet PlayerProgression pour stocker la progression du joueur"

    On pourrait se dire "comme il n'y a qu'un seul joueur de toutes manières, pourquoi ne pas créer une variable globale contenant mon PlayerProgression, et mon PlayScreen va mettre à jour cette variable globale directement"
    C'est un peu difficile à expliquer sans rentrer dans des détails bien chiants, mais faire ça, c'est mal, il vaut mieux le passer comme paramètre
    Rust fanboy

  5. #185
    Ok, c'est pas évident mais je crois avoir pigé. En gros, dans mon application principale, celle qui se lance quand je lance le jeu, je mets en haut :

    Code:
    PlayerProgression playerProgression;
    Et plus bas, dans "Initialize()" :

    Code:
    playerProgression = new PlayerProgression();
    Ensuite, je mets dans les constructeurs PlayScreen et Player ça :

    Code:
    public PlayScreen (PlayerProgression playerProgression)
    
    public Player (PlayerProgression playerProgression)
    J'ai bon ?

  6. #186
    Ouaip
    Tu mets la variable "playerProgression" comme membre de ta classe par contre, pas en globale (j'ai dit plus haut que c'était mal de mettre en global)

    Dans le constructeur de PlayScreen tu mets
    Code:
    player = new Player(playerProgression);
    Et dans Player tu rajoutes une variable membre pour stocker le PlayerProgression
    Quand le joueur gagne de l'XP ou ce genre de choses, tu le rajoutes dans PlayerProgression (en supposant que c'est la classe Player qui s'occupe de déterminer quand le joueur a fait un kill)
    Comme ça même quand le Player ou le PlayScreen sont détruits, le PlayerProgression existe encore et tu peux réutiliser le même la prochaine fois
    Rust fanboy

  7. #187
    Je viens encore vous demandez de l'aide :

    Comme convenu j'ai donc :
    - Créé ma classe PlayerProgression qui comporte le calcul de l'XP du joueur (et donc sa valeur)
    - J'ai créé une instance de cette classe dans la classe principal du jeu (à savoir Game1.cs, c'est la classe principal par défaut dans XNA) en écrivant "playerProgression = new PlayerProgression();" dans le constructeur de cette classe.
    - J'ai mis en argument des constructeurs Player et PlayScreen ceci : "PlayerProgression playerProgression".

    Vient maintenant le problème de l'affichage de l'XP via la méthode DrawString en bas de la classe PlayScreen. En gros j'essaie de faire comme ça :

    Code:
    string info = "XP : " + playerProgression.GetXP() + " Level : " + playerProgression.GetLevel() + " Kills: " + playerProgression.GetKills();
    Le truc c'est que évidemment il faudrait, pour que ça marche, créer une nouvelle instance de PlayerProgression au sein de PlayScreen. Là en faisant sans la création de cette instance j'ai une erreur du type "NullReferenceExeption" quand je lance une partie. Mais je ne veux pas recréer une instance "playerProgression = new PlayerProgression();" à chaque fois que PlayScreen se lance (cad à chaque fois qu'on fait Play Again quand on crève) pour justement éviter de remettre à 0 l'XP.
    J'ai donc relu ton post LaVaBo, là où tu parles de créer un attribut du type PlayerProgression. Ne connaissant pas du tout ce genre d'astuce de prog, j'ai fouiné un peu et vu qu'il fallait par exemple mettre ça en haut de la classe dont on veut récupérer des valeurs :

    Code:
    [AttributeUsage(AttributeTargets.All)]
        public class PlayerProgression : System.Attribute
    Comme fait-on pour pouvoir utiliser, avec les attributs, ma méthode "GetXP()" (qui revoit l'XP sous forme de string) dans PlayScreen sans avoir à créer une nouvelle instance de PlayerProgression ?

    EDIT : Ahah, je viens de voir qu'il est possible d'appeler une méthode d'une autre classe sans l'instancier simplement en la déclarant comme static !

    EDIT 2 : Wouhou ça marche
    Je ne sais pas si c'est très élégant, et pour l'instant je n'y vois pas d'inconvénient, mais j'ai tout mis en static dans PlayerProgression (variables telles que l'XP, les méthodes...) pour pouvoir appeler facilement les méthodes et les mettre à jour dans la classes PlayScreen.
    Du coup, quand je crève je garde bien mon XP quand je respawn. PROFIT !
    Dernière modification par Belhoriann ; 09/11/2011 à 00h51.

  8. #188
    Je n'ai pas suivi toute la conversation mais je ne vois pas trop où est le problème, ni comment tu peux te retrouver avec un nullReferenceException.

    Tu n'as qu'à instancier un playerProgression dans le constructeur de StarShooterGame (et non pas dans Initialize(), à mon avis ton nullReference vient de là) et après le passer en paramètre dans les constructeurs des classes qui l'utilisent.

    C'est plus élégant que d'utiliser des méthodes statiques et tu es sûr que ce dont tu as besoin sera accessible partout.

    Et je ne vois pas trop l'intérêt d'utiliser des attributs pour ça.

    Dans le truc que je code actuellement, j'ai quelque chose comme :

    Game.cs
    --->World.cs
    ------>PlayerEntity.cs

    Et bien le constructeur de la classe World prend en paramètre Game, le constructeur de la classe PlayerEntity prend en paramètre la classe World, etc...

    Après, dans chaque classe, le "parent" est stocké comme référence (publique) ce qui permet si nécessaire de "remonter" jusqu'à Game.

  9. #189
    Citation Envoyé par Belhoriann Voir le message
    EDIT 2 : Wouhou ça marche
    Je ne sais pas si c'est très élégant, et pour l'instant je n'y vois pas d'inconvénient, mais j'ai tout mis en static dans PlayerProgression (variables telles que l'XP, les méthodes...) pour pouvoir appeler facilement les méthodes et les mettre à jour dans la classes PlayScreen.
    Du coup, quand je crève je garde bien mon XP quand je respawn. PROFIT !
    Citation Envoyé par Tomaka17 Voir le message
    On pourrait se dire "comme il n'y a qu'un seul joueur de toutes manières, pourquoi ne pas créer une variable globale contenant mon PlayerProgression, et mon PlayScreen va mettre à jour cette variable globale directement"
    C'est un peu difficile à expliquer sans rentrer dans des détails bien chiants, mais faire ça, c'est mal, il vaut mieux le passer comme paramètre
    Tu noteras que j'avais anticipé le fait que tu ferais ça
    Absolument personne n'aime les variables globales (les classes avec tout en static et les singleton c'est la même chose)

    Je vois pas trop où tu as pu faire une connerie
    Je n'ai jamais fait de C# mais en principe tu devrais faire quelque chose qui ressemble à ça :

    Game1.cs :
    Code:
    public class Game1 {
        PlayerProgression playerProgression;
        PlayScreen playScreen;
        
        public Game1() {
            playerProgression = new PlayerProgression();
            playScreen = new PlayScreen(playerProgression);
        }
    };
    PlayScreen.cs :
    Code:
    public class PlayScreen {
        PlayerProgression playerProgression;
        
        public PlayScreen(PlayerProgression p) {
            playerProgression = p;
        }
    };
    L'objet 'p' que tu reçois dans le constructeur de PlayScreen sera le même que celui que tu as créé dans Game1
    Rust fanboy

  10. #190
    Merci Tomaka sur le pourquoi du comment de l'inconvénient des variables globales.

    Seulement cela veut dire aussi que chaque instance a en mémoire son parent, et donc utilise de la mémoire pour ça (à priori). Quid quand on commence à faire des milliers d'instances (genre des pnj) possédant chacun une ou plusieurs références aux parents et autres objets indispensables à son fonctionnement (mais qui font appel à un objet unique) ?

    L'avantage de l'objet statique (donc unique) est de l'appeler "facilement" quand on en a besoin, et donc ne pas s'embarrasser de l'avoir en mémoire. Et il me semble que quand il faut débugger, si on appelle World.getWorld().faitActionX(), World.getWorld() étant l'appel à un objet statique unique, on sait de quoi on cause, je ne vois pas les problèmes de compréhension (je fais référence au second lien de Tomaka).
    I am Moanaaaaaaa !!! (et en version legit!)

  11. #191
    Merci à LFS et Tomaka ! Ma structure est en effet comme vous dites, mais j'ai mis en static toute la classe PlayerProgression pour pouvoir accéder facilement à ses méthodes comme le dit Teto.

    Si je fais comme tu dis Tomaka, c'est à dire ça :

    Code:
    public class PlayScreen {
        PlayerProgression playerProgression;
        
        public PlayScreen(PlayerProgression p) {
            playerProgression = p;
        }
    };
    J'ai un problème quand j'écris ça dans la zone Update() de PlayScreen :

    Code:
        
    p.TotalKilled();
    p.CheckXP();
    p.CheckLevel();
    Se sont 3 méthodes de la classe PlayerProgression que j'ai besoin d'appeler pour mettre à jour les infos du joueurs. Mais j'ai une erreur qui dit :

    Le nom 'p' n'existe pas dans le contexte actuel
    De plus j'ai besoin d'accéder à d'autres méthodes de la classe PlayerProgression dans la classe de chaque ennemie, pour mettre à jour le compteur de kills de chaque type de vaisseau. C'est pour ça que mettre en static je trouvais ça super pratique.

    Je suis bien conscient que mes problèmes viennent d'un manque de connaissances basiques en programmation, et quand j'aurai bien tout compris ça me paraîtra trivial

    EDIT : My bad, c'est pas p.TotalKilled(); qu'il faut écrire mais plutôt playerProgression.TotalKilled();
    Pas évident de programmer en sortant du lit.
    Dernière modification par Belhoriann ; 09/11/2011 à 10h28.

  12. #192
    Citation Envoyé par Teto Voir le message
    Merci Tomaka sur le pourquoi du comment de l'inconvénient des variables globales.

    Seulement cela veut dire aussi que chaque instance a en mémoire son parent, et donc utilise de la mémoire pour ça (à priori). Quid quand on commence à faire des milliers d'instances (genre des pnj) possédant chacun une ou plusieurs références aux parents et autres objets indispensables à son fonctionnement (mais qui font appel à un objet unique) ?

    L'avantage de l'objet statique (donc unique) est de l'appeler "facilement" quand on en a besoin, et donc ne pas s'embarrasser de l'avoir en mémoire. Et il me semble que quand il faut débugger, si on appelle World.getWorld().faitActionX(), World.getWorld() étant l'appel à un objet statique unique, on sait de quoi on cause, je ne vois pas les problèmes de compréhension (je fais référence au second lien de Tomaka).
    Je suis aussi contre le fait que chaque objet ait en mémoire son "parent"

    Pour moi si un objet a besoin d'un pointeur vers son propriétaire c'est qu'il y a déjà un problème dans le schéma, puisque cela force l'objet à être utilisé dans une situation précise. Idéalement un objet ne devrait pas savoir quel est son propriétaire.
    Je pense que n'importe quel problème a une solution "propre", qui ne nécessite ni variable globale, ni couplage interface-implémentation, etc. il faut juste la trouver et ne pas forcément se réfugier vers sa première idée. Évidemment IRL t'as pas forcément le temps de réfléchir à une solution propre (euphémisme), et c'est justement ça la cause de nombreux bugs.

    Par exemple si tu as des milliers de PNJs, pourquoi ne pas stocker leurs infos dans une simple structure et les mettre à jour depuis l'extérieur plutôt que d'appeler des fonctions "Update".


    Et pour Belhoriann : la variable "p" n'existe que dans le constructeur, c'est pour ça qu'on en fait une copie dans "playerProgression". Il faut donc que tu utilises "playerProgression" dans ta fonction Update. Bon après tu fais comme tu veux...
    Rust fanboy

  13. #193
    Citation Envoyé par Tomaka17 Voir le message
    Et pour Belhoriann : la variable "p" n'existe que dans le constructeur, c'est pour ça qu'on en fait une copie dans "playerProgression". Il faut donc que tu utilises "playerProgression" dans ta fonction Update. Bon après tu fais comme tu veux...
    Oui oui j'ai vu ça, j'ai édité mon post. V'la le gros noob
    Merci en tout cas, ces discussions m'en apprennent beaucoup, et j'espère que c'est le cas pour tout les autres noob ici.

  14. #194
    Pour répondre à ta question, c'est parce que la variable p n'est connue que dans le cadre de la fonction du constructeur. C'est un point de programmation important mais pas instinctif : la portée d'une variable (ça rejoint la problématique de Tomaka17 sur les variables globales). Dans ta classe PlayScreen, l'instance de PlayerProgression s'appelle playerProgression, et pas du tout p. p existe uniquement dans le constructeur de PlayScreen, or lorsque tu appelles les fonctions TotalKilled() ou CheckXP(), j'imagine que tu n'es plus dans le constructeur.

    Sinon, un dernier point : dans les best practices, la règle de nommage est de commencer par une minuscule, pour les variables et pour les methods. L'écriture du nom en minuscule commençant par une majuscule est dédiée aux noms de classes (et évidemment au prototype du constructeur de la classe). Et les noms de variables entièrement en majuscules pour les constantes, qui sont positionnées une fois et ne sont plus modifiées ensuite (ex : définition manuelle de pi, ou un string de titre de menu).

  15. #195
    Wokay, ça marche !
    Ce coup ci, plus de static dans tous les sens, juste une instance au tout début, et des constructeurs qui trimbalent une variable PlayerProgression p.
    J'avais une erreur nullReferenceException parce que j'avais oublié de créer cette variable dans les constructeurs des écrans intermédiaires du jeu. En gros on a :

    Game1.cs (Création de l'instance new PlayerProgression())
    -->MainMenuScreen.cs (C'est ici que j'avais oublié de mettre playerProgression dans le constructeur pour faire le pont, car c'est à partie de MainMenuScreen que l'on lance PlayScreen qui a en argument playerProgression)
    ---->PlayScreen.cs

    Mais si j'ai bien compris, Tomaka tu as un problème avec cette méthode ?

  16. #196
    J'ai dit que j'avais un problème avec les variables globales, classes avec que des fonctions statiques, singleton, etc. (problème c'est un grand mot, je suis juste contre, si on me demande de faire des modifs sur un programme qui utilise cette méthode je vais pas tout chambouler par exemple)

    Dans ton cas il y a juste un truc "pas propre", c'est le fait que MainMenuScreen créé et stocke PlayScreen. Après tout, il n'est pas logique que le menu principal soit propriétaire du jeu. Il vaudrait mieux que quand tu cliques sur "Commencer la partie", ça envoie un "message" à Game1 sous la forme d'un callback (soit du genre "début de partie demandé", soit en renvoyant le PlayScreen créé sous la forme d'un pointer vers une interface), et c'est Game1 qui stocke le PlayScreen.
    Note : ne te sens pas du tout obligé de changer ça, c'est un détail. Les problèmes qui en découlent tu ne les ressentiras éventuellement que si tu fais un très gros programme
    Rust fanboy

  17. #197
    Je commence à comprendre ce que tu veux dire. En fait, ta philosophie c'est "Chacun son métier, les vaches seront bien gardées".
    A (World) crée B (GUI) et C (écran de jeu).
    C n'a pas à savoir ce qu'est B, en revanche il connait A, qui l'a crée.
    Donc une bonne logique de programmation c'est:
    - C vient de recevoir la commande que le joueur a appuyé sur "play".
    - C envoie donc cette commande à A, en lui disant "coco, le joueur a appuyé sur play, fais ce qu'il faut pour lancer l'écran de jeu".
    - A se débrouille ensuite avec B qu'il a crée pour afficher l'écran.

    Dans ces conditions effectivement, cela rend le travail de débogage bien plus efficace. Car sinon, si C squeeze A pour donner des ordres directement à B, ce serait vite le bordel sur de gros projets. Comme dans la vrai vie, en somme.
    I am Moanaaaaaaa !!! (et en version legit!)

  18. #198
    Ouais, d'un point de vue conceptuel c'est bien propre. Cependant niveau programmation j'imagine que cela demande un certain doigté que je ne possède pas. Alors je vais laisser les choses comme ça, mon premier jeu ne sera de toute façon jamais un énorme programme

  19. #199
    (EDIT : en réponse à Teto)
    Exactement

    Si on veut ma philosophie c'est :
    - je conçois d'abord l'interface d'une classe avant son implémentation (l'interface c'est la façon dont la classe communique avec les autres, c'est à dire ses fonctions publiques, son rôle, etc.)
    - ne surtout pas créer l'interface en ayant en tête la façon dont ça va fonctionner en interne, surtout pas, il faut que ce soit le fonctionnement qui s'adapte à l'interface
    - j'essaye de faire une interface aussi simple et réduite que possible (pour réduire les bugs dus aux incompréhensions)
    - moins une classe utilise d'autres classes dans son interface, mieux ça vaut (couplage faible)
    EDIT: - dans un programme idéal, tu devrais pouvoir créer deux instances de la classe principale (ici Game1) et les exécuter en simultané sans que cela ne pose de problème

    C'est un peu abstrait, je suis pas sûr d'avoir bien expliqué le truc, mais ça fait partie de mes "good practices"


    Encore un EDIT : au passage je pense que mes good practices vont bien évoluer avec l'introduction vraisemblable des modules dans la prochaine version de C++ (C++16 ?)
    Dernière modification par Tomaka17 ; 09/11/2011 à 11h50.
    Rust fanboy

  20. #200

  21. #201
    Citation Envoyé par Belhoriann Voir le message
    Ouais, d'un point de vue conceptuel c'est bien propre. Cependant niveau programmation j'imagine que cela demande un certain doigté que je ne possède pas. Alors je vais laisser les choses comme ça, mon premier jeu ne sera de toute façon jamais un énorme programme
    Ouais. Mais je te recommande vivement de prendre de bonnes habitudes tout de suite. Tomaka et d'autres programmeurs pourront te confirmer que quand tu prends des habitudes, après pour les changer c'est la plaie (d'Égypte). Tu pars quand même sur un petit jeu qui va te prendre du temps, parce que tu apprends. Si tu assimiles des choses qui fonctionnent mais qui sont crades, ce sera beaucoup plus difficile pour toi de "désapprendre". Ne serait-ce que parce que tu voudras aller vite, et t'auras "pas le temps" de penser à ta manière de programmer.

    Surtout que si ton jeu fonctionne bien, tu seras plus ambitieux pour le suivant, et là tes mauvaises habitudes te reviendront à la face.

    Exemple mylife : J'ai appris le graphisme avec The Gimp et la souris. Pour dessiner, le top c'est quand même le crayon. Je me suis acheté une tablette. Elle prend la poussière. Pourquoi ? J'avais tellement appris à dessiner avec une souris que je n'arrivais à rien avec un stylet. Pathétique.
    I am Moanaaaaaaa !!! (et en version legit!)

  22. #202
    Je suis entièrement d'accord avec toi, c'est d'ailleurs pour cela que j'ai abandonné le truc des méthodes static pour quelque chose de plus propre, comme suggéré par Sebum et Tomaka. Mais j'ai pu le faire parce que j'avais suffisamment de connaissance technique pour y arriver. Dans le cas des callbacks, n'y connaissant strictement rien, je préfère ne pas les utiliser de peur de m'y embourber et de me décourager rapidement.

  23. #203
    Pas le temps de développer (boulot) mais rien de sorcier. C'est un jargon pour dire "Je donne des actions/demandes à mon parent, et il s'en démerde".

    Tu vas avoir beaucoup plus de mal avec les gestions d'événements, crois-moi (c'est d'ailleurs un peu la même chose). Une fois compris, c'est ultra-simple à s'en servir, mais faut comprendre, sinon ça ne fonctionne pas ou sa bogue et on ne sait pas pourquoi.
    I am Moanaaaaaaa !!! (et en version legit!)

  24. #204
    Le principe d'un callback, c'est que plutôt qu'une classe fasse une action elle-même, c'est son propriétaire qui lui dit quelle action effectuer

    Imagine par exemple que tu as une classe "Bouton". Quand l'utilisateur clique sur un bouton, la classe le détecte, mais plutôt que d'effectuer l'action elle-même, elle va signaler à son propriétaire qu'on lui a cliqué dessus, et c'est le propriétaire qui fait ce qu'il faut faire. Ça permet d'avoir des classes plus génériques, et ça c'est le bien

    Encore une fois je n'ai jamais fait de C#, mais par exemple en C++ ça donnerait grosso-modo ça :
    Code:
    class Menu {
       Bouton boutonJouer;
       Bouton boutonOptions;
       Bouton boutonQuitter;
    
       Menu() {
          // constructeur de la classe Menu
    
          // on dit au bouton jouer ce qu'il doit faire quand on lui clique dessus
          boutonJouer.setActionCallback([&]() {
              // le code ici sera exécute quand on clique sur le bouton jouer
              jouer();
          });
    
          // pareil pour les autres boutons
          boutonOptions.setActionCallback([&]() {
              ouvrirOptions();
          });
    
          boutonQuitter.setActionCallback([&]() {
              exit();
          });
       } 
    
       void jouer() {
          ...
       }
    
       void ouvrirOptions() {
          ...
       }
    };
    Code:
    class Bouton {
        std::function<void ()>   callback;     // variable dans laquelle on va stocker le callback, ne prête pas attention au type un peu bizarre, c'est du C++
        
        void setActionCallback(std::function<void ()> cb) {
            callback = cb;
        }
        
        void clickDetecte() {
            // on a détecté un click !
            // on appelle le callback
            callback();
        }
    };
    De cette façon tu as la même classe "Bouton" qui sert à la fois aux boutons Jouer, Options et Quitter.

    Parfois tu peux aussi croiser du code basé sur les événements : le bouton déclenche un événement nommé "click" qui est détecté par son propriétaire. C'est une variante qui a ses avantages et ses inconvénients.

    Un autre avantage des "good practices" dont on parle depuis 3 pages c'est que tu arrives assez vite à des classes "définitives", c'est-à-dire que tu n'as plus besoin de les modifier par la suite. Là par exemple je code une fois la classe Bouton, et après je n'ai plus besoin d'y toucher. Alors que si je n'utilise pas de callback je suis obligé de modifier la classe Bouton à chaque fois que je rajoute un bouton dans le menu.
    Rust fanboy

  25. #205
    Je veux pas vous faire chier, mais vous pourriez pas créer un autre topic pour parler de tout ça ? C'est un peu hors-sujet je trouve : vous ne parlez pas de la rubrique du mag et je suis bien certain que les débutants dans mon genre ne comprennent pas un mot de ce que vous racontez. Or cet espace leur est destiné si j'ai bien compris. Après, ceux qui sont plus avancés peuvent demander des conseils bien sûr mais en faire des pages et des pages c'est un peu lourd... Voilà, vous pouvez me balancer des pierres ou des termes abscons maintenant

  26. #206
    Nan, t'as parfaitement raison.
    I am Moanaaaaaaa !!! (et en version legit!)

  27. #207
    Citation Envoyé par Raddi Voir le message
    Je veux pas vous faire chier, mais vous pourriez pas créer un autre topic pour parler de tout ça ? C'est un peu hors-sujet je trouve : vous ne parlez pas de la rubrique du mag et je suis bien certain que les débutants dans mon genre ne comprennent pas un mot de ce que vous racontez. Or cet espace leur est destiné si j'ai bien compris. Après, ceux qui sont plus avancés peuvent demander des conseils bien sûr mais en faire des pages et des pages c'est un peu lourd... Voilà, vous pouvez me balancer des pierres ou des termes abscons maintenant
    Tu n'es pas seul

  28. #208
    Arf, je m'excuse d'avoir un peu monopolisé le topic avec mes soucis
    Cela dit moi aussi je débute, et je pense que notre discussion contient de nombreuses informations importantes, alors profitez en au lieu de pleurer
    Mais dans le fond vous avez raison, la prochaine fois que j'ai besoin d'aide sur mon jeu, je créerai un topic dédié.

  29. #209
    Je te conseille même de créer un topic de ton jeu qui te servira aussi de blog. Plein de canards font ça et ça marche bien.
    I am Moanaaaaaaa !!! (et en version legit!)

  30. #210
    Bonjour, suite à la découverte de la rubrique développez couché, je me suis motivé pour la suivre et assouvir un vieux rêve: coder des jeux sérieusement.

    J'ai téléchargé les outils sans problème, et compilé le monochrome. Par contre, je n'arrive pas à lancer Lapin sur un fond gris.

    Voici une capture du code et de l'explorateur de fichier:


    Normalement, il ne manque rien, pourtant j'obtiens le message d'erreur suivant:
    Code:
    Error loading "gros_lapin.png". File not found.
    Une bonne âme qui aurait une idée ?

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •