프로그래밍
Hexagon
violetoz
2013. 5. 14. 08:46
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; namespace HexDemo { class Hex { private float radius; private float width; private float halfWidth; private float height; private float rowHeight; public Hex(float radius) { this.radius = radius; this.height = 2 * radius; this.rowHeight = 1.5f * radius; this.halfWidth = (float)Math.Sqrt((radius * radius) - ((radius / 2) * (radius / 2))); this.width = 2 * this.halfWidth; } public Vector2 TileOrigin(Vector2 tileCoordinate) { return new Vector2( (tileCoordinate.X * width) + ((tileCoordinate.Y % 2 == 1) ? halfWidth : 0), //Y % 2 == 1 is asking 'Is Y odd?' tileCoordinate.Y * rowHeight); } public Vector2 TileCenter(Vector2 tileCoordinate) { return TileOrigin(tileCoordinate) + new Vector2(halfWidth, halfWidth); } public enum Direction { NorthEast, East, SouthEast, SouthWest, West, NorthWest, NumberOfDirections, } public static Direction RotateDirection(Direction direction, int amount) { //Let's make sure our directions stay within the enumerated values. if (direction < Direction.NorthEast || direction > Direction.NorthWest || Math.Abs(amount) > (int)Direction.NorthWest) throw new InvalidOperationException("Directions out of range."); direction += amount; //Now we need to make sure direction stays within the proper range. //C# does not allow modulus operations on enums, so we have to convert to and from int. int n_dir = (int)direction % (int)Direction.NumberOfDirections; if (n_dir < 0) n_dir = (int)Direction.NumberOfDirections + n_dir; direction = (Direction)n_dir; return direction; } public static Direction Opposite(Direction direction) { return RotateDirection(direction, 3); } public static Vector2 Neighbor(Vector2 tile, Direction direction) { if (tile.Y % 2 == 0) //Is this row even? { switch (direction) { case Direction.NorthEast: tile.Y += 1; break; case Direction.East: tile.X += 1; break; case Direction.SouthEast: tile.Y -= 1; break; case Direction.SouthWest: tile.Y -= 1; tile.X -= 1; break; case Direction.West: tile.X -= 1; break; case Direction.NorthWest: tile.X -= 1; tile.Y += 1; break; default: throw new InvalidOperationException("Invalid direction"); } } else //This is an odd row. { switch (direction) { case Direction.NorthEast: tile.X += 1; tile.Y += 1; break; case Direction.East: tile.X += 1; break; case Direction.SouthEast: tile.X += 1; tile.Y -= 1; break; case Direction.SouthWest: tile.Y -= 1; ; break; case Direction.West: tile.X -= 1; break; case Direction.NorthWest: tile.Y += 1; break; default: throw new InvalidOperationException("Invalid direction"); } } return tile; } public Vector2 TileAt(Vector2 worldCoordinate) { float rise = height - rowHeight; float slope = rise / halfWidth; int X = (int)Math.Floor(worldCoordinate.X / width); int Y = (int)Math.Floor(worldCoordinate.Y / rowHeight); Vector2 offset = new Vector2(worldCoordinate.X - X * width, worldCoordinate.Y - Y * rowHeight); if (Y % 2 == 0) //Is this an even row? { //Section type A if (offset.Y < (-slope * offset.X + rise)) //Point is below left line; inside SouthWest neighbor. { X -= 1; Y -= 1; } else if (offset.Y < (slope * offset.X - rise)) //Point is below right line; inside SouthEast neighbor. Y -= 1; } else { //Section type B if (offset.X >= halfWidth) //Is the point on the right side? { if (offset.Y < (-slope * offset.X + rise * 2.0f)) //Point is below bottom line; inside SouthWest neighbor. Y -= 1; } else //Point is on the left side { if (offset.Y < (slope * offset.X)) //Point is below the bottom line; inside SouthWest neighbor. Y -= 1; else //Point is above the bottom line; inside West neighbor. X -= 1; } } return new Vector2(X, Y); } } }