You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.6 KiB
164 lines
4.6 KiB
--[[ AXIAL/CUBE COORDINATE SYSTEM FOR AMULET/LUA]]
|
|
--[[
|
|
|
|
all hexes in functions are assumed to be amulet vectors.
|
|
in amulet, vector arithmetic works already with [ + - * / ]
|
|
things like equality and distance are implemented here.
|
|
|
|
some algorithms use axial coordinates for hexes: vec2(s, t)
|
|
others use cube coordinates: vec3(s, t, z) where s + t + z = 0
|
|
this is for simplicity - many algorithms don't care about the
|
|
third coordinate, and if they do, the missing coordinate can
|
|
be calculated from the other two.
|
|
|
|
-- note on orientation:
|
|
because of the way amulet draws hexagons, it's much easier to assume
|
|
the user wants to use the flat map. rotation after the fact to
|
|
achieve other orienations is probably possible, but might have some
|
|
aliasing issues. TODO work on this.
|
|
|
|
consequently, I have not implemented stretching. all hexagons are
|
|
assumed to be regular. you could implement this yourself by making
|
|
layout.size a vec2(sizex, sizey), but you would have to play with
|
|
transforms in the amulet library if you wanted to use amulet.
|
|
|
|
some of the primary resources used to develop this library:
|
|
- https://redblobgames.com/grid/hexagons - simply amazing.
|
|
- http://amulet.xyz/doc - amulet documentation
|
|
- TODO that place that had the inner circle/outer circle ratio??
|
|
|
|
]]
|
|
|
|
-- GENERALLY USEFUL CONSTANTS -------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
-- GENERALLY USEFUL FUNCTIONS --------------------------------------------------
|
|
|
|
function round(n)
|
|
return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
|
|
end
|
|
|
|
function draw_axes(window, node)
|
|
xaxis = am.line(vec2(-window.width / 2, 0) , vec2(window.width / 2, 0))
|
|
yaxis = am.line(vec2(0, -window.height / 2), vec2(0, window.height / 2))
|
|
|
|
node:append(xaxis)
|
|
node:append(yaxis)
|
|
end
|
|
|
|
-- HEX CONSTANTS ---------------------------------------------------------------
|
|
|
|
-- all possible vector directions from a given hex by edge
|
|
HEX_DIRECTIONS = {vec2( 1 , 0),
|
|
vec2( 1 , -1),
|
|
vec2( 0 , -1),
|
|
vec2(-1 , 0),
|
|
vec2(-1 , 1),
|
|
vec2( 0 , 1)}
|
|
|
|
-- HEX UTILITY FUNCTIONS -------------------------------------------------------
|
|
|
|
function hex_equals(a, b)
|
|
return a.s == a.t and b.s == b.t
|
|
end
|
|
|
|
function hex_nequals(a, b)
|
|
return not hex_equals(a, b)
|
|
end
|
|
|
|
function hex_length(hex)
|
|
return ((math.abs(hex.s) + math.abs(hex.t) + math.abs(-hex.s - hex.t)) / 2)
|
|
end
|
|
|
|
function hex_distance(a, b)
|
|
return hex_length(a - b)
|
|
end
|
|
|
|
function hex_direction(direction)
|
|
return HEX_DIRECTIONS[direction]
|
|
end
|
|
|
|
function hex_neighbour(hex, direction)
|
|
return hex + HEX_DIRECTIONS[direction]
|
|
end
|
|
|
|
function hex_round(hex)
|
|
rs = round(hex.s)
|
|
rt = round(hex.t)
|
|
rz = round(-hex.s + -hex.t)
|
|
|
|
sdelta = math.abs(rs - hex.s)
|
|
tdelta = math.abs(rt - hex.t)
|
|
zdelta = math.abs(rz + hex.s + hex.t)
|
|
|
|
if sdelta > tdelta and sdelta > zdelta then
|
|
rs = -rt - rz
|
|
elseif tdelta > zdelta then
|
|
rt = -rs - rz
|
|
else
|
|
rz = -rs - rt
|
|
end
|
|
|
|
return vec2(rs, rt)
|
|
end
|
|
|
|
-- COORDINATE CONVERSION FUNCTIONS ---------------------------------------------
|
|
|
|
-- forward & inverse matrices used for coordinate conversion
|
|
local M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 )
|
|
local W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0)
|
|
|
|
-- hex to screen
|
|
function hex_to_pixel(hex, origin)
|
|
|
|
x = (M[1][1] * hex.s + M[1][2] * hex.t) * SIZE
|
|
y = (M[2][1] * hex.s + M[2][2] * hex.t) * SIZE
|
|
|
|
return vec2(x + origin.x, y + origin.y)
|
|
end
|
|
|
|
-- screen to hex
|
|
function pixel_to_hex(pix, origin)
|
|
pix = vec2(pix.x - origin.x) / SIZE,
|
|
(pix.y - origin.y) / SIZE
|
|
|
|
s = W[1][1] * pix.x + W[1][2] * pix.y
|
|
t = W[2][1] * pix.x + W[2][2] * pix.y
|
|
|
|
return hex_round(vec2(s, t))
|
|
end
|
|
|
|
-- MAP FUNCTIONS ---------------------------------------------------------------
|
|
|
|
function hexagonal_map(radius, origin)
|
|
for s = -radius, radius do
|
|
t1 = math.max(-radius, -s - radius)
|
|
t2 = math.min(radius, -s + radius)
|
|
|
|
for t = t1, t2 do
|
|
|
|
color = vec4(math.random(20, 80) / 100,
|
|
math.random(20, 80) / 100,
|
|
math.random(20, 80) / 100,
|
|
1)
|
|
|
|
map:append(am.circle(hex_to_pixel(vec2(s, t)), 24, color, 6))
|
|
end
|
|
end
|
|
end
|
|
|
|
function rectangular_map(width, height, origin)
|
|
for s = 0, height do
|
|
soffset = math.floor(s / 2)
|
|
|
|
for t = -soffset, width - soffset do
|
|
|
|
center = hex_to_pixel(vec2(s, t))
|
|
end
|
|
end
|
|
end
|
|
--]]
|
|
|