Comment obtenir le temps écoulé de pression sur une touche?


8

Je dois pouvoir déterminer la durée pendant laquelle une touche a été maintenue enfoncée avec une grande précision. Par exemple, si les touches sont tapées très rapidement, cela peut signaler une heure inférieure à l'heure de chaque trame de mise à jour.


Sur la base de vos autres commentaires, je dois vous demander, une précision de ~ 16 ms est-elle réellement préjudiciable à votre jeu? Presque tous les jeux que j'ai jamais réalisés n'ont pas pris la peine de saisir des données sur l'échelle du sous-cadre. Peut-être qu'il y a d'autres choses qui font que le jeu se sent mal (ce que je suppose, sinon pourquoi demandez-vous?)
Tetrad

1
Vous savez, les jeux Mario n'avaient pas besoin d'une précision de sous-trame pour retirer la chose "onglet rapide pour le saut en hauteur, pleine pression pour le saut en hauteur". Mieux vaut ajouter un vecteur d'accélération pour les 2-3 premières images du saut.
Kyte


@Andrew Russel: cela devrait être la réponse.
Michael Coleman

Réponses:


4

Vous pouvez capturer l'entrée en utilisant la classe System.Windows.Forms.NativeWindow. Vous recevrez une notification lorsqu'un événement d'entrée se produit. De cette façon, vous serez informé le plus rapidement possible dès qu'il se produit, vous permettant d'enregistrer l'heure avec une précision plus élevée. Cela devient un peu désordonné (code natif / dangereux), mais cela fonctionne.

Je pense que cela ne fonctionne que sur Windows, mais je pense que c'est la plate-forme que vous ciblez (pas besoin de cela sur Xbox et WP7).

Voici un bon exemple (du framework nuclex): WindowInputCapturer (note: ce code a peut-être été mis à jour récemment et je ne l'ai pas codé)

Modifier: Cela vous permet également d'obtenir le code de caractère de la touche pressée. Cela pourrait être utile pour la saisie de texte (en particulier des choses comme les caractères latins), je ne sais pas pourquoi vous auriez besoin d'une saisie avec une telle précision, mais ce serait un bon moyen de le faire à mon avis.


2

XNA est un cadre basé sur une boucle, pas un cadre basé sur des événements. Si vous avez besoin de l'heure exacte à laquelle un événement s'est produit, envisagez un projet winforms (un projet basé sur un événement) et connectez XNA à un contrôle si nécessaire pour le rendu.


1

Stockez l'état de la clé dans une variable et comparez-le dans la boucle suivante aux états de clé actuels. Créez un DateTimeobjet pour maintenir le début et vous pouvez comparer avec DateTime.Nowquand l'état clé précédent ne correspond pas.

Exemple très simple de ce que je veux dire:

   if(currentKeyboardState.IsKeyDown(Keys.Space)
      && !previousKeyboardState.IsKeyDown(Key.Space))
      { DateTime startTime = DateTime.Now; }
    ...
    if(!currentKeyboardState.IsKeyDown(Keys.Space)
      && previousKeyboardState.IsKeyDown(Key.Space))
      { TimeSpan elapsedTime = DateTime.Now - startTime; }

J'ai spécifiquement demandé quelque chose qui peut me donner un temps inférieur à celui de chaque mise à jour. Votre réponse ne me donnera que du temps par incréments de 16 ms.
AttackingHobo

1
Exécutez donc cela dans son propre fil. XNA n'a pas de gestionnaire d'événements pour les changements de clavier.
riv_rec

DateTime.Now a cependant une résolution pire que la mise à jour. Essayez le chronomètre.
Kyte

0

Je ne suis au courant d'aucune façon officielle de le faire, vous pouvez exécuter un deuxième thread dans une boucle très serrée juste pour vérifier l'entrée et l'envoyer à un tampon circulaire suffisamment grand pour nécessiter très peu de synchronisation entre les threads.

(Stockez une sorte de nombre croissant dans chaque emplacement du tampon et mettez à jour APRÈS que le thread a écrit toutes les données, puis continuez à lire les emplacements avec les données du tampon jusqu'à ce que le nombre diminue (n'oubliez pas de vérifier les nombres débordants!))


0

Si vous effectuez une mise à jour trente fois par seconde, un humain ne pourra pas appuyer sur les touches plus rapidement que vous ne pourrez échantillonner l'état du clavier. Si vous mettez à jour plus lentement qu'un humain ne peut taper, vous aurez peut-être besoin d'un thread pour le rendu des graphiques et d'un autre thread pour lire et répondre au clavier / souris.

Mais, si vous effectuez une mise à jour plus lentement qu'un humain ne peut saisir, vous ne pouvez pas non plus fournir de retour visuel pour chaque pression de touche. Cela n'a pas d'importance si l'idée est d'afficher des commentaires agrégés, tels que le temps moyen entre les pressions de touches.


Je n'ai jamais rien dit sur la frappe. Je veux savoir l'heure à laquelle une touche a été enfoncée, les millisecondes exactes.
AttackingHobo

Et en fait, un humain peut taper à un rythme de plus de 30 touches par seconde, mais seulement en une rafale de quelques touches, pas à un rythme soutenu.
AttackingHobo

Si vous mettez à jour soixante fois par seconde, vous obtenez une précision de 16 ms. De quelle précision avez-vous besoin et pourquoi?
bmcnett

Pour le mouvement du joueur, je veux que l'utilisateur puisse taper une fois rapidement et que le joueur bouge moins d'une pression complète.
AttackingHobo

@AttackingHobo Ne pourriez-vous pas utiliser des équations de mouvement pour cela? Pendant qu'il est maintenu enfoncé, appliquer un vecteur d'accélération à un vecteur de vitesse? Plus elle est maintenue enfoncée, plus la vitesse est élevée?
Ray Dey
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.