hexg

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 22, 2025 License: MIT Imports: 6 Imported by: 4

README

hexg

A Go package for hexagonal grids using cube coordinates.

This package implements the hexagonal grid system described in the excellent Red Blob Games Hexagonal Grids Guide.

Installation

go get github.com/maloquacious/hexg

Usage

Creating Hexes
import "github.com/maloquacious/hexg"

// Create a hex using axial coordinates (q, r)
// The s coordinate is derived from the constraint q + r + s = 0
hex := hexg.NewHex(2, -1)

// Access coordinates
q, r, s := hex.QRS()
Hex Operations
a := hexg.NewHex(1, 0)
b := hexg.NewHex(2, -1)

// Arithmetic
sum := a.Add(b)
diff := a.Subtract(b)
scaled := a.Multiply(3)

// Distance
dist := a.Distance(b)

// Neighbors (direction 0-5)
neighbor := a.Neighbor(0)

// Diagonal neighbors (direction 0-5)
diagonal := a.DiagonalNeighbor(0)

// Reflections across axes
reflected := a.ReflectQ() // also ReflectR(), ReflectS()

// Rotations (60° increments)
left := a.RotateLeft()
right := a.RotateRight()
Drawing Lines
start := hexg.NewHex(0, 0)
end := hexg.NewHex(5, -3)

// Get all hexes along the line
line := start.LineDraw(end)
Layouts and Screen Coordinates
// Create a layout for pointy-top hexes
// size is the hex size, origin is the screen origin
layout := hexg.NewLayout(hexg.OddR, hexg.Point{X: 32, Y: 32}, hexg.Point{X: 0, Y: 0})

// Convert hex to screen pixel
hex := hexg.NewHex(2, 1)
pixel := layout.HexToPixel(hex)

// Convert screen pixel to hex
clickedHex := layout.PixelToHexRounded(hexg.Point{X: 100, Y: 75})

// Get polygon corners for rendering
corners := layout.PolygonCorners(hex)
Layout Types
  • OddR - Pointy-top, horizontal rows, odd rows shoved right
  • EvenR - Pointy-top, horizontal rows, even rows shoved right
  • OddQ - Flat-top, vertical columns, odd columns shoved down
  • EvenQ - Flat-top, vertical columns, even columns shoved down
Generating Hex Grids
layout := hexg.NewLayout(hexg.OddR, hexg.Point{X: 32, Y: 32}, hexg.Point{X: 0, Y: 0})

// Hexagonal grid with radius 3
hexGrid := layout.Hexagon(3)

// Rectangular grid
rectGrid := layout.Rectangle(0, 10, 0, 8)

// Triangle grids
triUp := layout.TriangleUpDown(5)
triLR := layout.TriangleLeftRight(5)

// Ring of hexes at radius 3 from center
center := hexg.NewHex(0, 0)
ring := center.Ring(3)

// Spiral outward from center (all hexes within radius)
spiral := center.Spiral(3)
Offset Coordinates
hex := hexg.NewHex(2, -1)

// Convert to offset coordinates
offset := hex.CubeToROffset(false) // odd-r
col, row := offset.Col, offset.Row

// Convert back to cube coordinates
hexBack := offset.ROffsetToCube(false)
JSON Serialization

Hex coordinates serialize to a compact format:

hex := hexg.NewHex(2, -1)
data, _ := json.Marshal(hex) // "+2-1-1"

Acknowledgements

This package is a Go implementation based on the comprehensive hexagonal grid guide by Red Blob Games. Amit Patel's detailed explanations and interactive examples made this implementation possible.

Development assisted by Amp, an AI coding agent.

License

MIT License - see LICENSE for details.

Documentation

Overview

Package hexg implements hex grids in the style of the Red Blob Games blog https://www.redblobgames.com/grids/hexagons/ and https://www.redblobgames.com/grids/hexagons/implementation.html.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Version

func Version() semver.Version

Version returns the current version of the hexg package.

Types

type FractionalHex

type FractionalHex struct {
	// contains filtered or unexported fields
}

FractionalHex implements a hex with floating point coordinates. Used for linear interpolation and rounding.

func NewFractionalHex

func NewFractionalHex(q, r, s float64) FractionalHex

NewFractionalHex returns a FractionalHex initialized from cube coordinates.

func (FractionalHex) Lerp

Lerp returns the linear interpolation of points on the line between two hexes

func (FractionalHex) ReflectQ

