타원모양 오브젝트의 충돌체크를 하는 방법에 대한 글이에요


그리고 저도 잘 아는게 아니라 틀리거나 잘못된 내용이 있을수도 있어요



ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ



1. 타원의 극좌표계 방정식




29ec9e36ebd518986abce89544817564fc


위에 올려놓은 그림이 타원의 극좌표계에서의 방정식이에요


a와 b는 각각 타원의 가로 반지름 세로 반지름이에요, 그리고 그림에 나와있는것처럼 a>b 일때와 b>a일때의 경우 두가지에 따라서 각각 k와 i의 값이 달라져요


그래도 최종적인 공식은 맨 아래에 나와있는것처럼 x = i*cos(t) y=i*sin(t)로 동일해요, 여기서 t는 각도에요





ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

def ellipse(x,y,a,b,v,t)

if a >= b

k=(1-b**2/a**2)**0.5

i=b/(1-k**2*Math.cos(t-v)**2)**0.5

end

if b >= a

k=(1-a**2/b**2)**0.5

i=a/(1-k**2*Math.sin(t-v)**2)**0.5

end

ex, ey = i*Math.cos(t-v),i*Math.sin(t-v)

ex, ey = ex*Math.cos(v)-ey*Math.sin(v),

ex*Math.sin(v)+ey*Math.cos(v)

return x+ex, y+ey

end

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ




그리고 위에 올려놓은 코드가 앞에서 설명한대로 타원의 좌표를 계산해주는 코드에요, ruby프로그래밍 언어로 작성한거에요


x,y에 중심점의 좌표, a,b에 가로와 세로의 반지름의 크기, v에 타원을 회전시킬 각도, t에 앞에서 설명한대로 각도를 넣으면, 


최종적으로 타원의 해당 각도에서의 가장자리의 점의 좌표를 출력해줘요





29ef9e36ebd518986abce8954181746ff9

위에 올려놓은건 벡터의 회전공식이에요,앞의 함수에서 v로 타원을 특정 각도만큼 회전시키는대에 사용되요







2. 타원과 점의 충돌체크

29ee9e36ebd518986abce8954185736d




앞에서 설명한 타원의 극좌표계 방정식을 이용하면, 타원과 점의 충돌체크를 할 수 있어요


즉 첫번째로 설명한 함수로, 타원의 중심점에서 체크하고자 하는 점 까지의 각도로 타원의 가장자리의 점을 구한다음


타원의 중심점에서 그렇게 구한 점까지의 거리가, 타원의 중심점에서 체크하고자 하는 점까지의 거리보다 크다면


해당 점은 타원 안에 포함되어 있다고 판정하는거에요




ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

def ellipse_point_collision(x,y,a,b,v,px,py)

angle = Math.atan2(py-y,px-x)

ex, ey = ellipse(x,y,a,b,v,angle)

dist1 = ((px-x)**2+(py-y)**2)**0.5

dist2 = ((ex-x)**2+(ey-y)**2)**0.5

if dist2 > dist1

return 1

else

return 0

end

end

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ



그리고 이게 해당 과정의 코드에요, x,y,a,b,v 에 첫번째에서 설명한대로 값을 넣고


px py에 구하고자 하는 점의 좌표를 넣으면 만약 해당 점이 타원과 충돌한다면 1을 그렇지 않으면 0을 출력해줘요


그리고 함수를 사용하려면 앞에서 설명한 타원의 함수도 정의해 놓아야 해요





3. 타원과 원의 충돌체크

29e99e36ebd518986abce8954f817d64

타원과 원의 충돌체크를 하기 위해서는 두가지 경우를 체크해야 해요


우선 타원의 가장자리가 원과 겹치는지를 체크해야 해요,


그리고 그 다음 서로 가장자리가 겹치지 않고 완전히 포함되는지를 체크하기 위해서 타원의 한점이 원에 포함되거나, 혹은 원의 한 점이 타원에 포함되는지를 체크해야해요


여기서는 타원의 중심점이 원에 포함되거나 혹은 원의 중심점이 타원에 포함되는지를 체크하는 방식으로 했어요


그리고 위의 경우중 하나라도 해당된다면 타원은 원과 충돌했다고 판정해요




그리고 이때 타원의 가장자리가 원에 포함되는지를 체크하기 위해서, 타원의 가장자리를 여러개의 점으로 근사화하는 방법을 사용해요


