원형 모션으로 물체를 가로채는 방법


23

나는 2D 우주 게임을 만들고 있는데 우주선이 행성을 가로 채도록해야합니다. 직선 요격에 대한 작업 코드가 있지만 원형 궤도에서 행성 위치를 계산하는 방법을 알 수 없습니다.

게임은 과학적으로 정확하지 않으므로 관성, 중력, 타원형 궤도 등에 대해 걱정하지 않습니다.

우주선의 위치와 속도 그리고 행성의 궤도 (반지름)와 속도를 알고 있습니다

여기에 이미지 설명을 입력하십시오


1
아니오 나는 행성을 가로 채기 위해 배가 움직일 각도를 계산하려고합니다.
Ausa

4
이것은 아마도 math.stackexchange.com에서 더 잘 작동 할 것입니다.
Jari Komppa

2
배가 속도와 방향을 바꿀 수 있습니까, 아니면 일정합니까? 또한, 목표물에 미사일을 피하는 것에 대한 이 질문이 도움이 될 수 있습니다.
thegrinner

4
명확히하기 위해 상황이 있습니까? 행성에 주어진 : 궤도 중심, 궤도 반경, 각속도, 현재 위치; 에 대한 선박 : 현재 위치, 현재 속도, 행성을 가로 채기 위해 선박의 움직임 방향 결정
AakashM

6
흥미로운 역사적 메모 : 행성은 보통 궤도와 같은 방향으로 회전하므로 북반구 위에서 볼 때 반 시계 방향입니다. 이 사실로부터 우리는 해시계가 북반구에서 발명 되었다고 추론 할 수있다 . 남반구에서 해시계가 발명 되었으면 시계 방향이 다른 방법 이 될 것입니다.
Eric Lippert

답변:


3

이에 대한 분석 솔루션은 어렵지만 이진 검색 을 사용 하여 필요한 정확도 내에서 솔루션을 찾을 수 있습니다.

선박은 시간 t_min 에서 궤도상의 가장 가까운 지점에 도달 할 수 있습니다 .

shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;

선박은 궤도에서 t_max 이하의 어느 지점 에나 도달 할 수 있습니다 .

(여기에서는 간단하게하기 위해 배가 태양을 통과 할 수 있다고 가정합니다. 이것을 피하려면 적어도 일부 경우에는 직선이 아닌 경로로 전환해야합니다. 역학 -y, 상수 요소 이상으로 알고리즘을 변경하지 않고)

if(shipOrbitRadius > planet.orbitRadius)
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}

우리의 궤도주기가 짧다면, 행성이 우주선의 시작 위치에 가장 가까이 접근 t_max한 후 t_min를 처음으로 선택함으로써이 상한선을 개선 할 수있을 것 입니다. 이 두 값 중 t_max작은 값을 취하십시오 . 이것이 왜 효과가 있는지에 대해서는이 답변을 참조하십시오.

이제이 극단 t_mint_max 사이에서 이진 검색을 사용할 수 있습니다 . 오류 가 0에 가까워 지는 t- 값을 검색 합니다.

error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;

(이 구성을 사용하면 오류 @ t_min> = 0 및 오류 @ t_max <= 0이므로 t- 값 사이에 error = 0 인 인터셉트가 하나 이상 있어야합니다.)

완전 함을 위해 위치 함수는 다음과 같습니다.

Vector2 Planet.positionAtTime(float t)
{
  angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
  return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}

행성의 궤도주기가 선박의 속도와 비교하여 매우 짧은 경우,이 오차 함수는 범위에 걸쳐 부호를 t_min에서 t_max로 여러 번 변경할 수 있습니다. 발생하는 가장 빠른 + ve & -ve 쌍을 추적하고 오류가 0에 가까워 질 때까지 계속 탐색하십시오 ( "충분히 닫기"는 장치와 게임 플레이 상황에 민감합니다). 잘 작동-프레임 내에서 가로 채기가 정확함을 보장합니다)

오류를 최소화하는 멋진 t가 있으면 우주선을 planet.positionAtTime (t)로 향하고 스로틀을 완전히 움직여 행성이 그 시점과 동시에 그 지점에 도달 할 것이라고 확신 할 수 있습니다.

Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold) 반복 내에서 항상 솔루션을 찾을 수 있습니다. 예를 들어, 만약 우주선이 60 개의 프레임으로 궤도를 통과 할 수 있고 한 프레임 내에서 정확한 인터셉트를 원한다면 약 6 회의 반복이 필요합니다.


