발사체 모션-화살표


13

2D 게임에서는 비행 중에 화살표의 궤도를 그리려고합니다. 아래 코드를 사용하면 궤적 (포물선)이 올바르게 보이지만 각도 (또는 회전) 또는 화살표는 그렇지 않습니다.

float g = -9.8f;
float x = (launchVelocity * time);
float y = (launchVelocity * time) + (0.5f * g * (float)Math.Pow(time, 2));
float angle = (float)Math.Tanh(y / x);

내가 무엇을 놓치고 있습니까? 감사.


3
스크린 샷 도움이 될 수 있습니다
doppelgreener

답변:


10

Arctanh쌍곡선 곡선에 대한 접선을 제공합니다! 내가 아는 한 당신의 포물선은 쌍곡선이 아닙니다.

그러나 우리는 좋은 소식이 있습니다. 포물선의 탄젠트를 찾는 것이 더 쉽습니다. 방정식은

x = s · t => t = x / s; y = s · t + g / 2 · t² => y = x + g / 2 · x² / s²

s는 어디에 있습니까 launchVelocity? 이제 화살표의 기울기는 다음과 같습니다.

∂y / ∂y = g / (2s²) · x + 1

원한다면 Arctan지금 안전하게 사용할 수 있습니다 .

물리학에 대한 추가 정보 :

시뮬레이션하는 대략적인 궤적은 화살표의 질량 중심에 적용됩니다. "위치"(x, y)라고 말하면 질량 중심 위치에 대해 이야기하는 것입니다. 화살표의 질량 중심은 중간 점에서 약간 앞쪽에 있으며 화살표를 그리려면이를 고려해야합니다.

화살의 관성 운동량을 고려하지 않고 (거대한 발리스타를 발사 할 때 크게 다를 수 있음) 화살의 유체 역학을 고려하지 않습니다. 활 화살 비행은 포물선 경로를 따르지 않습니다!


Fxlll 감사합니다. 화살표의 물리학에 적용되는 수식을 어디에서 얻을 수 있습니까?
Martin

나는 당신이 의미한다고 생각합니다 :! [& part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2] 그러나 어쨌든 아래의 더 나은 접근법을 추천했다고 생각합니다. 우선 x와 y 컴포넌트를 분리하는 것에 대해 설명하지 않았으므로 launchVelocity가 실제로 launchVelocity가 아니라 x와 y의 컴포넌트로 임의의 45도 각도로 하드 코딩됩니다.
Dov

관성 모멘트를 쉽게 계산할 수 있습니다. 이것들은 막대의 두 가지입니다. 하나는 질량 중심을 중심으로 회전하고 다른 하나는 막대 축을 중심으로 한 회전입니다. 중첩 원리는 관성 모멘트에 적용되므로 화살표를 깃털, 몸체 및 팁의 세 부분으로 나눌 수 있습니다.
FxIII

1
문제는 계산하기 쉬운 유일한 운동량은 각도 변화 때문입니다 (포물선의 두 배를 유도하는 것은 일정한 항이 남아 있음을 알 수 있습니다). 다른 하나는 등 깃털로 인한 회전으로 인해 발생합니다. 여기서 깃털 끌기와 마찰은 운동 에너지를 회전으로 변환하고, 화살표를 늦추지 만 자이로 스코프 효과를 추가하는 것과 관련됩니다. 이것은 궤도에 영향을 미치며 모델링하기가 매우 어렵습니다.
FxIII

어쨌든 깃털 설정이 주어진 속도로 운동량을 속도와 관련시킬 수 있다면 모든 통합을 철저히 계산할 수 있지만 모션 방정식에 대해 닫힌 형태를 가질 수 있는지 확실하지 않습니다 (즉, 통합 알고리즘을 얻을 수 있지만 매개 변수는 얻을 수 없음) 방정식).
FxIII

4

어느 시점에서든 화살표 각도를 원합니다. 각도를 계산하기 위해 접선이 있다는 것을 기억했습니다. 그러나 당신의 생각이 잘못되기 시작한 곳은 다음과 같습니다.

  1. 기울기가 변화율이기 때문에 원하는 것은 델타 y / 델타 x입니다 (다른 답변 중 하나에서 언급). x는 dx가 아닌 특정 시점의 위치입니다.

