나는 2D 우주 게임을 만들고 있는데 우주선이 행성을 가로 채도록해야합니다. 직선 요격에 대한 작업 코드가 있지만 원형 궤도에서 행성 위치를 계산하는 방법을 알 수 없습니다.
게임은 과학적으로 정확하지 않으므로 관성, 중력, 타원형 궤도 등에 대해 걱정하지 않습니다.
우주선의 위치와 속도 그리고 행성의 궤도 (반지름)와 속도를 알고 있습니다
나는 2D 우주 게임을 만들고 있는데 우주선이 행성을 가로 채도록해야합니다. 직선 요격에 대한 작업 코드가 있지만 원형 궤도에서 행성 위치를 계산하는 방법을 알 수 없습니다.
게임은 과학적으로 정확하지 않으므로 관성, 중력, 타원형 궤도 등에 대해 걱정하지 않습니다.
우주선의 위치와 속도 그리고 행성의 궤도 (반지름)와 속도를 알고 있습니다
답변:
이에 대한 분석 솔루션은 어렵지만 이진 검색 을 사용 하여 필요한 정확도 내에서 솔루션을 찾을 수 있습니다.
선박은 시간 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_min 과 t_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 회의 반복이 필요합니다.
이것을 너무 복잡하게 만들지 마십시오. 이 방법은 "완벽한"솔루션은 아니지만 대부분의 게임에서 작동하며 결함은 플레이어에게 보이지 않습니다.
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...]
우주선이 가까워 질수록 오류가 낮아지기 때문에 작동합니다. 따라서 계산은 시간이 지남에 따라 더 안정적이됩니다.
오차는 계산 된 행성에 도달하는 데 필요한 시간 (TimeNeeded)과 행성에 도달하는 데 필요한 실제 시간 (새 TargetPoint를 고려한 후)의 차이입니다.
문제의 배후에있는 수학을 살펴보면서 시작하겠습니다.
선과 도형 사이의 교차점을 찾는 것은 선의 방정식을 도형의 방정식에 삽입하는 것입니다.이 경우에는 원입니다.
중심이 c 이고 반지름이 r 인 원을 그리십시오 . 점 p 는 원에 있습니다
제곱 거리는 내적 제품 ( http://en.wikipedia.org/wiki/Dot_product ) 으로 다시 쓸 수 있습니다 .
이것은 간단한 2 차 방정식이며, 우리는 해에 도달합니다
경우 , 귀하의 경우 선박의 라인은 행성의 궤도하지 교차한다.
경우 , 선박의 라인은 단순히 한 점에서 원을 터치합니다.
그렇지 않으면, 이것은 궤도상의 두 지점에 해당하는 두 개의 제공합니다 !
따라서 선박의 선을 정의 할 수 있으며 그 중에서 0, 1 또는 2 -values를 얻습니다 . 값이 1이면 그 값을 사용하십시오. 우리가 2를 얻는다면, 단순히 그중 하나를 선택하십시오.
우리는 이것으로 무엇을 할 수 있습니까? 글쎄, 우리는 이제 배가 이동해야하는 거리와 그 끝이 어디인지 알게되었습니다!
는 우리에게 좌표를 제공하고 -component는 우리가 얼마나 멀리 이동해야하는지 알려줍니다. 이 마지막 구성 요소를 선박 속도로 나누면 도착하는 데 걸리는 시간이 얼마 남지 않습니다!
이제 남은 일은 우주선이 궤도를 향하여 오기 시작할 때 행성의 위치를 계산하는 것입니다. 이것은 극성 Coodinates ( http://mathworld.wolfram.com/PolarCoordinates.html ) 로 쉽게 계산됩니다.
그리고 당신은 당신의 배의 속도를 가지고 있고, 우리는 우주선이 궤도에 도달하는데 걸리는 시간이 있고, 충돌 할 곳을 가지고 있기 때문에, 우리는 지구를 궤도에서 degree로 됩니다. !
우주선의 선을 선택하고 행성 궤도와 충돌하는지 수학을 실행하십시오. 그렇다면 해당 시점에 도달하는 데 걸리는 시간을 계산하십시오. 이 시간을 사용하여 우주선과 함께이 지점에서 궤도로 돌아가 우주선이 움직이기 시작할 때 행성의 위치를 계산하십시오.
다음은 약간의 "즉시 사용 가능한"솔루션입니다.
문제는 배가 주어진 속도로 직선으로 움직이고 행성이 주어진 각속도로 주어진 반지름의 원으로 움직이며 행성과 배의 시작 위치가 배의 방향 벡터를 결정한다는 것입니다. 요격 코스를 그리려면 직선이 있어야합니다.
해결 방법 1 : 질문의 전제를 거부하십시오. 질문에서 "미끄럼 가능"한 수량이 각도입니다. 대신 고치십시오. 우주선이 궤도의 중심을 똑바로 향하게하십시오.
해결 방법 2 : 자동 조종 장치에서 전혀하지 마십시오. 플레이어가 스러 스터를 사용하여 행성에 접근 해야하는 미니 게임을 만들고 상대 속도로 너무 높은 속도로 충돌하면 폭발하지만 연료는 제한적입니다. 플레이어가 가로 채기 문제를 해결하는 방법을 배우게하십시오!
극좌표를 사용하지 않으려면 선박의 모든 가능한 위치가 공간 에서 원뿔을 형성하는 것을 고려하십시오 . 이에 대한 방정식은
여기서 는 선박 속도입니다. 배가 0에서 시작한다고 가정합니다.
공간과 시간에서 행성의 위치는 다음과 같이 매개 변수화 될 수 있습니다.
여기서 는 위쪽으로 갑니다 . 는 각속도이고 는 시간 0에서 행성의 시작 각도입니다. 그런 다음 시간과 공간에서 배와 행성이 만나는 곳을 해결하십시오. 당신은 방정식을 얻을 해결하기 :
이 방정식은 수치 적으로 풀어야합니다. 많은 솔루션이있을 수 있습니다. 그것을 눈으로 볼 때 항상 해결책이있는 것처럼 보입니다.
솔루션의 일부입니다. 나는 그것을 제 시간에 끝내지 못했습니다. 나중에 다시 시도하겠습니다.
내가 정확하게 이해한다면, 당신은 우주선의 위치와 속도뿐만 아니라 행성의 위치와 속도가 있습니다. 당신은 배의 이동 방향을 원합니다. 나는 우주선과 행성의 속도가 일정하다고 가정합니다. 또한 일반성을 잃지 않고 배가 (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로 가져갈 수 있습니다.
요격 할 위치를 정할 것입니다 (궤도의 "발송"쪽에서 원을 움켜 쥐십시오).
이제 우주선과 우주선이 동시에 그 지점에 도달하도록 우주선의 속도를 조정해야합니다.
우주선이 얼마나 멀리 떨어져 있는지, 그리고 행성이 얼마나 빨리 별을 공전하고 있는지에 따라 랑데부는 N 더 많은 궤도를 따라갈 수 있습니다.
시간에 따라 현재 속도에서 선박의 여행 시간에 가장 가까운 N을 선택하십시오.
그런 다음 해당 N 궤도의 타임 스탬프와 정확하게 일치하도록 우주선의 속도를 높이거나 줄입니다.
이 모든 과정에서 실제 과정은 이미 알려져 있습니다! 속도가 아닙니다.