func (h FractionalHex) ReflectQ() FractionalHex

ReflectQ reflects the fractional hex across the Q axis.

func (FractionalHex) ReflectR

func (h FractionalHex) ReflectR() FractionalHex

ReflectR reflects the fractional hex across the R axis.

func (FractionalHex) ReflectS

func (h FractionalHex) ReflectS() FractionalHex

ReflectS reflects the fractional hex across the S axis.

func (FractionalHex) Round

func (h FractionalHex) Round() Hex

Round turns a fractional hex coordinate into the nearest integer hex coordinate.

func (FractionalHex) Scale

func (h FractionalHex) Scale(factor float64) FractionalHex

Scale returns a FractionalHex scaled by a float64 factor.

type Hex

type Hex struct {
	// contains filtered or unexported fields
}

Hex stores the `q`, `r`, and `s` coordinates.

func DiagonalDirectionVector

func DiagonalDirectionVector(direction int) Hex

DiagonalDirectionVector returns the unit vector for a diagonal hex direction. Direction is coerced to the range 0..5.

func DirectionVector

func DirectionVector(direction int) Hex

DirectionVector returns the unit vector for a hex direction. Direction must be in the range 0..5. Panics on invalid input.

func NewHex

func NewHex(q, r int) Hex

NewHex returns a Hex initialized from axial coordinates.

func (Hex) Add

func (h Hex) Add(b Hex) Hex

Add returns the sum of two hexes.

func (Hex) ConciseString

func (h Hex) ConciseString() string

ConciseString returns the coordinates with signs. It returns the coordinates formatted as "+q+r+s".

func (Hex) CubeToQOffset

func (h Hex) CubeToQOffset(even bool) OffsetCoord

CubeToQOffset converts cube coordinates to q-offset coordinates. If even is true, uses even-q offset; otherwise uses odd-q offset.

func (Hex) CubeToROffset

func (h Hex) CubeToROffset(even bool) OffsetCoord

CubeToROffset converts cube coordinates to r-offset coordinates. If even is true, uses even-r offset; otherwise uses odd-r offset.

func (Hex) DiagonalNeighbor

func (h Hex) DiagonalNeighbor(direction int) Hex

DiagonalNeighbor returns the hex that is one diagonal step away in the given direction. Direction is coerced to the range 0..5.

func (Hex) Distance

func (h Hex) Distance(b Hex) int

Distance between two hexes is the length of the line between them.

func (Hex) Equals

func (h Hex) Equals(b Hex) bool

Equals returns true if the two hexes have the same coordinates.

func (Hex) Length

func (h Hex) Length() int

Length is the distance from the origin to the hex.

func (Hex) Lerp

func (h Hex) Lerp(b Hex, t float64) FractionalHex

Lerp returns the linear interpolation of points on the line between two hexes

func (Hex) LineDraw

func (h Hex) LineDraw(b Hex) []Hex

LineDraw returns the set of hexes on the line between two hexes.

func (Hex) LineDrawNudged

func (h Hex) LineDrawNudged(b Hex) []Hex

LineDrawNudged returns the set of hexes on the line between two hexes, with nudging to push points on an edge in a consistent direction.

func (Hex) MarshalJSON

func (h Hex) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for Hex.

func (Hex) Multiply

func (h Hex) Multiply(k int) Hex

Multiply returns a Hex scaled by an integer.

func (Hex) Neighbor

func (h Hex) Neighbor(direction int) Hex

Neighbor returns the hex that is one step away in the given direction. Direction is coerced to the range 0..5.

func (Hex) NotEquals

func (h Hex) NotEquals(b Hex) bool

NotEquals returns true if the two hexes have different coordinates.

func (Hex) Q

func (h Hex) Q() int

Q returns the q coordinate.

func (Hex) QRS

func (h Hex) QRS() (int, int, int)

QRS returns all three coordinates.

func (Hex) R

func (h Hex) R() int

R returns the r coordinate.

func (Hex) ReflectQ

func (h Hex) ReflectQ() Hex

ReflectQ reflects the hex across the Q axis.

func (Hex) ReflectR

func (h Hex) ReflectR() Hex

ReflectR reflects the hex across the R axis.

func (Hex) ReflectS

func (h Hex) ReflectS() Hex

ReflectS reflects the hex across the S axis.

func (Hex) Ring

func (h Hex) Ring(radius int) []Hex

