Skip to content

Commit

Permalink
feat(hex): use axial coordinates by default
Browse files Browse the repository at this point in the history
Also add isAxial() util function and some more ideas to readme
  • Loading branch information
flauwekeul committed Apr 22, 2021
1 parent 2c6687f commit 775e711
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 9 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ All existing JS hex grid libraries I could find are coupled with some form of vi
### Coordinates

- [ ] Store coordinates as ~~"tuples" (arrays)~~ simple 3D objects. Investigate whether arrays or objects (without prototype?) (maybe even strings, ArrayBuffer?) are more performant.
- [x] Take [Amit's advice](https://www.redblobgames.com/grids/hexagons/#coordinates-comparison) and use axial coordinates by default.
- [ ] Use `x`, `y` and `z` for cube coordinates?
- [ ] Rename cartesian to offset?
- [ ] Also use [doubled coordinates](https://www.redblobgames.com/grids/hexagons/#coordinates-doubled)?
- [x] Currently there are 3 types of coordinates: cube `{ q, r, s }`, cartesian `{ x, y }` and point `[x, y]`. Only use cube `{ q, r, s }` and cartesian `{ x, y }`.
- [x] Problem: how to differentiate between 2D hex coordinate and 2D "pixel" coordinate?
**Solution**: `CartesianCoordinates` is an alias of `Point`. A "coordinate" is a point in a grid, a "point" is any 2D/3D point in any system (e.g. a grid).
Expand Down Expand Up @@ -114,6 +118,7 @@ All existing JS hex grid libraries I could find are coupled with some form of vi

### Grid

- [ ] Do something with this: [https://www.redblobgames.com/grids/hexagons/#map-storage](https://www.redblobgames.com/grids/hexagons/#map-storage)?
- [ ] There's a function to create a `traverser`: a [generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) that determines how to traverse a grid. It's called with a start direction and returns a [Generator object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator):
```ts
const hexPrototype = createHexPrototype({ size: 10, orientation: 'flat' })
Expand Down
6 changes: 3 additions & 3 deletions src/hex/functions/createHex.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CubeCoordinates, DefaultHexPrototype, Hex } from '../types'
import { AxialCoordinates, CubeCoordinates, DefaultHexPrototype, Hex } from '../types'

export const createHex = <T extends DefaultHexPrototype>(prototype: T, coordinates: CubeCoordinates) =>
Object.assign(Object.create(prototype), coordinates) as T extends Hex ? T : T & Hex
export const createHex = <T extends DefaultHexPrototype>(prototype: T, { q, r }: AxialCoordinates | CubeCoordinates) =>
Object.assign(Object.create(prototype), { q, r }) as T extends Hex ? T : T & Hex
6 changes: 3 additions & 3 deletions src/hex/functions/toPoint.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { CubeCoordinates, Ellipse, HexSettings, Orientation, Point } from '../types'
import { AxialCoordinates, Ellipse, HexSettings, Orientation, Point } from '../types'

// todo: benchmark if currying the higher order functions has significant performance impact

export const createToPointPointy = ({ xRadius, yRadius }: Ellipse) => ({ q, r }: CubeCoordinates) =>
export const createToPointPointy = ({ xRadius, yRadius }: Ellipse) => ({ q, r }: AxialCoordinates) =>
({
x: xRadius * Math.sqrt(3) * (q + r / 2),
y: ((yRadius * 3) / 2) * r,
} as Point)

export const createToPointFlat = ({ xRadius, yRadius }: Ellipse) => ({ q, r }: CubeCoordinates) =>
export const createToPointFlat = ({ xRadius, yRadius }: Ellipse) => ({ q, r }: AxialCoordinates) =>
({
x: ((xRadius * 3) / 2) * q,
y: yRadius * Math.sqrt(3) * (r + q / 2),
Expand Down
7 changes: 5 additions & 2 deletions src/hex/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ export const enum Orientation {
POINTY = 'POINTY',
}

export interface CubeCoordinates {
export interface AxialCoordinates {
q: number
r: number
}

export interface CubeCoordinates extends AxialCoordinates {
s: number
}

Expand Down Expand Up @@ -47,4 +50,4 @@ export interface DefaultHexPrototype extends HexSettings {
toPoint(): Point
}

export interface Hex extends DefaultHexPrototype, CubeCoordinates {}
export interface Hex extends DefaultHexPrototype, AxialCoordinates {}
2 changes: 2 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from './isAxial'
export * from './isCartesian'
export * from './isCube'
export * from './isFunction'
export * from './isObject'
export * from './offsetFromZero'
export * from './signedModulo'
5 changes: 5 additions & 0 deletions src/utils/isAxial.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AxialCoordinates } from '../hex'
import { isObject } from './isObject'

export const isAxial = (value: unknown): value is AxialCoordinates =>
isObject<AxialCoordinates>(value) && Number.isFinite(value.q) && Number.isFinite(value.r)
1 change: 0 additions & 1 deletion src/utils/isCube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ export const isCube = (value: unknown): value is CubeCoordinates =>
Number.isFinite(value.q) &&
Number.isFinite(value.r) &&
Number.isFinite(value.s) &&
// todo: not sure if this is necessary
value.q + value.r + value.s === 0
1 change: 1 addition & 0 deletions src/utils/signedModulo.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
// todo: this might be a redundant function
export const signedModulo = (dividend: number, divisor: number) => ((dividend % divisor) + divisor) % divisor

0 comments on commit 775e711

Please sign in to comment.