2016-08-08 1 views
0
그린 스프라이트 이동

I 바인딩 및 두 개의 삼각형 내 Sprite.cpp을 int로 이루어지는 사각형을 그리하는 FBO 및 VBO 사용한 여기 내 init 메소드이다SDL2는 OpenGL은 C가 ++ VBO 및 FBO

void Sprite::init(float x, float y, float width, float height) { 

_x = x; 
_y = y; 
_width = width; 
_height = height; 

if (_vboID == 0) { 

    glGenBuffers(1, &_vboID); 

} 



vertexData[0] = x + width; 
vertexData[1] = y + height; 

vertexData[2] = x; 
vertexData[3] = y + height; 

vertexData[4] = x; 
vertexData[5] = y; 

vertexData[6] = x + width; 
vertexData[7] = y + height; 

vertexData[8] = x; 
vertexData[9] = y; 

vertexData[10] = x + width; 
vertexData[11] = y; 


glBindBuffer(GL_ARRAY_BUFFER, _vboID); 

glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DYNAMIC_DRAW); 

glBindBuffer(GL_ARRAY_BUFFER, 0); 

}

여기

및 내가 분명히 매우 명백한 공동 실종 추첨 방법

void Sprite::draw() { 

glBindBuffer(GL_ARRAY_BUFFER, _vboID); 
glEnableVertexAttribArray(0); 


glVertexAttribPointer(0, 2, 0x1406, GL_FALSE, 0, 0); 
glDrawArrays(GL_TRIANGLES, 0, 6); 

glDisableVertexAttribArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

}

입니다 ncept 어디서나 솔루션을 찾을 수 없기 때문에 내 문제는 내가 눌러 내 사각형을 내리지 않습니다. (S I는 WASD 이동을 사용하고 있기 때문에) 여기서이 방법은 정적으로 액세스

입력 처리기

void InputHandler::handleInput(SDL_Event* event, Sprite *toMove) { 

switch (event->type) { 

case SDL_KEYDOWN: 
{ 
    if (event->key.keysym.sym == SDLK_a) { 
     toMove->setMovementBooleans(MovementTuples::LEFT, true); 
     std::cout << "Set left "; 
    } 
    if (event->key.keysym.sym == SDLK_d) { 
     toMove->setMovementBooleans(MovementTuples::RIGHT, true); 
     std::cout << "Set right "; 
    } 
    if (event->key.keysym.sym == SDLK_s) { 
     toMove->setMovementBooleans(MovementTuples::DOWN, true); 
     std::cout << "Set down "; 
    } 
    if (event->key.keysym.sym == SDLK_w) { 
     toMove->setMovementBooleans(MovementTuples::UP, true); 
     std::cout << "Set up "; 
    } 
    break; 

} 

case SDL_KEYUP: 
{ 
    if (event->key.keysym.sym == SDLK_a) { 
     toMove->setMovementBooleans(MovementTuples::LEFT, false); 
    } 
    if (event->key.keysym.sym == SDLK_d) { 
     toMove->setMovementBooleans(MovementTuples::RIGHT, false); 
    } 
    if (event->key.keysym.sym == SDLK_s) { 
     toMove->setMovementBooleans(MovementTuples::DOWN, false); 
    } 
    if (event->key.keysym.sym == SDLK_w) { 
     toMove->setMovementBooleans(MovementTuples::UP, false); 
    } 
} 

} 

}에 대한 코드이다. 여기에 내가 아래로 클릭하면 내 스프라이트 CPP

