Search code examples
javamathtrigonometrydegreesradians

Java: My object won't travel at an angle between 0 and 45 degrees


I started learning java just over a year ago so i'm still fairly new.

I'm trying to make an object travel from one point to another at a constant net velocity no matter where the second point is in the frame. Currently it's working fairly well as long as I run the method every few frames.

The only problem is that it it will only move horizontally unless the second point is approximately between 45 and 135 degrees or between 225 and 315 degrees (1/2π and 3/2π or 5/2π and 7/2π).

It may be because of the 'if' statements meant to stop it from dividing by 0 but it doesn't seem like it. Also if there is any way to simplify those equations or remove 'if' statements I wouldn't mind some advice there too.

Note: vel is the net velocity the objects travel at and Prime.mx and Prime.my is the location of the target point.

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)))))));
 }
}

I use Math.round twice because the first brings it to a float from a double and the second makes it an int. I need the x and y as ints so the paint method can draw the objects.

I found a few simillar problems on the site but the closest one was in python and and the anwer didn't seem applicable to my problem.


Solution

  • I believe you are overcomplicating this. If your starting point is (sx, sy) and your destination is (dx, dy) then you can easily calculate any point (x, y) that is p distance along the line (0.0 <= p <= 1.0). You can use this to move at velocity v. So I suggest finding your end point and then using simple arithmetic to move on the x and y axis.

    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);
    }
    

    The Math.min expression in the for loop ensures that you end up exactly at the destination point.

    If you already have the destination point then it's just as easy. Instead of finding dx and dy from dist and angle you find dist from dx and dy using pythagoras.