2017-04-06 4 views
0

현재 일부 기본 2D RigidBody Physics에서 작업 중이며 문제가 발생했습니다. Circle과 AABB 사이의 충돌을 검사하는 함수가 있지만 때로는 Circle (이 경우 플레이어)이 충돌하여 사라질 때가 있습니다. 그리고 이런 상황이 발생하면 인쇄 할 때 "nan"을 설정합니다.개체 충돌을 유발하는 C++ 충돌 감지

bool Game::Physics::RigidBody2D::CircleAABB(RigidBody2D& body) 
{ 
    sf::Vector2f diff = m_Position - body.m_Position; 

    sf::Vector2f halfExtents = sf::Vector2f(body.m_Size.x/2.0f, body.m_Size.y/2.0f); 

    sf::Vector2f diffContrained = diff; 

    if (diff.x > halfExtents.x) 
    { 
     diffContrained.x = halfExtents.x; 
    } 
    else if (diff.x < -halfExtents.x) 
    { 
     diffContrained.x = -halfExtents.x; 
    } 
    if (diff.y > halfExtents.y) 
    { 
     diffContrained.y = halfExtents.y; 
    } 
    else if (diff.y < -halfExtents.y) 
    { 
     diffContrained.y = -halfExtents.y; 
    } 
    sf::Vector2f colCheck = diff - diffContrained; 
    sf::Vector2f VDirNorm = NormVector(colCheck); 
    sf::Vector2f colToPlayer = NormVector(m_Position - (diffContrained + body.m_Position)); 
    float dist = getMagnitude(colCheck) - m_fRadius; 
    //std::cout << dist << std::endl; 
    if (dist < 0) 
    { 
     OnCollision((diffContrained + body.m_Position) - m_Position); 
     m_Position += (VDirNorm * abs(dist)); 
     body.m_Position -= (VDirNorm * abs(dist))* (1.0f - body.m_fMass); 

     return true; //Collision has happened 
    } 
    return false; 
} 

는 원 빠르게 이동 할 때 더 자주 일어날 것 같다하지만로 이동하지 않을 때 천천히 하나 또는 두 번 이동하는 경우도 발생할 수 있지만이 무작위로 거의 명확한 이유 일 모든.

보다 더 물리 경험이있는 사람들에게 여기 분명히 뭔가 잘못이다, 노트 내가 Y 속도로 충돌에 중력을 적용

그래서 내 질문은 0으로 조정 축 속도를 설정한다는 것입니다 추가 나를?

참고 : SFML을 드로잉 및 Vector2 클래스 물리 코드로 사용하는 것은 모두 내 것입니다.

EDIT : OnCollision 함수는 상속 된 객체가이를 사용할 수 있도록 충돌 측면을 검사합니다 (예 : 충돌이 "isGrounded"부울을 트리거하기 위해 아래에 있었는지 확인). 이 경우 플레이어는 측면을 확인한 다음 해당 축의 속도를 0으로 설정하고 아래에있을 때 isGrounded 부울을 트리거합니다.

void Game::GamePlay::PlayerController::OnCollision(sf::Vector2f vDir) 
{ 

if (abs(vDir.x) > abs(vDir.y)) 
    { 
     if (vDir.x > 0.0f) 
     { 
      //std::cout << "Right" << std::endl; 
      //Collision on the right 
      m_Velocity.x = 0.0f; 
     } 
     if (vDir.x < 0.0f) 
     { 
      //std::cout << "Left" << std::endl; 
      //Collision on the left 
      m_Velocity.x = 0.0f; 
     } 
     return; 
    } 
    else 
    { 
     if (vDir.y > 0.0f) 
     { 
      //std::cout << "Below" << std::endl; 
      //Collision below 
      m_Velocity.y = 0.0f; 
      if (!m_bCanJump && m_RecentlyCollidedNode != nullptr) 
      { 
       m_RecentlyCollidedNode->ys += 3.f; 
      } 
      m_bCanJump = true; 
     } 
     if (vDir.y < 0.0f) 
     { 
      //std::cout << "Above" << std::endl; 
      //Collision above 
      m_Velocity.y = 0.0f; 

     } 
    } 
} 

속도와 위치를 디버깅 할 때 실제적인 이유가 없습니다.

inline sf::Vector2f NormVector(sf::Vector2f vec) 
{ 
    float mag = getMagnitude(vec); 
    return vec/mag; 
} 

솔루션 : 내가 볼

if (colCheck.x == 0 && colCheck.y == 0) 
{ 
    std::cout << "Zero Vector" << std::endl; 
    float impulse = m_Velocity.x + m_Velocity.y; 
    m_Velocity.x = 0; 
    m_Velocity.y = 0; 
    m_Velocity += NormVector(diff)*impulse; 
} 
else 
{ 
    VDirNorm = NormVector(colCheck); 
    dist = getMagnitude(colCheck) - m_fRadius; 
} 
+1

일부 디버깅을 수행하고 찾은 것으로보고해야합니다. –

+1

적절한 [mcve]를 제공해야합니다. 특히 NormVector가 코드 단위로 수행하는 작업과 OnCollision이 수행하는 작업을 알아야합니다. 지금까지, 그 가능성이 가장 높은 범인처럼 보입니다. – Xirema

+0

죄송합니다! 더 자세한 내용을 추가합니다. –

답변

2

하나의 문제는 제로 벡터 NormVector입니다. 반환 된 벡터에서 NaN을 생성하여 0으로 나눕니다. diffdiffContrained이 같을 때 기존 코드에서 발생할 수 있으므로 colCheck은 (0,0)이되어 VDirNorm에 NaN이 포함되어 m_position으로 전파됩니다.

일반적으로 정규화 된 길이가 0 인 벡터는 길이가 0 인 벡터 (this post 참조)를 유지해야하지만이 경우 정규화 된 벡터를 사용하여 충돌 후 신체를 오프셋하므로 코드를 추가해야합니다 합리적인 방식으로 처리해야합니다.

+0

오 와우, 나는 그것을 고치기 위해 어떻게 갈 것인지 완전히 모르겠다. 그러나 너는 완전히 옳다. 나는 내가 할 수있는 것을보고 이것이 문제인지를 볼 것이다! 감사! –

+0

NaN은 Zero-Vector를 정규화하는 데 완벽하게 유효한 응답이라고 주장하고 싶습니다. (OP는 여전히 Zero Vector에서 정규화를 호출하지 않도록 코드를 변경해야하지만) [This Post] (http://stackoverflow.com/questions/722073/how-do-you-normalize-a-zero-vector), 제로 벡터를 정규화하는 올바른 방법 인 것처럼 들리지만 변경되지 않은 상태로 두는 것이 좋습니다. 그래서 아마 그 대답에 추가 할 것입니다. – Xirema

+0

몇 가지 작은 디버깅을 완료 한 후에는 colCheck가 0,0 일 때 오류가 발생합니다. 이런 일이 생길 때 VDirNorm을 0,0으로 유지하려고했지만 같은 문제가 발생합니다. 이 문제를 해결하는 것은 어려울 수 있습니다! 그러나 그것을 지적 해 주셔서 감사합니다! –