2011-03-24 3 views
4

내 게임에서 오브젝트와 충돌을 감지하고 있습니다. 지금은 모든 것이 수직으로 움직이지만 다른 운동을위한 옵션은 계속 열려 있습니다. 고전적인 2 차원 수직 공간 사수입니다. 충돌 검사 모든 개체를 통해산발적 충돌 감지

가 지금 내가 루프 :

여기
for(std::list<Object*>::iterator iter = mObjectList.begin(); iter != mObjectList.end();) { 
    Object *m = (*iter); 
    for(std::list<Object*>::iterator innerIter = ++iter; innerIter != mObjectList.end(); innerIter++) { 
      Object *s = (*innerIter); 

      if(m->getType() == s->getType()) { 
       break; 
      } 

      if(m->checkCollision(s)) { 
       m->onCollision(s); 
       s->onCollision(m); 
      } 
     } 
    } 

나는 충돌을 확인하는 방법입니다,

bool checkCollision(Object *other) { 
     float radius = mDiameter/2.f; 
     float theirRadius = other->getDiameter()/2.f; 
     Vector<float> ourMidPoint = getAbsoluteMidPoint(); 
     Vector<float> theirMidPoint = other->getAbsoluteMidPoint(); 

     // If the other object is in between our path on the y axis 
     if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y && 
      theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius)) { 

       // Get the distance between the midpoints on the x axis 
       float xd = abs(ourMidPoint.x - theirMidPoint.x); 

       // If the distance between the two midpoints 
       // is greater than both of their radii together 
       // then they are too far away to collide 
       if(xd > radius+theirRadius) { 
        return false; 
       } else { 
        return true; 
       } 

     } 
     return false; 
} 

문제는 무작위로 제대로 충돌을 감지하지만, 다른 시간은 그것을 전혀 감지하지 못합니다. 객체가 다른 유형을 가지기 때문에 객체 루프에서 이탈하는 if 문이 아닙니다. 물체가 화면 상단에 가까울수록 충돌이 더 잘 감지됩니다. 화면 하단에 가까울수록 정확하게 또는 심지어 전혀 감지되지 않을 확률이 적습니다. 그러나 이러한 상황이 항상 발생하는 것은 아닙니다. 물체의 직경은 문제가 있는지보기 위해 방대한 양 (10과 20)이지만 전혀 도움이되지 않습니다.

편집 - 당신의 내부 루프가 mObjectList.begin에서 시작해야

bool checkCollision(Object *other) { 
    float radius = mDiameter/2.f; 
    float theirRadius = other->getDiameter()/2.f; 
    Vector<float> ourMidPoint = getAbsoluteMidPoint(); 
    Vector<float> theirMidPoint = other->getAbsoluteMidPoint(); 

    // Find the distance between the two points from the center of the object 
    float a = theirMidPoint.x - ourMidPoint.x; 
    float b = theirMidPoint.y - ourMidPoint.y; 

    // Find the hypotenues 
    double c = (a*a)+(b*b); 
    double radii = pow(radius+theirRadius, 2.f); 

    // If the distance between the points is less than or equal to the radius 
    // then the circles intersect 
    if(c <= radii*radii) { 
     return true; 
    } else { 
     return false; 
    } 
} 
+0

가 아직 변화가 베타의 대답의 최신 버전에 제안했다 가지고 (즉, 합을 제곱하지 -of-radii 두 번)? 문제가 해결되면 베타의 대답을 받아 들여야합니다. 그렇지 않다면, 여전히 작동하지 않는 방법을 나타내야합니다. –

답변

2

이 논리는 잘못된 것입니다 교활한; 나는 현재 충돌을 점검하고, 먼저 충돌하도록 제안 할 것이다. 충돌 (지금)을 확인할 때 x와 y를 독립적으로 확인할 수 없으면 객체 센터 사이의 거리를 조사해야합니다.

편집 :

편집 된 코드는 여전히 매우 옳지 않다.

// Find the hypotenues 
double c = (a*a)+(b*b); // actual hypotenuse squared 
double radii = pow(radius+theirRadius, 2.f); // critical hypotenuse squared 

if(c <= radii*radii) { // now you compare a distance^2 to a distance^4 
    return true; // collision 
} 

그것도이 있어야한다 :

double c2 = (a*a)+(b*b); // actual hypotenuse squared 
double r2 = pow(radius+theirRadius, 2.f); // critical hypotenuse squared 

if(c2 <= r2) { 
    return true; // collision 

} 

또는이 그들의 중심 사이의 거리가 충분히 작은 경우

double c2 = (a*a)+(b*b); // actual hypotenuse squared 
double c = pow(c2, 0.5); // actual hypotenuse 
double r = radius + theirRadius; // critical hypotenuse 

if(c <= r) { 
    return true; // collision 

} 
+0

