Gestion du clavier

Résolu
cs_Tomvan Messages postés 3 Date d'inscription lundi 24 mai 2010 Statut Membre Dernière intervention 5 juillet 2010 - 4 juil. 2010 à 16:23
cs_Tomvan Messages postés 3 Date d'inscription lundi 24 mai 2010 Statut Membre Dernière intervention 5 juillet 2010 - 5 juil. 2010 à 17:49
Bonjour.

Actuellement, j'essaye de développer un petit jeux du genre rpg. J'arrive à déplacer mon personnage (dans un tableau à deux dimension affiché par une pictureBox) mais je ne suis pas vraiment satisfait du résultat. J'aimerais déplacer mon personnage grâce aux flèches directionnelles, pour cela j'utilise l'événement KeyDown. Mais le problème, c'est que si je maintient une flèche appuyé, mon personnage se déplace correctement une fois et puis se déplacer de plusieurs cases d'un coup.

J'aimerais que son mouvement soit constant et qu'en maintenant une touche enfoncé il continue à se déplacer et qu'il s'arrête dès que la touche est relâché. Le meilleur résultat que j'ai obtenu, c'est ceci :

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            e.SuppressKeyPress = true;
            switch (e.KeyCode)
            {
                case Keys.Up:
                    player.moveUp();
                    break;
                case Keys.Left:
                    player.moveLeft();
                    break;
                case Keys.Down:
                    player.moveDown();
                    break;
                case Keys.Right:
                    player.moveRight();
                    break;
                default:
                    break;
            }

            my_UCMap.pb_main.Invalidate(); // C'est la pictureBox qui affiche la carte.
            
            System.Threading.Thread.Sleep(300);
            this.Enabled = false;
            this.Enabled = true;
        }


Mais je doute fortement que c'est la meilleur façon de faire. De plus les autres composant clignote sans arrêt (bonjour l'épilepsie). En fait d'après ce que j'ai compris de mes recherches, il faudrait que j'arrive à vider la file d'événement du formulaire à la fin de chaque déplacement, mais je n'ai aucune idée de comment faire cela.

Merci d'avance pour vos réponses.

4 réponses

krimog Messages postés 1860 Date d'inscription lundi 28 novembre 2005 Statut Membre Dernière intervention 14 février 2015 49
5 juil. 2010 à 10:15
Salut

Tout d'abord, System.Threading.Thread.Sleep(...), je te conseille de ne JAMAIS l'utiliser sur le thread principal. En effet, cette instruction bloque complètement le thread (donc en l'occurrence, l'affichage et l'interaction utilisateur).

Je te conseille de te pencher du côté des Timers (System.Windows.Forms.Timer).

En gros, au départ, tu associes une méthode à l'événement Tick.
monTimer.Tick += new EventHandler(maMethode);

avec bien sûr maMethode avec ce prototype :
void maMethode(object sender, EventArgs e);

L'important, c'est la valeur que tu donnes à Interval.
monTimer.Interval = 300;

Toujours à l'initialisation, tu associes ta méthode Form1_KeyDown à l'événement KeyDown.
this.KeyDown += new KeyEventHandler(Form1_KeyDown);


Tu fais la même chose dans la méthode maMethode
this.KeyDown += new KeyEventHandler(Form1_KeyDown);

Puis, tu arrêtes le timer :
monTimer.Stop();


Dans ta méthode Form1_KeyDown, tu vires les 3 dernières lignes. Puis tu enlèves la méthode Form1_KeyDown de l'événement KeyDown :
this.KeyDown -= new KeyEventHandler(Form1_KeyDown);

et tu démarres le timer :
monTimer.Start();



Si je résume ce que ton programme fait : au départ, il est normal : quand tu appuies sur une touche, ça appelle Form1_KeyDown. Puis, tu dis qu'il ne doit plus appeler cette méthode quand tu appuies sur une touche, mais tu démarres un Timer qui appellera une méthode 300ms après. Et cette méthode reprépare l'événement KeyDown, donc ta méthode Form1_KeyDown sera rappelée 300ms plus tard si tu appuies encore sur ta touche.

Je ne garantis absolument pas que ce soit la méthode la plus propre, mais elle me semble assez simple, et devrait résoudre ton problème.

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
3
cs_Tomvan Messages postés 3 Date d'inscription lundi 24 mai 2010 Statut Membre Dernière intervention 5 juillet 2010
5 juil. 2010 à 12:03
Merci beaucoup ca marche très bien, j'ai juste un petit problème.
A chaque fois que je laisse une touche appuyé pour me déplacer de plusieurs cases, lorsque je relâche la touche il y a un petit son genre erreur Windows qui est joué.

Je n'arrive pas à savoir d'où provient ce son car en essayant de déboguer je ne peux me déplacer que d'une case à la fois et cela ne joue pas de son.

Si quelqu'un à une bonne idée, je suis preneur.

Merci d'avance.

Ps: est-ce que je met déjà "réponse acceptée" ou cela bloque le post ?
0
krimog Messages postés 1860 Date d'inscription lundi 28 novembre 2005 Statut Membre Dernière intervention 14 février 2015 49
5 juil. 2010 à 12:20
Désolé, mais je ne vois pas d'où peut venir ce son. De plus, je ne peux pas tester mon code en ce moment, donc je ne peux pas voir si j'ai aussi ce problème. J'essaierai de me pencher dessus ce soir si j'ai un peu de temps (je ne garantis cependant rien).

En ce qui concerne "Réponse acceptée", non, ça ne bloque absolument pas le post. Tu peux même accepter plusieurs réponses.

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
0
cs_Tomvan Messages postés 3 Date d'inscription lundi 24 mai 2010 Statut Membre Dernière intervention 5 juillet 2010
5 juil. 2010 à 17:49
J'ai finalement trouvé une solution. Si j'ai bien compris, tous les événements n'était pas bien gérer.
Si ca intéresse quelqu'un, voici ma solution :

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
            if (ActiveKeyboard == true)
            {
                e.SuppressKeyPress = true;
                switch (e.KeyCode)
                {
                    case Keys.Up:
                        player.moveUp();
                        break;
                    case Keys.Left:
                        player.moveLeft();
                        break;
                    case Keys.Down:
                        player.moveDown();
                        break;
                    case Keys.Right:
                        player.moveRight();
                        break;
                    default:
                        break;
                }

                ActiveKeyboard = false;
                timerPlayer.Start();
            }
        }


avec :

bool ActiveKeyboard;


et pour la méthode lancé par le timer :

        private void pausePlayer(object sender, EventArgs e)
        {
            ActiveKeyboard = true;
            timerPlayer.Stop();
        }


Ps: encore merci krimog !
0
Rejoignez-nous