Ring returns all hexes at exactly the given radius from the center hex. Returns a single-element slice containing the center if radius is 0. Panics if radius is negative.

func (Hex) RotateLeft

func (h Hex) RotateLeft() Hex

RotateLeft shifts the q, r, and s coordinates. The effect depends on the layout.

func (Hex) RotateRight

func (h Hex) RotateRight() Hex

RotateRight shifts the q, r, and s coordinates. The effect depends on the layout.

func (Hex) S

func (h Hex) S() int

S returns the s coordinate.

func (Hex) Scale

func (h Hex) Scale(factor int) Hex

Scale returns a Hex scaled by an integer factor. This is an alias for Multiply for API consistency.

func (*Hex) Scan

func (h *Hex) Scan(src any) (err error)

Scan implements sql.Scanner for database retrieval.

func (Hex) Spiral

func (h Hex) Spiral(radius int) []Hex

Spiral returns all hexes within the given radius from the center hex, starting from the center and spiraling outward. Panics if radius is negative.

func (Hex) String

func (h Hex) String() string

String returns the coordinates formatted as "(q, r, s)".

func (Hex) Subtract

func (h Hex) Subtract(b Hex) Hex

Subtract returns the difference of two hexes.

func (*Hex) UnmarshalJSON

func (h *Hex) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler for Hex.

func (Hex) Value

func (h Hex) Value() (driver.Value, error)

Value implements driver.Valuer for database storage.

type HexSet

type HexSet map[Hex]struct{}

HexSet is a set of hexes.

type Layout

type Layout struct {
	// contains filtered or unexported fields
}

Layout implements the conversion between hex (q,r,s) and screen (x,y) coordinates. The conversion uses a matrix as well as the inverse of the matrix for each orientation.

func NewLayout

func NewLayout(offset LayoutOffset, size, origin Point) Layout

NewLayout returns a layout with either flat-top or pointy-top hexes.

Flat-top layouts have vertical columns and staggered rows. Drawing corners start at 0°.

Pointy-top layouts have staggered columns and horizontal rows. Drawing corners start at 30°.

func (*Layout) BoundingBox

func (l *Layout) BoundingBox(hexes ...Hex) (upperLeft, lowerRight Hex)

BoundingBox returns the bounding box of a list of hexes. If the list is empty, returns (0,0,0), (0,0,0)

func (*Layout) CubeToOffset

func (l *Layout) CubeToOffset(h Hex) OffsetCoord

CubeToOffset converts cube coordinates to offset coordinates based on the layout.

func (*Layout) HexCornerOffset

func (l *Layout) HexCornerOffset(corner int) Point

HexCornerOffset returns the screen location (pixel) of a corner of a hex on the grid.

func (*Layout) HexToPixel

func (l *Layout) HexToPixel(h Hex) Point

HexToPixel returns the origin of the hex on the grid as a Point.

func (*Layout) Hexagon

func (l *Layout) Hexagon(radius int) HexSet

Hexagon returns a grid centered about (0,0,0). Does not depend on the orientation of the grid.

func (*Layout) IsEven

func (l *Layout) IsEven() bool

IsEven returns true if the layout uses even offset coordinates.

func (*Layout) IsEvenQ

func (l *Layout) IsEvenQ() bool

IsEvenQ returns true if the layout supports even-q offset coordinates (vertical layout, shoves even columns down).

func (*Layout) IsEvenR

func (l *Layout) IsEvenR() bool

IsEvenR returns true if the layout supports even-r offset coordinates (horizontal layout, shoves even rows right).

func (*Layout) IsFlat

func (l *Layout) IsFlat() bool

IsFlat returns true if the layout uses flat-top hexes.

func (*Layout) IsHorizontal

func (l *Layout) IsHorizontal() bool

IsHorizontal returns true if the layout has horizontal rows.

func (*Layout) IsOdd

func (l *Layout) IsOdd() bool

IsOdd returns true if the layout uses odd offset coordinates.

func (*Layout) IsOddQ

func (l *Layout) IsOddQ() bool

IsOddQ returns true if the layout supports odd-q offset coordinates (vertical layout, shoves odd columns down).

func (*Layout) IsOddR

func (l *Layout) IsOddR() bool

IsOddR returns true if the layout supports odd-r offset coordinates (horizontal layout, shoves odd rows right).

func (*Layout) IsPointy

func (l *Layout) IsPointy() bool

IsPointy returns true if the layout uses pointy-top hexes.

func (*Layout) IsVertical