공기 마찰을 무시하면 화살표의 x- 속도는 일정합니다.

먼저, 속도를 x와 y 성분으로 분해하십시오. 45도 또는 60도 각도로 촬영할 수 있습니다. 따라서 launchVelocity와 각도가 필요합니다. 스칼라가 아닙니다.

둘째, 모든 것을 float가 아닌 double로 계산하십시오. 반올림 오류가 당신을 죽이지 않을 때를 알기에 충분히 정교하지는 않으므로 시도하지 마십시오. 어쨌든 시간을 절약하는 것은 아닙니다.

셋째, Math.pow를 사용하지 마십시오. 정수를 곱하는 것만 큼 느리고 정확하지 않습니다. 또한 Horner의 양식을 사용하여 많은 시간을 절약 할 수 있습니다 (아래 참조).

final double DEG2RAD = Math.PI/180;
double ang = launchAngle * DEG2RAD;
double v0x = launchVelocity * cos(ang); // initial velocity in x
double v0y = launchVelocity * sin(ang); // initial velocity in y

double x = (v0x * time);
// double y = (v0y * time) + (0.5 * g * (float)Math.Pow(time, 2));
double y = (0.5 * g * time + v0y) * time

성능에 필사적 인 경우 0.5 * g를 사전 계산할 수도 있지만 위의 코드는 너무 미친 짓을하지 않고도 90 %의 방법을 사용합니다. 원하는 경우이 천만 번을 수행하는 벤치 마크는 시간이 많지 않지만 백분율로 보면 상당히 큽니다 .Java에서 라이브러리가 매우 느립니다.

따라서 화살표의 각도를 원한다면 원하는 것은

atan(dy/dx)

그리고이 경우에는 dx가 상수이기 때문에 작동합니다. 그러나 일반적으로 dx는 0이 될 수 있으므로 일반적으로 다음을 사용하려고합니다.

atan2(dy, dx)

이 작업을 위해 특별히 설계된 기능입니다.

그러나 내가 말했듯이 Java의 라이브러리 함수는 엄청나게 느리며,이 경우 위의 @FxIII에서 언급하지 않고 더 좋은 방법이 있습니다.

수평 속도가 항상 v0x이고 수직 속도가 다음과 같은 경우

double vy = v0y - 0.5 * g * time;

다음 델타는 : vx, vy

각도가 필요하지 않습니다. 화살표를 그리려면 명목상 다음과 같은 것을 사용하십시오.

음모 (x, y, x + vx, y + vy);

나는 당신이 무엇을 그리는지 모른다. 따라서 JOGL을 사용하는 것처럼 회전하기 위해 각도가 필요하다면 각도를 사용하십시오.

ATAN2는 라디안을 반환하므로 opengl을 사용하여 각도를 다시 각도로 돌리는 것을 잊지 마십시오.

final double RAD2DEG = 180 / Math.PI;
double ang = Math.atan2(vy,vx); // don't forget, vy first!!!
double deg = ang * RAD2DEG;

2

Tanh () (hyperbolic tangent )는 매개 변수로 각도를 취하지 만 측면의 비율을 입력했습니다.

실제로 원하는 것은 변의 비율을 매개 변수로 사용하고 각도를 반환하는 쌍곡선 아크 탄젠트 를 사용하는 것 입니다. (이에 대한 이름은 "atanh", "atanh2", "arctanh"또는 이와 유사한 것이 될 수 있습니다. 다른 수학 라이브러리마다 많은 것으로 보입니다.)


당신은 쌍곡선을 원하지 않습니다
Dov

가, 당신 말이 맞아요 나는 즉시 "기본 삼각법 사용"오류를 발견하고 그가 사용하던 기능이 나머지 접근 방식에 대해 완전히 부정확하다는 사실을 놓쳤다.
Trevor Powell

Tan ()은 각도를 취합니다. Atan은 삼각형 측면 비율 (sin / cos)을 사용합니다.
3Dave
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.