1
여기에 많은 좋은 답변과 흥미로운 대안 옵션이 있지만 이미이 솔루션에서 얻은 것이 인스턴스에 가장 적합합니다. 결과에 대한 작은 JavaScript 데모를 만들었습니다. 데모
Ausa

11

이것을 너무 복잡하게 만들지 마십시오. 이 방법은 "완벽한"솔루션은 아니지만 대부분의 게임에서 작동하며 결함은 플레이어에게 보이지 않습니다.

if(!OldTargetPoint)
  TargetPoint = PlanetPosition;
else
  TargetPoint = OldTargetPoint;
Distance = CurPosition - TargetPoint;
TimeNeeded = Distance / Speed;
TargetPoint = PlanetPositionInFuture(TimeNeeded);
SteerTowards(TargetPoint);
[...repeat this every AI update, for example every second...]
  1. 목표 지점에 도달하는 데 필요한 시간을 계산하십시오.
  2. 계산 된 시간에 행성이 어떤 위치에 있을지 계산하십시오.
  3. 계산 된 점쪽으로 이동하십시오.
  4. 반복

우주선이 가까워 질수록 오류가 낮아지기 때문에 작동합니다. 따라서 계산은 시간이 지남에 따라 더 안정적이됩니다.

오차는 계산 된 행성에 도달하는 데 필요한 시간 (TimeNeeded)과 행성에 도달하는 데 필요한 실제 시간 (새 TargetPoint를 고려한 후)의 차이입니다.


1
인터셉트 코스를 시작할 때이 과정을 2 번 반복 할 수 있습니다. 가까이 나) 행성의 궤도 내
DMGregory

1
@DMGregory 아! 우리는 궤도 중심 대신 현재 지구의 위치를 ​​출발점으로 삼을 수 있습니다. 우리가 가까이있을 때 훨씬 더 가까이 있고, 멀리 있으면 문제가되지 않습니다.
API-Beast

또한 행성과 우주선이 느리게 움직일 때 가장 잘 작동한다는 점도 주목할 가치가 있습니다. 행성의 속도가 선박의 속도와 비슷하거나 더 크면 선박의 경로에 진동이 나타날 수 있습니다. 병리학적인 속도 비율에서 배는 동심 궤도에서 지구를 영원히 쫓을 수 있습니다. 행성이 빠르며 이런 일이 발생하면 비행 중반을 반복하는 대신 전체 요격 코스를 미리 계획하는 것이 좋습니다.
DMGregory

3

문제의 배후에있는 수학을 살펴보면서 시작하겠습니다.

1 단계:

선과 도형 사이의 교차점을 찾는 것은 선의 방정식을 도형의 방정식에 삽입하는 것입니다.이 경우에는 원입니다.

원과 교차하는 선

중심이 c 이고 반지름이 r 인 원을 그리십시오 . 점 p 는 원에 있습니다

|pc|2=r2

p=p0+μv

|p0+μvc|2=r2

