쿼드 트리 / 그리드 기반 충돌-로직을 실행 //somewhere else for(i:int =

우선, 나는 잠시 동안 내 자신의 게임 논리를 쓰고 있었기 때문에 이것이 곧 보일지 사과드립니다.

쿼드 트리와 그리드 기반 충돌 감지에 대해 많이 읽었습니다. 나는 논리를 이해합니다-기본적으로 객체가 기본적으로 가까이 있지 않으면 충돌을 확인하지 않습니다. 그러나 실제로 어떻게 이것을 실행하는지는 언급되지 않았습니다.

머리에 몇 가지 가능한 방법이 있지만 어느 것이 가장 좋은지 잘 모르겠습니다.

일반 충돌 테스트-최적화 없음

for(var i:int = 0; i < objects.length; i++){
        //find object A
        var objectA = objects[i];

        for(var j:int = i + 1; j < objects.length; j++){
            //find object B
            var objectB = objects[j];

            if(objectA.collidesWith(objectB){

               //handle collision logic
              }
        }

이웃 저장 (방법 1)
그러나 충돌을 최적화하여 가까운 객체 만 확인하려면 어떻게해야합니까? 우리는 여전히 모든 객체를 통과합니까, 아니면 검사 할 객체가 가까운 배열을 생성합니까?

var objects:Array = new Array();
    var neighbours:Array = new Array();

    for(var i:int = 0; i < objects.length; i++){
        //find object A
        var objectA = objects[i];

        for(var j:int = i + 1; j < objects.length; j++){
            //find object B
            var objectB = objects[j];

            if(objectA.isNear(objectB){

               neighbours.push(objectA, objectB);
              }
        }

    }

    //somewhere else
    for(i:int = 0; i < neighbours.length; i++){
        //only check neighbours

        for(j:int = i + 1; j < neighbours.length; j++){

            if(objectA.collidesWith(objectB){

               //handle collision logic
              }
        }
    }

모든 객체를 반복하지만 이웃에 대해서만 충돌을 검사합니다 (방법 3)
또 다른 가능성은 충돌을 테스트하기 전에 객체가 근처에 있는지 확인하지만 모든 것을 반복합니다.

for(var i:int = 0; i < objects.length; i++){
        //find object A
        var objectA = objects[i];

        for(var j:int = i + 1; j < objects.length; j++){
            //find object B
            var objectB = objects[j];

            if(objectA.isNear(objectB){
               //they are near - check collision!
               if(objectA.collidesWith(objectB){

               //handle collision logic
              }
            }
        }

    }

타일 ​​데이터에 객체 저장 (방법 3)
타일 ​​기반 시스템을 사용하면 다른 옵션을 사용할 수 있습니다. 타일 ​​데이터 자체에서 특정 타일에있는 객체를 저장합니다. 주변 타일이 어떤 타일인지 확인하고 충돌 할 수있는 객체가 포함되어 있는지 확인하십시오.

var ObjectA;

for(var i:int = 0; i < 4; i ++){
//check 4 surrounding tiles from object A

   if(Object.currentTile + surroundingTile[i] CONTAINS collidable object){
   //check collision!
    if(objectA.collidesWith(surroundingTile.object){

    //handle collision logic
     }

}
}

저는 항상 현실 세계를 예로 들어 봅니다. 같은 색상의 항목을 비교하려면 색상이 일치하지 않더라도 전체 항목을 모두 확인하는 것이 비논리적 인 것 같습니다 (방법 2, 각 항목 확인). 아마도 모든 것을 확인하는 대신 동일한 색상 (서로 가까운 객체)으로 항목을 수집하고 그 방법 (방법 1)을 검사 할 것입니다.

충돌 검사의 항목이 지속적으로 이동하여 주문이 혼합되기 때문에 이것은 적절한 비교가 아닙니다. 그게 저를 혼란스럽게합니다.

각 항목을 확인하는 것이 더 효율적이므로 이웃 배열을 계속 생성하는 부담을 없애줍니다.

아니면 충돌을 확인하기 위해 너무 많은 객체를 반복 할 필요가없는 이웃을 찾는 것이 더 효율적입니까?

각 타일의 데이터를 계속 변경하면 매우 집중적 인 것처럼 보이므로 좋은 아이디어인지 확실하지 않습니다.

나는 물체가 쏘기 전에 물체가 범위 내에 있으면 타워가 물체를 감지 해야하는 타워 방어 게임을 생각했습니다. 그리고 때로는 모든 물건을 확인하는 것이 어리석은 것처럼 보이지만 때로는 근처에 물건이 없을 수도 있습니다.

긴 글에 대해 사과 드리며 항상 설명하는 데 어려움을 겪고 있습니다.



답변

실제 충돌 검사 횟수를 줄여야합니다. 그래, 나도 알아 이에 대해 자세히 설명하겠습니다.

최적화하지 않은 첫 번째 충돌 검사 알고리즘 : 한 번의 실행으로 몇 개의 검사를 수행합니까? n이 객체의 개수 인 경우 약 n * (n-1) 개의 검사입니다. 많은 물체 (> 100)의 경우 이것은 엄청나게 느릴 것입니다.

이웃 검사 방법은 훨씬 빠르지 않습니다. 객체가 정적이지 않고 많이 움직이면 게임 루프에서 매번 각 객체에 대한 이웃 목록을 작성해야합니다. n * (n-1)을 수행하여 이웃 목록을 작성한 다음 각 객체가 이웃 중 하나와 충돌하는지 확인하기 때문에 실제로는 첫 번째 알고리즘보다 나쁩니다.

게임 공간을 분할해야합니다. 게임 공간의 너비가 400×400 픽셀이라고 가정 해 보겠습니다. 이 크기를 각각 200×200 크기의 4 개 하위 공간으로 분할하고 각 하위 공간이 속한 하위 개체를 확인할 수 있습니다 (한 개체가 두 개 이상의 하위 공간 내에있을 수 있음). 그런 다음 각 하위 공간의 객체가 동일한 하위 공간의 다른 객체와 충돌하는지 확인해야합니다.

따라서 런타임 비용은 다음과 같습니다. n 4 개의 하위 공간 목록 + (n / 4) * ((n-1) / 4)를 빌드하는 데 이전 런타임 비용보다 훨씬 낫습니다. 이는 하위 공간을 더 작게 만들어서 더 줄일 수 있습니다 (예 : 50×50).

이제 우리 알고리즘은 다음과 같습니다.

for each (object in objects)
  check into which subspace the object belongs

for each (subspace in subspaces)
  for each (object in subspace)
    check object for collision with other objects in same subspace

이것은 타일 데이터 아이디어와 다소 유사합니다. 그러나 서브 스페이스는 타일과 동일한 크기 일 필요는 없습니다.

쿼드 트리를 사용하여이를 더욱 최적화하기 위해 마지막 단계를 수행 할 수 있습니다. k를 부분 공간의 개수라고하자. 스페이스 오브젝트리스트를 빌드하기 위해 k * n 검사를 수행하여 게임 세계가 커지면 많은 검사를 수행합니다.

이 비용을 줄이기 위해 쿼드 트리를 사용합니다. 쿼드 트리는 게임 공간을 분할하는 또 다른 방법입니다. 400×400 공간을 64 50×50 하위 공간으로 나누고 현재 64 개의 하위 공간이있는 각 개체를 확인하는 대신 게임 공간이 게임 공간 크기 (200×200)의 절반 인 4 개의 하위 공간으로 나뉩니다. 더 작은 부분 공간 (100×100), 다시 50×50 부분 공간으로 나뉩니다. 이것이 우리의 쿼드 트리입니다.

이제 객체가 어떤 50×50 하위 공간에 속하는지 알고 싶다면 200×200 하위 공간 중 어느 것이 속하는지 확인합니다. 그런 다음 쿼드 트리에서 한 단계 더 깊이 들어가서 방금 찾은 200×200 하위 공간 내에있는 4 개의 100×100 하위 공간을 검사합니다. 이것은 객체가 속하는 50×50 하위 공간을 알 때까지 반복됩니다. 이제 몇 개의 점검이 필요 했습니까? 쿼드 트리의 각 레벨에 대해 4 (오브젝트가 두 개의 서브 스페이스의 가장자리에있을 수 있음을 기억하십시오). 따라서 개체를 올바른 50×50 하위 공간에 할당하려면 4 * 3 검사가 필요합니다. 64 검사보다 훨씬 낫습니다.

따라서 쿼드 트리 알고리즘은 부분 공간리스트를 빌드하기 위해 4 * 3 * n 검사가 필요하다가 각 객체의 충돌을 검사하기 위해 k * (n / k) 검사와 같은 것이 필요합니다.