게임

부채꼴 모양 스킬 타겟 구하기

MAKGA 2021. 10. 9. 15:47
320x100

흔히 스킬 범위 중에 부채꼴 모양들이 있어서 현재 내 좌표 기준으로 해당되는 타겟이 누가있는지 알아야할 때가 있다.

리그 오브 레전드에서 자크의 스킬 범위

 

그래서 부채꼴의 넓이를 구하기 위해선 관련 공식을 알아야할 필요가 있다.

 

우리는 주입식 교육으로 원의 넓이를 구하는 공식은 대부분 알고 있다.

반지름 x 반지름 x 3.14인데 사실 부채꼴은 원의 일부분 이므로 부채꼴의 각도 만큼만 구하면 부채꼴의 넓이가 된다.

 

부채꼴의 넓이(S) 구하는 공식
부채꼴의 호(L)를 구하는 공식

 

'호'란 원의 전체 둘레에서 부채꼴의 각만큼에 해당하는 길이다. 즉 피자 1조각으로 치자면 크러스트의 길이랄까...

 

자 그럼 다시 원래 주제로 돌아와서 해당 범위에 해당하는 적을 어떻게 구분해 내느냐인데 방법은 선택하기 나름이다.

 

1. 먼저 해당 스킬 범위를 반지름으로 하는 원에 해당하는 모든 actor 목록을 가져오고 각각 나와 actor 내적을 계산해 스킬 데이터의 중심선의 내적(스킬 범위의 1/2) 안에 위치하는지 확인하기

// 두 액터간의 거리
double Distance(Actor* actor1, Actor* actor2)
{
    double diffx = actor1.GetX() - actor2.GetX();
    double diffy = actor2.GetY() - actor2.GetY();
    // 피타고라스의 정리로 구할 수 있다.
    return sqrt(pow(diffx, 2) + pow(diffy, 2));
}

// 벡터의 크기
double VectorSize(double A1, double A2)
{
    // 2차원에서의 벡터에서는 피타고라스 정리처럼 구할 수 있다.
    // 3차원이라면 x,y축이 이루는 평면의 길이를 구하고 그 값을 z축과 다시 구한다.
    // ‖v‖ =  sqrt(v0^2 + v1^2 + v2^2... + vn^2)
    return sqrt(pow(A1, 2) + pow(A2, 2));
}

// 벡터의 내적
double Inner(double X1, double Y1, double X2, double Y2)
{
    return (X1 * X2) + (Y1 * Y2);
}

// x, y는 마우스 커서의 좌표
// allTarget에는 일정 범위로 추린 대상을 전달한다.
vector<ACTOR*>& GetTarget(double x, double y, vector<ACTOR*>& allTarget)
{
    vector<ACTOR*> hitTarget;
    for (ACTOR* actor : allTarget)
    {
        // 스킬 사정거리 밖이면 걸러내기
        if (Distance(this, actor) > Skill.GetDistance())
            continue;

        // 마우스 커서의 벡터 크기
        double u = VectorSize(x - this.GetX(), y - this.GetY());
        // 상대방 위치의 벡터 크기
        double v = VectorSize(actor->GetX() - this.GetX(), actor->GetY() - this.GetY());
        // 두 벡터간의 내적 구하기
        double inner = Inner(this->GetX(), this->GetY(), actor->GetX(), actor->GetY());
        // 스킬 각도 밖이면 걸러내기('스킬 각도/2'와 '나와 상대'의 내적 비교)
        if (acos(inner / (u * v)) <= Skill.GetRange() / 2)
            hitTarget.push_back(actor);    
    }

    return hitTarget;
}

-> 이 방법은 간단해보이지만 불필요한 범위의 actor 목록을 가져와야 하므로 조금 비효율적이다.

 

2. 내 캐릭터 좌표로 계산된 부채꼴의 넓이를 좌표계로 변환하고 해당 좌표에 있는 actor 목록만 가져오기

#define PI 3.141592
#define DEGREE_TO_RADIAN(degree) ((PI/180)*(degree)) // 60분법 -> 호도법
#define RADIAN_TO_DEGREE(radian) ((180/PI)*(radian)) // 호도법 -> 60분법

// ...
vector<Actor*> hitList;
double radian = DEGREE_TO_RADIAN(Skill.GetDegree() / 2 + GetDegree());
double cosval = cos(radian);
double sinval = sin(radian);
for (int i = 1; i < r; ++i)
{
    double rangeX = i * cosval;
    double rangeY = i * sinval;
    for (double x = GetX() - rangeX; x < GetX() + rangeX; ++x)
    {
        for (double y = GetY() - rangeY; y < GetY() + rangeY; ++y)
        {
            Actor* actor = GetActorForPos(x, y);
            if (actor) hitList.push_back(hitList);
        }
    }
}

-> 불필요한 부분이 없지만 조금 더 계산해야한다.


그냥 내용을 바탕으로 메모장에 작성해본 코드라 돌아갈진 모르겠다.

 

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=since201109&logNo=220817604846 

 

부채꼴 넓이와 호의 길이 구하는 공식 증명(유도)

부채꼴 부채꼴의 넓이와 호의 길이를 구하는 공식은 아래와 같습니다. r은 반지름, l은 호의 길이, x는 부...

blog.naver.com

https://rangsub.tistory.com/15

 

[Algorithm] [C++] 부채꼴 범위 안의 적 판별하기

해당 문제는 최근 한 기업의 입사 코딩테스트에서 나왔던 문제입니다. 유명한 온라인 게임 리그오브레전드의 '애쉬' 챔피언이 스킬을 사용하는 그림이 이 문제의 설명을 돕는 이미지로 출제 되

rangsub.tistory.com

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gooldare&logNo=221479323579 

 

3. 부채꼴 충돌

부채꼴은 360도인 원을 일정 각도만큼 자른 모양에 해당한다 아래 그림에서 파란 점을 물체라고 하면 원의 ...

blog.naver.com

https://3001ssw.tistory.com/154

 

[C++] 각도, 길이로 원하는 좌표값 구하기

오랜만에 글을 쓰네요. 이번 글에서는 특정한 좌표에서 각도, 거리를 입력했을 때 좌표를 구하는 방법을 알아보겠습니다. 해당 방법을 알기 위해서 삼각함수(sin, cos)를 사용해야하는데 이 함수

3001ssw.tistory.com

 

320x100