제곱 거리는 내적 제품 ( http://en.wikipedia.org/wiki/Dot_product ) 으로 다시 쓸 수 있습니다 .

(p0+μvc)(p0+μvc)=r2

a=cp0(μva)(μva)=r2

μ2(vv)2μ(av)+aa=r2

|v|=1

μ22μ(av)+|a|2r2=0

이것은 간단한 2 차 방정식이며, 우리는 해에 도달합니다

μ=av+sqrt((av)2a2r2)

경우 , 귀하의 경우 선박의 라인은 행성의 궤도하지 교차한다.μ<0

경우 , 선박의 라인은 단순히 한 점에서 원을 터치합니다.μ=0

그렇지 않으면, 이것은 궤도상의 두 지점에 해당하는 두 개의 제공합니다 !μ

2 단계:

따라서 선박의 선을 정의 할 수 있으며 그 중에서 0, 1 또는 2 -values를 얻습니다 . 값이 1이면 그 값을 사용하십시오. 우리가 2를 얻는다면, 단순히 그중 하나를 선택하십시오.μ

우리는 이것으로 무엇을 할 수 있습니까? 글쎄, 우리는 이제 배가 이동해야하는 거리와 그 끝이 어디인지 알게되었습니다!

p=p0+μv 는 우리에게 좌표를 제공하고 -component는 우리가 얼마나 멀리 이동해야하는지 알려줍니다. 이 마지막 구성 요소를 선박 속도로 나누면 도착하는 데 걸리는 시간이 얼마 남지 않습니다!μv

이제 남은 일은 우주선이 궤도를 향하여 오기 시작할 때 행성의 위치를 ​​계산하는 것입니다. 이것은 극성 Coodinates ( http://mathworld.wolfram.com/PolarCoordinates.html ) 로 쉽게 계산됩니다.

x=c+rcos(θ)

y=c+rsin(θ)

그리고 당신은 당신의 배의 속도를 가지고 있고, 우리는 우주선이 궤도에 도달하는데 걸리는 시간이 있고, 충돌 할 곳을 가지고 있기 때문에, 우리는 지구를 궤도에서 degree로 됩니다. !tangularVelocity

개요

우주선의 선을 선택하고 행성 궤도와 충돌하는지 수학을 실행하십시오. 그렇다면 해당 시점에 도달하는 데 걸리는 시간을 계산하십시오. 이 시간을 사용하여 우주선과 함께이 지점에서 궤도로 돌아가 우주선이 움직이기 시작할 때 행성의 위치를 ​​계산하십시오.


8
좋은 분석이지만,이 질문에 대한 답은 나오지 않는 것 같습니다 (의견에 명시되어 있음). 당신은 주어진 방향으로 배의 각도를 취하고 다른 방향 대신에 행성의 위치를 ​​계산하고 있습니다.
Chaosed0

4
유용한 분석이기 때문에 이것을 다운 투표하지는 않지만 @ Chaosed0에 동의하지 않으면 질문에 대답하지 않습니다. 요약하면 "선의 선을 선택하십시오 ..."라고 말하지만 선을 선택하는 것은 어려운 부분입니다.
Drake

1

다음은 약간의 "즉시 사용 가능한"솔루션입니다.

문제는 배가 주어진 속도로 직선으로 움직이고 행성이 주어진 각속도로 주어진 반지름의 원으로 움직이며 행성과 배의 시작 위치가 배의 방향 벡터를 결정한다는 것입니다. 요격 코스를 그리려면 직선이 있어야합니다.

해결 방법 1 : 질문의 전제를 거부하십시오. 질문에서 "미끄럼 가능"한 수량이 각도입니다. 대신 고치십시오. 우주선이 궤도의 중심을 똑바로 향하게하십시오.

  • 배가 행성을 만날 위치 를 계산하십시오 . 쉽습니다.
  • 선박에서 차단 위치까지의 거리를 계산하십시오. 또한 쉽게.
  • 행성이 다음에 요격 위치에 도달 할 때까지 걸리는 시간을 계산하십시오. 쉬운.
  • 행성이 요격에 도달 할 때까지 배에서 요격까지의 거리를 나눕니다.
  • 그것이 선박의 최대 속도보다 작거나 같으면 완료된 것입니다. 배가 태양을 향해 그 속도로 똑바로 움직 이도록 설정하십시오.
  • 그렇지 않으면, 행성의 궤도주기를 시간에 더하고 다시 시도하십시오. 배의 속도에 도달 할 때까지 속도를 유지하십시오.

해결 방법 2 : 자동 조종 장치에서 전혀하지 마십시오. 플레이어가 스러 스터를 사용하여 행성에 접근 해야하는 미니 게임을 만들고 상대 속도로 너무 높은 속도로 충돌하면 폭발하지만 연료는 제한적입니다. 플레이어가 가로 채기 문제를 해결하는 방법을 배우게하십시오!


1

극좌표를 사용하지 않으려면 선박의 모든 가능한 위치가 공간 에서 원뿔을 형성하는 것을 고려하십시오 . 이에 대한 방정식은(엑스,와이,)

V=엑스2+와이2

여기서 는 선박 속도입니다. 배가 0에서 시작한다고 가정합니다.V

공간과 시간에서 행성의 위치는 다음과 같이 매개 변수화 될 수 있습니다.

엑스=엑스0+아르 자형기음영형에스(+에이)와이=와이0+아르 자형에스나는(+에이)=

여기서 는 위쪽으로 갑니다 . 는 각속도이고 는 시간 0에서 행성의 시작 각도입니다. 그런 다음 시간과 공간에서 배와 행성이 만나는 곳을 해결하십시오. 당신은 방정식을 얻을 해결하기 :0에이

V=(엑스0+아르 자형기음영형에스(+에이))2+(와이0+아르 자형에스나는(+에이))22V2=(엑스0+아르 자형기음영형에스(+에이))2+(와이0+아르 자형에스나는(+에이))22V2=엑스02+와이02+아르 자형2+2엑스0아르 자형기음영형에스(+에이)+2와이0아르 자형에스나는(+에이)

이 방정식은 수치 적으로 풀어야합니다. 많은 솔루션이있을 수 있습니다. 그것을 눈으로 볼 때 항상 해결책이있는 것처럼 보입니다.


1

솔루션의 일부입니다. 나는 그것을 제 시간에 끝내지 못했습니다. 나중에 다시 시도하겠습니다.

내가 정확하게 이해한다면, 당신은 우주선의 위치와 속도뿐만 아니라 행성의 위치와 속도가 있습니다. 당신은 배의 이동 방향을 원합니다. 나는 우주선과 행성의 속도가 일정하다고 가정합니다. 또한 일반성을 잃지 않고 배가 (0,0)에 있다고 가정합니다. 이렇게하려면 행성에서 우주선의 위치를 ​​빼고 아래에 설명 된 작업의 결과에 우주선의 위치를 ​​다시 추가하십시오.

불행히도 라텍스 가 없으면이 답변을 잘 형식화 할 수 없지만 시도하려고합니다. 방해:

  • s_s = 선박의 속도 (s_s.x, s_s.y, 마찬가지로)
  • s_a= 선박의 방위 ( 우리가 계산하고자하는 움직임의 각도 )
  • p_p = 지구의 초기 위치, 글로벌 조정
  • p_r = 궤도 중심으로부터의 행성 거리 (반지름) p_p
  • p_a = 궤도 중심을 기준으로 한 행성의 초기 각도 (라디안)
  • p_s = 행성의 각속도 (rad / sec)
  • t = 충돌 시간 (이것은 우리가 계산해야하는 것으로 밝혀 짐)

다음은 두 몸체의 위치에 대한 방정식을 구성 요소로 세분화 한 것입니다.

ship.x = s_s.x * t * cos(s_a)
ship.y = s_s.y * t * sin(s_a)

planet.x = p_r * cos(p_a + p_s * t) + p_p.x
planet.y = p_r * sin(p_a + p_s * t) + p_p.y

우리는 원 ship.x = planet.x하고 ship.y = planet.y어떤 순간 t에이 방정식을 얻습니다 ( y사례는 거의 대칭입니다).

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
   s_s.y * t * sin(s_a) = p_r * sin(p_a + p_s * t) + p_p.y

s_a에 대한 최고 방정식 풀기 :

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
=> s_a = arccos((p_r * cos(p_a + p_s * t) + p_p.x) / (s_s.x * t))

이것을 두 번째 방정식으로 바꾸면 Wolfram 알파가 나를 위해 풀지 못할 상당히 무서운 방정식이 됩니다 . 극좌표를 사용하지 않는 더 좋은 방법이있을 수 있습니다. 누구든지이 방법을 원한다면 환영합니다. 나는 이것을 위키로 만들었다. 그렇지 않으면 이것을 Math StackExchange로 가져갈 수 있습니다.


2
이 사이트에서 TeX를 활성화하고 싶습니다. 그래픽 관련 요소 (예 : 벡터, 행렬, 쿼터니언 등)를보다 쉽게 ​​표현할 수 있습니다.
mvw

0

요격 할 위치를 정할 것입니다 (궤도의 "발송"쪽에서 원을 움켜 쥐십시오).

이제 우주선과 우주선이 동시에 그 지점에 도달하도록 우주선의 속도를 조정해야합니다.

우주선이 얼마나 멀리 떨어져 있는지, 그리고 행성이 얼마나 빨리 별을 공전하고 있는지에 따라 랑데부는 N 더 많은 궤도를 따라갈 수 있습니다.

시간에 따라 현재 속도에서 선박의 여행 시간에 가장 가까운 N을 선택하십시오.

그런 다음 해당 N 궤도의 타임 스탬프와 정확하게 일치하도록 우주선의 속도를 높이거나 줄입니다.

이 모든 과정에서 실제 과정은 이미 알려져 있습니다! 속도가 아닙니다.


이것은 불필요하게 긴 여행을 줄 수 있습니다. 지구가 우리를 향해오고 지구와 동시에 "들어오는"방목 지점에 도달 할 수 있다고 가정 해 봅시다. 우리가 "발송"방목 지점 만보고 있다면, 우리는 반년 반을 추가로 운송하는 데 소비 할 수 있습니다!
DMGregory

사실 ... 궤도 속도에 따라 다릅니다. 그러나 항상 나가는 동안 방목하는 경우 델타 속도를 최소화합니다. "들어오는"에서는 대기에서 타는 반면 "나가는"에서는 일치 할 가능성이 더 높습니다. @DMGregory
Bram
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.