2015-02-04 14 views
1

1 년 전부터 자바를 배우기 시작 했으므로 저는 아직 상당히 새롭습니다.Java : 내 대상이 0도에서 45도 사이의 각도로 움직이지 않습니다.

두 번째 점이 프레임에 상관없이 일정한 순 속도로 한 지점에서 다른 지점으로 객체를 이동하려고합니다. 현재 몇 프레임마다이 메서드를 실행하는 한 상당히 잘 작동합니다.

유일한 문제는 두 번째 점이 대략 45도에서 135도 사이이거나 225와 315도 사이가 아니면 (1/2π과 3/2π 또는 5/2π과 7/2π) 수평으로 만 이동한다는 것입니다.

'if'문으로 인해 0으로 나누지 못하게 할 수 있지만 그럴 것 같지 않을 수 있습니다. 또한 이러한 방정식을 단순화하거나 'if'문을 제거 할 수있는 방법이 있으면 거기에 대한 조언도 신경 쓰지 않을 것입니다.

참고 : vel은 객체가 이동하는 순 속도이며 Prime.my 및 Prime.my는 대상 점의 위치입니다.

public void target() 
{ 
if (Prime.mx > x) 
{ 
    if (Math.abs(x-Prime.mx) != 0) 
    x = Math.round(Math.round((x + (vel*Math.cos(Math.atan(Math.abs(y-Prime.my)/Math.abs(x-Prime.mx))))))); 
} 
if (Prime.mx < x) 
{ 
    if (Math.abs(x-Prime.mx) != 0) 
    x = Math.round(Math.round((x - (vel*Math.cos(Math.atan(Math.abs(y-Prime.my)/Math.abs(x-Prime.mx))))))); 
} 
if (Prime.my > y) 
{ 
    if (Math.abs(x-Prime.mx) != 0) 
    y = Math.round(Math.round((y + (vel*Math.sin(Math.atan(Math.abs(y-Prime.my)/Math.abs(x-Prime.mx))))))); 
} 
if (Prime.my < y) 
{ 
    if (Math.abs(x-Prime.mx) != 0) 
    y = Math.round(Math.round((y - (vel*Math.sin(Math.atan(Math.abs(y-Prime.my)/Math.abs(x-Prime.mx))))))); 
} 
} 

Math.round를 두 번 사용합니다. 첫 번째는 double에서 float으로 가져오고 두 번째는 int로 만들기 때문입니다. 페인트 메소드가 객체를 그릴 수 있도록 int로 x와 y가 필요합니다.

사이트에서 몇 가지 비슷한 문제가 발견되었지만 the closest one은 파이썬에 있었고 anwer는 내 문제에 적용되지 않는 것 같습니다.

+4

'Math.atan()'대신 'Math.atan2 (delta_y, delta_x)'를 사용하여 대부분의 사분면 검사 논리 (if 문과 Math.abs() 호출)를 제거 할 수 있습니다. 또한 모든 중간 결과를 부동 소수점으로 계산하고 프로세스 끝 부분의 정수로 변환해야합니다. –

+0

두 점이 주어지면 [this] (http://stackoverflow.com/questions/22930952/java-graphics-draw-a-line-using-fillrect/22931106#22931106)와 같은 것을 사용하여 주어진 시간 (0에서 1)에 걸친 시간. 점, 천사 및 거리 (반지름)가있는 경우 [this] (http://stackoverflow.com/questions/25923480/simple-circle-rotation-simulate-motion/25923780#25923780)와 같은 것을 사용하여 두 번째 요점을 적용한 다음 첫 번째 예제를 적용합니다. – MadProgrammer

답변

1

저는 이것을 지나치게 복잡하게 만들고 있습니다. 출발점이 (sx, sy)이고 목적지가 (dx, dy) 인 경우 인 점을 p 거리 (0.0 < = p < = 1.0)로 쉽게 계산할 수 있습니다. 속도를 v으로 이동하는 데 사용할 수 있습니다. 따라서 종점을 찾고 x 및 y 축으로 이동하는 간단한 산술을 사용하는 것이 좋습니다.

float dx = dist * Math.cos(angle); 
float dy = dist * Math.sin(angle); 
for (float p = 0.0; p <= 1.0; p = Math.min(1.0, p + dist/v) { 
    x = sx + p * (dx - sx); 
    y = sy + p * (dy - sy); 
} 

for 루프의 Math.min 표현은 대상 지점에 정확히 끝날 것을 보장한다.

목적지가 이미 있다면 쉽게 알 수 있습니다. dxdydistangle에서 찾는 대신 dxdy에서 피타고라스를 사용하면 dist을 찾을 수 있습니다.

1

해결 방법 이상으로 몇 가지 조언이 있습니다.

먼저 모든 좌표 변수를 부동 소수점으로 구현하여 반올림 정밀 손실 오류를 방지하고 페인팅 직전에만 라운드하십시오.

두 번째로, 나중에 사용하기 위해 현재 점에서 float dx = Prime.mx - x; float dy = Prime.my - y;까지의 거리를 정의하십시오. 나는 Math.atan2 (dy, dx)을 사용하여 현재 포인트와 타겟 사이의 각도를 계산할 것입니다. 그러면 이런 좌표를 증가하는 각도를 사용하여 개체가 적절한 반경 (dx*dx + dy*dy <= radius*radius)를 사용 대상에 있으면

x += Math.cos(angle)*vel; 
y += Math.sin(angle)*vel; 

셋째는, (1 일 수있다)을 확인.

y 축이 작아지면 CCW (시계 반대 방향) 대신 각도가 CW (시계 방향)가됩니다.