void Sprite::update() { 

if (movementBooleans[MovementTuples::DOWN]) { 
    _x -= .1f; 
    init(_x, _y, _width, _height); 
    std::cout << "Moved to: (" << _x << ", " << _y << ")"<< std::endl; 
} 

에서의 키를 클릭하면 스프라이트를 아래로 이동하는 코드 내 사각형이 완전히 사라하고 _x 값은 동일하게 유지됩니다. 나는 입력을 테스트했고 정확히 원하는대로 작동합니다. 사각형을 움직일 수없는 것 같습니다. 아무도 내 스프라이트를 이동하는 방법을 알아낼 수 있습니다, 감사합니다!

답변

1

OpenGL을 사용하고 있습니다. 사용자가 구현 한 입력 핸들러를 사용하고 있기 때문에 SDL을 사용하지는 않지만 개념은 동일해야합니다.

현재 사용중인 게임 엔진에는 Engine 클래스가 Singleton 개체 인 Engine 클래스 개체에서 상속 된 Game 클래스 개체가 있습니다. 이 게임 엔진의 구조 때문에; Engine 클래스는 GameInput 함수를 구현하기 위해 Game 클래스를 필요로합니다. 여기에 프로토 타입 모습입니다

같은 엔진 클래스

class Engine : public Singleton { 
protected: 
    // Protected Members 
private: 
    // Private Members 

public: 
    // virtual destructor & public functions 
protected: 
    // explicit protected Constructor & protected functions 
private: 
    bool messageHandler(unsigned uMsg, WPARAM wParam, LPARAM lParam); 

    virtual void keyboardInput(unsigned vkCode, bool isPressed) = 0; 

    // Other Private Functions 

}; // Engine 

다음
class Game sealed : public Engine { 
private: 
    // private members here 

public: 
    // Constructor and virtual Destructor 

private: 
    virtual void keyBoardInput(unsigned vkCode, bool isPressed) override; 
}; // Game 

마침내

// ---------------------------------------------------------------------------- 
// messageHandler() 
bool Engine::messageHandler(unsigned uMsg, WPARAM wParam, LPARAM lParam) { 
    switch(uMsg) { 
     case WM_CLOSE: { 
      PostQuitMessage(0); 
      return true; 
     } 
     case WM_SYSKEYDOWN : { 
      if ((VK_MENU == wParam) && (lParam & 0x1000000)) { 
       wParam = VK_RMENU; // Alt Key 
      } 
      // Fall Through 
     } 
     case WM_KEYDOWN: { 
      if ((VK_RETURN == wParam) && (lParam & 0x1000000)) { 
       wParam = VK_SEPARATOR; 

      } else if ((VK_CONTROL == wParam) && (lParam & 0x1000000)) { 
       wParam = VK_RCONTROL; 
      } 

      if (0 == (lParam & 0x40000000)) { // Supress Key Repeats 
       keyboardInput(wParam, true); 
      } 
      return true; 
     } 
     case WM_SYSKEYUP: { 
      if ((VK_MENU == wParam) && (lParam & 0x1000000)) { 
       wParam = VK_RMENU; // Alt Key 
      } 
      // Fall Through 
     } 
     case WM_KEYUP: { 
      if ((VK_RETURN == wParam) && (lParam & 0x1000000)) { 
       wParam = VK_SEPARATOR; 

      } else if ((VK_CONTROL == wParam) && (lParam & 0x1000000)) { 
       wParam = VK_RCONTROL; 
      } 

      keyboardInput(wParam, false); 

      return true; 
     } 
     case WM_MOUSEMOVE: { 
      // Mouse Motion Detected, Coordinates Are WRT Window Therefore 
      // 0,0 Is The Coordinate Of The Top Left Corner Of The Window 
      m_mouseState.position = glm::ivec2(LOWORD(lParam), HIWORD(lParam)); 
      mouseInput(); 
      return true; 
     } 
     case WM_LBUTTONDOWN: { 
      m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] = true; 
      mouseInput(); 
      return true; 
     } 
     case WM_LBUTTONUP: { 
      m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] = false; 
      mouseInput(); 
      return true; 
     } 
     case WM_RBUTTONDOWN: { 
      m_mouseState.isButtonPressed[MOUSE_RIGHT_BUTTON] = true; 
      mouseInput(); 
      return true; 
     } 
     case WM_RBUTTONUP: { 
      m_mouseState.isButtonPressed[MOUSE_RIGHT_BUTTON] = false; 
      mouseInput(); 
      return true; 
     } 
     case WM_MBUTTONDOWN: { 
      m_mouseState.isButtonPressed[MOUSE_MIDDLE_BUTTON] = true; 
      mouseInput(); 
      return true; 
     } 
     case WM_MBUTTONUP: { 
      m_mouseState.isButtonPressed[MOUSE_MIDDLE_BUTTON] = false; 
      mouseInput(); 
      return true; 
     } 
     case WM_MOUSEWHEEL: { 
      // Mouse Wheel Moved 
      // wParam Contains How Much It Was Moved 
      return true; 
     } 
     default: { 
      return false; // Did Not Handle The Message 
     } 
    } 
} // messageHandler 

