Partage
  • Partager sur Facebook
  • Partager sur Twitter

Scrutation et evenements

    18 avril 2011 à 19:38:13

    Bonjour à tous,


    Je suis en train d'apprendre le C# mais je bloque un peu sur la notion d'événements. Enfin, je la comprend quand il s'agit de l'utiliser pour le design de l'interface graphique, mais je n'arrive pas à créer mes propres évenements encore.

    Histoire d'illustrer, en lisant un des tutos, je m'étais entrainer à réaliser l'exemple proposé ici (http://www.siteduzero.com/tutoriel-3-419399-travaux-pratique-le-jeux-de-role.html) à savoir la création d'un mini jeu de rôle.

    Pour la maîtrise des windows form, je me suis dit que comme j'avais passé pas mal de temps à coder le tp jdr, il serai plutôt intéressant de lui donner une interface graphique. Ce que je me suis occupé à faire

    Grosso modo, j'ai créé un nouveau projet dans lequel j'ai ramené tout ce que j'avais codé, j'ai commencé à codé l'interface dans le designer, ça ressemble à ça.
    WindowsForm

    Le code du Form1.cs est le suivant
    public partial class Form1 : Form
        {
            monHero Hero;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void create_hero_Click(object sender, EventArgs e)
            {
                Hero = new monHero(HeroName.Text, 100);
                create_hero.Enabled = false;
                HeroName.Enabled = false;
                status_label.Text = string.Format("Nom : {0}, PV : {1}", Hero._nom, Hero._pv);
                label1.Text = string.Format("X:{0},Y:{1}", Hero._positionX, Hero._positionY);
            }
    
            private void up_button_Click(object sender, EventArgs e)
            {
                Button senderButton = (Button)sender;
                switch (senderButton.Name)
                {
                    case "up_button":
                        Hero.Deplacer(0);
                        break;
                    case "down_button":
                        Hero.Deplacer(1);
                        break;
                    case "left_button":
                        Hero.Deplacer(2);
                        break;
                    case "right_button":
                        Hero.Deplacer(3);
                        break;
                }
                label1.Text = string.Format("X:{0},Y:{1}", Hero._positionX, Hero._positionY);
            }
        }
    


    Jusqu'ici tout fonctionne donc mais je voudrai que par exemple, quand on arrive en position XY (3,2) par exemple, le hero tombe sur un piege par exemple et perde un certain nombre de point de vie.

    Est ce que ça ne serai pas créer un évenement donc qui scrute les valeurs de Hero._positionX et Hero._positionY. Celui ci se déclenche quand on a l'égalité et s'occupe de retrancher 20 à ma variable Hero._pv par exemple.

    Comment puis-je procéder ?

    Autre question : il faut que je rafraichisse manuellement mon label pour qu'il puisse me donner les positions exacte du joueur. Est ce que je pourrai pas créer une sorte de scrutation ? Genre le label scrute constament les variables Hero._positionX et Hero._positionY et se met à jour automatiquement.
    • Partager sur Facebook
    • Partager sur Twitter
      18 avril 2011 à 20:36:44

      Salut!

      Alors ton problème, je crois, est que tu comprends la gestions des évènements à l'envers!

      Un évènement n'écoute rien. C'est toi qui écoute l'évènement.

      Une façon de procédé pour ton problème :
      -Dans ta classe Hero, tu as un évènement HeroDeplacer qui sera lancer à chaque fin de la méthode "Déplacer"
      -Dans ta Form1, tu écoute cet évènement.
      -Quand tu "Attrapes" l'évènement, tu fait les changement nécessaires, soit le rafraîchissement du label, changer le nombre de points de vie du héro, etc.

      Je te laisse chercher comment créer les évènements, autant pour que tu aprenne, que je ne sais pas comment les faire en VB :euh: .

      Cependant, tu ne pourras pas utiliser les évènement comme tu l'entends.
      • Partager sur Facebook
      • Partager sur Twitter
        18 avril 2011 à 23:31:48

        Ca veut dire que dans ma methode "Deplacer" il faut que je crée un truc à base de "if" ?

        Genre faire un test avec un "if" sur les position et si la condition est rempli, je retire des hp ? N'y a-t-il pas une autre méthode ? (ou alors j'ai mal compris ton explication), parce que si je dois faire les scrutation moi même sur mes variables, ça veut dire que ça va devenir super compliqué si je dois surveiller beaucoup de choses en même temps.

        Quand je programmait en C sur microcontrolleur on avait un truc qui s'appelait les interruption, ça se déclenchait à la fin d'un timer par exemple ou au changement d'état d'une sortie. Peut être que je part dans le mauvais sens parce que j'essai de faire le rapprochement avec ce fonctionnement. Dans ma tête un événement serai une fonction qui scruterai des changements et quand le changement interviens, lance un travail à effectuer. Pour cet exemple, selon cette logique là, je scruterai la position et le travail à effectuer serai d'enlever des points de vie. Mais je ne sais pas si c'est le fonctionnement réel des événements en C#

        J'ai un peu de mal à la compréhension, je sors de deux ans de programmation bas niveau (assembleur et C) et la POO c'est encore tout frais pour moi. Alors je veux bien un éclaircissement sur les events (ou de la lecture), les tutos que j'ai pu lire n'ont pas vraiment réussi à m'éclaire sur le fonctionnement exacte des events et dans ma phase d'analyse, j'ai un peu du mal à cerner qui déclenche l'événement, qui le reçoit et quelles sont les informations que transporte mon événement (dans le cas du déplacement par exemple).
        • Partager sur Facebook
        • Partager sur Twitter
          18 avril 2011 à 23:53:13

          Je crois que tu as bien compris le principe des évènements, mais que ne sais pas trop comment l'appliquer.

          Tu peux voir l'évènement comme une interruption système. C'est pas ça en tant que tel, mais si ça t'aide à comprendre, on va faire comme ça.

          Alors,

          Non, ce ne sera pas un fratra de if.

          Imagine ton Hero comme le bouton.
          Pour le bouton, le fonctionnement est ainsi : Tu cliques sur le bouton, le bouton lance un évènement "Click". Ta Form "attrape" l'évènement et fait le traitement nécessaire.
          C'est la même chose pour ton Objet Hero.
          Lorsque tu fait "Déplacer" (le Click) ton hero lance un évènement que ta Form attrape. Suite à cela, tu fait du traitement nécessaire.

          Sinon, je n'ai pas lu le tuto VB du sdz, mais à ce qu'on en parle, il est très bon, tu pourras passer jeté un coup d'oeil.
          • Partager sur Facebook
          • Partager sur Twitter
            19 avril 2011 à 15:16:38

            Je suis sur du C# là, pas sur du VB .NET, le tuto parle de C# ?


            Je commence à cerner un petit peu mieux le truc avec ton explication, mais cependant le traitement n'est pas prévu à chaque déplacement. Comment l'évenement va savoir que dans un cas il faut traiter et dans l'autre il n'y a rien à faire ?

            Comme tu dis, ça sera ma Form qui attrapera l'evenement de la même façon que celle ci attrape les click sur les boutons de mon interface.

            Je vais donc créer une nouvelle fonction du genre
            private void piege(object sender, EventArgs e)
                    {
                        Hero._pv-=20;
                    }
            


            Ça ressemblerai à ça ?

            Mais tu me dit que c'est mon hero qui va lancer l'evenement, comment je fais ça ?

            Les tutos C# présent sur le SdZ s'arrête très brievement sur la notion d'évenement et parle surtout des evenements genre boutons sur la Form. Pas d'evenement personnalisés comme ici par exemple.
            • Partager sur Facebook
            • Partager sur Twitter
              19 avril 2011 à 15:33:10

              AH! t'es en C#, tant mieux! (je sais pas pourquoi, j'avais pris pour acquis que c'était du VB... :-° )

              Dans ta classe Hero
              public delegate void HeoDeplacer(); //Type delegate qui se charge de l'évènement, c'est comme le EventArgs
              public event HeroDeplacer eventHeroDeplacer; //l'évènement en tant que tel
              protected virtual void OnHeroDeplacer()
              {
                 if (eventHeroDeplacer!= null)
                 {
                    eventHeroDeplacer();  // Notify Subscribers
                  }
              }
              


              Ici, l'évènement est créer. Maintenant, il faut le lancer :
              Encore dans Hero
              public void deplacer()
              {
                 // Traitement [...]
                 OnHeroDeplacer(); //L'évènement est lancer!
              }
              


              Finalement, dans ta forme, tu doit associer l'évènement à une méthode.

              Hero = new monHero(HeroName.Text, 100);
              Hero.eventHeroDeplacer += HeroDeplacer //Ici, c'est le nom de la méthode
              


              Et finalement, le traitement :

              private void HeroDeplacer() //éxecuter a chaque fois que l'évènement eventHeroDeplacer  est lancé
              {
                 ///...
              }
              


              Si t'as d'autre question, n'hésite pas.

              EDIT : Si tu veux faire un traitement par rapport au coordonnés du Hero, tu peux mopdifier l'évènement comme ceci :

              public delegate void HeoDeplacer(int positionX, int positionY); //Type delegate qui se charge de l'évènement, c'est comme le EventArgs
              public event HeroDeplacer eventHeroDeplacer; //l'évènement en tant que tel
              protected virtual void OnHeroDeplacer(int positionX, int positionY)
              {
                 if (eventHeroDeplacer!= null)
                 {
                    eventHeroDeplacer(_X, _Y);  // Notify Subscribers, avec les position X et Y du hero
                  }
              }
              


              Ensuite, dans la form :
              private void HeroDeplacer(int x, int y) //éxecuter a chaque fois que l'évènement eventHeroDeplacer  est lancé
              {
                 // traitement avec x et y du hero. Ça évite d'aller les rechercher, et c'est même mieux en fait comme ça.
              }
              
              • Partager sur Facebook
              • Partager sur Twitter
                19 avril 2011 à 16:30:23

                Citation : Neirbo

                Comment l'évenement va savoir que dans un cas il faut traiter et dans l'autre il n'y a rien à faire ?


                Ce n'est justement pas à l'événement de savoir ça.
                Un événement est un signal envoyé par un objet, qui peut donner lieu à une ou plusieurs opérations dont l'objet se moque éperdument. Pense à un feu rouge qui passe au vert: il envoie son signal "Je passe au vert !" et se fiche de savoir combien de voitures ou de piétons étaient en attente (s'il y en avait), ou après combien de temps ils vont effectivement démarrer.
                C'est pareil ici: tu ne peux pas faire de suppositions sur les cas qui intéressent ou non les éventuels objets qui écoutent l'événement. Tu peux juste te contenter de balancer l'événement, avec suffisamment d'infos pour décrire la situation et donc permettre à un autre objet de déterminer éventuellement s'il y a quelque chose à faire ou pas.

                @M4N!aC:
                C'est une mauvaise pratique de définir des nouveaux types de delegates, et même, dans le cas des événements, d'utiliser autre chose que le type EventHandler (ou sa forme générique). C'est aussi une mauvaise pratique de préfixer le nom de ses événements avec "event".
                Ainsi que d'utiliser du français pour son code, mais je m'arrête là sinon on va me prendre pour un intégriste :p

                Ton code devrait donc plutôt s'écrire

                // devrait être en Anglais, mais bon
                public event EventHandler HerosDeplacé
                
                protected virtual void RaiseHeroDeplacé()
                {
                    if (HerosDeplacé != null)
                    {
                        HerosDeplacé(this, EventArgs.Empty);  // Notify Subscribers
                    }
                }
                

                S'il y a des paramètres à transmettre, on crée une nouvelle classe dérivée de EventArgs:

                public class HerosDeplacéEventArgs : EventArgs
                {
                    public HerosDeplacéEventArgs(int positionX, int positionY)
                    {
                        this.PositionX = positionX;
                        this.PositionY = positionY;
                    }
                
                    public int PositionX { get; private set; }
                    public int PositionY { get; private set; }
                }
                

                Et on déclare et envoie l'événement comme ceci:

                public event EventHandler<HerosDeplacéEventArgs> HerosDeplacé
                
                protected virtual void RaiseHeroDeplacé(int positionX, int positionY)
                {
                    if (HerosDeplacé != null)
                    {
                        HerosDeplacé(this, new HerosDeplacéEventArgs(positionX, positionY));
                    }
                }
                

                Le objets qui souscrivent à l'événement doivent ainsi implémenter une méthode qui respecte la signature classique:

                private void OnHerosDeplacé(object sender, HerosDeplacéEventArgs e) 
                {
                   // Les arguments de l'événement sont dans le paramètre "e", comme toujours.
                }
                

                • Partager sur Facebook
                • Partager sur Twitter
                  19 avril 2011 à 16:36:41

                  Pour la mauvaise pratique.. pourquoi? Il y a énormément d'exemple comme ça sur internet qui démontre cette utilisation. Pas une critique, je m'informe ^^ .

                  Pour le français et le event, je sais, mais c'est du copier-collé arranger pour le cas présent... normes d'entreprise bizarre, quand tu nous tiens >_<

                  Mais oui... pourquoi est-ce mauvais? Moins performant? Ou c'est juste au niveau de la lisibilité?

                  EDIT : autant pour moi, j'viens de remarquer que j'ai pas lu les exemple a moitié >_<
                  • Partager sur Facebook
                  • Partager sur Twitter
                    19 avril 2011 à 16:44:31

                    Pour une question d'uniformité :) Ce sont des conventions qu'il vaut mieux s'efforcer de respecter pour ne pas surprendre d'autres développeurs qui pourraient lire ce code.

                    Si tu observes les classes du framework .Net, tu verras qu'elles respectent toutes ces conventions au pied de la lettre (à l'exception de certains types qui datent des premières versions). Tu ne verras jamais un événement préfixé avec "event" par exemple. Puisque tous les développeurs .Net sont amenés à manipuler ces classes de façon plus ou moins intensive, on considère c'est un exemple à suivre et qu'il faut donc éviter de faire autrement pour le reste du code ;)
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      19 avril 2011 à 16:45:11

                      Citation : M4N!aC

                      Pour la mauvaise pratique.. pourquoi? Il y a énormément d'exemple comme ça sur internet qui démontre cette utilisation. Pas une critique, je m'informe ^^ .

                      Pour le français et le event, je sais, mais c'est du copier-collé arranger pour le cas présent... normes d'entreprise bizarre, quand tu nous tiens >_<

                      Mais oui... pourquoi est-ce mauvais? Moins performant? Ou c'est juste au niveau de la lisibilité?


                      Le framework .NET entier utilise les EventHandler, ainsi que les librairies tierces.
                      Y a ça comme doc : http://msdn.microsoft.com/en-us/library/w369ty8x.aspx même si c'est un peu court (je dois avouer que j'ai toujours pas trouvé d'endroit qui regroupe toutes les conventions de nommage ou d'écriture en C# sur MSDN...)
                      Et puis le "event" au début du nom c'est de la notation hongroise, c'est le Mal incarné :-°
                      • Partager sur Facebook
                      • Partager sur Twitter
                        19 avril 2011 à 16:47:38

                        Citation : Aethec

                        (je dois avouer que j'ai toujours pas trouvé d'endroit qui regroupe toutes les conventions de nommage ou d'écriture en C# sur MSDN...)


                        Quelque chose comme ça: Instructions de conception pour le développement de bibliothèques de classes ?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          19 avril 2011 à 16:48:28

                          Citation : Aethec


                          Et puis le "event" au début du nom c'est de la notation hongroise, c'est le Mal incarné :-°


                          Pas de misère à y croire... quand on se fait imposer des normes par un analyste qui dit qu'utiliser des Objet .Net, c'est pas objet o_O
                          • Partager sur Facebook
                          • Partager sur Twitter
                            19 avril 2011 à 16:57:03

                            Je sens que c'est un lien qu'on va communiquer souvent :p
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Scrutation et evenements

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown