0

My game has a 2d tilemap that I want to be initially hidden to players, and then expose it as they move. Assuming I've already exposed a circle of tiles around the player, and I want to just expose the edge of the quadrant(s).

I'm assuming it's correct for example to expose Q1 and Q2 when the player moves up, Q2 only when player moves up left, etc.

I think I've got the exposing code worked out, what I'm having a problem with is coming up with an elegant solution in the initialisation.

I want to have already created an array of the quadrants I need to expose when the player moves and passes in a direction xy vector.

I can create individual calls to manually do this for each of the possible 8 directions, something like this:

    private void CreateUpDirection()
    {
        directionDetails[Vector2Int.up.x + 1, Vector2Int.up.y + 1] = new DirectionDetail(quadrantDetails[Constants.QUADRANT_ONE],
            quadrantDetails[Constants.QUADRANT_TWO]);
    }

but is there a way I can determine the correct quadrant(s) by the xy vector values themselves, so I can do something like this?

        CreateDirectionDetail(Vector2Int.up);
        CreateDirectionDetail(Vector2Int.up + Vector2Int.left);
        CreateDirectionDetail(Vector2Int.up + Vector2Int.right);
        CreateDirectionDetail(Vector2Int.left);
        CreateDirectionDetail(Vector2Int.right);
        CreateDirectionDetail(Vector2Int.down);
        CreateDirectionDetail(Vector2Int.down + Vector2Int.left);
        CreateDirectionDetail(Vector2Int.down + Vector2Int.right);   

I hope I've made that clear enough. Thanks.

cerestorm
  • 43
  • 7
  • Would this eventual help you? [How to get an actual direction like east - west in unity?](https://stackoverflow.com/a/59624190/7111561). A part of my answer there covers the angle delta and how to convert this into a direction ... you would just have 8 instead of 4 cases – derHugo Aug 23 '21 at 11:28
  • I don' think so in this case? I say tilemap but the actual code is run on a server, where the map is a 1d array of locations. The client is then informed of the newly exposed tiles. – cerestorm Aug 23 '21 at 11:33
  • Ok .. and why not simply have a `Dictionary` that already contains the resulting `DirectionDetail` for each of your directions or at least a method that returns the according next details in that direction ? This one you only have to setup once – derHugo Aug 23 '21 at 11:49
  • The question really is how to create those DirectionDetails with the correct quadrants, based only on the direction vector. Is there a correlation between the vector value and the quadrants required? – cerestorm Aug 23 '21 at 11:57
  • Well you say yes ... if vector is up => Q1+Q2, if vector is up-right => Q1 .... what I mean is you can write these once but then store in a `Dictionary` which ones you get for each direction ... then later indded you will just use `yourDictionary[Vector2Int.up]` or `yourDictionary[Vector2Int.up + Vector2Int.left]` etc – derHugo Aug 23 '21 at 12:01
  • I am doing that already, just accessing by x,y coords rather then a key. I wanted to see if there's a clever bit of math that I can learn of a relationship between a direction vector and quadrants. If so great, if not and it's awkward to work out I'll stick with the manual initialisation calls. – cerestorm Aug 23 '21 at 12:11
  • I don't know tbh .. but I don't think there is something special ... you could use simplifications however like e.g. [these](https://answers.unity.com/questions/617076/calculate-the-general-direction-of-a-vector.html) or as said some `if - else if` checks ... **BUT** as a complete alternatvie I could think about you could / should rather use an `enum` like `public enum Direction { Up, UpLeft, UpRight, .... }` and then you could simply build one `switch - case` block to return the according items for given enum value ... either way you will have to initialize it / write it manually – derHugo Aug 23 '21 at 12:14
  • Thanks derHugo, I'll go with whatever's faster. At the moment the enum is an extra step that would have to pay off on the lookup. I'll go with what I have for now but may change later, depending on if the code works as well as it does inside my head. :) – cerestorm Aug 23 '21 at 12:48
  • the `enum` is basically just a "named" `int` and pretty fast ;) probably faster to let the `switch` check one `int`/`enum` than to compare 2 int components within a Vector2Int ;) The enum additionally allows you as a developer to just write `Direction.Up` or `Direction.UpLeft` instead of everytime have an additional opertaion of `Vector2Int.up + Vector2Int.left` before you can use and compare that resulting vector ;) And you could also have additional two `Dictionary` and `Dictionary` for easy forth and back conversion between the enum and vectors – derHugo Aug 23 '21 at 12:52
  • I'm not new to programming but I appreciate the explanation. I'm using a lot of enums, and [Flags], that was a new concept to me coming from Java. Dictionaries I don't use so much, my head is stuck in the past and slow cpu's, always thinking about overhead. – cerestorm Aug 23 '21 at 13:12
  • hehe in contrary .. Dictionary access and `switch` are both pretty fast if you use fast keys .. and `enum`/`int` is basically the fastest you can get I would claim ;) But I would also claim this is a micro-improvement which you shouldn't be caring about too much ;) – derHugo Aug 23 '21 at 13:14

1 Answers1

0

This was bugging me so I tried a different approach, I stopped thinking about quadrants and just focused on angles. I found that atan2 can give me the angle I need from the direction vector so I don't need to worry about look ups.

Here's an example:

        float radians = Mathf.Atan2(vector.x, vector.y);

        int angle = (int)(Mathf.Rad2Deg * radians);

        int fov = 180;

        int centreAngle = ((360 + angle) % 360);
        int startAngle = ((360 + centreAngle) - fov / 2) % 360;
        int endAngle = ((360 + centreAngle) + fov / 2) % 360;

I call atan2(x,y) instead of atan2(y,x) so zero degrees start at the +y instead of +x. The field of view is an arbitrary value for how big an arc I want to check.

Here's the results for each of the 8 directions:

X: 0     Y: 1    angle: 0    centreAngle: 0     startAngle: 270  endAngle: 90
X: -1    Y: 1    angle: -45  centreAngle: 315   startAngle: 225  endAngle: 45
X: 1     Y: 1    angle: 45   centreAngle: 45    startAngle: 315  endAngle: 135
X: -1    Y: 0    angle: -90  centreAngle: 270   startAngle: 180  endAngle: 0
X: 1     Y: 0    angle: 90   centreAngle: 90    startAngle: 0    endAngle: 180
X: 0     Y: -1   angle: 180  centreAngle: 180   startAngle: 90   endAngle: 270
X: -1    Y: -1   angle: -135 centreAngle: 225   startAngle: 135  endAngle: 315
X: 1     Y: -1   angle: 135  centreAngle: 135   startAngle: 45   endAngle: 225
cerestorm
  • 43
  • 7