Событие выборки состояния ключа, управляемое SDL, затягивается после отпускания ключа. - PullRequest
0 голосов
/ 08 апреля 2020

Я создаю игру на C ++ и испытываю перетаскивание ввода, когда использую клавиатуру в качестве устройства ввода для управления плеером. В идеальных условиях ввод работает достаточно хорошо, но когда мой компьютер перегружен другими программами, производительность ухудшается, и проигрыватель постепенно теряет синхронизацию c при нажатии клавиш. Чем дольше я удерживаю клавишу направления, тем больше «ввода», похоже, сохраняется в компьютере.

Если я, например, удерживаю «S», чтобы двигаться вниз в течение нескольких секунд, а затем нажимаю клавишу go, игрок продолжает движение вниз через несколько секунд после отпускания, прежде чем остановиться. Если я удерживаю «S», а затем «D», игрок перемещается вниз на несколько секунд, а затем вправо на несколько секунд, отвечая увеличивающейся задержкой в ​​зависимости от того, как долго удерживались клавиши. Дальнейший ввод правильно фиксируется, но все испытывают одно и то же перетаскивание: игрок движется, как ожидалось, , он делает это так долго после нажатия клавиши и гораздо дольше, чем удерживается клавиша.

Если я позволю воспроизвести все входные данные и игрок остановится, проблема возобновится - сначала игрок реагирует, но медленно теряет синхронизацию c с клавишами. Задержка увеличивается, чем дольше я удерживаю клавиши, и не появляется / становится заметным, если вместо этого нажимаю только клавиши, заставляя меня верить, что очередь заполняется событиями, которые не очищаются достаточно быстро, когда мой компьютер работает медленно. Я подозревал, что это может быть очередь событий SDL, но не смог ее обработать sh после прохождения основного l oop.

Интересно, что я кодировал игру, чтобы использовать контроллер в качестве дополнительного устройства ввода , Независимо от того, насколько плохо работает мой компьютер, проигрыватель всегда немедленно реагирует на ввод с контроллера и не страдает от перетаскивания ввода, как клавиатура. Если я перемещаю ручку вправо, игрок двигается вправо, и если я наклоняю или отпускаю ручку, игрок немедленно меняет направление или останавливается, как и ожидалось.

Я считаю, что управляемые событиями клавиши замедляются низкая производительность, в то время как управляемый опросом контроллер не страдает от того же самого эффекта. Я попытался очистить очередь событий SDL, обновить ее, очистить, вытащить все входы из нее, но пока мне не повезло.

Ниже мое событие l oop, с некоторыми разделы удалены. Удаленные части - это главным образом логи c рендеринга, рисования и обновления сущностей, которые выгружаются в другие классы; Логика c для прицеливания также опущена, так как в остальном она идентична движению (нажмите клавишу для наведения в этом направлении).

  const Uint8* keystate = SDL_GetKeyboardState(NULL);

  while(!quit) {

//==== PLAYER INPUT here ======================================================

    //get the keystate
    SDL_PumpEvents();

    if(pause) { /*pause menu*/ }
    else {

//-----------------------------------------------------------------------------
//this section does not protect against keybounce - ideally, it is checking at
//each frame, about every 20 ms (delta time is taken care of elsewhere).
//it feels like a "queue" is being built up of inputs that isn't emptied
//out in real time.

      //no keybounce protection

      //handle movement
      if(keystate[SDL_SCANCODE_W])
        { e_handler::get().move_player(e_handler::UP); }
      if(keystate[SDL_SCANCODE_A])
        { e_handler::get().move_player(e_handler::LF); }
      if(keystate[SDL_SCANCODE_S])
        { e_handler::get().move_player(e_handler::DN); }
      if(keystate[SDL_SCANCODE_D])
        { e_handler::get().move_player(e_handler::RT); }

      if(keystate[SDL_SCANCODE_LSHIFT])
        { e_handler::get().boost_player(true); }


      //(some other keystate sampling for aiming and shooting)



//-----------------------------------------------------------------------------
//this section is an optional alternative for when a controller is plugged in.
//even when my computer is running slowly, there's never any delay in input
//here - the program responds immediately to controller controls.

      if(controller) {
        //process controller input
        vec2d lrud(
          SDL_JoystickGetAxis(controller, LSTICK_LR),
          SDL_JoystickGetAxis(controller, LSTICK_UD)
        );

        if(abs(lrud[0]) > CONTROLLER_DEADZONE) {
          if(lrud[0] < 0) { e_handler::get().move_player(e_handler::LF); }
          else { e_handler::get().move_player(e_handler::RT); }
        }
        if(abs(lrud[1]) > CONTROLLER_DEADZONE) {
          if(lrud[1] < 0) { e_handler::get().move_player(e_handler::UP); }
          else { e_handler::get().move_player(e_handler::DN); }
        }
      }
    }



//-----------------------------------------------------------------------------
//this section has keybounce protection, to prevent the game from, for 
//example, pausing and unpausing extremely quickly when "P" is pressed.
//supposedly, while(SDL_PollEvent(&e) != 0) is supposed to empty out the event
//queue, so i'm not sure if it really *is* the event queue that's causing the
//input dragging issue.

    while(SDL_PollEvent(&e) != 0) {
      //get an event: protect from keybounce
      if(e.type == SDL_QUIT) { quit = true; }
      else if(e.type == SDL_KEYDOWN) {

        //pause unpause
        if(keystate[SDL_SCANCODE_P]) { pause = !pause; }
        if(pause || !pause) { //TODO: remove this / update it
          //pause menu
          if(keystate[SDL_SCANCODE_ESCAPE]) { quit = true; }
        }

        if(keystate[SDL_SCANCODE_O]) {
          //TODO: make "tryjump" in map handler
          if(map_h::get().debug_jump(e_handler::get().get_player_pos())) {
            //jumped
            e_handler::get().teleport_player_new_map();
          }
        }

        //draw debug things
        if(keystate[SDL_SCANCODE_PERIOD]) {
          e_handler::get().set_draw_debug_info(
            !e_handler::get().get_draw_debug_info()
          );
        }

      }
    }



//-----------------------------------------------------------------------------
    //updating and drawing happens down here

  }

Есть ли решение этой проблемы? Если нет, я планирую переключиться на опрос клавиатуры один раз в каждом кадре.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...