0
\$\begingroup\$

I'm guessing the default XNA model encourages checking for button presses in Update(). However, I am developing a game-like application for research and need to measure reaction times as quickly as possible. If I only check button presses in Update(), this constrains me to the refresh rate of the application. For example, if Update() runs 60 times per second, button capture times could be off by up to 16.6ms (1/60) if they happen soon after the thread goes to sleep. Is there another way to design my application to catch button presses as soon as possible?

Should I run a separate thread that polls the game controller and runs faster than the regular application's 60 Hz, say 120 Hz?

Or should I run a thread that gets a hardware interrupt when a button is pressed and store the time?

Other ideas?

(I know this sounds excessive when we are talking about button pressing and 20ms or less, but there are a number of scientific applications out there that advertise millisecond level timing precision. I am just wondering if I might be able to get something reasonably close with XNA.)

\$\endgroup\$
  • \$\begingroup\$ "millisecond level timing precision", well i suppose increasing fps to 200 would achieve 5ms precision without any coding effort, but lower coding effeciency.. \$\endgroup\$ – dimitris93 Jan 18 '15 at 17:52
  • \$\begingroup\$ Decouple he input loop with the gameplay loop, so when update hit, it get a list of button event for that frame. \$\endgroup\$ – user29244 Jan 19 '15 at 0:47
  • \$\begingroup\$ Can you explain how, user29244? \$\endgroup\$ – Doug Jan 19 '15 at 0:48
  • \$\begingroup\$ I would suggest an alternative approach: the keyboard presses or gamepad presses should be timestamped (at least under the hood). I have looked through the XNA documentation but have not found it, meaning XNA might be throwing away this information, but it is present in the underlying DirectX calls. Microsoft Robotics (very similar to XNA) gives access to timestamps, for instance msdn.microsoft.com/en-us/library/dd145260.aspx \$\endgroup\$ – mklingen Jan 21 '15 at 21:56
  • 1
    \$\begingroup\$ @Doug Are you really sure you're using the right tool for the job? If you do research, you should probably not use a purely game-oriented framework. If you create a simple window application with WinForms or WPF, you just implement the button's click event and thus get a perfectly accurate measurement. \$\endgroup\$ – Hackworth Apr 22 '15 at 9:58
1
\$\begingroup\$

Rather than polling for events, where the only option for higher precision is to poll faster, you could try listening for the events directly.

You can attach an event listener to the windows event queue like so:

// Define a message filter which all messages will pass through
private class Filter : IMessageFilter
{
    public bool PreFilterMessage(ref Message m)
    {
        //Do your stuff here!
        //e.g. note down the exact system time.
        Stuff(ref m);

        //Returning false allows the message to continue to the next filter or control.
        return false;
    }
}

// Do this somewhere to begin listening
void AttachMessageListener()
{
    Application.AddMessageFilter(new Filter());
}

This gets you a stream of Message structures to handle. If you're trying to read a specific keyboard key you could do something like this:

void Stuff(ref Message msg)
{
    if (msg.Msg != 0x0102) //0x0102 == WM
        return;

    char c = (char)msg.WParam;

    //the char in c was pressed, do something!
    DoStuffWithChar(DateTime.Now, c);
}
\$\endgroup\$
0
\$\begingroup\$

Expanding Shiro's comment: You could increase the speed the game updates to a higher fixed rate (as long as you know beforehand it can handle that FPS). While this isn't really SOLVING your problem it will at least reduce it's effect.

You could either set the FPS to a specific amount:

this.TargetElapsedTime = TimeSpan.FromSeconds(1.0f / 200.0f);
//Where 100.0f is how many updates per second

Or you could set the FPS to unlimited so it runs as fast as possible:

this.IsFixedTimeStep = false;
graphics.SynchronizeWithVerticalRetrace = false;

Again: this depends on hardware and the performance of your application, but in simple cases it will be more than fast enough for your precision. Just get the amount of time elapsed from the start of your application (or a separate TimeSpan) whenever a button is pressed and compare it.

\$\endgroup\$
  • \$\begingroup\$ When I use TargetElapsedTime I can get the app to perform at 200 Hz, but when I use this.IsFixedTimeStep = false; it only runs at 60 Hz. Any idea why? \$\endgroup\$ – Doug Jan 19 '15 at 21:07
  • \$\begingroup\$ Add graphics.SynchronizeWithVerticalRetrace = false; where graphics is your GraphicsDeviceManager. This prevents the game from trying to synchronize draw calls with the monitor's refresh rate, which is what is limiting the FPS. \$\endgroup\$ – Saliken Jan 21 '15 at 20:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.