충돌감지

2023. 6. 14. 13:33개인공부/Direct2D

충돌감지 예시


1. AABB

1
2
3
4
5
6
7
8
9
10
11
12
13
    // AABB 충돌
    else
    {
        Vector2 leftMin = leftPosition - leftScale * 0.5f;
        Vector2 leftMax = leftPosition + leftScale * 0.5f;
        Vector2 rightMin = rightPosition - rightScale * 0.5f;
        Vector2 rightMax = rightPosition + rightScale * 0.5f;
 
        if (leftMin.x <= rightMax.x && leftMax.x >= rightMin.x
            && leftMin.y <= rightMax.y && leftMax.y >= rightMin.y)
            return true;
    }
    return false;
cs

2. OBB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// OBB 충돌처리 
    if (_leftBox->IsRotatable() || _rightBox->IsRotatable())
    {
        // 회전각도
        float leftRotation = _leftBox->GetRotation();
        float rightRotation = _rightBox->GetRotation();
 
        Vector2 boxToBox = rightPosition - leftPosition;
 
        // 각각의 가로세로 벡터를 구한다.
        Vector2 leftWidth = Vector2::RotateRadian(Vector2(leftScale.x *0.5f, 0.f), Vector2::Zero, leftRotation);
        Vector2 leftHeight = Vector2::RotateRadian(Vector2(0.f, leftScale.y *0.5f), Vector2::Zero, leftRotation);
        Vector2 rightWidth = Vector2::RotateRadian(Vector2(rightScale.x *0.5f, 0.f), Vector2::Zero, rightRotation);
        Vector2 rightHeight = Vector2::RotateRadian(Vector2(0.f, rightScale.y *0.5f), Vector2::Zero, rightRotation);
 
        vector<Vector2> basis{ leftWidth,leftHeight,rightWidth,rightHeight };
 
        for (int i = 0; i < 4++i)
        {
            float sum = 0.f;
            Vector2 normal = basis[i].GetNormalize();
            for (int j = 0; j < 4++j)
            {
                sum += abs(normal.Dot(basis[j]));
            }
            
            float distance = abs(boxToBox.Dot(normal));
            if (distance >= sum)
            {
                return false;
            }
        }
        return true;
cs

3. 원과 원의 충돌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    // 원과 원의 충돌
    
    Vector2 leftPosition = _leftCircle->GetPosition();
    float leftRadius = _leftCircle->GetRadius();
 
    Vector2 rightPosition = _rightCircle->GetPosition();
    float rightRaius = _rightCircle->GetRadius();
 
    float distance = (leftPosition - rightPosition).Size();
    
    if (distance <= rightRaius + leftRadius)
    {
        return true;
    }
 
    return false;
cs

4. 원과 박의 충돌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    // 박스 
    Vector2 boxPosition = _leftBox->GetPosition();
    Vector2 boxHalfScale = _leftBox->GetScale() * 0.5f;
    
    // 원
    Vector2 circlePoisiton = _rightCircle->GetPosition();
    float radius = _rightCircle->GetRadius();
 
    // 회전된 사각형과 원의 충돌 -> 역으로 원을 돌려서 계산함
    if (_leftBox->IsRotatable())
    {
        float rotation = _leftBox->GetRotation();
        circlePoisiton = Vector2::RotateRadian(circlePoisiton, boxPosition, -rotation);
    }
 
    float minBoxX = boxPosition.x - boxHalfScale.x;
    float maxBoxX = boxPosition.x + boxHalfScale.x;
    float minBoxY = boxPosition.y - boxHalfScale.y;
    float maxBoxY = boxPosition.y + boxHalfScale.y;
 
    // 1. 먼저 사각형의 변들을 반지름만큼 확장해서 원의 중심좌표와 비교해서 판단
    if ((minBoxX - radius <= circlePoisiton.x && maxBoxX + radius >= circlePoisiton.x
        && minBoxY <= circlePoisiton.y && maxBoxY >= circlePoisiton.y) ||
        (minBoxX <= circlePoisiton.x && maxBoxX >= circlePoisiton.x
            && maxBoxY + radius >= circlePoisiton.y && minBoxY - radius <= circlePoisiton.y))
    {
        return true;
    }
    
    // 2. 가장 가까운 사각형의 꼭지점 좌표를 계산해서 원과의 거리를 계산 
    Vector2 boxVertex{};
    boxVertex.x = (boxPosition.x < circlePoisiton.x) ? maxBoxX : minBoxX;
    boxVertex.y = (boxPosition.y < circlePoisiton.y) ? maxBoxY : minBoxY;
 
    float distanceSquared = (boxVertex - circlePoisiton).SizeSquared();
    if (distanceSquared <= radius*radius)
    {
        return true;
    }
 
    // 충돌하지 않음
    return false;
cs

'개인공부 > Direct2D' 카테고리의 다른 글

스타크래프트 기능 구현 2  (0) 2023.07.14
충돌 연산 최적화  (0) 2023.07.12
스타크래프트 기능 구현 1  (0) 2023.07.10
카메라  (0) 2023.07.06
계층구조 설계  (0) 2023.07.05