func (l *Layout) IsVertical() bool

IsVertical returns true if the layout has vertical columns.

func (*Layout) OffsetToCube

func (l *Layout) OffsetToCube(oc OffsetCoord) Hex

OffsetToCube converts offset coordinates to cube coordinates based on the layout.

func (*Layout) ParallelogramQR

func (l *Layout) ParallelogramQR(q1, r1 int, q2, r2 int) HexSet

ParallelogramQR returns a parallelogram-shaped grid using q and r axes.

func (*Layout) ParallelogramQS

func (l *Layout) ParallelogramQS(q1, s1 int, q2, s2 int) HexSet

ParallelogramQS returns a parallelogram-shaped grid using q and s axes.

func (*Layout) ParallelogramRS

func (l *Layout) ParallelogramRS(r1, s1 int, r2, s2 int) HexSet

ParallelogramRS returns a parallelogram-shaped grid using r and s axes.

func (*Layout) PixelToFractionalHex

func (l *Layout) PixelToFractionalHex(p Point) FractionalHex

PixelToFractionalHex returns the fractional hex that encloses the pixel. In theory, the origin of that fractional hex will be the pixel.

func (*Layout) PixelToHexRounded

func (l *Layout) PixelToHexRounded(p Point) Hex

PixelToHexRounded converts a screen pixel to the nearest hex coordinate.

func (*Layout) PolygonCorners

func (l *Layout) PolygonCorners(h Hex) [6]Point

PolygonCorners returns the location of the six corners of the hex on the grid.

func (*Layout) Rectangle

func (l *Layout) Rectangle(left, right, top, bottom int) HexSet

Rectangle returns a grid centered about (0,0,0). The internal logic depends on the orientation of the grid.

func (*Layout) RotateLeft

func (l *Layout) RotateLeft(h Hex) Hex

RotateLeft rotates the hex 60° counter-clockwise around the origin. The underlying operation depends on the layout orientation.

func (*Layout) RotateRight

func (l *Layout) RotateRight(h Hex) Hex

RotateRight rotates the hex 60° clockwise around the origin. The underlying operation depends on the layout orientation.

func (*Layout) TriangleLeftRight

func (l *Layout) TriangleLeftRight(mapSize int) HexSet

TriangleLeftRight returns a grid originating at (0,0,0). mapSize is the length of a side.

func (*Layout) TriangleUpDown

func (l *Layout) TriangleUpDown(mapSize int) HexSet

TriangleUpDown returns a grid originating at (0,0,0). mapSize is the length of a side.

type LayoutOffset

type LayoutOffset int

LayoutOffset describes the layout (horizontal row or vertical columns) and which way odd rows and columns are pushed or pulled.

const (
	// OddR is a pointy-top layout with horizontal rows that shoves odd rows right
	OddR LayoutOffset = iota
	// EvenR is a pointy-top layout with horizontal rows that shoves even rows right
	EvenR
	// OddQ is a flat-top layout with vertical columns that shoves odd columns down
	OddQ
	// EvenQ is a flat-top layout with vertical columns that shoves even columns down
	EvenQ
)

type OffsetCoord

type OffsetCoord struct {
	Col, Row int
}

OffsetCoord represents offset coordinates (col, row) for hex grids.

func NewOffsetCoord

func NewOffsetCoord(col, row int) OffsetCoord

NewOffsetCoord returns an OffsetCoord initialized with the given column and row.

func (OffsetCoord) ConciseString

func (oc OffsetCoord) ConciseString() string

ConciseString returns the coordinates formatted as "+col+row".

func (OffsetCoord) QOffsetToCube

func (oc OffsetCoord) QOffsetToCube(even bool) Hex

QOffsetToCube converts q-offset coordinates to cube coordinates. If even is true, uses even-q offset; otherwise uses odd-q offset.

func (OffsetCoord) ROffsetToCube

func (oc OffsetCoord) ROffsetToCube(even bool) Hex

ROffsetToCube converts r-offset coordinates to cube coordinates. If even is true, uses even-r offset; otherwise uses odd-r offset.

func (OffsetCoord) String

func (oc OffsetCoord) String() string

String returns the coordinates formatted as "(col,row)".

type Point

type Point struct {
	X float64
	Y float64
}

Point represents a screen coordinate.

func (Point) String

func (p Point) String() string

String returns the coordinates formatted as "x,y".

Directories

Path Synopsis
cmd
examples command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL