3
\$\begingroup\$

I'm working on a top-down 2D strategy game in XNA, and the tiles are hexagons. I can't have a grid because of the game mechanics, so everything has its own location, and every tile object is stored in a list. What I'm trying to do is have it so that if you place a tile close to the side of another tile, they will snap together and become one object. I can't seem to figure out how to get what side it should snap to.

The red represents the different sections I want to check for mouse clicks in (these would of course not be an actual texture in the game). The white represents the area where if you clicked, it wouldn't allow you to place a tile because it would be on top of another. The closest thing I can think of is to have a larger hexagon around the actual tile that's divided into triangles from the center to the edges, but I'm not sure how to do this.

And I'm gonna move it to Windows Phone with Monogame and I don't think the phone is fast enough to make some sort of thing that checks colors for each sector, so I don't think it can be texture based. I feel like there's some kind of relatively simple math to do this but I can't seem to figure it out.

\$\endgroup\$
1
\$\begingroup\$

Compare a line between the center of the nearest hex shape within a close radius of the mouse and the mouse itself and get the angle of the line between them relative to the horizontal axis of the grid. Then you could use a function like.

public Vector2 CalcHexPositionFromAngle(double angle, Vector2 point, double radius)
        {
            //assume the angle is in degrees and shed any numbers over 360 eg: 427 becomes 67
            while(angle >= 360)
            {
                angle -= 360;
            }

            //This is a trick using the nature of truncation in most programming laguages
            int tempAngle = angle/60;

            //now we just multiply the number by 60 to bring it back up 
            //to an increment of 60 degrees and add half that again to find an angle between
            //corners in the hex shape
            int angleOfPlacement = (tempAngle*60) +30;

            //assume the angle is in degrees (If angle is in radians forget this step)
            //sin uses radians not degrees.
            double newRadianAngle = angleOfPlacement*Math.PI();

            //calculate the new position.
            double P_X = point.X + radius * Mathf.Cos(newRadianAngle);
            double p_Y = point.Y + radius * Mathf.Sin(newRadianAngle);

            return new Vector2(p_X,P_Y);


        }

This should give you the new position for your hex given that it is handed the the

angle in degrees between the originating hex you are snapping to and the mouse

the vector2 that is the center position of the originating hex you are snapping to

and radius or (half the distance between opposing faces of your hex shapes)

Note: this function takes degrees but can easily be adapted for radians.

\$\endgroup\$
1
\$\begingroup\$

The way I might approach it is to create a list of all possible hex center locations during the initialization stage before the game loop starts. Then during the game loop, if there is a mouse click within 1.5 tile radius (or whatever dist you think is approp) of a white tile, simply iterate the list and find the closest list Point to the click point. If the mouse click is closer to the result than it is to the white tile center, use that result as the center of the new tile you want to place. It can all be done using distaceSquared to avoid a bunch of square rooting too.

Better yet, simply store 6 relative offset vectors for each possible neighbor's center location. Then when a mouse click occurs near a white placed hex, iterate through the 6 offests and find the one closest to (mouseClick - whiteHexCenter). The new Hex should be placed such that its center is at (offsetResult + whiteHexCenter).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.