Last active
August 29, 2015 14:10
-
-
Save TheSeamau5/23e094aae22f4a8ae6f3 to your computer and use it in GitHub Desktop.
How to make a simple hexagonal grid in Elm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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