윈도우

의에 messageHandler() 함수이다 게임의 클래스 티 그의 키보드 입력() 함수입니다

// ---------------------------------------------------------------------------- 
// keyboardInput() 
void Game::keyboardInput(unsigned vkCode, bool isPressed) { 
    std::ostringstream strStream; 
    strStream << "Key 0" << std::hex << vkCode << " was " << (isPressed ? "Pressed" : "Released"); 
    Logger::log(strStream); 

    if (VK_ESCAPE == vkCode) { 
     PostQuitMessage(0); 
    } 

    static bool keyPressed[256] = { 0 }; 
    if (vkCode < 256) { 
     keyPressed[vkCode] = isPressed; 
    } 

    if (isPressed) { 
     return; 
    } 

    switch (vkCode) { 
     case VK_DOWN: 
     case 'S' : { 
      // do logic here 
      break; 
     } 
     case VK_LEFT: 
     case 'A' : { 
      // do logic here 
      break; 
     } 
     case VK_RIGHT: 
     case 'D' : { 
      // do logic here 
      break; 
     } 
     case VK_UP: 
     case 'W' : { 
      // do logic here 
      break; 
     } 
    } 

} // handleKeyboard 

코드를 자세히 살펴보면; 키를 눌렀을 때 폴링을하지는 않지만 키를 누를 때 쿼리하거나 기다리는 중입니다. 이 논리의 이유는 이것입니다. 키를 누르면 아래쪽으로 누를 필요없이 반복적으로 누를 수 있습니다. 이것은 같은 키를 화면에 표시하는 텍스트 편집기에서 동일한 키를 누르는 것과 같습니다. 이 문제를 피하거나이 동작을 피하려면 우리는 반대 논리를합니다.

키가 해제되었을 때를 찾습니다. 키는 한 번만 놓을 수 있고 다시 놓기 상태로 들어가려면 다시 눌러야합니다. 이렇게하면 각 키를 누를 때마다 한 번씩 프로그램의 동작이 발생하고 해제됩니다.

이제 우리는 키가 눌려진 상태인지 확인한 다음 키가 눌려진 상태인지 확인합니다. 이것이 중요하지 않은 경우 키 누름 상태가 이미 기본적으로 해제 된 상태이므로 프로그램에서 자동으로 메시지 처리기 내에서 처리합니다. 따라서 여기서 일어나는 일은 Game::keyboardInput()Engine::messageHandler() 함수가 호출 될 때 렌더링 프레임 또는 업데이트 프레임 중에 발생하며 키 누르기가 해당 상태를 true로 변경했다는 것을 감지하면 함수에서 반환하고 해당 키를 놓을 때까지 계속해서 다시 호출됩니다. 키; 일단 키가 해제되고 상태가 다시 릴리스로 변경되면 if 문을 건너 뛰고 처리중인 키에 대한 switch 문으로 이동합니다.

+0

+1 노력하지만이 말 그대로 내 질문에 상관 없어요, 네가 무슨 일을하는지 알아 내 질문은 내 스프라이트를 이동하는 방법입니다 ... 내 입력 작동합니다. – Luke

+0

당신이 나에게 설명했던 것에서 : "... ... 내 문제는 내가 누르면 사각형이 움직이지 않는다." "그러면 inputHandler()에 대한 논리를 보여 주었다. 말하자면, " '아래를 클릭하면 사각형이 완전히 사라지고 _x 값이 그대로 유지되며 ...'"동작은 키가 반복적으로 눌려진 것처럼 들립니다. 귀하의'Sprite :: update()'에서'0.1f'에서'0.05f'까지의 작은 값을 사용하고'_x' 변수를 수정하는 대신'_y'로 바꾸십시오. 수직으로 이동하려면 벡터의 Y 구성 요소를 늘리거나 줄입니다. –

+0

또한이 함수를 호출하는 코드도 표시하지 않았습니다. –

1

OpenGL 셰이프를 이동하려면 실제로 행렬 변환을 수행해야합니다.

나는 개인적으로 GLM을 사용하여 나를 위해 모든 힘든 일을 처리했다. 따라서 변환이 완료된 후에 행렬을 GLSL로 전달해야한다.