From 51c31833499f2fe47f3c49fa3200e5e4fdf6b045 Mon Sep 17 00:00:00 2001 From: churchianity Date: Fri, 22 Feb 2019 15:58:46 -0500 Subject: [PATCH] Formatting + Starting on Terrain Gen --- README.md | 81 ++++++++++++++++++---------------------- hex.lua | 73 ++++++++++++++++-------------------- main.lua | 109 ++++++++++++++++++------------------------------------ util.lua | 48 +++++++++++++++++++++++- 4 files changed, 153 insertions(+), 158 deletions(-) diff --git a/README.md b/README.md index 3cecc28..50580e4 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,73 @@ -## INTRODUCTION [1.1] +## INTRODUCTION this is a library for using hexagonal grids in amulet/lua. it is extremely incomplete. the following list of features is 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: - -* amulet vectors -* lua tables -* individual coordinate numbers +## COORDINATE SYSTEMS -so you can use what your graphics library likes best! +As much coordinate manipulation as possible is done internally. +Depending on the task, uses either Axial, Cube, or Offset coordinates. -## MAPS & MAP STORAGE [1.4] +## MAPS & MAP STORAGE Some map shapes: parallelogram, rectangular, hexagonal, triangular. (and more) - The storage system used is based on the map shape - see chart: | 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 | -| spiral | ordered, array-like** | +| spiral | ordered, array-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 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: -| 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. +| NAME | REFERS TO | +| ---- | ------------------------------------------------------------ | +| 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: * 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. diff --git a/hex.lua b/hex.lua index 544516b..5bec5a1 100644 --- a/hex.lua +++ b/hex.lua @@ -1,12 +1,16 @@ ------ [[ GENERALLY USEFUL FUNCTIONS ]] ----------------------------------------- +--[[============================================================================ + ----- GENERALLY USEFUL FUNCTIONS ----- +==============================================================================]] -- rounds numbers. would've been cool to have math.round in lua. local function round(n) return n % 1 >= 0.5 and math.ceil(n) or math.floor(n) end ------ [[ HEX CONSTANTS & UTILITY FUNCTIONS ]] ---------------------------------- +--[[============================================================================ + ----- HEX CONSTANTS AND UTILITY FUNCTIONS ----- +==============================================================================]] -- all possible vector directions from a given hex by edge local CUBE_DIRECTIONS = {vec2( 1 , 0), @@ -23,22 +27,19 @@ end -- return hexagon adjacent to |hex| in integer index |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 --- 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) - end function cube_rotate_right(hex) - 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 ry = round(y) local rz = round(z) or round(-x - y) @@ -58,7 +59,9 @@ function cube_round(x, y, z) return vec2(rx, ry) end ------ [[ LAYOUT, ORIENTATION & COORDINATE CONVERSION ]] ----------------------- +--[[============================================================================ + ----- ORIENTATION & LAYOUT ----- +==============================================================================]] -- 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 ), @@ -111,19 +114,25 @@ function hex_corners(hex, layout) local corners = {} end +-- function cube_to_offset(cube) return vec2(cube[1], -cube[1] - cube[2] + (cube[1] + (cube[1] % 2)) / 2) end +-- function offset_to_cube(off) return vec2(off[1], off[2] - off[1] * (off[1] % 2) / 2) 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|. function ring_map(center, radius) @@ -143,10 +152,9 @@ function ring_map(center, radius) return map 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) local map = {center} local mt = {__index={center=center, radius=radius}} @@ -222,28 +230,11 @@ function rectangular_map(width, height) return map end ------ [[ TESTS ]] -------------------------------------------------------------- +--[[============================================================================ + ----- TESTS ----- +==============================================================================]] function test_all() - test_rectangular_map() + print("it works trust me") 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 diff --git a/main.lua b/main.lua index 088f38c..7d8d339 100644 --- a/main.lua +++ b/main.lua @@ -1,74 +1,33 @@ ------ WARZONE 2 - HEXAGONAL GRID RESOURCE BASED TOWER DEFENSE GAME ------------- --- author@churchianity.ca - require"hex" require"util" ------- GLOBALS ----------------------------------------------------------------- +--[[============================================================================ + ----- GLOBALS ----- +==============================================================================]] 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 height = 800 * 3 / 4, -- 600px + + clear_color = vec4(0.01, 34/255, 45/255, 0), title = "Warzone 2: Electric Boogaloo", - resizable = false + resizable = false, } local layout = layout(vec2(-268, win.top - 10)) -local map = rectangular_map(45, 31) +local map 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() - 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 mouse = cube_to_offset(hex) @@ -78,7 +37,7 @@ function show_hex_coords() local coords = am.group{ am.translate(win.right - 25, win.top - 10) ^ 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 pix = cube_to_pixel(hex, layout) @@ -87,35 +46,41 @@ function show_hex_coords() end) end -function init() +function world_init() 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 off = cube_to_offset(hex) local tag = tostring(hex) - local color + local color + local mask + + -- testing noise with color + color = vec4(1, 1, 1, (elevation + 1) / 2) - 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 + -- 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"gui".color = vec4(0, 43/255, 54/255, am.frame_time / 20) + 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)) end + show_hex_coords() end)) win.scene = world end ------ [[ MAIN ]] --------------------------------------------------------------- +--[[============================================================================ + ----- MAIN ----- +==============================================================================]] + +world_init() -init() -show_hex_coords() diff --git a/util.lua b/util.lua index 14dc1cf..cea8767 100644 --- a/util.lua +++ b/util.lua @@ -1,5 +1,5 @@ -function rhue(a) +function terr(a) local R = math.random(35, 75) / 100 local G = math.random(35, 75) / 100 local B = math.random(35, 75) / 100 @@ -11,3 +11,49 @@ end function rmono() return vec4(1, 1, 1, math.random()) 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 +}