제안 해 주셔서 감사합니다.하지만 x 축에서 사용한 것과 같은 방법을 사용하기 위해 y 축의 감지를 변경했습니다. 나는 같은 결과를 얻습니다. 때로는 충돌이 올바르게 감지되고 전혀 감지되지 않는 경우가 있습니다. 문제가 일부 일 수 있음을 나타 냅니까? 다른 어디? – rcapote

-1

업데이트 코드() 대신 ITER의.

내부 루프는 전체 목록을 반복해야합니다. 그렇지 않으면 외부 루프에서 진행할 때 충돌 후보가 누락됩니다.

if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y && 
     theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius)) 
{ 
    // then a collision is possible, check x 
} 

(괄호 내부의 논리도 잘못이지만, 그 거짓 네거티브, 잘못된 반응을 생산하지 않아야합니다.) 충돌이 될 수있는 시간 간격 동안 발생했는지 여부를 확인 :

+0

고마워하지만 문제는 여전히 지속됩니다. : – rcapote

+0

첫 번째 대답이 잘못되었습니다. 목록 대신 두 개의 다른 목록을 자체적으로 비교한다고 가정했습니다. x 및 y 좌표에 대해 동일한 충돌 기준을 사용해 보았습니까? x 좌표 검사가 정확하다고 생각합니다. y에 사용해야합니다. 왜 이전 y 좌표가 필요한지 이해할 수 없습니다. –

+0

이전 좌표를 사용하는 이유는 이동의 단계로 인해 충돌이 발생했기 때문입니다. 스프라이트가 12로 이동하면 다른 객체는 10 픽셀이므로 충돌이 감지되지 않을 가능성이 있습니다 – rcapote

3

두 원형 물체가 충돌합니다. 이 작업을 확인하려면 다음 코드를 사용할 수 있습니다

double distanceSquared = 
    pow(ourMidPoint.x - theirMidPoint.x, 2.0) + 
    pow(ourMidPoint.x - theirMidPoint.x, 2.0); 
bool haveCollided = (distanceSquared <= pow(radius + theirRadius, 2.0)); 

시간에 두 점 사이의 충돌, 당신은 시간 간격의 시작에서 충돌을 확인할 수 있었다 여부를 확인하기 위해 그것의 끝에서 ; 그러나 개체가 매우 빠르게 이동하면 충돌 감지가 실패 할 수 있습니다 (화면 맨 아래에서 속도가 가장 빠른 낙하물에 대해이 문제가 발생했습니다).

다음은 충돌 검색을 더욱 안정적으로 만들 수 있습니다 (여전히 완벽하지는 않지만). 객체가 일정한 속도로 움직인다 고 가정하십시오. 다음, 자신의 위치는 시간의 선형 함수는 다음과 같습니다

our_x(t) = our_x0 + our_vx * t; 
our_y(t) = our_y0 + our_vy * t; 
their_x(t) = their_x0 + their_vx * t; 
their_y(t) = their_y0 + their_vy * t; 

지금 당신은 시간의 차 함수로 그들 사이의 (제곱) 거리를 정의 할 수 있습니다. 그것의 최소값 (즉, 그 미분은 0)을 가정 한 시간을 찾으십시오. 이 시간이 현재 시간 간격에 속하면 최소값을 계산하고 충돌을 확인하십시오.

이것은 거의 완벽하게 충돌을 감지 할 수 있어야합니다. 응용 프로그램이 자유 낙하 심하게 작동하는 경우, 당신이 차로 이동 기능을 수정 할 수 있습니다 :

our_x(t) = our_x0 + our_v0x * t; 
our_y(t) = our_y0 + our_v0y * t + g/2 * t^2; 
+0

'pow (x, 2.0)'은'x * x'보다 빠를 수 없으며 (구현 및 하드웨어에 따라) 상당히 느릴 수 있습니다. 여기에서'x' 매개 변수가 복합 표현식이라면'inline double Square (double x) {return x * x; }'. – TonyK

+1

@ TonyK 내 컴파일러 (gcc 4.1.2)가 실제로이 최적화를 수행합니다 – anatolyg

+0

이전에이 방법을 사용하여 충돌을 테스트했지만 여전히 동일한 결과를 얻었습니다. 이 방법을 사용하여 원본 게시물을 코드로 업데이트했습니다. 물체의 움직임은 사용자가 묘사 한 것과 똑같지 만 중력의 영향을받지 않습니다. 물체가 화면에서 벗어날 때까지 일정한 속도로 움직입니다. 저는 연구에서 미적분의 표면을 겨우 긁어 모으고 있습니다. 그래서 이것은 단지 수학 지식에서 벗어났습니다. 좌표의 미분은 속도입니다. 나는 그것을 어떻게합니까? – rcapote