Wie erhalte ich die verstrichene Zeit des Tastendrucks?

8

Ich muss in der Lage sein zu bestimmen, wie lange ein Schlüssel mit hoher Genauigkeit gedrückt wurde. Wenn sie beispielsweise sehr schnell auf die Taste tippen, wird möglicherweise eine Zeit gemeldet, die kürzer als die Zeit für jeden Aktualisierungsrahmen ist.

AttackingHobo
quelle
Aufgrund Ihrer anderen Kommentare muss ich fragen, ob eine Genauigkeit von ~ 16 ms tatsächlich schädlich für Ihr Spiel ist. So ziemlich jedes Spiel, das ich jemals gemacht habe, hat sich nicht mit Eingaben auf der Subframe-Skala beschäftigt. Vielleicht gibt es einige andere Dinge, die dazu führen, dass sich das Spiel schlecht anfühlt (was ich annehme, sonst warum
fragst
1
Wissen Sie, Mario-Spiele brauchten keine Subframe-Genauigkeit, um die Sache "Schnellzugriff für Tiefsprung, Volldruck für Hochsprung" zu lösen. Fügen Sie besser einen Beschleunigungsvektor für die ersten 2-3 Frames des Sprungs hinzu.
Kyte
@ Andrew Russel: Das sollte die Antwort sein.
Michael Coleman

Antworten:

4

Sie können die Eingabe mithilfe der System.Windows.Forms.NativeWindow-Klasse erfassen. Sie erhalten eine Benachrichtigung, wenn ein Eingabeereignis auftritt. Auf diese Weise werden Sie so schnell wie möglich benachrichtigt, sobald es auftritt, sodass Sie die Zeit mit einer höheren Genauigkeit aufzeichnen können. Es wird etwas chaotisch (nativer / unsicherer Code), aber es funktioniert.

Ich denke, dies funktioniert nur unter Windows, aber ich denke, das ist die Plattform, auf die Sie abzielen (dies ist auf Xbox und WP7 nicht erforderlich).

Hier ist ein gutes Beispiel (aus dem Nuclex-Framework): WindowInputCapturer (Hinweis: Dieser Code wurde möglicherweise kürzlich aktualisiert und ich habe ihn nicht codiert. )

Bearbeiten: Hiermit können Sie auch den Zeichencode des Tastendrucks abrufen. Dies könnte nützlich sein, um Texteingaben zu machen (insbesondere Dinge wie lateinische Zeichen). Ich bin mir nicht sicher, warum Sie Eingaben mit so hoher Präzision benötigen würden, aber dies wäre meiner Meinung nach eine gute Möglichkeit, dies zu tun.

Michael Coleman
quelle
2

XNA ist ein Loop-basiertes Framework, kein ereignisbasiertes Framework. Wenn Sie den genauen Zeitpunkt benötigen, zu dem ein Ereignis aufgetreten ist, ziehen Sie ein Winforms-Projekt (ein ereignisbasiertes Projekt) in Betracht und verbinden Sie XNA bei Bedarf mit einem Steuerelement zum Rendern.

Steve H.
quelle
1

Speichern Sie den Schlüsselstatus in einer Variablen und vergleichen Sie ihn in der nächsten Schleife mit den aktuellen Schlüsselzuständen. Erstellen Sie ein DateTimeObjekt, das den Start enthält, und vergleichen Sie es, DateTime.Nowwenn der vorherige Schlüsselstatus nicht übereinstimmt.

Sehr einfaches Beispiel für das, was ich meine:

   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; }
riv_rec
quelle
Ich habe speziell nach etwas gefragt, das mir eine Zeit geben kann, die kürzer ist als die Zeit für jedes Update. Ihre Antwort gibt mir nur Zeit in Schritten von 16 ms.
AttackingHobo
1
Führen Sie das also in einem eigenen Thread aus. XNA verfügt nicht über einen Ereignishandler für Tastaturänderungen.
Riv_rec
DateTime.Now hat jedoch eine schlechtere Auflösung als das Update. Versuchen Sie Stoppuhr.
Kyte
0

Mir ist kein offizieller Weg bekannt, dies zu tun. Sie könnten einen zweiten Thread in einer sehr engen Schleife ausführen, um die Eingabe zu überprüfen und diesen an einen kreisförmigen Puffer zu senden, der groß genug ist, um nur eine sehr geringe Synchronisation zwischen den Threads zu erfordern.

(Speichern Sie eine zunehmende Zahl in jedem Steckplatz des Puffers und aktualisieren Sie diese, nachdem der Thread alle Daten geschrieben hat. Lesen Sie dann die Steckplätze mit Daten aus dem Puffer weiter, bis die Anzahl abnimmt (vergessen Sie nicht, nach überfüllten Zahlen zu suchen!))

Elva
quelle
0

Wenn Sie dreißig Mal pro Sekunde aktualisieren, kann ein Mensch die Tasten nicht schneller drücken, als Sie den Tastaturstatus abtasten können. Wenn Sie langsamer aktualisieren, als ein Mensch eingeben kann, benötigen Sie möglicherweise einen Thread zum Rendern von Grafiken und einen anderen Thread zum Lesen und Reagieren auf die Tastatur / Maus.

Wenn Sie jedoch langsamer aktualisieren, als ein Mensch eingeben kann, können Sie auch nicht für jeden Tastendruck ein visuelles Feedback geben. Dies spielt keine Rolle, wenn die Idee darin besteht, aggregiertes Feedback anzuzeigen, z. B. die durchschnittliche Zeit zwischen Tastendrücken.

bmcnett
quelle
Ich habe nie etwas über das Tippen gesagt. Ich möchte wissen, wann eine Taste gedrückt wurde, genau in Millisekunden.
AttackingHobo
Und tatsächlich kann ein Mensch mit einer Geschwindigkeit von mehr als 30 Tasten pro Sekunde tippen, aber nur mit wenigen Tasten, nicht mit einer anhaltenden Geschwindigkeit.
AttackingHobo
Wenn Sie sechzig Mal pro Sekunde aktualisieren, erhalten Sie eine Genauigkeit von 16 ms. Welche Genauigkeit benötigen Sie und warum?
Bmcnett
Für die Bewegung des Spielers möchte ich, dass der Benutzer einmal schnell tippen kann und der Spieler weniger als einen vollen Druck ausführt.
AttackingHobo
@AttackingHobo Könnten Sie dafür keine Bewegungsgleichungen verwenden? Während es gedrückt gehalten wird, einen Beschleunigungsvektor auf einen Geschwindigkeitsvektor anwenden? Je länger es gedrückt gehalten wird, desto höher ist die Geschwindigkeit?
Ray Dey