Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pmcxs/hexgrid
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: soupstoregames/hexgrid
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Oct 27, 2022

  1. Make privates public

    nicklanng committed Oct 27, 2022
    Copy the full SHA
    64aabc7 View commit details

Commits on Dec 2, 2022

  1. Copy the full SHA
    a21d382 View commit details
Showing with 205 additions and 159 deletions.
  1. +2 −0 .gitignore
  2. +8 −0 .idea/modules.xml
  3. +54 −49 hex.go
  4. +105 −75 hex_test.go
  5. +4 −4 layout.go
  6. +32 −31 layout_test.go
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -22,3 +22,5 @@ _testmain.go
*.exe
*.test
*.prof

.idea
8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

103 changes: 54 additions & 49 deletions hex.go
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ const (
directionS
)

var directions = []hex{
var directions = []Hex{
NewHex(1, 0),
NewHex(1, -1),
NewHex(0, -1),
@@ -25,44 +25,49 @@ var directions = []hex{
NewHex(0, +1),
}

// hex describes a regular hexagon with Cube Coordinates (although the S coordinate is computed on the constructor)
// It's also easy to reference them as axial (trapezoidal coordinates):
// Hex describes a regular hexagon with Cube Coordinates (although the S coordinate is computed on the constructor)
// It'S also easy to reference them as axial (trapezoidal coordinates):
// - R represents the vertical axis
// - Q the diagonal one
// - S can be ignored
// For additional reference on these coordinate systems: http://www.redblobgames.com/grids/hexagons/#coordinates
// _ _
// / \
// _ _ /(0,-1) \ _ _
// / \ -R / \
//
// _ _
// / \
// _ _ /(0,-1) \ _ _
// / \ -R / \
//
// /(-1,0) \ _ _ /(1,-1) \
// \ -Q / \ /
// \ _ _ / (0,0) \ _ _ /
// / \ / \
//
// \ _ _ / (0,0) \ _ _ /
// / \ / \
//
// /(-1,1) \ _ _ / (1,0) \
// \ / \ +Q /
// \ _ _ / (0,1) \ _ _ /
// \ +R /
// \ _ _ /
type hex struct {
q int // x axis
r int // y axis
s int // z axis
//
// \ _ _ / (0,1) \ _ _ /
// \ +R /
// \ _ _ /
type Hex struct {
Q int // x axis
R int // y axis
S int // z axis
}

func NewHex(q, r int) hex {
func NewHex(q, r int) Hex {

h := hex{q: q, r: r, s: -q - r}
h := Hex{Q: q, R: r, S: -q - r}
return h

}

func (h hex) String() string {
return fmt.Sprintf("(%d,%d)", h.q, h.r)
func (h Hex) String() string {
return fmt.Sprintf("%d-%d", h.Q, h.R)
}

// fractionHex provides a more precise representation for hexagons when precision is required.
// It's also represented in Cube Coordinates
// It'S also represented in Cube Coordinates
type fractionalHex struct {
q float64
r float64
@@ -77,7 +82,7 @@ func NewFractionalHex(q, r float64) fractionalHex {
}

// Rounds a FractionalHex to a Regular Hex
func (h fractionalHex) Round() hex {
func (h fractionalHex) Round() Hex {

roundToInt := func(a float64) int {
if a < 0 {
@@ -101,59 +106,59 @@ func (h fractionalHex) Round() hex {
} else {
s = -q - r
}
return hex{q, r, s}
return Hex{q, r, s}

}

// Adds two hexagons
func HexAdd(a, b hex) hex {
return NewHex(a.q+b.q, a.r+b.r)
func HexAdd(a, b Hex) Hex {
return NewHex(a.Q+b.Q, a.R+b.R)
}

// Subtracts two hexagons
func HexSubtract(a, b hex) hex {
return NewHex(a.q-b.q, a.r-b.r)
func HexSubtract(a, b Hex) Hex {
return NewHex(a.Q-b.Q, a.R-b.R)
}

// Scales an hexagon by a k factor. If factor k is 1 there's no change
func HexScale(a hex, k int) hex {
return NewHex(a.q*k, a.r*k)
// Scales an hexagon by a k factor. If factor k is 1 there'S no change
func HexScale(a Hex, k int) Hex {
return NewHex(a.Q*k, a.R*k)
}

func HexLength(hex hex) int {
return int((math.Abs(float64(hex.q)) + math.Abs(float64(hex.r)) + math.Abs(float64(hex.s))) / 2.)
func HexLength(hex Hex) int {
return int((math.Abs(float64(hex.Q)) + math.Abs(float64(hex.R)) + math.Abs(float64(hex.S))) / 2.)
}

func HexDistance(a, b hex) int {
func HexDistance(a, b Hex) int {
sub := HexSubtract(a, b)
return HexLength(sub)
}

// Returns the neighbor hexagon at a certain direction
func HexNeighbor(h hex, direction direction) hex {
func HexNeighbor(h Hex, direction direction) Hex {
directionOffset := directions[direction]
return NewHex(h.q+directionOffset.q, h.r+directionOffset.r)
return NewHex(h.Q+directionOffset.Q, h.R+directionOffset.R)
}

// Returns the slice of hexagons that exist on a line that goes from hexagon a to hexagon b
func HexLineDraw(a, b hex) []hex {
func HexLineDraw(a, b Hex) []Hex {

hexLerp := func(a fractionalHex, b fractionalHex, t float64) fractionalHex {
return NewFractionalHex(a.q*(1-t)+b.q*t, a.r*(1-t)+b.r*t)
}

N := HexDistance(a, b)

// Sometimes the hexLerp will output a point that’s on an edge.
// Sometimes the hexLerp will output a point that’S on an edge.
// On some systems, the rounding code will push that to one side or the other,
// somewhat unpredictably and inconsistently.
// To make it always push these points in the same direction, add an “epsilon” value to a.
// This will “nudge” things in the same direction when it’s on an edge, and leave other points unaffected.
// This will “nudge” things in the same direction when it’S on an edge, and leave other points unaffected.

a_nudge := NewFractionalHex(float64(a.q)+0.000001, float64(a.r)+0.000001)
b_nudge := NewFractionalHex(float64(b.q)+0.000001, float64(b.r)+0.000001)
a_nudge := NewFractionalHex(float64(a.Q)+0.000001, float64(a.R)+0.000001)
b_nudge := NewFractionalHex(float64(b.Q)+0.000001, float64(b.R)+0.000001)

results := make([]hex, 0)
results := make([]Hex, 0)
step := 1. / math.Max(float64(N), 1)

for i := 0; i <= N; i++ {
@@ -163,9 +168,9 @@ func HexLineDraw(a, b hex) []hex {
}

// Returns the set of hexagons around a certain center for a given radius
func HexRange(center hex, radius int) []hex {
func HexRange(center Hex, radius int) []Hex {

var results = make([]hex, 0)
var results = make([]Hex, 0)

if radius >= 0 {
for dx := -radius; dx <= radius; dx++ {
@@ -181,9 +186,9 @@ func HexRange(center hex, radius int) []hex {
}

// Returns the set of hexagons that form a rectangle with the specified width and height
func HexRectangleGrid(width, height int) []hex {
func HexRectangleGrid(width, height int) []Hex {

results := make([]hex, 0)
results := make([]Hex, 0)

for q := 0; q < width; q++ {
qOffset := int(math.Floor(float64(q) / 2.))
@@ -198,9 +203,9 @@ func HexRectangleGrid(width, height int) []hex {
}

// Determines if a given hexagon is visible from another hexagon, taking into consideration a set of blocking hexagons
func HexHasLineOfSight(center hex, target hex, blocking []hex) bool {
func HexHasLineOfSight(center Hex, target Hex, blocking []Hex) bool {

contains := func(s []hex, e hex) bool {
contains := func(s []Hex, e Hex) bool {
for _, a := range s {
if a == e {
return true
@@ -220,9 +225,9 @@ func HexHasLineOfSight(center hex, target hex, blocking []hex) bool {
}

// Returns the list of hexagons that are visible from a given hexagon
func HexFieldOfView(source hex, candidates []hex, blocking []hex) []hex {
func HexFieldOfView(source Hex, candidates []Hex, blocking []Hex) []Hex {

results := make([]hex, 0)
results := make([]Hex, 0)

for _, h := range candidates {

Loading