앞에서 설명한 타원의 극좌표계 방정식에 각도를 0부터 360까지 동일한 간격으로 넣으면, 해당하는 각도들에서의 타원의 가장자리의 점들을 얻을수 있어요,


그리고 그렇게 얻은 점들이 원 안에 포함되면, 타원의 가장자리가 원에 포함되었다고 판정하는 거에요, 



점이 원 안에 포함되는지를 체크하기 위해서는 원의 중심점과 거리를 비교하면 되요


그리고 원의 중심점이 타원 안에 포함되는지를 체크하기 위해서는 2번에서 설명한 타원과 점의 충돌체크를 하는 방법을 사용하면 되요


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

def ellipse_circle_collision(x1,y1,a1,b1,v1,x2,y2,r2,c)

i = 1

j = (Math::PI/180)*(360/c)

while i <= c

ex, ey = ellipse(x1,y1,a1,b1,v1,i*j)

if ((ex-x2)**2+(ey-y2)**2)**0.5 < r2

return 1

end

i +=1

end

if ((x1-x2)**2+(y1-y2)**2)**0.5 < r2 || ellipse_point_collision(x1,y1,a1,b1,v1,x2,y2) == 1

return 1

end

return 0

end

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ



그리고 이게 해당 과정의 코드에요, (x1,y1,a1,b1,v1,x2,y2,r2,c)에 위의 그림에 나온대로 값들을 입력하면 되요, 그렇게해서 만약 타원이 원과 충돌한다면 1을, 그렇지 않으면 0을 출력해요


여기서 v1은 타원을 회전시키는 각도에요, 그리고 c는 타원의 가장자리를 점으로 근사할때 몇도 간격으로 할지를 입력해요


예를들어서 c에 60을 입력하면, 타원의 가장자리를 총 60개의 점(6도 간격)으로 근사해서, 그 각각의 점들이 원 안에 포함되는지를 체크하는 거에요


역시 사용하려면 앞에서 설명한 함수들도 정의해놓아야 해요





4. 타원과 타원의 충돌체크



29e89e36ebd518986abce89547817469e7

타원과 타원의 충돌체크도 동일한 방식을 사용해요


우선 한 타원의 가장자리가 다른 타원의 가장자리에 포함되는지를 체크한다음


역시 서로 겹치지 않게 포함되는 경우를 체크하기 위해서 한 타원의 중심점이 다른 타원 안에 포함되는지를 체크해요


그리고 여기서도 역시 앞에서 설명한것과 동일하게 타원의 가장자리를 점으로 근사하는 방법을 사용해요




역시 타원의 가장자리를 근사하는대에는 타원의 극좌표계 방정식을 사용하고


그렇게 구한 한 점이 타원 안에 포함되는지를 체크하기 위해서는 타원과 점의 충돌체크를 하는 함수를 사용해요



ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

def ellipse_ellipse_collision(x1,y1,a1,b1,v1,x2,y2,a2,b2,v2,c)

i = 1

j = (Math::PI/180)*(360/c)

while i <= c

ex, ey = ellipse(x1,y1,a1,b1,v1,i*j)

if ellipse_point_collision(x2,y2,a2,b2,v2,ex,ey) == 1

return 1

end

i +=1

end

if ellipse_point_collision(x1,y1,a1,b1,v1,x2,y2) == 1 || ellipse_point_collision(x2,y2,a2,b2,v2,x1,y1) == 1

return 1

end

return 0

end

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ



위에 올려놓은 코드가 해당 과정의 코드에요, (x1,y1,a1,b1,v1,x2,y2,a2,b2,v2,c)에 값들을 입력하면 두 타원이 충돌했다면 1을 그렇지 않으면 0을 출력해요


역시 앞에서 설명한것과 동일한 방식이에요, 그리고 함수를 사용하려면 앞에서 설명한 함수들도 모두 정의해 놓아야 해요




위에 올려놓은 영상들은 앞에서 설명한대로 타원의 충돌체크를 실행하는 영상이에요, 첫번째가 타원과 원의 충돌체크고, 두번째가 타원과 타원의 충돌체크에요


파랑색 오브젝트가 플레이어가 방향키로 움직이는 오브젝트에요, 중앙의 연두색 오브젝트와 충돌했다면 둘다 불투명하게 표시되요


여기서는 c를 60으로 했어요, 즉 타원의 가장자리를 6도 간격의 60개의 점으로 근사화해서 체크한거에요





그리고 이런식으로 하면 타원과 원의 충돌체크를 할 수 있어요