2015-07-19 112 views
0

我正在按键之间产生一个主要的(1-2秒)延迟。SDL事件处理延迟

下面是main.cpp中(滞后输入处理):

#include <iostream> 

#include "src/Input/InputManager.h" 
#include "src/Graphics/Display.h" 

#define LOG(x) std::cout << x << std::endl; 

using namespace Rambug; 

int main(int arc, char** argv) 
{ 
    Graphics::Display display(900, 600, "Rambug Engine Tester", true); 
    display.createDisplay(); 

    SDL_Event event; 
    Input::InputManager inputManager; 

    // "Game" Loop 
    while (!display.isClosed()) 
    { 
     display.update(); 

     glClearColor(0.0f, 0.02f, 0.5f, 1.0f); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     while (SDL_PollEvent(&event)) 
     { 
      if (event.type == SDL_KEYDOWN) 
      { 
       std::cout << "Keydowner" << std::endl; 
      } 
      if (event.type == SDL_KEYUP) 
      { 
       std::cout << "Keyupper" << std::endl; 
      } 
     } 

    // inputManager.update(); 
    } 

    display.destroyDisplay(); 

    system("PAUSE"); 
    return 0; 
} 

这里是Display.cpp,其运行完全没有任何延迟,当我运行相同的代码(SDL_KEYDOWN,SDL_KEYUP)我就跑SDL_QUIT在下面。

#include "Display.h" 

namespace Rambug 
{ 
    namespace Graphics 
    { 
     Display::Display(int width, int height, std::string title, bool log) 
     { 
      m_displayWidth = width; 
      m_displayHeight = height; 
      m_displayTitle = title; 
      m_log = log; 
      m_window = nullptr; 
     } 

     Display::Display() 
     { 

     } 

     Display::~Display() 
     { 

     } 

     void Display::createDisplay() 
     { 
      // Initialize SDL 
      SDL_Init(SDL_INIT_EVERYTHING); 

      // Setting attributes to our window 
      SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 
      SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 
      SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); 
      SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); 
      SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); 
      SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 

      // Create window 
      m_window = SDL_CreateWindow((m_displayTitle.c_str()), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_displayWidth, m_displayHeight, SDL_WINDOW_OPENGL); 

      // Error Check Window 
      if (m_window == nullptr) 
      { 
       if (m_log) 
        std::cerr << "Window could not be created!" << std::endl; 
      } 
      else 
      { 
       if (m_log) 
        std::cout << "Window Created Successfully With SDL!" << std::endl; 
      } 

      // Create OpenGL Context 
      m_glContext = SDL_GL_CreateContext(m_window); 

      // Initialize GLEW 
      glewExperimental = GL_TRUE; 
      GLenum status = glewInit(); 

      if (glewExperimental) 
      { 
       if (m_log) 
        std::cout << "Glew Experimental: On" << std::endl; 
      } 

      // Error Check GLEW 
      if (status != GLEW_OK) 
      { 
       if (m_log) 
       { 
        std::cerr << "GLEW could not be initialized!" << std::endl; 
       } 
      } 
      else 
      { 
       if (m_log) 
       { 
        std::cout << "GLEW Was Initilized Successfully!" << std::endl; 
       } 
      } 

      // Log OpenGL Version Number 
      if (m_log) 
      { 
       std::cout << "Using OpenGL Version: " << glGetString(GL_VERSION) << std::endl; 
      } 

      m_closed = false; 
     } 

     void Display::destroyDisplay() 
     { 
      SDL_GL_DeleteContext(m_glContext); 
      SDL_DestroyWindow(m_window); 
      SDL_Quit(); 
     } 

     void Display::update() 
     { 
      SDL_GL_SwapWindow(m_window); 

      // Check for Input 
      while (SDL_PollEvent(&m_sdlEvent)) 
      { 
       if (m_sdlEvent.type == SDL_QUIT) 
       { 
        m_closed = true; 
       } 
      } 
     } 

     bool Display::isClosed() 
     { 
      return m_closed; 
     } 
    } 
} 

我也尝试过使用输入管理器类进行试验,但这是相同的处理:延迟。更新的方法是什么,我会在main.cpp中(我认为,它已被注释掉)

#include "InputManager.h" 
#include <iostream> 

#define LOG(x) std::cout << x << std::endl; 

namespace Rambug 
{ 
    namespace Input 
    { 
     InputManager::InputManager() 
     { 

     } 

     InputManager::~InputManager() 
     { 

     } 

     void InputManager::keyPressed(unsigned int keyCode) 
     { 
      m_keyMap[keyCode] = true; 
     } 

     void InputManager::keyReleased(unsigned int keyCode) 
     { 
      m_keyMap[keyCode] = false; 
     } 

     bool InputManager::isKeyDown(unsigned int keyCode) 
     { 
      auto it = m_keyMap.find(keyCode); 

      if (it != m_keyMap.end()) 
      { 
       return it->second; 
      } 
      else 
      { 
       return false; 
      } 
     } 

     void InputManager::update() 
     { 
      while (SDL_PollEvent(&m_event)) 
      { 
       switch (m_event.type) 
       { 
       case SDL_KEYDOWN: 
        LOG("SDL_KEYDOWN"); 
        keyPressed(m_event.key.keysym.sym); 
        break; 
       case SDL_KEYUP: 
        LOG("SDL_KEYUP"); 
        keyReleased(m_event.key.keysym.sym); 
        break; 
       } 
      } 
     } 
    } 
} 

所以输入管理和main.cpp中有重大延误打电话,而Display.cpp运行完美。是否因为我无法运行两次SDL_PollEvents?

+0

对两个不同地方的事件进行投票似乎确实是一个糟糕的主意。您应该从Display类中移除它,并以其他方式处理退出事件。 – jpw

回答

1

是不是因为我不能运行SDL_PollEvents两次?

你的问题不是我所期望的,但是,是的,运行SDL_PollEvents两次是个坏主意。 SDL保留一个事件堆栈,该堆栈在您的程序运行时添加。 SDL_PollEvents从堆栈中弹出事件直到它为空。结果,运行两个轮询循环,一个会删除另一个不会看到的事件。盲目运气(或运行瓶颈)将决定哪个循环更有可能发生任何特定事件。 (见http://wiki.libsdl.org/SDL_PollEvent)。

如果你真的想运行两个轮询循环,可以存储事件未处理在默认情况下,每个回路与SDL_PushEvent后回推事件列表:http://wiki.libsdl.org/SDL_PushEvent

此说,我很惊讶,你的活动在延迟后“通过”:我希望它们消失。你握着钥匙了吗?然后,你的操作系统密钥重复延迟可能就是你所看到的,之后事件队列在每个循环之间被淹没。您可能要检查的一些关键事件的重复标志:http://wiki.libsdl.org/SDL_KeyboardEvent

我会说这指向一个设计问题。你应该问自己,为什么显示器委托游戏结束?把这个事实告诉显示器和其他所有事情,是不是更明智?

+0

是的,当我拿着它时,它确实注册了,而不是当我快速点击它时。我现在进行了尝试,从Display类中删除了PollEvents,并且在InputManager类中只有一个轮询事件。感谢您的帮助 –

+0

@JavaManTeaMan很高兴能帮助您!如果您的问题得到解决,您应该考虑将答案标记为解决方案,或者您可以将自己的解决方案作为答案并标记出来。这样很明显,问题解决了,答案是什么。 – Qualia