0
\$\begingroup\$

Currently in our game we use a 4 directional movement. Some abilities are triggered on mouse click and "fired" in the direction the player has clicked. For this, I have split the screen in 4 sectors (like 2 diagonal cuts) to determine in which general direction the player has clicked.

Back then, I found a short helper class for this:

public static class Triangle
{
    private static Vector2 topLeft = new Vector2(0, 0);
    private static Vector2 topRight = new Vector2(Orbs.graphics.PreferredBackBufferWidth, 0);
    private static Vector2 bottomRight = new Vector2(Orbs.graphics.PreferredBackBufferWidth, Orbs.graphics.PreferredBackBufferHeight);
    private static Vector2 bottomLeft = new Vector2(0, Orbs.graphics.PreferredBackBufferHeight);

    //Return true if p1 and p2 are on the same side of BA
    private static bool SameSide(Vector2 p1, Vector2 p2, Vector2 A, Vector2 B)
    {
        // Convert points to Vector3 for use the Cross product, which is Vector3-only
        Vector3 cp1 = Vector3.Cross(new Vector3(B - A, 0), new Vector3(p1 - A, 0));
        Vector3 cp2 = Vector3.Cross(new Vector3(B - A, 0), new Vector3(p2 - A, 0));
        return Vector3.Dot(cp1, cp2) >= 0;
    }

    //Return true if the point p is in the triangle ABC
    private static bool PointInTriangle(Vector2 p, Vector2 A, Vector2 B, Vector2 C)
    {
        return SameSide(p, A, B, C) && SameSide(p, B, A, C) && SameSide(p, C, A, B);
    }

    public static string GetAndSetPlayerOrientationByClickedSector()
    {
        Vector2 playerCenter = new Vector2(//getPlayerCenter);
        Vector2 mouseWindowPos = Microsoft.Xna.Framework.Input.Mouse.GetState().Position.ToVector2();

        if (PointInTriangle(mouseWindowPos, topLeft, playerCenter, topRight))
            return "North";

        if (PointInTriangle(mouseWindowPos, topRight, playerCenter, bottomRight))
            return "East";

        if (PointInTriangle(mouseWindowPos, bottomRight, playerCenter, bottomLeft))
            return "South";

        if (PointInTriangle(mouseWindowPos, topLeft, playerCenter, bottomLeft))
            return "West";

        return "";
    }
}

Now, we are extending our movement in eight directions and therefore I need to extend this helper class to return the diagonal directions (SouthEast and so on) as well.

I am not even sure if this is doable properly with this approach, but I guess I only need to define the points of the additional triangles. Any suggestions on how to solve this are welcome.

\$\endgroup\$
  • 1
    \$\begingroup\$ So you want to be able to have your cursor on the screen somewhere, and from that, get the closest general direction (ie North, North East, etc) from the center of the screen? \$\endgroup\$ – Ibrahim May 20 '19 at 10:13
  • \$\begingroup\$ @Ibrahim exactly \$\endgroup\$ – Pavel Slesinger May 20 '19 at 11:06
  • \$\begingroup\$ In case you haven't figured it out, get the angle from the center to the point using atan2(-dy,dx) where dy = mouse_y - center_y, and dx = mouse_x - center_x. Convert to degrees (from radians) then check for each octant (if angle between -22.5 and 22.5, then direction is east. If angle between 22.5 and 67.5, then direction is northeast. etc...) \$\endgroup\$ – Ibrahim May 20 '19 at 12:48
  • \$\begingroup\$ Yeah, got the solution from the linked question above. thanks for your answer anyways :) \$\endgroup\$ – Pavel Slesinger May 20 '19 at 13:59

Browse other questions tagged or ask your own question.