Getting Smooth Key Navigation

When first planning navigational controls, it initially makes sense to react to key events. Using our libgfx framework, this would look something like this:

int GUI::key_press(int key)
{
    switch( key )
    {
    case FL_Shift_L:  ... flap ...; break;

    case FL_Left:     ... go left ...; break;
    case FL_Right:    ... go right ...; break;

    ... etc ...
    }
}

But this is bad for two reasons. First of all, it treats keys as mutually exclusive. Thus you can’t flap and turn at the same time. Second of all, it limits the rate at which you can hit keys to whatever the key repeat rate of the OS is. This usually results in very choppy motion.

The solution to this problem is to process key navigation controls on a per-frame basis. In our GUI code, this is accomplished by moving the code to GUI::update_animation(), which is always called just before drawing each frame.

int GUI::update_animation()
{
    if( Fl::event_key(FL_Shift_L) )  ... flap ...;

    if( Fl::event_key(FL_Left) )     ... go left ...;
    if( Fl::event_key(FL_Right) )    ... go right ...;

    ... etc ...
}

The function Fl::event_key() returns true if the given key was pressed during the last event. (In this case, it’s the timer event that is being processed to draw the next frame.) You can similarly use the function Fl::get_key() which returns true if the given key is currently held down. However, this is significantly less efficient on platforms like X11, as it requires a round-trip to the server to process the query.