흔히 스킬 범위 중에 부채꼴 모양들이 있어서 현재 내 좌표 기준으로 해당되는 타겟이 누가있는지 알아야할 때가 있다.
그래서 부채꼴의 넓이를 구하기 위해선 관련 공식을 알아야할 필요가 있다.
우리는 주입식 교육으로 원의 넓이를 구하는 공식은 대부분 알고 있다.
반지름 x 반지름 x 3.14인데 사실 부채꼴은 원의 일부분 이므로 부채꼴의 각도 만큼만 구하면 부채꼴의 넓이가 된다.
'호'란 원의 전체 둘레에서 부채꼴의 각만큼에 해당하는 길이다. 즉 피자 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
https://rangsub.tistory.com/15
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gooldare&logNo=221479323579
https://3001ssw.tistory.com/154