Browse Source

Eliminated Layout. Dealing with the Consequences.

master
churchianity 6 years ago
parent
commit
16fcc8ead1
  1. 231
      src/hexyz.lua
  2. 369
      src/main.lua
  3. 16
      src/sprites.lua

231
src/hexyz.lua

@ -1,9 +1,5 @@
--[[============================================================================
----- GENERALLY USEFUL FUNCTIONS -----
============================================================================]]--
-- rounds numbers. would've been cool to have math.round in lua.
-- Rounds Numbers.
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
@ -12,35 +8,40 @@ end
----- HEX CONSTANTS AND UTILITY FUNCTIONS ----- ----- HEX CONSTANTS AND UTILITY FUNCTIONS -----
============================================================================]]-- ============================================================================]]--
-- all possible vector directions from a given hex by edge
local HEX_DIRECTIONS = {vec2( 0 , 1),
vec2( 1 , 0),
vec2( 1 , -1),
vec2( 0 , -1),
vec2(-1 , 0),
vec2(-1 , 1)}
-- Hex Equality - Meant to Operate on two Amulet Vectors (vec2)
function hex_equals(a, b) return a[1] == b[1] and a[2] == b[2] end
function hex_not_equals(a, b) return not hex_equals(a, b) end
-- return hex vector direction via integer index |direction|.
-- All Possible Vector Directions from a Given Hex by Edge
local HEX_DIRECTIONS = {vec2( 0 , 1), vec2( 1 , 0), vec2( 1 , -1),
vec2( 0 , -1), vec2(-1 , 0), vec2(-1 , 1)}
-- Return Hex Vector Direction via Integer Index |direction|.
function hex_direction(direction) function hex_direction(direction)
return HEX_DIRECTIONS[(direction % 6) % 6 + 1] return HEX_DIRECTIONS[(direction % 6) % 6 + 1]
end end
-- return hexagon adjacent to |hex| in integer index |direction|.
-- Return Hexagon Adjacent to |hex| in Integer Index |direction|.
function hex_neighbour(hex, direction) function hex_neighbour(hex, direction)
return hex + HEX_DIRECTIONS[(direction % 6) % 6 + 1] return hex + HEX_DIRECTIONS[(direction % 6) % 6 + 1]
end end
-- return cube coords at location 60deg away to the left; counter-clockwise
-- Return Hex 60deg away to the Left; Counter-Clockwise
function hex_rotate_left(hex) function hex_rotate_left(hex)
return vec2(hex.x + hex.y, -hex.x) return vec2(hex.x + hex.y, -hex.x)
end end
-- return cube coords at location 60deg away to the right; clockwise
-- Return Hex 60deg away to the Right; Clockwise
function hex_rotate_right(hex) function hex_rotate_right(hex)
return vec2(-hex.y, hex.x + hex.y) return vec2(-hex.y, hex.x + hex.y)
end end
-- rounds a float coordinate trio |x, y, z| to nearest integer coordinate trio
-- NOT a General 3D Vector Round - Only Returns a vec2!
local function hex_round(x, y, z) local function hex_round(x, y, z)
local rx = round(x) local rx = round(x)
local ry = round(y) local ry = round(y)
@ -60,66 +61,66 @@ local function hex_round(x, y, z)
return vec2(rx, ry) return vec2(rx, ry)
end end
--[[============================================================================
--[[==========================================================================--
----- ORIENTATION & LAYOUT ----- ----- 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 ),
W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0), W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0),
start_angle = 0.0}
angle = 0.0}
-- forward & inverse matrices used for the pointy orientation
-- Forward & Inverse Matrices used for the Pointy Orientation
local POINTY = {M = mat2(3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0), local POINTY = {M = mat2(3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0),
W = mat2(3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0), W = mat2(3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0),
start_angle = 0.5}
angle = 0.5}
-- stores layout: information that does not pertain to map shape
function layout(origin, size, orientation)
return {origin = origin or vec2(0),
size = size or vec2(11),
orientation = orientation or FLAT}
end
-- hex to screen
function hex_to_pixel(hex, layout)
local M = layout.orientation.M
-- Hex to Screen -- Orientation Must be Either POINTY or FLAT
function hex_to_pixel(hex, size, orientation_M)
local M = orientation_M or FLAT.M
local x = (M[1][1] * hex[1] + M[1][2] * hex[2]) * layout.size[1]
local y = (M[2][1] * hex[1] + M[2][2] * hex[2]) * layout.size[2]
local x = (M[1][1] * hex[1] + M[1][2] * hex[2]) * size[1]
local y = (M[2][1] * hex[1] + M[2][2] * hex[2]) * size[2]
return vec2(x + layout.origin[1], y + layout.origin[2])
return vec2(x, y)
end end
-- screen to hex
function pixel_to_hex(pix, layout)
local W = layout.orientation.W
local pix = (pix - layout.origin) / layout.size
-- Screen to Hex -- Orientation Must be Either POINTY or FLAT
function pixel_to_hex(pix, size, orientation_W)
local W = orientation_W or FLAT.W
local pix = pix / size
local s = W[1][1] * pix[1] + W[1][2] * pix[2]
local t = W[2][1] * pix[1] + W[2][2] * pix[2]
local x = W[1][1] * pix[1] + W[1][2] * pix[2]
local y = W[2][1] * pix[1] + W[2][2] * pix[2]
return hex_round(s, t, -s - t)
return hex_round(x, y, -x - y)
end end
-- TODO test, learn am.draw -- TODO test, learn am.draw
function hex_corner_offset(corner, layout)
local angle = 2.0 * math.pi * layout.orientation.start_angle + corner / 6
return vec2(layout.size[1] * math.cos(angle),
layout.size[2] * math.sin(angle))
function hex_corner_offset(corner, size, orientation_angle)
local angle = 2.0 * math.pi * orientation_angle or FLAT.angle + corner / 6
return vec2(size[1] * math.cos(angle),
size[2] * math.sin(angle))
end end
-- TODO this thing -- TODO this thing
function hex_corners(hex, layout)
function hex_corners(hex, size, orientation)
local corners = {} local corners = {}
end end
-- offset coordinates are prettier to look at
-- Offset Coordinates are Useful for UI-Implementations
function hex_to_offset(hex) function hex_to_offset(hex)
return vec2(hex[1], -hex[1] - hex[2] + (hex[1] + (hex[1] % 2)) / 2) return vec2(hex[1], -hex[1] - hex[2] + (hex[1] + (hex[1] % 2)) / 2)
end end
-- back to cube coordinates -- back to cube coordinates
function offset_to_hex(off) function offset_to_hex(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)
@ -128,7 +129,7 @@ end
--[[============================================================================ --[[============================================================================
----- MAPS & STORAGE ----- ----- MAPS & STORAGE -----
This means, you are not to draw using the coordinates stored in your map.
You are not to draw using the coordinates stored in your map.
You are to draw using the hex_to_pixel of those coordinates. You are to draw using the hex_to_pixel of those coordinates.
If you wish to draw a hexagon to the screen, you must first use hex_to_pixel If you wish to draw a hexagon to the screen, you must first use hex_to_pixel
@ -137,23 +138,21 @@ end
am.circle with |sides| = 6, or gather the vertices with hex_corners and am.circle with |sides| = 6, or gather the vertices with hex_corners and
use am.draw - TODO, haven't used am.draw yet. use am.draw - TODO, haven't used am.draw yet.
Information about the maps' dimensions are stored in a metatable, so you can
retrieve details about maps after they are created.
Maps have metatables containing information about their dimensions, and
seed (if applicable), so you can retrieve information about maps after they
are created.
----- NOISE ----- ----- NOISE -----
To simplify terrain generation, unordered, hash-like maps automatically To simplify terrain generation, unordered, hash-like maps automatically
calculate and store simplex noise as their values. You can modify the nature
of the noise by providing different |frequencies| as a tables of values, for
example: {1, 2, 4, 8} or {1, 0.5, 0.25, 0.125}. These just increase the
complexity of the curvature of the noise. The default is {1}.
calculate and store seeded simplex noise as their values. You can provide
a seed if you wish. The default is a randomized seed.
----- TODO -----
make all functions work regardless of layout. as it stands, they kind
of do, just not always nicely.
TODO Pointy Hex testing and support.
============================================================================]]-- ============================================================================]]--
-- 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)
local map = {} local map = {}
@ -169,7 +168,8 @@ function ring_map(center, radius)
return map return map
end end
-- returns ordered spiral hexagonal map of |radius| rings from |center|.
-- Returns Ordered Spiral Hexagonal Map of |radius| Rings from |center|
function spiral_map(center, radius) function spiral_map(center, radius)
local map = {center} local map = {center}
@ -180,50 +180,52 @@ function spiral_map(center, radius)
return map return map
end end
-- returns unordered parallelogram-shaped map of |width| and |height| with simplex noise
-- Returns Unordered Parallelogram-Shaped Map of |width| and |height| with Simplex Noise
function parallelogram_map(width, height, seed) function parallelogram_map(width, height, seed)
local seed = seed or math.random(width * height) local seed = seed or math.random(width * height)
-- fill the map
local map = {} local map = {}
for i = 0, width do for i = 0, width do
for j = 0, height do for j = 0, height do
-- generate noise
-- Calculate Noise
local idelta = i / width local idelta = i / width
local jdelta = j / height local jdelta = j / height
local noise = 0 local noise = 0
for oct = 1, math.max(width, height) do
noise = noise + 1/4^oct * math.simplex(vec2(idelta + seed * width, jdelta + seed * height) * 2^oct)
for oct = 1, 6 do
local f = 1/4^oct
local l = 2^oct
local pos = vec2(idelta + seed * width, jdelta + seed * height)
noise = noise + f * math.simplex(pos * l)
end end
-- straightforward iteration produces a parallelogram
map[vec2(i, j)] = noise
map[vec2(i, j)] = noise -- Straightforward Iteration Produces a Parallelogram
end end
end end
setmetatable(map, {__index={width=width, height=height, seed=seed}}) setmetatable(map, {__index={width=width, height=height, seed=seed}})
return map return map
end end
-- returns unordered triangular map of |size| with simplex noise
-- Returns Unordered Triangular Map of |size| with Simplex Noise
function triangular_map(size, seed) function triangular_map(size, seed)
local seed = seed or math.random(size) local seed = seed or math.random(size)
-- fill the map
local map = {} local map = {}
for i = 0, size do for i = 0, size do
for j = size - i, size do for j = size - i, size do
-- generate noise
-- Generate Noise
local idelta = i / size local idelta = i / size
local jdelta = j / size local jdelta = j / size
local noise = 0 local noise = 0
for oct = 1, size do
noise = noise + 1/3^oct * math.simplex(vec2(idelta + seed * size, jdelta + seed * size) * 2^oct)
for oct = 1, 6 do
local f = 1/3^oct
local l = 2^oct
local pos = vec2(idelta + seed * size, jdelta + seed * size)
noise = noise + f * math.simplex(pos * l)
end end
map[vec2(i, j)] = noise map[vec2(i, j)] = noise
@ -233,47 +235,61 @@ function triangular_map(size, seed)
return map return map
end end
-- returns unordered hexagonal map of |radius| with simplex noise
-- Returns Unordered Hexagonal Map of |radius| with Simplex Noise
function hexagonal_map(radius, seed) function hexagonal_map(radius, seed)
local seed = seed or math.random(radius * 2)
local seed = seed or math.random(radius * 2 + 1)
-- fill the map
local map = {} local map = {}
for i = -radius, radius do for i = -radius, radius do
local j1 = math.max(-radius, -i - radius) local j1 = math.max(-radius, -i - radius)
local j2 = math.min(radius, -i + radius) local j2 = math.min(radius, -i + radius)
for j = j1, j2 do for j = j1, j2 do
map[vec2(i, j)] = true
-- Calculate Noise
local idelta = i / radius
local jdelta = j / radius
local noise = 0
for oct = 1, 6 do
local f = 2/3^oct -- NOTE, for some reason, I found 2/3 produces better looking noise maps. As far as I am aware, this is weird.
local l = 2^oct
local pos = vec2(idelta + seed * radius, jdelta + seed * radius)
noise = noise + f * math.simplex(pos * l)
end
map[vec2(i, j)] = noise
end end
end end
setmetatable(map, {__index={radius=radius, seed=seed}}) setmetatable(map, {__index={radius=radius, seed=seed}})
return map return map
end end
-- returns unordered rectangular map of |width| and |height| with simplex noise
-- Returns Unordered Rectangular Map of |width| and |height| with Simplex Noise
function rectangular_map(width, height, seed) function rectangular_map(width, height, seed)
local seed = seed or math.random(width * height) local seed = seed or math.random(width * height)
-- fill the map
local map = {} local map = {}
for i = 0, width do for i = 0, width do
for j = 0, height do for j = 0, height do
-- generate noise
-- Calculate Noise
local idelta = i / width local idelta = i / width
local jdelta = j / height local jdelta = j / height
local noise = 0 local noise = 0
for oct = 1, math.max(width, height) do
noise = noise + 2/3^oct * math.simplex(vec2(idelta + seed*width,
jdelta + seed*height
* 2^oct))
end
for oct = 1, 6 do
local f = 2/3^oct
local l = 2^oct
local pos = vec2(idelta + seed * width, jdelta + seed * height)
-- store hex in the map paired with its associated noise value
noise = noise + f * math.simplex(pos * l)
end
-- Store Hex in the Map Paired with its Associated Noise Value
map[vec2(i, j - math.floor(i/2))] = noise map[vec2(i, j - math.floor(i/2))] = noise
end end
end end
@ -281,22 +297,45 @@ function rectangular_map(width, height, seed)
return map return map
end end
--[[============================================================================
----- PATHFINDING -----
--[[==========================================================================--
----- PATHFINDING -----
============================================================================]]-- ============================================================================]]--
-- first try
function search(map, start)
local neighbours
for i = 1, 6 do
neighbours[#neighbours + 1] = hex_neighbour(start, i)
end
end
--[[============================================================================
----- TESTS -----
============================================================================]]--
function test_all()
print("it works trust me")
--
function breadth_first_search(map, start)
local frontier = {start}
local visited = {start = true}
while next(frontier) ~= nil do
local current = next(frontier)
local neighbours
for i = 1, 6 do
neighbours[#neighnours + 1] = hex_neighbour(current, i)
end
for _,n in neighbours do
if visited[n] ~= true then
visited[n] = true
end
end
end
end end

369
src/main.lua

@ -4,11 +4,11 @@ require"hexyz"
math.randomseed(os.time()) math.randomseed(os.time())
--[[============================================================================ --[[============================================================================
----- COLOR CONSTANTS -----
----- GLOBALS -----
============================================================================]]-- ============================================================================]]--
local EIGENGRAU = vec4(0.08, 0.08, 0.11, 1)
-- Ethan Schoonover Solarized Colorscheme
-- Ethan Schoonover Solarized Colorscheme w/ Eigengrau
local EIGENGRAU = vec4(0.08, 0.08, 0.11, 1)
local BASE03 = vec4(0 , 0.16, 0.21, 1) local BASE03 = vec4(0 , 0.16, 0.21, 1)
local BASE02 = vec4(0.02, 0.21, 0.25, 1) local BASE02 = vec4(0.02, 0.21, 0.25, 1)
local BASE01 = vec4(0.34, 0.43, 0.45, 1) local BASE01 = vec4(0.34, 0.43, 0.45, 1)
@ -17,7 +17,7 @@ local BASE0 = vec4(0.51, 0.58, 0.58, 1)
local BASE1 = vec4(0.57, 0.63, 0.63, 1) local BASE1 = vec4(0.57, 0.63, 0.63, 1)
local BASE2 = vec4(0.93, 0.90, 0.83, 1) local BASE2 = vec4(0.93, 0.90, 0.83, 1)
local BASE3 = vec4(0.99, 0.96, 0.89, 1) local BASE3 = vec4(0.99, 0.96, 0.89, 1)
local YELLOW = vec4(0.70, 0.53, 0 , 1)
local YELLOW = vec4(0.70, 0.53, 0, 1)
local ORANGE = vec4(0.79, 0.29, 0.08, 1) local ORANGE = vec4(0.79, 0.29, 0.08, 1)
local RED = vec4(0.86, 0.19, 0.18, 1) local RED = vec4(0.86, 0.19, 0.18, 1)
local MAGENTA = vec4(0.82, 0.21, 0.50, 1) local MAGENTA = vec4(0.82, 0.21, 0.50, 1)
@ -26,179 +26,274 @@ local BLUE = vec4(0.14, 0.54, 0.82, 1)
local CYAN = vec4(0.16, 0.63, 0.59, 1) local CYAN = vec4(0.16, 0.63, 0.59, 1)
local GREEN = vec4(0.52, 0.60, 0 , 1) local GREEN = vec4(0.52, 0.60, 0 , 1)
table.merge(am.ascii_color_map,
{
E = EIGENGRAU,
K = BASE03,
k = BASE02,
L = BASE01,
l = BASE00,
s = BASE0,
S = BASE1,
w = BASE2,
W = BASE3,
Y = YELLOW,
O = ORANGE,
R = RED,
M = MAGENTA,
V = VIOLET,
B = BLUE,
C = CYAN,
G = GREEN
})
local beetle =
[[
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . y . . . . . . . . .
. . . . . . . . y . y . . . . . . . .
. . . . . . . . y y y . . . . . . . .
. . . . . . . y y . y y . . . . . . .
. . . . . . . y y . y y . . . . . . .
. . . . . . y O y O y O y . . . . . .
. . . . . . o O y o y O o . . . . . .
. . o . . o y o O O O o y o . . o . .
. . . o . o W o O O O o W o . o . . .
. . . . o O o O O O O O o O o . . . .
. . . . o o O O O O O O O o o . . . .
. . . . . . o O O O O O o . . . . . .
. . o o o o O o o o o o O o o o o . .
. . . . . o O O o o o O O o o . . . .
. . . . . o O O O o O O O o . . . . .
. . . . . o O O O o O O O o . . . . .
. . . . . . o O O o O O o . . . . . .
. . . . . o o o O o O o o o . . . . .
. . . o o o . . o O o . . o o o . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
]]
--[[============================================================================
----- SETUP -----
============================================================================]]--
local win = am.window local win = am.window
{ {
-- base resolution = 3/4 * WXGA standard 16:10
width = 1280 * 3/4, -- 960px
height = 800 * 3/4, -- 600px
-- Base Resolution = 3/4 * WXGA standard 16:10
width = 1280 * 3/4, -- 960px
height = 800 * 3/4, -- 600px
clear_color = BASE03
clear_color = EIGENGRAU
} }
local map = rectangular_map(45, 31)
local layout = layout(vec2(-268, win.bottom))
local home = hex_to_pixel(vec2(23, 4), layout)
local curtain = am.rect(win.left, win.top, win.right, win.bottom
, vec4(0, 0, 0, 0.7)) -- Color
--local log = io.open(os.date("log %c.txt"), "w")
--[[============================================================================ --[[============================================================================
----- FUNCTIONS -----
----- ROUTINES -----
============================================================================]]-- ============================================================================]]--
-- Template for Buttons
function rect_button(text)
return am.group
{
am.rect(-150, -20, 150, 20, vec4(0)):action(am.tween(1, {color=BASE2{a=0.4}})),
am.text(text, vec4(0)):action(am.tween(1, {color=BASE02}))
}
end
-- --
function text_field(tag)
local field = am.text(""):action(function()
-- Special Cases
if win:key_pressed("backspace") then
field.text = field.text:sub(1, -2)
elseif win:key_pressed("enter") then
field.text = ""
-- I Only Use This To Get Seeds At The Moment
elseif win:key_pressed("0") then field.text = field.text .. 0
elseif win:key_pressed("1") then field.text = field.text .. 1
elseif win:key_pressed("2") then field.text = field.text .. 2
elseif win:key_pressed("3") then field.text = field.text .. 3
elseif win:key_pressed("4") then field.text = field.text .. 4
elseif win:key_pressed("5") then field.text = field.text .. 5
elseif win:key_pressed("6") then field.text = field.text .. 6
elseif win:key_pressed("7") then field.text = field.text .. 7
elseif win:key_pressed("8") then field.text = field.text .. 8
elseif win:key_pressed("9") then field.text = field.text .. 9
end
end)
return field:tag(tag)
end
-- Tween Multiple Nodes of the Same Type
function multitween(nodes, time, values)
for _,node in pairs(nodes) do
node:action(am.tween(time, values))
end
end
-- Returns Appropriate Tile Color for Specified Elevation
function color_at(elevation)
if elevation < -0.5 then -- Lowest Elevation : Impassable
return vec4(0.10, 0.30, 0.40, (elevation + 1.2) / 2)
elseif elevation < 0 then -- Med-Low Elevation : Passable
return vec4(0.10, 0.25, 0.10, (elevation + 1.8) / 2)
elseif elevation < 0.5 then -- Med-High Elevation : Passable
return vec4(0.25, 0.20, 0.10, (elevation + 1.6) / 2)
else -- Highest Elevation : Impassable
return vec4(0.15, 0.30, 0.20, (elevation + 1.0) / 2)
end
end
-- Handler for Scoring
function keep_score() function keep_score()
local offset = am.current_time() local offset = am.current_time()
world:action(function()
world:remove("time")
win.scene:action(function()
win.scene:remove("time")
local time_str = string.format("%.2f", am.current_time() - offset) local time_str = string.format("%.2f", am.current_time() - offset)
world:append(
am.translate(-374, win.top - 10)
^ am.text(time_str):tag"time")
win.scene:append(am.translate(-374, win.top - 10)
^ am.text(time_str):tag"time")
end) end)
end end
-- TODO refactor to something like - poll-mouse or mouse-hover event
function show_coords()
world:action(function()
world:remove("coords")
world:remove("selected")
local hex = pixel_to_hex(win:mouse_position(), layout)
local mouse = hex_to_offset(hex)
-- In-Game Pause Menu
function pause()
win.scene:append(curtain:tag"curtain")
win.scene:append(am.group
{
am.rect(-200, 150, 200, -150, BASE03{a=0.9})
}:tag"menu")
-- check mouse is within bounds of game map
if mouse.x > 0 and mouse.x < map.width and
-mouse.y > 0 and -mouse.y < map.height then -- north is positive
-- Event Handler
win.scene:action(function()
local text = am.text(string.format("%d,%d", mouse.x, mouse.y))
local coords = am.group{
am.translate(win.right - 25, win.top - 10)
^ am.text(string.format("%d,%d", mouse.x,-mouse.y)):tag"coords"}
world:append(coords)
local color = vec4(0, 0, 0, 0.2)
local pix = hex_to_pixel(hex, layout)
world:append(am.circle(pix, layout.size.x, color, 6):tag"selected")
-- Back to Main Game
if win:key_pressed("escape") then
win.scene:remove("curtain"); win.scene:remove("menu")
game_action(); return true
end end
end) end)
end end
-- generate map, no seed means random map
function render_map(seed)
-- setup
world = am.group{}:tag"world"
-- Returns Node
function draw_(map)
local world = am.group():tag"world"
for hex,elevation in pairs(map) do
local off = hex_to_offset(hex)
local mask = vec4(0, 0, 0, math.max(((off.x - 23) / 45) ^ 2,
((-off.y - 16) / 31) ^ 2))
local color = color_at(elevation) - mask
local node = am.circle(hex_to_pixel(hex, vec2(11)), 11, vec4(0), 6)
node:action(am.tween(0.3, {color = color})) -- fade in
world:append(node:tag(tostring(hex))) -- unique identifier
end
return world
end
--
function ghandler(game)
win.scene:remove("coords"); win.scene:remove("selected")
-- Pause Game
if win:key_pressed("escape") then
pause(); return true
end
local hex = pixel_to_hex(win:mouse_position(), vec2(11)) - vec2(10, 10)
local mouse = hex_to_offset(hex)
-- Check if Mouse is Within Bounds of Game Map
if mouse.x > 0 and mouse.x < map.width and
-mouse.y > 0 and -mouse.y < map.height then -- North is Positive
local text = am.text(string.format("%d,%d", mouse.x, mouse.y))
game:append(am.translate(450, 290) ^ text:tag"coords")
local color = vec4(0, 0, 0, 0.4)
local pix = hex_to_pixel(hex, vec2(11))
game:append(am.circle(pix, 11, color, 6):tag"selected")
end
end
-- Begin Game - From Seed or Random Seed (if ommitted)
function game_init(seed)
local game = am.group()
game:append(am.rect(win.left, win.top, -268, win.bottom, BASE03))
map = rectangular_map(45, 31, seed) map = rectangular_map(45, 31, seed)
game:action(ghandler)
win.scene = am.group(am.translate(-268, -300) ^ draw_(map), game)
end
-- render world
world:action(coroutine.create(function()
-- begin map generation
for hex,elevation in pairs(map) do
-- Title Action
function thandler(title)
local mouse = win:mouse_position()
-- determine cell
local color
if mouse.x > -150 and mouse.x < 150 then
-- lowest elevation : impassable
if elevation < -0.5 then
color = vec4(0.10, 0.30, 0.20, (elevation + 1) / 2)
-- Button 1
if mouse.y > -70 and mouse.y < -30 then
-- med-low elevation : passable
elseif elevation < 0 then
color = vec4(0.10, 0.25, 0.10, (elevation + 1.9) / 2)
title"button1""rect":action(am.tween(0.5, {color = BASE2{a=1}}))
-- med-high elevation : passable
elseif elevation< 0.5 then
color = vec4(0.25, 0.20, 0.10, (elevation + 1.9) / 2)
if win:mouse_pressed("left") then
win.scene:action(am.play(am.sfxr_synth(57784609)))
game_init(map.seed)
return true
end
-- highest elevation : impassable
else
color = vec4(0.10, 0.30, 0.20, (elevation + 1) / 2)
-- Button 2
elseif mouse.y > -120 and mouse.y < -80 then
title"button2""rect":action(am.tween(0.5, {color = BASE2{a=1}}))
if win:mouse_pressed("left") then
win.scene:action(am.play(am.sfxr_synth(91266909)))
end end
-- subtly shade edges of map. offset coords are easier to work with
local off = hex_to_offset(hex)
local mask = vec4(0, 0, 0, math.max(((off.x - 23) / 45)^2,
((-off.y - 16) / 31)^2))
color = color - mask
-- Button 3
elseif mouse.y > -170 and mouse.y < -130 then
-- determine hexagon center for drawing
local center = hex_to_pixel(hex, layout)
title"button3""rect":action(am.tween(0.5, {color = BASE2{a=1}}))
if win:mouse_pressed("left") then
local synth_seed = math.random(100000000)
win.scene:action(am.play(am.sfxr_synth(synth_seed)))
print(synth_seed)
end
-- prepend hexagon to screen
world:prepend(am.circle(center, 11, color, 6):tag(tostring(hex)))
-- Button 4
elseif mouse.y > -220 and mouse.y < -180 then
title"button4""rect":action(am.tween(0.5, {color = BASE2{a=1}}))
if win:mouse_pressed("left") then
win.scene:action(am.play(am.sfxr_synth(36002209)))
end
else
multitween({title"button1""rect", title"button2""rect",
title"button3""rect", title"button4""rect"},
0.5, {color = BASE2{a=0.4}})
end end
-- home base
world:append(am.translate(home)
^ am.rotate(0):tag"home_rotate"
^ am.circle(vec2(0), 22, MAGENTA, 5)):tag"home"
world:append(am.scale(5) ^ am.sprite(beetle))
world:action(function()
world"home_rotate".angle = am.frame_time / 5
end)
show_coords() -- mouse-hover events
keep_score() -- scoring
end))
win.scene = world -- make it so
else
multitween({title"button1""rect", title"button2""rect",
title"button3""rect", title"button4""rect"},
0.5, {color = BASE2{a=0.4}})
end
end end
--[[============================================================================
----- MAIN -----
============================================================================]]--
render_map()
-- Setup and Display Title Screen
function title_init()
local title = am.group()
title:append(am.translate(0, -50) ^ rect_button("NEW SCENARIO"):tag"button1")
title:append(am.translate(0, -100) ^ rect_button("LOREMIPSUM"):tag"button2")
title:append(am.translate(0, -150) ^ rect_button("FUN BUTTON"):tag"button3")
title:append(am.translate(0, -200) ^ rect_button("SETTINGS"):tag"button4")
map = hexagonal_map(45)
backdrop = am.scale(1.3) ^ am.rotate(0) ^ draw_(map)
backdrop:action(function()
backdrop"rotate".angle = am.frame_time / 40 + 45
end)
-- Event Handler
title:action(thandler)
win.scene = am.group(backdrop, title)
end
-- Alias
function init()
title_init()
end
--=============================================================================
----- Main -----
init()

16
src/sprites.lua

@ -0,0 +1,16 @@
settings =
[[
.
.
.
.
.
.
.
.
]]
Loading…
Cancel
Save