먼저 포탑 방향과 목표 방향 사이의 각도 차이를 결정해야합니다.
Vector2 turretToTarget = target.position - turret.position;
float desiredAngle = atan2(turretToTarget.y, turretToTarget.x);
float angleDiff = desiredAngle - turret.angle;
// Normalize angle to [-PI,PI] range. This ensures that the turret
// turns the shortest way.
while (angleDiff < -PI) angleDiff += 2*PI;
while (angleDiff >= PI) angleDiff -= 2*PI;
이 수량을 확보하면 터릿 각도에 대한 2 차 표현을 설정할 수 있습니다. 항상 최신 위치 및 속도 데이터를 사용하려면 각 업데이트에서이를 계산해야합니다.
// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;
여기서 가속도 표현의 첫 번째 항 (0도)은 터릿이 목표를 향해 회전하기 시작합니다. 그러나 정시에 멈추지 않고 오히려 앞뒤로 진동합니다. 정지시키기 위해서는 높은 가속도에 의해 높은 회전 속도가 반대되는 감쇠 제 2 항 (1도)이 필요합니다.
이제 양의 상수 (필수적으로 프로그램 상수는 아님)를 결정하고 시스템이 제대로 작동하도록 균형을 조정해야합니다. C0
시스템 속도의 주요 제어입니다. 값이 높으면 C0
선회 속도가 빠르고 값이 낮 으면 선회 속도가 느려집니다. 실제 값은 많은 요소에 따라 다르므로 여기에서 시행 착오를 사용해야합니다. C1
댐핑 크기를 제어합니다. 이차 방정식 의 판별 은 C1*C1 - 4*C0 >= 0
비 진동 시스템을 가졌다 고 알려줍니다 .
// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.
C1
숫자로 인해이 값보다 조금 더 큰 값을 선택해야 하지만 너무 크게 댐핑되지 않고 응답 속도가 느려질 수 있으므로 너무 크지 않아야합니다. 다시, 당신은 조정해야합니다.
또한이 코드는 각도 가속 만 계산한다는 점에 유의해야합니다. 각도와 각속도는 어떤 종류의 통합기를 사용하여 다른 곳에서 업데이트해야합니다. 질문에서 나는 이것이 커버되었다고 가정합니다.
마지막으로 빠른 목표물을 추적 할 때 포탑이 항상 뒤에 있기 때문에 지연에 대해 할 말이 있습니다. 이 문제를 해결하는 간단한 방법은 대상 위치에 선형 예측을 추가하는 것입니다. 즉, 항상 대상의 앞으로 방향을 약간 앞쪽으로 조준합니다.
// Improvement of the first lines above.
const float predictionTime = 1; // One second prediction, you need to experiment.
Vector2 turretToTarget = target.position + predictionTime * target.velocity - turret.position;
/// ...
포탑을 목표 반경 안에 일정 시간 유지하기 위해서는 이런 종류의 시스템에 직접 적용하기가 매우 어려울 수 있습니다. 이 컨트롤러는 항상 포탑이 목표물 (또는 예측 된 위치)을 목표로하도록 노력할 것입니다. 결과가 만족하지 밝혀 경우에 당신은 매개 변수를 수정해야 할 predictionTime
, C0
그리고 C1
(안정의 범위 내에서).