Keyboard/Mouse input missing because of low FPS

Started by
8 comments, last by Satharis 8 years, 3 months ago

Hi,

I actually have an action manager which process events using poll event from SDL2.

The problem is when you have low FPS you miss events and gives issues (keyboard, mouse,...).

What is the best way to handle event to avoid issues ?

Thanks

Advertisement

You shouldn't miss those events? There may be a delay but you missing events shouldnt happen?
?

Would you post you event polling code please?

I missed one information you right, it only happens on action in the mode "Press Once" (example : character punch on the mouse left click).

It's surely because of mouse down + mouse up events ? On this case the state of the action is then not actionned and the game code will never do the action.

I use 3 modes "Hold", "Press Once" and "Release Once", surely the "Release Once" mode has the same issue.

Maybe you clear the event queue somewhere?
Maybe you don't loop until the queue is empty (and discard the event at some other place?)

But yeah, as imoogiBG said, we need to see the polling code for less random guesses about what may be wrong.

The poll event while loop :


SDL_Event Event;
while( SDL_PollEvent( &Event ) )
{
  switch( Event.type )
  {
    ...
    ...
    default: ActionManager.ProcessEvent( Event );
  }
}

Process event does simply a switch to handle input events, here the two cases for the mouse :


case SDL_MOUSEBUTTONDOWN :
{
  // Each action.
  for( UInt32 i = 0; i < m_ActionArray.GetSize(); ++i )
  {
    // Each input.
    for( UInt32 k = 0; k < m_ActionArray[ i ].InputArray.GetSize(); ++k )
    {
      // Get the input.
      const TInput& Input = m_ActionArray[ i ].InputArray[ k ];

      // Check if the input type is not mouse.
      if( Input.InputType != IT_MOUSE )
        continue;

      // Check if the mouse button is not the same.
      if( Input.MouseButton != Event.button.button )
        continue;

      // Check if the mod state is not the same only if the mod is not none.
      if( ( Input.KeyMod != KMOD_NONE ) && ( SDL_GetModState() != Input.KeyMod ) )
        continue;

      // Change the action activated state.
      m_ActionActivatedArray[ i ] = m_ActionArray[ i ].ActionType != AT_RELEASE_ONCE;
    }
  }

  // Stop here.
  break;
}

case SDL_MOUSEBUTTONUP :
{
  // Each action.
  for( UInt32 i = 0; i < m_ActionArray.GetSize(); ++i )
  {
    // Each input.
    for( UInt32 k = 0; k < m_ActionArray[ i ].InputArray.GetSize(); ++k )
    {
      // Get the input.
      const TInput& Input = m_ActionArray[ i ].InputArray[ k ];

      // Check if the input type is not mouse.
      if( Input.InputType != IT_MOUSE )
        continue;

      // Check if the mouse button is not the same.
      if( Input.MouseButton != Event.button.button )
        continue;

      // Check if the mod state is not the same only if the action type is not hold and if the mod is not none.
      if( ( m_ActionArray[ i ].ActionType != AT_HOLD ) && ( Input.KeyMod != KMOD_NONE ) && ( SDL_GetModState() != Input.KeyMod ) )
        continue;

      // Change the action activated state.
      m_ActionActivatedArray[ i ] = m_ActionArray[ i ].ActionType == AT_RELEASE_ONCE;
    }
  }

  // Stop here.
  break;
}
Hmm, still too many things that can go wrong. Simplest way to find the problem is debug it, I think.
If you use a normal debugger, set a break-point at the button-up handler, triggger it, and then see what condition fails.
If you use printf-style debugging, add a few printf-lines between the ifs, compile, and trigger it, to see which printf lines get reached.


BTW: Why does your comment repeat exactly what the code says? In this way, you write every line of code twice, once as code and once as text.
The usual approach is to read the code to tell you what it does, and read the comment to you *why* that code has to be done here.

You have to be careful with functions like SDL_GetModState(), this gets the state at the time you call it, which can be different than when the event is consumed. Do you do any other non-event related input handling, e.g. calling SDL_GetKeyboardState()?

I have logged in the two mouse case and before activation checking called in game code :


[2016/01/02-21:07:33] Try Fire Action
[2016/01/02-21:07:33] Try Fire Action
[2016/01/02-21:07:33] Try Fire Action
[2016/01/02-21:07:33] SDL_MOUSEBUTTONDOWN
[2016/01/02-21:07:33] SDL_MOUSEBUTTONUP
[2016/01/02-21:07:33] Try Fire Action
[2016/01/02-21:07:33] Try Fire Action
[2016/01/02-21:07:33] Try Fire Action

It's a case when the fire action is not called, and the logger shows the problem, down and up is generated the same frame.

Do you do any other non-event related input handling, e.g. calling SDL_GetKeyboardState()?

I don't, I simply check the mod using SDL_GetModState().

Yes, you are effectively "losing" events due to the way that code is written. You will need to either buffer some kind of custom input actions yourself (if necessary, for game replays or something), or just react to SDL events in a more direct fashion (e.g. a callback handling function of some kind).

Keep in mind input generally comes in two forms: events and polling.

Events are like what you get from windows messaging(the OS, or more specifically the things you drag around that the OS of the same name creates for you), you get messages posted to a queue that happily sit there until doomsday until you process them, so you can package them up and ship them off wherever to process when you need them, you don't 'lose' messages that way.

Polling is usually just checking the state of some array that is being updated for you, or calling an OS function that will actually return the state it has on the device as soon as the function call is made. Problem with polling is that it happens essentially in realtime, if someone clicks a mouse button and releases it and you poll the state at a certain speed, you might flat out miss the message(because it is a state existing between two time periods, not an actual event.)

Theoretically you could make your own events by polling constantly and packaging up the data so you don't 'miss' it but that's hacky at best and would probably need a dedicated thread, usually you'll want to set your input up to deal with the message side of things to generate your own events.

This topic is closed to new replies.

Advertisement