views:

56

answers:

5

For my tile-based game, I need to calculate direction based on a given point offset (difference between two points). For example, let's say I'm standing at point (10, 4) and I want to move to point (8, 6). The direction I move at is north-west. What would be the best way to calculate this?

Here's me basic implementation in Java.

public int direction(int x, int y) {
    if (x > 0) {
        if (y > 0) {
            return 0; // NE
        } else if (y < 0) {
            return 1; // SE
        } else {
            return 2; // E
        }
    } else if (x < 0) {
        if (y > 0) {
            return 3; // NW
        } else if (y < 0) {
            return 4; // SW
        } else {
            return 5; // W
        }
    } else {
        if (y > 0) {
            return 6; // N
        } else if (y < 0) {
            return 7; // S
        } else {
            return -1;
        }
    }
}

Surely it can be optimised or shortened. Any help? Thanks.

+3  A: 

I think the easiest to understand way would be making a static array that contains the values for all cases.

// Won't say anything about how much these values make sense
static final int[][] directions = {
    {3,  6, 0},
    {5, -1, 2}, // -1 for "no direction", feel free to replace
    {4,  7, 1}
};

public int direction(int x, int y) {
    x = (x < 0) ? 0 : ((x > 0) ? 2 : 1);
    y = (y < 0) ? 0 : ((y > 0) ? 2 : 1);

    return directions[y][x];
}

Edit: Now it's correct (why are so many languages missing a proper sgn function?)

Matti Virkkunen
almost correct. but x or y can be > 1 or < -1
mohammad shamsi
@mohammad shamsi For what input does `Math.sgn` return a value other than -1, 0 or 1?
Pascal Cuoq
@Pascal: I forgot to use `sgn` at first which is probably what prompted his comment. And then I found out that Java doesn't even seem to have `sgn` for integers. Meh.
Matti Virkkunen
@Matti Indeed: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4780454 . I hate SO's "feature" of not showing quick edits after posting as edits.
Pascal Cuoq
A: 
  • define a 2D array to hold all states.

  • convert x and y to 0, 1 or 2 based on their value (x>0 or x<0 or x ==0)

  • return the specific index of array.

mohammad shamsi
A: 

This is about as short and clean as you can get, if you represent the eight cardinal directions this way, as separate enumerated values. You're choosing between eight distinct return values, so a decision tree with eight leaves is the best you can do.

You might get something a little tidier if you split direction into two components (N-S and E-W), but without knowing more about what you do with direction, we can't know whether that's worth the trouble.

Beta
A: 

You can receive and return your direction as a Point or something similar (anyway, an (x,y) tuple). So if you're standing in p0 = (10, 4) and want to move to p1 = (8, 6), the result would be (in pseudocode):

norm(p1 - p0) = norm((-2,2)) = (-1,1)

You can calculate the norm of an integer if you divide it by its absolute value. So for a point you calculate the norm of both members. Just bear in mind that (-1,1) is more expressive than 3 and you can operate in an easier fashion with it.

If you need specific operations, you can create your own Java Point class or extend the existing ones in the library.

spyked
+1  A: 

My answers with if conditions :).

   public int direction(int x, int y) {
        //0 NE, 1 SE, 2 E, 3 NW, 4 SW, 5 W, 6 N, 7 S, 8 (Same place / Not a direction)  
        int direction = 0;

        if(x < 0){
            direction = 3;
        }else if(x == 0){
            direction = 6;
        }

        if(y < 0){
            direction = direction + 1;
        }else if(y == 0){
            direction = direction + 2;
        }
            return direction;
    }
YoK