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

DirectX Discussion :

Scrutation du clavier avec DirectInput


Sujet :

DirectX

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19
    Points : 7
    Points
    7
    Par défaut Scrutation du clavier avec DirectInput
    Bonjour à tous,

    Je suis face à un problème classique. Je scrute le clavier avant chaque génération de frame (environ toutes les 30 ms) avec GetDeviceState. Quand l'utilisateur presse une touche, elle peut rester enfoncée pendant 1/4 de seconde, par exemple, ce qui fait que le scruteur l'intercepte plusieurs fois et déclenche plusieurs fois le handler approprié... D'où le problème. J'ai essayé de bufferiser l'accès au clavier avec GetDeviceData mais ça n'a pas solutionné le problème. De plus, comment gérer justement le fait que la touche reste enfoncée plusieurs secondes ? La seule méthode que j'ai trouvée pour résoudre partiellement le problème est de créer artificiellemetn un délai entre 2 scrutations du clavier successives, mais du coup, le jeu n'est plus très réactif aux impulsions du clavier, ce qui crée un autre problème.

    Ceux qui ont créé des jeux vidéo, comment avez-vous géré ce problème classique ?

    Merci d'avance,
    Mark

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    De mémoire je crois qu'il y a un mode à spécifier pour que DirectInput gère l'appui de touches "façon Windows" (càd avec un délai avant répetition), mais je ne me souviens vraiment plus ce que c'est. Tu as regardé les samples du SDK ?

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19
    Points : 7
    Points
    7
    Par défaut
    Salut Loulou,

    Merci pour ta réponse. En fait, je n'ai pas d'exemple dans mon SDK, mais je me suis inspiré des fichiers d'aide de DirectX 7 et d'exemples sur le Net. Mais je me dis qu'il y a forcément d'autres développeurs qui ont rencontré ce problème... Si tu fais une recherche sur google, tu vas voir que le sujet est largement abordé... Le problème est que je n'arrive pas à trouver de réponse. En fait, j'aimerais gérer à la fois la frappe d'une touche et le fait que la touche reste enfoncée...

    Allez, à plus,
    Mark

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    108
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 108
    Points : 128
    Points
    128
    Par défaut
    En faites, tu as deux évènements que l'on peut récupérer.

    Le moment où une touche est enfoncée et le moment où une touche est relachée. Pour du ponctuel, on utilise plutôt le moment où une touche est relachée.

    Ex : clique sur un bouton avec ta souris en maintenant le bouton. Tu contateras que l'évènement associé n'est activé que lorsque tu relacheras le bouton de la souris mais seulement si tu es encore sur le bouton.

    A partir de ces deux évènement tu peux aussi créer des animations syncroniser si celles-ci se base sur le temps qui s'écoule.

    Ex : la touche est enfoncé => le temps s'écoule => l'animation se déroule en fonction du temps qui s'est passé depuis la dernière scutation.
    la touche est relaché => le temps ne s'écoule plus => l'animation est stopée.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19
    Points : 7
    Points
    7
    Par défaut
    Salut olivic,

    Merci à toi pour ton aide. En effet, c'est une bonne idée de déclencher un événement uniquement quand le bouton est relâché. Mais alors comment gérer le fait que le bouton est appuyé longtemps ? Si on se base sur le même principe, l'événement sera activé bien trop tard...

    Pensez aux jeux vidéos qui existent. Prenons Mario. Vous appuyez sur la droite, et le bonhomme fait juste un pas vers la droite. Maintenez le bouton enfoncé, et il va courir... Hé bien c'est exactement le résultat que j'aimerais obtenir ! Pas facile...

    Bonne soirée,
    Mark

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Si vraiment tu ne trouves pas comment faire avec l'API, tu peux toujours mettre une temporisation toi-même lors de l'appui sur une touche et ne pas générer d'évènement pendant ce laps de temps, puis lorsqu'il est ecoulé générer l'évènement en continu. Bien sûr si entre temps la touche a été relâchée, il faut tuer la tempo et la relancer. Enfin voilà c'est l'idée, pour les détails je te laisse voir .

  7. #7
    Membre expérimenté

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Points : 1 679
    Points
    1 679
    Par défaut
    Ton clavier fonctionne de deux façons dans DInput

    L'une par état, qui t'indique simplement si la touche est en ce moment enfoncée ou pas mais qui n'indique pas depuis quand elle est enfoncée ni l'ordre dans lesquelles elles sont enfoncées.

    La deuxième par évènement, qui indique : "la touche est entrée dans l'état enfoncé à telle date" puis "la touche est sortie de l'état enfoncée à telle date" mais qui nécessite de maintenir le buffer de manière précise pour chaque touche utilisé (alors qu'avec l'autre méthode tu peux ne sonder que la touche qui t'interesse à l'instant t).

    Dans un des programmes que j'avais écrit, je faisais simplement un "polling" de l'état des touches à intervalle régulier. Tant que la touche "avant" était enfoncée, le mouvement "vers l'avant" était actif, tu peux mémoriser l'historique des sondages précédents pour dire que si pendant x ms la touche est toujours enfoncée, alors on va passer de l'état marcher à l'état courir.

    L'inconvénient de la méthode "état" c'est que tu n'es pas sur que la touche n'est pas passée de l'état enfoncé à pas enfoncé alors que tu faisais autre chose (affichage ou gestion de l'IA). Dans mon cas ce n'etait pas un probleme parce que le sondage était suffisamment fréquent (framerate élevé) et l'action à l'écran était basée sur la durée de pression plus que sur la précision du nombre d'appuis successifs.
    Par contre si tu veux un jeu ou le framerate est faible, ou encore si tu veux capter une frappe de texte au clavier, il est indispensable que tu utilises le mode par évenements, ne serait-ce que pour l'ordre d'arrivée des éenévnmtes dnas le cas cnortiare tu aruias du mal à reconstruire le signal.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    108
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 108
    Points : 128
    Points
    128
    Par défaut
    Dans ce cas là, il faut utiliser la deuxième solution que je t'ai donné.

    Je réexplique :
    Tu appuis sur la touche droite.
    On applique donc une fonction de déplacement sur le personnage de Mario.
    Tu relache la touche droite.
    On arrête la fonction de déplacement du personnage.

    La fonction de déplacement doit être en fonction du temps. Ce temps est le temps qui c'est écoulé pendant l'exécution complète de ta boucle d'évènement.

    De manière mathématique :
    d = v/t avec t != 0
    d : la distance que doit parcourir on personnage => ta matrice de déplacement.
    v : la vitesse que tu veux appliquer à ton personnage.
    t : le temps qui s'est écoulé

    Par contre, il existe un petite chose en plus dans le cadre des jeux. Tu disais que Mario marche au début puis se met progressivement à courrir.
    Mais il y a aussi le fait que Mario se met à glisser avant de s'arrêter.

    En définitive, la vitesse est variable ; c'est donc une accélération.
    Donc il faut rajouter d = a * t².

    En conclusion on a :
    d = v / t + a * t² avec t != 0

    Explication supplémentaire :
    Quand par exemple tu appuis sur la touche courrir, v est remplacer par un autre v qui à une valeur plus élevé (et inversement).

    a doit obligatoirement varier en fonction du temps. Sinon, tu te retrouve à avoir un accélération infini. On le fixe à 1 (accélération de départ) à l'appui sur la touche droite, puis on l'augmente progressivement jusqu'à 2 au bout de 20ms. Et inversemment à l'arrêt du personnage ; on supprime la vitesse et on réduit l'accélération emganiser.

    Par exemple, si tu augmentes la valeur d'accélération finale pour les valeurs d'accélération ainsi que le temps d'amorti, tu peux faire glisser ton personnage.

    Par contre, tu as du remarquer que quand tu lâches la touche, l'animation va continuer un certain temps. Il va donc falloir utiliser les Thread (ou des Timer).

    Je n'ai jamais eu le temps d'implémenter cet algorithme donc de ce coté là, je te souhaites bonne chance.

  9. #9
    Membre expérimenté

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Points : 1 679
    Points
    1 679
    Par défaut
    En gros, ça ferait un truc comme:

    tu aurais une variable locale que tu initialiserais à zéro
    qui s'appelerait "WalkingForMilliseconds".
    Lors du premier sondage, tu détectes la touche avant enfoncée.
    Tu mets WalkingForMilliseconds à une valeur arbitraire et tu signales au reste du programme que tu commences à marcher.
    Au deuxième sondage, la touche avant est toujours enfoncée,
    "WalkingForMilliseconds" est augmentée du montant nécessaire et au bout de x passages quand ""WalkingForMilliseconds" dépasse le montant que tu t'es fixé, tu passes au reste du programmes l'info comme quoi tu t'es mis à "courir".

    Aux sondage suivant, la touche n'est pas détectée comme enfoncée, tu remets "WalkingForMilliseconds" à zéro et tu signales au reste du programme que tu as arréte de marcher et de courir.

    Après tu customises en fonction de tes besoins..

  10. #10
    Membre expérimenté

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Points : 1 679
    Points
    1 679
    Par défaut
    Citation Envoyé par olivic
    Par contre, tu as du remarquer que quand tu lâches la touche, l'animation va continuer un certain temps. Il va donc falloir utiliser les Thread (ou des Timer)..
    Il n'est vraiment pas nécessaire de faire appel aux threads ni aux timers,
    ta boucle de jeu suffit.
    Le thread ou le timer est a reserver aux choses vraiment plus complexes. (comme gérer les appels bloquants sur le disque ou sur le réseau, tirer parti du multiprocessing etc..).

Discussions similaires

  1. [VB6] Comment Désactiver et activer le clavier avec VB6
    Par filton dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 08/03/2006, 15h14
  2. Réponses: 5
    Dernier message: 29/12/2005, 16h03
  3. Le buffer clavier avec cin, et getch()
    Par Info420 dans le forum SL & STL
    Réponses: 1
    Dernier message: 06/12/2004, 13h45
  4. "Drag and drop" avec directinput
    Par batosai dans le forum DirectX
    Réponses: 1
    Dernier message: 16/06/2004, 17h48
  5. Probleme avec DirectInput 8
    Par Johngame dans le forum DirectX
    Réponses: 1
    Dernier message: 28/06/2003, 20h25

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