Browse Source

Formatting + Starting on Terrain Gen

master
churchianity 6 years ago
parent
commit
51c3183349
  1. 79
      README.md
  2. 73
      hex.lua
  3. 107
      main.lua
  4. 48
      util.lua

79
README.md

@ -1,80 +1,73 @@
## INTRODUCTION [1.1]
## INTRODUCTION
this is a library for using hexagonal grids in amulet/lua. this is a library for using hexagonal grids in amulet/lua.
it is extremely incomplete. the following list of features is it is extremely incomplete. the following list of features is
either implemented shoddily, or not at all. either implemented shoddily, or not at all.
if you want an actual good resource, go to [1.9].
if you want an actual good resource, go to TODO LINK.
## GETTING STARTED [1.2]
## GETTING STARTED
* TODO
## COORDINATE SYSTEMS [1.3]
as much coordinate manipulation as possible is done internally.
depending on the task, uses either Axial, Cube, or Doubled coordinates.
1) initialize a map.
2) iterate over the map and draw some hexagons.
three different ways of returning and sending coordinates:
## COORDINATE SYSTEMS
* amulet vectors
* lua tables
* individual coordinate numbers
As much coordinate manipulation as possible is done internally.
Depending on the task, uses either Axial, Cube, or Offset coordinates.
so you can use what your graphics library likes best!
## MAPS & MAP STORAGE [1.4]
## MAPS & MAP STORAGE
Some map shapes: parallelogram, rectangular, hexagonal, triangular. (and more) Some map shapes: parallelogram, rectangular, hexagonal, triangular. (and more)
The storage system used is based on the map shape - see chart: The storage system used is based on the map shape - see chart:
| SHAPE | MAP STORAGE | | SHAPE | MAP STORAGE |
| ----------------- | --------------------------------------------- | | ----------------- | --------------------------------------------- |
| parallelogram | unordered, hash-like OR ordered, array-like |
| rectangular | unordered, hash-like OR ordered, array-like |
| hexagonal | unordered, hash-like OR ordered, array-like |
| triangular | unordered, hash-like OR ordered, array-like |
| parallelogram | unordered, hash-like |
| rectangular | unordered, hash-like |
| hexagonal | unordered, hash-like |
| triangular | unordered, hash-like |
| ring | ordered, array-like | | ring | ordered, array-like |
| spiral | ordered, array-like** |
| spiral | ordered, array-like |
| arbitrary | unordered, hash-like | | arbitrary | unordered, hash-like |
** note that a spiral map is just a hexagonal one with a particular order.
* note that a spiral map is just a hexagonal one with a particular order.
By default, the unordered, hash-like maps have pseudo-random noise stored
as their values. This can be useful for a whole bunch of things, but if you
wish, you can simply iterate over your map and set every value to 'true'.
## CONVENTIONS AND TERMINOLOGY [1.8]
## CONVENTIONS AND TERMINOLOGY
If you have read amit's guide to hexagon grids, (see [1.9]), a lot of the
If you have read amit's guide to hexagon grids, (see TODO LINK), a lot of the
terminology will be familiar to you - I utilize many conventions he does in terminology will be familiar to you - I utilize many conventions he does in
his guide. That being said... his guide. That being said...
Because so many different kinds of coordinate groupings are used in this library,
and they are all fundamentally tables/vectors/arrays of integers, it can be hard
to remember what they are all referring to.
Because so many similar kinds of data structures with different goals are used
in this library it can be hard to remember precisely what they all refer to.
The following table shows what each table/vector/array refers to in the code: The following table shows what each table/vector/array refers to in the code:
| NAME | REFERS TO | | NAME | REFERS TO |
| ---- | ---------------------------------------------------------- |
| cube | xyz, used for most maps, with constraint x+y+z=0. ** |
| pix | xy, true screen pixel coordinates |
| dbl | xy, 'doubled', used for rectangular maps |
| off | xy, 'offset', used for UI implementations |
| ---- | ---------------------------------------------------------- |
| map | xy, table of unit hexagon centerpoints arranged in a shape |
** note that 'axial' coordinates are a subset of cube coordinates, where
you simply omit the z value. for many algorithms this is done, but instead
of using some reference name 'axial', I just used the name 'cube' for both
cases. I found this to be clearer and less prone to end-user error. when
an algorithm asks for a cube, give it a cube. if you want to know if it works
with axial as well, look at the code and see if it uses a 'z' value.
| ---- | ------------------------------------------------------------ |
| cube | xyz, *vector* used for most maps, with constraint x+y+z=0. |
| pix | xy, *vector* true screen pixel coordinates |
| off | xy, 'offset', *vector* used for UI implementations |
| map | xy, *table* of unit hexagon centerpoints arranged in a shape |
* note that 'axial', vec2() coordinates are a subset of cube coordinates,
where you simply omit the z value. for many algorithms this is done, but
instead of using a seperate reference name 'axial' in these cases, I used
the name 'cube' for both. I found this to be simpler. when an algorithm
asks for a cube, give it a cube. if you want to know if it works with axial
as well, look at the code and see if it uses a 'z' value.
Other terminology: Other terminology:
* TODO * TODO
## RESOURCES USED TO DEVELOP THIS LIBRARY, AND FOR WHICH I AM GRATEFUL [1.9]
## RESOURCES USED TO DEVELOP THIS LIBRARY, AND FOR WHICH I AM GRATEFUL
* [Hex Map 1](https://catlikecoding.com/unity/tutorials/hex-map/) - unity tutorial for hexagon grids with some useful generalized math. * [Hex Map 1](https://catlikecoding.com/unity/tutorials/hex-map/) - unity tutorial for hexagon grids with some useful generalized math.

73
hex.lua

@ -1,12 +1,16 @@
----- [[ GENERALLY USEFUL FUNCTIONS ]] -----------------------------------------
--[[============================================================================
----- GENERALLY USEFUL FUNCTIONS -----
==============================================================================]]
-- rounds numbers. would've been cool to have math.round in lua. -- rounds numbers. would've been cool to have math.round in lua.
local function round(n) local function round(n)
return n % 1 >= 0.5 and math.ceil(n) or math.floor(n) return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
end end
----- [[ HEX CONSTANTS & UTILITY FUNCTIONS ]] ----------------------------------
--[[============================================================================
----- HEX CONSTANTS AND UTILITY FUNCTIONS -----
==============================================================================]]
-- all possible vector directions from a given hex by edge -- all possible vector directions from a given hex by edge
local CUBE_DIRECTIONS = {vec2( 1 , 0), local CUBE_DIRECTIONS = {vec2( 1 , 0),
@ -23,22 +27,19 @@ end
-- return hexagon adjacent to |hex| in integer index |direction|. -- return hexagon adjacent to |hex| in integer index |direction|.
function cube_neighbour(hex, direction) function cube_neighbour(hex, direction)
return hex + HEX_DIRECTIONS[(6 + (direction % 6)) % 6 + 1]
return hex + CUBE_DIRECTIONS[(6 + (direction % 6)) % 6 + 1]
end end
-- TODO rotations are different depending on the coordinate system you use.
-- implement this for cube/axial, and doubled.
-- TODO cube rotations
function cube_rotate_left(hex) function cube_rotate_left(hex)
end end
function cube_rotate_right(hex) function cube_rotate_right(hex)
end end
-- rounds a float coordinate trio |x, y, z| to its nearest integer coordinate trio.
-- TODO make work with a table {x, y, z} and vec3(x, y, z)
function cube_round(x, y, z)
-- rounds a float coordinate trio |x, y, z| to nearest integer coordinate trio
-- only ever used internally; no need to use a vector.
local function cube_round(x, y, z)
local rx = round(x) local rx = round(x)
local ry = round(y) local ry = round(y)
local rz = round(z) or round(-x - y) local rz = round(z) or round(-x - y)
@ -58,7 +59,9 @@ function cube_round(x, y, z)
return vec2(rx, ry) return vec2(rx, ry)
end end
----- [[ LAYOUT, ORIENTATION & COORDINATE CONVERSION ]] -----------------------
--[[============================================================================
----- ORIENTATION & LAYOUT -----
==============================================================================]]
-- forward & inverse matrices used for the flat orientation. -- forward & inverse matrices used for the flat orientation.
local FLAT = {M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 ), local FLAT = {M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 ),
@ -111,19 +114,25 @@ function hex_corners(hex, layout)
local corners = {} local corners = {}
end end
--
function cube_to_offset(cube) function cube_to_offset(cube)
return vec2(cube[1], -cube[1] - cube[2] + (cube[1] + (cube[1] % 2)) / 2) return vec2(cube[1], -cube[1] - cube[2] + (cube[1] + (cube[1] % 2)) / 2)
end end
--
function offset_to_cube(off) function offset_to_cube(off)
return vec2(off[1], off[2] - off[1] * (off[1] % 2) / 2) return vec2(off[1], off[2] - off[1] * (off[1] % 2) / 2)
end end
----- [[ MAP STORAGE & RETRIEVAL ]] --------------------------------------------
--[[
TODO make all functions work regardless of layout. as it stands, they kind
of do, just not always nicely.
]]
--[[============================================================================
----- MAPS & STORAGE -----
==============================================================================]]
-- information about the maps' dimensions are stored in a metatable, so you can
-- retrieve details about arbitrary maps after they are created.
-- TODO make all functions work regardless of layout. as it stands, they kind
-- of do, just not always nicely.
-- returns ordered ring-shaped map of |radius| from |center|. -- returns ordered ring-shaped map of |radius| from |center|.
function ring_map(center, radius) function ring_map(center, radius)
@ -143,10 +152,9 @@ function ring_map(center, radius)
return map return map
end end
--[[ returns ordered hexagonal map of |radius| rings from |center|.
the only difference between hex_spiral_map and hex_hexagonal_map is that
hex_spiral_map is ordered, in a spiral path from the |center|.
]]
-- returns ordered hexagonal map of |radius| rings from |center|.
-- the only difference between hex_spiral_map and hex_hexagonal_map is that
-- hex_spiral_map is ordered, in a spiral path from the |center|.
function spiral_map(center, radius) function spiral_map(center, radius)
local map = {center} local map = {center}
local mt = {__index={center=center, radius=radius}} local mt = {__index={center=center, radius=radius}}
@ -222,28 +230,11 @@ function rectangular_map(width, height)
return map return map
end end
----- [[ TESTS ]] --------------------------------------------------------------
--[[============================================================================
----- TESTS -----
==============================================================================]]
function test_all() function test_all()
test_rectangular_map()
print("it works trust me")
end end
function test_rectangular_map()
local map = rectangular_map(8, 5)
local layout = layout()
for hex,_ in pairs(map) do
print(cube_to_pixel(hex, layout))
end
for i = 0, 10 do
local mouse = pixel_to_cube(vec2(math.random(map.width) * 22,
math.random(map.height) * 10),
layout)
print(mouse)
end
end

107
main.lua

@ -1,74 +1,33 @@
----- WARZONE 2 - HEXAGONAL GRID RESOURCE BASED TOWER DEFENSE GAME -------------
-- author@churchianity.ca
require"hex" require"hex"
require"util" require"util"
------ GLOBALS -----------------------------------------------------------------
--[[============================================================================
----- GLOBALS -----
==============================================================================]]
local win = am.window{ local win = am.window{
-- BASE RESOLUTION = 3/4 * WXGA Standard 16:10
-- base resolution = 3/4 * WXGA standard 16:10
width = 1280 * 3 / 4, -- 960px width = 1280 * 3 / 4, -- 960px
height = 800 * 3 / 4, -- 600px height = 800 * 3 / 4, -- 600px
clear_color = vec4(0.01, 34/255, 45/255, 0),
title = "Warzone 2: Electric Boogaloo", title = "Warzone 2: Electric Boogaloo",
resizable = false
resizable = false,
} }
local layout = layout(vec2(-268, win.top - 10)) local layout = layout(vec2(-268, win.top - 10))
local map = rectangular_map(45, 31)
local map
local world = am.group{}:tag"world" local world = am.group{}:tag"world"
-- modified ethan shoonover solarized colortheme
am.ascii_color_map = {
E = vec4( 22/255, 22/255, 29/255, 1), -- eigengrau
K = vec4( 0, 43/255, 54/255, 1), -- dark navy
k = vec4( 7/255, 54/255, 66/255, 1), -- navy
L = vec4( 88/255, 110/255, 117/255, 1), -- gray1
l = vec4(101/255, 123/255, 131/255, 1), -- gray2
s = vec4(131/255, 148/255, 150/255, 1), -- gray3
S = vec4(147/255, 161/255, 161/255, 1), -- gray4
w = vec4(238/255, 232/255, 213/255, 1), -- bone
W = vec4(253/255, 246/255, 227/255, 1), -- white
y = vec4(181/255, 137/255, 0, 1), -- yellow
o = vec4(203/255, 75/255, 22/255, 1), -- orange
r = vec4(220/255, 50/255, 47/255, 1), -- red
m = vec4(211/255, 54/255, 130/255, 1), -- magenta
v = vec4(108/255, 113/255, 196/255, 1), -- violet
b = vec4( 38/255, 139/255, 210/255, 1), -- blue
c = vec4( 42/255, 161/255, 152/255, 1), -- cyan
g = vec4(133/255, 153/255, 0, 1) -- green
}
local titlebutton =
[[
KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
KwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
]]
----- FUNCTIONS ----------------------------------------------------------
function show_axes()
local xaxis = am.line(vec2(win.left, 0), vec2(win.right, 0))
local yaxis = am.line(vec2(0, win.top), vec2(0, win.bottom))
win.scene:append(am.translate(0, 0) ^ am.group{xaxis, yaxis}:tag"axes")
end
--[[============================================================================
----- FUNCTIONS -----
==============================================================================]]
function show_hex_coords() function show_hex_coords()
win.scene:action(function()
win.scene:remove("coords")
win.scene:remove("select")
world:action(function()
world:remove("coords")
world:remove("select")
local hex = pixel_to_cube(win:mouse_position(), layout) local hex = pixel_to_cube(win:mouse_position(), layout)
local mouse = cube_to_offset(hex) local mouse = cube_to_offset(hex)
@ -78,7 +37,7 @@ function show_hex_coords()
local coords = am.group{ local coords = am.group{
am.translate(win.right - 25, win.top - 10) am.translate(win.right - 25, win.top - 10)
^ am.text(string.format("%d,%d", mouse.x, mouse.y)):tag"coords"} ^ am.text(string.format("%d,%d", mouse.x, mouse.y)):tag"coords"}
win.scene:append(coords)
world:append(coords)
local mask = vec4(1, 1, 1, 0.2) local mask = vec4(1, 1, 1, 0.2)
local pix = cube_to_pixel(hex, layout) local pix = cube_to_pixel(hex, layout)
@ -87,35 +46,41 @@ function show_hex_coords()
end) end)
end end
function init()
function world_init()
world:action(coroutine.create(function() world:action(coroutine.create(function()
local gui = am.rect(win.left, win.top, -268, win.bottom):tag"gui"
world:append(gui)
-- init guiblock
local bg = am.rect(win.left, win.top, -268, win.bottom):tag"bg"
world:append(bg)
for hex,_ in pairs(map) do
-- init map
map = rectangular_map(45, 31)
for hex,elevation in pairs(map) do
local pix = cube_to_pixel(hex, layout) local pix = cube_to_pixel(hex, layout)
local off = cube_to_offset(hex) local off = cube_to_offset(hex)
local tag = tostring(hex) local tag = tostring(hex)
local color local color
local mask
if off.x == 0 or off.x == map.width or
off.y == 0 or off.y == map.height then
color = rhue(0.3)
else
color = rhue(1 - math.max(((off.x-23)/30)^2, ((off.y-16)/20)^2))
end
-- testing noise with color
color = vec4(1, 1, 1, (elevation + 1) / 2)
world"gui".color = vec4(0, 43/255, 54/255, am.frame_time / 20)
world:prepend(am.circle(pix, layout.size.x, color, 6):tag(tag))
-- determine cell shading mask based on map position
--mask = vec4(0, 0, 0, math.max(((off.x-23)/30)^2, ((off.y-16)/20)^2))
--color = color - mask
world"bg".color = vec4(0, 43/255, 54/255, am.frame_time)
world:prepend(am.circle(pix, layout.size.x, color, 6):tag(tag))
am.wait(am.delay(0.01)) am.wait(am.delay(0.01))
end end
show_hex_coords()
end)) end))
win.scene = world win.scene = world
end end
----- [[ MAIN ]] ---------------------------------------------------------------
--[[============================================================================
----- MAIN -----
==============================================================================]]
world_init()
init()
show_hex_coords()

48
util.lua

@ -1,5 +1,5 @@
function rhue(a)
function terr(a)
local R = math.random(35, 75) / 100 local R = math.random(35, 75) / 100
local G = math.random(35, 75) / 100 local G = math.random(35, 75) / 100
local B = math.random(35, 75) / 100 local B = math.random(35, 75) / 100
@ -11,3 +11,49 @@ end
function rmono() function rmono()
return vec4(1, 1, 1, math.random()) return vec4(1, 1, 1, math.random())
end end
function show_axes()
local xaxis = am.line(vec2(win.left, 0), vec2(win.right, 0))
local yaxis = am.line(vec2(0, win.top), vec2(0, win.bottom))
win.scene:append(am.translate(0, 0) ^ am.group{xaxis, yaxis}:tag"axes")
end
local titlebutton =
[[
KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
KwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
]]
-- modified ethan shoonover solarized colortheme
am.ascii_color_map = {
E = vec4( 22/255, 22/255, 29/255, 1), -- eigengrau
K = vec4( 0, 43/255, 54/255, 1), -- dark navy
k = vec4( 7/255, 54/255, 66/255, 1), -- navy
L = vec4( 88/255, 110/255, 117/255, 1), -- gray1
l = vec4(101/255, 123/255, 131/255, 1), -- gray2
s = vec4(131/255, 148/255, 150/255, 1), -- gray3
S = vec4(147/255, 161/255, 161/255, 1), -- gray4
w = vec4(238/255, 232/255, 213/255, 1), -- bone
W = vec4(253/255, 246/255, 227/255, 1), -- white
y = vec4(181/255, 137/255, 0, 1), -- yellow
o = vec4(203/255, 75/255, 22/255, 1), -- orange
r = vec4(220/255, 50/255, 47/255, 1), -- red
m = vec4(211/255, 54/255, 130/255, 1), -- magenta
v = vec4(108/255, 113/255, 196/255, 1), -- violet
b = vec4( 38/255, 139/255, 210/255, 1), -- blue
c = vec4( 42/255, 161/255, 152/255, 1), -- cyan
g = vec4(133/255, 153/255, 0, 1) -- green
}
Loading…
Cancel
Save