Skip to content

Instantly share code, notes, and snippets.

@TheSeamau5
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheSeamau5/23e094aae22f4a8ae6f3 to your computer and use it in GitHub Desktop.
Save TheSeamau5/23e094aae22f4a8ae6f3 to your computer and use it in GitHub Desktop.
How to make a simple hexagonal grid in Elm
import List (..)
import Graphics.Collage (..)
import Graphics.Element (..)
import Color (..)
------------------------------------------
-- 2D Point Type
type alias Point = {
x : Float,
y : Float
}
-- Flat-topped regular hexagon
hexagon : number -> Shape
hexagon size = ngon 6 size
-- Calculate the height of a regular hexagon from its radius
hexHeight : number -> number
hexHeight radius = (sqrt 3) / 2 * radius
-- Make a single column of hexagons
-- rows : number of rows / hexagons in the given column
-- size : size of each hexagon
-- start: starting point of column / center of bottom-most hexagon
makeHexColumn : number -> number -> Point -> List Point
makeHexColumn rows size start =
if rows <= 0
then []
else start :: makeHexColumn (rows - 1) size {start | y <- start.y + 2 * (hexHeight size)}
-- Make a grid of hexagons
-- rows : number of rows in the grid
-- columns : number of columns in the grid
-- size : size of each hexagon
-- start : starting point of grid / center of bottomleft-most hexagon
makeHexGrid : number -> number -> number -> Point -> List (List Point)
makeHexGrid rows columns size start =
let helper columnCounter =
let shifted =
if (floor columnCounter) % 2 == 0
then {start | x <- start.x + ((3 / 2 * size) * (columnCounter - 1)),
y <- start.y - (hexHeight size)}
else {start | x <- start.x + ((3 / 2 * size) * (columnCounter - 1))}
in
if columns - columnCounter < 0
then []
else makeHexColumn rows size shifted :: helper (columnCounter + 1)
in helper 1
-- Makes it easier to work with grid by converting
-- them from a 2d list of points to a 1d list of points
grid : number -> number -> number -> Point -> List Point
grid rows columns size start = concat <| makeHexGrid rows columns size start
-------------------------------
-- TEST CODE
--------
-- GLOBALS TO MESS AROUND WITH
hexSize = 20
hexRows = 10
hexColumns = 7
hexStart = Point -150 -150
----------
-- compact function to make a hexagon of a given color
-- at a given point
hex : Color -> Point -> Form
hex color point =
move (point.x, point.y) <| filled color <| hexagon hexSize
-- make a blue hexagon
blueHex : Point -> Form
blueHex = hex blue
-- make a red hexagon
redHex : Point -> Form
redHex = hex red
-- make a green hexagon
greenHex : Point -> Form
greenHex = hex green
-- function that filters out all the elements of a list
-- located at odd indices of the list and then
-- applies a function to the remaining elements (the ones
-- at even indices)
-- ----
-- Example : mapEven square [2,3,4,5] -> [9, 25]
-- ----
-- f : function to be mapped onto
-- list : list to be filtered and mapped to
mapEven : (a -> b) -> List a -> List b
mapEven f list =
let helper f list counter =
if | list == [] -> []
| counter % 2 == 0 -> (f (head list)) :: helper f (tail list) (counter + 1)
| otherwise -> helper f (tail list) (counter + 1)
in helper f list 1
-- function that filters out all the elements of a list
-- located at even indices of the list and then
-- applies a function to the remaining elements (the ones
-- at odd indices)
-- ----
-- Example : mapEven square [2,3,4,5] -> [4, 16]
-- ----
-- f : function to be mapped onto
-- list : list to be filtered and mapped to
mapOdd : (a -> b) -> List a -> List b
mapOdd f list =
let helper f list counter =
if | list == [] -> []
| counter % 2 == 1 -> (f (head list)) :: helper f (tail list) (counter + 1)
| otherwise -> helper f (tail list) (counter + 1)
in helper f list 1
-- Make the test grid (4 x 4 grid start)
testGrid : List Point
testGrid = grid hexRows hexColumns hexSize hexStart
-- Make the blue hexagons
blues : List Form
blues = mapEven blueHex testGrid
-- Make the red hexagons
reds : List Form
reds = mapOdd redHex testGrid
-- Make the scene (canvas)
scene : List Form -> Element
scene = collage 400 400
-- Join the red and blue hexagons and push them onto the scene
main : Element
main = scene <| (reds ++ blues)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment