Browse Source

stuff

master
Nicholas Hayashi 4 years ago
parent
commit
3754dabc2d
  1. 2
      src/color.lua
  2. 9
      src/extra.lua
  3. 33
      src/grid.lua
  4. 40
      src/hexyz.lua
  5. 52
      src/main.lua
  6. 9
      src/math.lua
  7. 23
      src/mob.lua
  8. 11
      src/texture.lua
  9. 15
      src/tower.lua
  10. 10
      src/util.lua

2
src/color.lua

@ -6,7 +6,7 @@ COLORS = {
-- tones -- tones
WHITE = vec4(0.8, 0.8, 0.7, 1), WHITE = vec4(0.8, 0.8, 0.7, 1),
BLACK = vec4(0, 0, 0, 1), BLACK = vec4(0, 0, 0, 1),
TRUEBLACK = vec4(0, 0, 0, 1),
TRUE_BLACK = vec4(0, 0, 0, 1),
-- hues -- hues
BLUE_STONE = vec4(0.12, 0.3, 0.3, 1), BLUE_STONE = vec4(0.12, 0.3, 0.3, 1),

9
src/table.lua → src/extra.lua

@ -1,4 +1,13 @@
function math.wrapf(float, range)
return float - range * math.floor(float / range)
end
function math.lerpv2(v1, v2, t)
return v1 * t + v2 * (1 - t)
end
function table.rchoice(t) function table.rchoice(t)
return t[math.floor(math.random() * #t) + 1] return t[math.floor(math.random() * #t) + 1]
end end

33
src/grid.lua

@ -1,4 +1,5 @@
require "gui"
require "hexyz" require "hexyz"
HEX_SIZE = 20 HEX_SIZE = 20
@ -6,11 +7,13 @@ HEX_GRID_WIDTH = 65 -- 65
HEX_GRID_HEIGHT = 33 -- 33 HEX_GRID_HEIGHT = 33 -- 33
HEX_GRID_DIMENSIONS = vec2(HEX_GRID_WIDTH, HEX_GRID_HEIGHT) HEX_GRID_DIMENSIONS = vec2(HEX_GRID_WIDTH, HEX_GRID_HEIGHT)
-- this is in hex coordinates
-- leaving y == 0 makes this the center in hex coordinates
HEX_GRID_CENTER = vec2(math.floor(HEX_GRID_DIMENSIONS.x/2), 0) HEX_GRID_CENTER = vec2(math.floor(HEX_GRID_DIMENSIONS.x/2), 0)
-- index is hex coordinates [x][y] -- index is hex coordinates [x][y]
-- { { elevation, sprite, tile } }
-- { { elevation, node, etc. } }
HEX_MAP = {} HEX_MAP = {}
function grid_pixel_dimensions() function grid_pixel_dimensions()
@ -25,9 +28,15 @@ end
GRID_PIXEL_DIMENSIONS = grid_pixel_dimensions() GRID_PIXEL_DIMENSIONS = grid_pixel_dimensions()
WORLDSPACE_COORDINATE_OFFSET = -GRID_PIXEL_DIMENSIONS/2 WORLDSPACE_COORDINATE_OFFSET = -GRID_PIXEL_DIMENSIONS/2
-- convience function for when getting a tile at x,y could fail
function get_tile(x, y)
return HEX_MAP[x] and HEX_MAP[x][y]
HEX_GRID_INTERACTABLE_REGION_PADDING = 2
function is_interactable(tile, evenq)
return point_in_rect(evenq, {
x1 = HEX_GRID_INTERACTABLE_REGION_PADDING,
x2 = HEX_GRID_WIDTH - HEX_GRID_INTERACTABLE_REGION_PADDING,
y1 = HEX_GRID_INTERACTABLE_REGION_PADDING,
y2 = HEX_GRID_HEIGHT - HEX_GRID_INTERACTABLE_REGION_PADDING
})
end end
-- map elevation to appropriate tile color. -- map elevation to appropriate tile color.
@ -43,17 +52,16 @@ function color_at(elevation)
elseif elevation < 1 then -- highest elevation : impassable elseif elevation < 1 then -- highest elevation : impassable
return COLORS.BOTTLE_GREEN{ a = (elevation + 1.0) / 2 + 0.2 } return COLORS.BOTTLE_GREEN{ a = (elevation + 1.0) / 2 + 0.2 }
else else
log('bad elevation') log('bad elevation')
return vec4(0) return vec4(0)
end end
end end
function random_map(seed, do_seed_rng)
local map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y, 105)
--log(map.seed)
if do_seed_rng then math.randomseed(elevation_map.seed) end
function random_map(seed)
local map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y)
math.randomseed(map.seed)
local world = am.group():tag"world" local world = am.group():tag"world"
for i,_ in pairs(map) do for i,_ in pairs(map) do
@ -67,8 +75,7 @@ function random_map(seed, do_seed_rng)
map.set(i, j, { map.set(i, j, {
elevation = noise, elevation = noise,
sprite = node,
tile = {}
node = node
}) })
world:append(node) world:append(node)
@ -82,7 +89,7 @@ function random_map(seed, do_seed_rng)
local home = spiral_map(HEX_GRID_CENTER, 3) local home = spiral_map(HEX_GRID_CENTER, 3)
for _,hex in pairs(home) do for _,hex in pairs(home) do
map[hex.x][hex.y].elevation = 0 map[hex.x][hex.y].elevation = 0
map[hex.x][hex.y].sprite.color = color_at(0)
map[hex.x][hex.y].node.color = color_at(0)
world:append(am.circle(hex_to_pixel(vec2(hex.x, hex.y)), HEX_SIZE/2, COLORS.MAGENTA, 4)) world:append(am.circle(hex_to_pixel(vec2(hex.x, hex.y)), HEX_SIZE/2, COLORS.MAGENTA, 4))
end end

40
src/hexyz.lua

@ -1,5 +1,10 @@
if not math.round then
math.round = function(n) return math.floor(n + 0.5) end math.round = function(n) return math.floor(n + 0.5) end
else
log("clobbering a math.round function.")
end
--============================================================================ --============================================================================
-- HEX CONSTANTS AND UTILITY FUNCTIONS -- HEX CONSTANTS AND UTILITY FUNCTIONS
@ -93,11 +98,13 @@ HEX_DIRECTIONS = { vec2( 1 , -1), vec2( 1 , 0), vec2(0 , 1),
-- Return Hex Vector Direction via Integer Index |direction| -- Return Hex Vector Direction via Integer Index |direction|
function hex_direction(direction) function hex_direction(direction)
return HEX_DIRECTIONS[(direction % 6) % 6 + 1] end
return HEX_DIRECTIONS[(direction % 6) % 6 + 1]
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] end
return hex + HEX_DIRECTIONS[(direction % 6) % 6 + 1]
end
-- Collect All 6 Neighbours in a Table -- Collect All 6 Neighbours in a Table
function hex_neighbours(hex) function hex_neighbours(hex)
@ -109,6 +116,7 @@ function hex_neighbours(hex)
end end
-- Returns a vec2 Which is the Nearest |x, y| to Float Trio |x, y, z| -- Returns a vec2 Which is the Nearest |x, y| to Float Trio |x, y, z|
-- assumes you have a working math.round function (should be guarded at top of this file)
local function hex_round(x, y, z) local function hex_round(x, y, z)
local rx = math.round(x) local rx = math.round(x)
local ry = math.round(y) local ry = math.round(y)
@ -238,11 +246,11 @@ function spiral_map(center, radius)
return setmetatable(map, {__index={center=center, radius=radius}}) return setmetatable(map, {__index={center=center, radius=radius}})
end end
function map_get(t, x, y)
local function map_get(t, x, y)
return t[x] and t[x][y] return t[x] and t[x][y]
end end
function map_set(t, x, y, v)
local function map_set(t, x, y, v)
if t[x] then if t[x] then
t[x][y] = v t[x][y] = v
else else
@ -253,7 +261,8 @@ function map_set(t, x, y, v)
return t return t
end end
function map_partial_set(t, x, y, k, v)
-- @NOTE probably shouldn't use this...
local function map_partial_set(t, x, y, k, v)
local entry = map_get(t, x, y) local entry = map_get(t, x, y)
if not entry then if not entry then
@ -406,6 +415,25 @@ end
--============================================================================ --============================================================================
-- PATHFINDING -- PATHFINDING
-- @TODO @FIXME
function breadth_first(map, target, neighbour_f)
local neighbour_f = neighbour_f or hex_neighbours
local frontier = { target }
local reached = {}
reached[target.x] = {}
reached[target.x][target.y] = true
while not #frontier == 0 do
local current = table.remove(frontier, 1)
for _,next_ in pairs(neighbour_f(current)) do
end
end
end
-- generic A* pathfinding -- generic A* pathfinding
-- @NOTE is it better to move the functions to be members of the map? -- @NOTE is it better to move the functions to be members of the map?
-- --
@ -453,6 +481,6 @@ function Astar(map, start, goal, neighbour_f, heuristic_f, cost_f)
log(" we didn't make it!") log(" we didn't make it!")
end end
return came_from
return came_from, made_it
end end

52
src/main.lua

@ -6,38 +6,67 @@ math.randomseed(os.time()); math.random(); math.random(); math.random()
require "color" require "color"
require "grid" require "grid"
require "mob" require "mob"
require "math"
require "table"
require "tower"
--============================================================================ --============================================================================
-- Globals -- Globals
win = am.window{ width = 1920, height = 1080 }
TIME = 0 TIME = 0
SCORE = 0
win = am.window{ width = 1920, height = 1080 }
local COORDINATE_DISPLAY_TYPES = {
CENTERED_EVENQ = 0,
EVENQ = 1,
HEX = 2
}
local COORDINATE_DISPLAY_TYPE = COORDINATE_DISPLAY_TYPES.CENTERED_EVENQ
function game_action(scene) function game_action(scene)
TIME = am.current_time() TIME = am.current_time()
SCORE = TIME
local mouse = win:mouse_position() local mouse = win:mouse_position()
local hex = pixel_to_hex(mouse - WORLDSPACE_COORDINATE_OFFSET) local hex = pixel_to_hex(mouse - WORLDSPACE_COORDINATE_OFFSET)
local _off = hex_to_evenq(hex)
local off = _off{ y = -_off.y } - vec2(math.floor(HEX_GRID_WIDTH/2)
local evenq = hex_to_evenq(hex)
local centered_evenq = evenq{ y = -evenq.y } - vec2(math.floor(HEX_GRID_WIDTH/2)
, math.floor(HEX_GRID_HEIGHT/2)) , math.floor(HEX_GRID_HEIGHT/2))
local tile = get_tile(hex.x, hex.y)
if tile and win:mouse_pressed"left" then
local tile = HEX_MAP.get(hex.x, hex.y)
if win:mouse_pressed"left" then
end end
if win:key_pressed"f1" then end
if win:key_pressed"f3" then
COORDINATE_DISPLAY_TYPE = (COORDINATE_DISPLAY_TYPE + 1) % #table.keys(COORDINATE_DISPLAY_TYPES)
end
do_mob_updates() do_mob_updates()
do_mob_spawning() do_mob_spawning()
-- draw stuff
if tile and is_interactable(tile, evenq{ y = -evenq.y }) then
win.scene"hex_cursor".center = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET win.scene"hex_cursor".center = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET
win.scene"score".text = string.format("SCORE: %.2f", TIME)
win.scene"coords".text = string.format("%d,%d", hex.x, hex.y)
else
win.scene"hex_cursor".center = vec2(6969)
end
win.scene"score".text = string.format("SCORE: %.2f", SCORE)
do
local str, coords
if COORDINATE_DISPLAY_TYPE == COORDINATE_DISPLAY_TYPES.CENTERED_EVENQ then
str, coords = "evenqc: ", centered_evenq
elseif COORDINATE_DISPLAY_TYPE == COORDINATE_DISPLAY_TYPES.EVENQ then
str, coords = "evenq: ", evenq
elseif COORDINATE_DISPLAY_TYPE == COORDINATE_DISPLAY_TYPES.HEX then
str, coords = "hex: ", hex
end
win.scene"coords".text = string.format("%s%d,%d", str, coords.x, coords.y)
end
end end
function game_scene() function game_scene()
@ -52,7 +81,6 @@ function game_scene()
end)) end))
local world local world
HEX_MAP, world = random_map() HEX_MAP, world = random_map()
local scene = am.group{ local scene = am.group{

9
src/math.lua

@ -1,9 +0,0 @@
function math.wrapf(float, range)
return float - range * math.floor(float / range)
end
function math.lerpv2(v1, v2, t)
return v1 * t + v2 * (1 - t)
end

23
src/mob.lua

@ -4,34 +4,33 @@ MOBS = {}
--[[ --[[
mob structure: mob structure:
{ {
position - vec2 -- true pixel coordinates
TOB - float -- time stamp in seconds of when the mob when spawned TOB - float -- time stamp in seconds of when the mob when spawned
hex - vec2 -- hexagon the mob is on
position - vec2 -- true pixel coordinates
node - node -- the root graph node for this mob node - node -- the root graph node for this mob
hex - vec2 -- hexagon the mob is on top of
update - function -- the function that gets called every frame
update - function -- function that gets called every frame with itself as an argument
} }
]] ]]
require "extra"
require "sound" require "sound"
require "util"
MOB_UPDATES = { MOB_UPDATES = {
BEEPER = function(mob, index) BEEPER = function(mob, index)
mob.hex = pixel_to_hex(mob.position - WORLDSPACE_COORDINATE_OFFSET)
mob.hex = pixel_to_hex(mob.position)
local frame_target = map_get(mob.path, mob.hex.x, mob.hex.y)
local frame_target = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y]
if frame_target then if frame_target then
mob.position = math.lerpv2(mob.position, hex_to_pixel(frame_target.hex) + WORLDSPACE_COORDINATE_OFFSET, 0.91)
mob.position = math.lerpv2(mob.position, hex_to_pixel(frame_target.hex), 0.91)
mob.node.position2d = mob.position mob.node.position2d = mob.position
-- can't find path, or dead
else
else -- can't find path, or dead
win.scene:action(am.play(am.sfxr_synth(SOUNDS.EXPLOSION1), false, math.random() + 0.5)) win.scene:action(am.play(am.sfxr_synth(SOUNDS.EXPLOSION1), false, math.random() + 0.5))
local i,v = table.find(MOBS, function(_mob) return _mob == mob end) local i,v = table.find(MOBS, function(_mob) return _mob == mob end)
table.remove(MOBS, index) table.remove(MOBS, index)
win.scene:remove(mob.node)
win.scene"world":remove(mob.node)
end end
-- passive animation -- passive animation
@ -86,7 +85,7 @@ function make_mob()
mob.TOB = TIME mob.TOB = TIME
mob.update = MOB_UPDATES.BEEPER mob.update = MOB_UPDATES.BEEPER
mob.hex = get_spawn_hex(mob) mob.hex = get_spawn_hex(mob)
mob.position = hex_to_pixel(mob.hex) + WORLDSPACE_COORDINATE_OFFSET
mob.position = hex_to_pixel(mob.hex)
mob.path = Astar(HEX_MAP, HEX_GRID_CENTER, mob.hex, mob.path = Astar(HEX_MAP, HEX_GRID_CENTER, mob.hex,
-- neighbour function -- neighbour function
@ -112,7 +111,7 @@ function make_mob()
^ am.rotate(mob.TOB) ^ am.rotate(mob.TOB)
^ pack_texture_into_sprite(TEX_MOB1_1, 20, 20) ^ pack_texture_into_sprite(TEX_MOB1_1, 20, 20)
win.scene:append(mob.node)
win.scene"world":append(mob.node)
return mob return mob
end end

11
src/texture.lua

@ -3,3 +3,14 @@ function load_textures()
TEX_MOB1_1 = am.texture2d("../res/mob1_1.png") TEX_MOB1_1 = am.texture2d("../res/mob1_1.png")
end end
function pack_texture_into_sprite(texture, width, height)
return am.sprite{
texture = texture,
s1 = 0, s2 = 1, t1 = 0, t2 = 1,
x1 = 0, x2 = width, width = width,
y1 = 0, y2 = height, height = height
}
end

15
src/tower.lua

@ -0,0 +1,15 @@
TOWERS = {}
function is_buildable(tile, tower)
end
function make_tower()
end
function do_tower_updates()
end

10
src/util.lua

@ -1,10 +0,0 @@
function pack_texture_into_sprite(texture, width, height)
return am.sprite{
texture = texture,
s1 = 0, s2 = 1, t1 = 0, t2 = 1,
x1 = 0, x2 = width, width = width,
y1 = 0, y2 = height, height = height
}
end
Loading…
Cancel
Save