diff --git a/res/077-8332_001.jpg b/res/077-8332_001.jpg new file mode 100644 index 0000000..dd08220 Binary files /dev/null and b/res/077-8332_001.jpg differ diff --git a/res/arrow.png b/res/arrow.png new file mode 100644 index 0000000..0073c43 Binary files /dev/null and b/res/arrow.png differ diff --git a/res/marquis.png b/res/marquis.png new file mode 100644 index 0000000..57880d6 Binary files /dev/null and b/res/marquis.png differ diff --git a/res/tower1.png b/res/tower1.png new file mode 100644 index 0000000..10782a8 Binary files /dev/null and b/res/tower1.png differ diff --git a/res/tower2.png b/res/tower2.png new file mode 100644 index 0000000..ec94374 Binary files /dev/null and b/res/tower2.png differ diff --git a/src/color.lua b/src/color.lua index 8f0a2e6..f5d288b 100644 --- a/src/color.lua +++ b/src/color.lua @@ -1,7 +1,7 @@ COLORS = { - TRANSPARENT = vec4(0.4), + TRANSPARENT = vec4(0.6), -- tones WHITE = vec4(0.8, 0.8, 0.7, 1), @@ -21,6 +21,7 @@ COLORS = { PALE_SILVER = vec4(193/255, 178/255, 171/255, 1), CLARET = vec4(139/255, 30/255, 63/255, 1), BISTRO = vec4(73/255, 44/255, 29/255, 1), - DEEP_SPACE_SPARKLE = vec4(61/255, 90/255, 108/255, 1) + DEEP_SPACE_SPARKLE = vec4(61/255, 90/255, 108/255, 1), + WHEAT = vec4(225/255, 202/255, 150/255, 1) } diff --git a/src/extra.lua b/src/extra.lua index 1d64683..bc83b9d 100644 --- a/src/extra.lua +++ b/src/extra.lua @@ -4,7 +4,7 @@ function math.wrapf(float, range) return float - range * math.floor(float / range) end -function math.lerpv2(v1, v2, t) +function math.lerp(v1, v2, t) return v1 * t + v2 * (1 - t) end diff --git a/src/grid.lua b/src/grid.lua index 6e2ea1b..26ca933 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -1,13 +1,15 @@ + require "gui" require "hexyz" HEX_SIZE = 20 -HEX_GRID_WIDTH = 65 -- 65 -HEX_GRID_HEIGHT = 33 -- 33 -HEX_GRID_DIMENSIONS = vec2(HEX_GRID_WIDTH, HEX_GRID_HEIGHT) - +-- with 1920x1080, this is the minimal dimensions to cover the screen (65x33) +-- odd numbers are important because we want a 'true' center +HEX_GRID_WIDTH = 65 +HEX_GRID_HEIGHT = 33 +HEX_GRID_DIMENSIONS = vec2(HEX_GRID_WIDTH, HEX_GRID_HEIGHT) -- leaving y == 0 makes this the center in hex coordinates HEX_GRID_CENTER = vec2(math.floor(HEX_GRID_DIMENSIONS.x/2), 0) @@ -16,51 +18,59 @@ HEX_GRID_CENTER = vec2(math.floor(HEX_GRID_DIMENSIONS.x/2), 0) -- { { elevation, node, etc. } } HEX_MAP = {} -function grid_pixel_dimensions() +local function grid_pixel_dimensions() local hhs = hex_horizontal_spacing(HEX_SIZE) local hvs = hex_vertical_spacing(HEX_SIZE) -- number of 'spacings' on the grid == number of cells - 1 - return vec2((HEX_GRID_DIMENSIONS.x - 1) * hhs - , (HEX_GRID_DIMENSIONS.y - 1) * hvs) + return vec2((HEX_GRID_WIDTH - 1) * hhs + , (HEX_GRID_HEIGHT - 1) * hvs) end GRID_PIXEL_DIMENSIONS = grid_pixel_dimensions() -WORLDSPACE_COORDINATE_OFFSET = -GRID_PIXEL_DIMENSIONS/2 -HEX_GRID_INTERACTABLE_REGION_PADDING = 2 +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, + 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 +function is_passable(tile, mob) + return tile.elevation > -0.5 and tile.elevation < 0.5 +end + -- map elevation to appropriate tile color. function color_at(elevation) if elevation < -0.5 then -- lowest elevation : impassable return COLORS.BLUE_STONE{ a = (elevation + 1.4) / 2 + 0.2 } elseif elevation < 0 then -- med-low elevation : passable - return COLORS.MYRTLE{ a = (elevation + 1.8) / 2 + 0.2 } + return math.lerp(COLORS.MYRTLE, COLORS.BROWN_POD, elevation + 0.5){ a = (elevation + 1.8) / 2 + 0.2 } elseif elevation < 0.5 then -- med-high elevation : passable - return COLORS.BROWN_POD{ a = (elevation + 1.6) / 2 + 0.2 } + return math.lerp(COLORS.MYRTLE, COLORS.BROWN_POD, elevation + 0.5){ a = (elevation + 1.6) / 2 + 0.2 } elseif elevation < 1 then -- highest elevation : impassable return COLORS.BOTTLE_GREEN{ a = (elevation + 1.0) / 2 + 0.2 } else - log('bad elevation') - return vec4(0) + log('bad elevation'); return vec4(0) end end +function grid_neighbours(map, hex) + return table.filter(hex_neighbours(hex), function(_hex) + return map.get(_hex.x, _hex.y) + end) +end + function random_map(seed) - local map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y) + local map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y, seed) math.randomseed(map.seed) local world = am.group():tag"world" @@ -90,9 +100,10 @@ function random_map(seed) for _,hex in pairs(home) do map[hex.x][hex.y].elevation = 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)) end + world:append(am.circle(hex_to_pixel(HEX_GRID_CENTER), HEX_SIZE/2, COLORS.MAGENTA, 4)) + WORLDSPACE_COORDINATE_OFFSET = -GRID_PIXEL_DIMENSIONS/2 return map, am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world:tag"world" end diff --git a/src/gui.lua b/src/gui.lua index b456892..49551de 100644 --- a/src/gui.lua +++ b/src/gui.lua @@ -21,15 +21,15 @@ function register_button_widget(id, rect) local click = false if active and active.id == id then - if win:mouse_released"left" then + if WIN:mouse_released"left" then if hot and hot.id == id then click = true end active = false end elseif hot and hot.id == id then - if win:mouse_pressed"left" then active = { id = id } end + if WIN:mouse_pressed"left" then active = { id = id } end end - if point_in_rect(win:mouse_position(), rect) then set_hot(id) end + if point_in_rect(WIN:mouse_position(), rect) then set_hot(id) end return click end) diff --git a/src/hexyz.lua b/src/hexyz.lua index 6d1605a..e8a993d 100644 --- a/src/hexyz.lua +++ b/src/hexyz.lua @@ -6,8 +6,6 @@ else log("clobbering a math.round function.") end ---============================================================================ --- HEX CONSTANTS AND UTILITY FUNCTIONS -- wherever 'orientation' appears as an argument, use one of these two, or set a default just below ORIENTATION = { @@ -261,6 +259,14 @@ local function map_set(t, x, y, v) return t end +local function map_traverse(t, callback) + for i,_ in pairs(t) do + for _,entry in pairs(t[i]) do + callback(entry) + end + end +end + -- @NOTE probably shouldn't use this... local function map_partial_set(t, x, y, k, v) local entry = map_get(t, x, y) @@ -304,7 +310,8 @@ function parallelogram_map(width, height, seed) seed = seed, get = function(x, y) return map_get(map, x, y) end, set = function(x, y, v) return map_set(map, x, y, v) end, - partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end + partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end, + traverse = function(callback) return map_traverse(map, callback) end }}) end @@ -336,7 +343,8 @@ function triangular_map(size, seed) seed = seed, get = function(x, y) return map_get(map, x, y) end, set = function(x, y, v) return map_set(map, x, y, v) end, - partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end + partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end, + traverse = function(callback) return map_traverse(map, callback) end }}) end @@ -373,7 +381,8 @@ function hexagonal_map(radius, seed) seed = seed, get = function(x, y) return map_get(map, x, y) end, set = function(x, y, v) return map_set(map, x, y, v) end, - partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end + partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end, + traverse = function(callback) return map_traverse(map, callback) end }}) end @@ -408,51 +417,89 @@ function rectangular_map(width, height, seed) seed = seed, get = function(x, y) return map_get(map, x, y) end, set = function(x, y, v) return map_set(map, x, y, v) end, - partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end + partial = function(x, y, k, v) return map_partial_set(map, x, y, k, v) end, + traverse = function(callback) return map_traverse(map, callback) end }}) end --============================================================================ -- PATHFINDING --- @TODO @FIXME -function breadth_first(map, target, neighbour_f) - local neighbour_f = neighbour_f or hex_neighbours - local frontier = { target } +-- maps each hex of |map| to a numeric value, which is its distance from |start| +-- returns this new map +function breadth_first_distance(map, start, neighbour_f) + local neighbour_f = neighbour_f or function(map, hex) return hex_neighbours(hex) end + + local frontier = { start } - local reached = {} - reached[target.x] = {} - reached[target.x][target.y] = true + local distance = {} + distance[start.x] = {} + distance[start.x][start.y] = 0 - while not #frontier == 0 do + while not (#frontier == 0) do local current = table.remove(frontier, 1) - for _,next_ in pairs(neighbour_f(current)) do + for _,next_ in pairs(neighbour_f(map, current)) do + if not map_get(distance, next_.x, next_.y) then + table.insert(frontier, next_) + map_set(distance, next_.x, next_.y, 1 + map_get(distance, current.x, current.y)) + end + end + end + + return setmetatable(distance, { __index = { + get = function(x, y) return map_get(distance, x, y) end + }}) +end + +-- maps each hex of |map| to an adjacent cell that is on the path to |start|, or nil if no path exists +-- returns this new map +function breadth_first_vectorfield(map, start, neighbour_f) + local neighbour_f = neighbour_f or function(map, hex) return hex_neighbours(hex) end + + local frontier = { start } + + local came_from = {} + came_from[start.x] = {} + came_from[start.x][start.y] = false + + while not (#frontier == 0) do + local current = table.remove(frontier, 1) + for _,next_ in pairs(neighbour_f(map, current)) do + if not map_get(came_from, next_.x, next_.y) then + table.insert(frontier, next_) + map_set(came_from, next_.x, next_.y, current) + end end end + + came_from.get = function(x, y) return map_get(came_from, x, y) end + + return came_from end -- generic A* pathfinding --- @NOTE is it better to move the functions to be members of the map? -- --- returns a map that has map[hex.x][hex.y] = 'the vec2 which is the hex you came from when trying to get to |goal|' +-- returns a map that has map[hex.x][hex.y] = { hex = vec2, priority = number }, +-- where the hex is the spot it thinks you should go to from the indexed hex, and priority is the cost of that decision, +-- as well as 'made_it' a bool that tells you if we were successful in reaching |goal| function Astar(map, start, goal, neighbour_f, heuristic_f, cost_f) - local neighbour_f = neighbour_f or hex_neighbours + local neighbour_f = neighbour_f or function(map, hex) return hex_neighbours(hex) end local heuristic_f = heuristic_f or math.distance - local cost_f = cost_f or function() return 1 end + local cost_f = cost_f or function(from, to) return 1 end - local came_from = {} - came_from[start.x] = {} - came_from[start.x][start.y] = false + local path = {} + path[start.x] = {} + path[start.x][start.y] = false local frontier = {} frontier[1] = { hex = start, priority = 0 } - local cost_so_far = {} - cost_so_far[start.x] = {} - cost_so_far[start.x][start.y] = 0 + local path_so_far = {} + path_so_far[start.x] = {} + path_so_far[start.x][start.y] = 0 local made_it = false while not (#frontier == 0) do @@ -463,24 +510,19 @@ function Astar(map, start, goal, neighbour_f, heuristic_f, cost_f) break end - for _,next_ in pairs(neighbour_f(current.hex)) do - local new_cost = map_get(cost_so_far, current.hex.x, current.hex.y) - + cost_f(next_) - local next_cost = map_get(cost_so_far, next_.x, next_.y) + for _,next_ in pairs(neighbour_f(map, current.hex)) do + local new_cost = map_get(path_so_far, current.hex.x, current.hex.y) + cost_f(current, next_) + local next_cost = map_get(path_so_far, next_.x, next_.y) if not next_cost or new_cost < next_cost then - map_set(cost_so_far, next_.x, next_.y, new_cost) + map_set(path_so_far, next_.x, next_.y, new_cost) local priority = new_cost + heuristic_f(goal, next_) table.insert(frontier, { hex = next_, priority = priority }) - map_set(came_from, next_.x, next_.y, current) + map_set(path, next_.x, next_.y, current) end end end - if not made_it then - log(" we didn't make it!") - end - - return came_from, made_it + return path, made_it end diff --git a/src/log.txt b/src/log.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/main.lua b/src/main.lua index 196d80e..1a3ea63 100644 --- a/src/main.lua +++ b/src/main.lua @@ -1,83 +1,108 @@ -math.randomseed(os.time()); math.random(); math.random(); math.random() ---============================================================================ --- Imports +math.randomseed(os.time()) +math.random() +math.random() +math.random() + require "color" require "grid" require "mob" require "tower" - ---============================================================================ -- Globals -win = am.window{ width = 1920, height = 1080 } +WIN = am.window{ width = 1920, height = 1080 } TIME = 0 SCORE = 0 +OFF_SCREEN = vec2(WIN.width * 2) -- random pixel position that is garunteed to be off screen local COORDINATE_DISPLAY_TYPES = { - CENTERED_EVENQ = 0, - EVENQ = 1, - HEX = 2 + CENTERED_EVENQ = 0, + EVENQ = 1, + HEX = 2 } local COORDINATE_DISPLAY_TYPE = COORDINATE_DISPLAY_TYPES.CENTERED_EVENQ - -function game_action(scene) +local function game_action(scene) 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 rounded_mouse = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET 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)) - local tile = HEX_MAP.get(hex.x, hex.y) + local hot = is_interactable(tile, evenq{ y = -evenq.y }) - if win:mouse_pressed"left" then + if WIN:mouse_pressed"left" then + if hot and is_buildable(hex, tile, nil) then + make_tower(hex) + end end - if win:key_pressed"f3" then + if WIN:key_pressed"f3" then COORDINATE_DISPLAY_TYPE = (COORDINATE_DISPLAY_TYPE + 1) % #table.keys(COORDINATE_DISPLAY_TYPES) end + do_tower_updates() do_mob_updates() do_mob_spawning() - if tile and is_interactable(tile, evenq{ y = -evenq.y }) then - win.scene"hex_cursor".center = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET + if tile and hot then + WIN.scene"hex_cursor".center = rounded_mouse else - win.scene"hex_cursor".center = vec2(6969) + WIN.scene"hex_cursor".center = OFF_SCREEN end - win.scene"score".text = string.format("SCORE: %.2f", SCORE) + 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 + str, coords = "evenqc", centered_evenq elseif COORDINATE_DISPLAY_TYPE == COORDINATE_DISPLAY_TYPES.EVENQ then - str, coords = "evenq: ", evenq + str, coords = "evenq", evenq elseif COORDINATE_DISPLAY_TYPE == COORDINATE_DISPLAY_TYPES.HEX then - str, coords = "hex: ", hex + str, coords = "hex", hex end - win.scene"coords".text = string.format("%s%d,%d", str, coords.x, coords.y) + WIN.scene"coords".text = string.format("%d,%d (%s)", coords.x, coords.y, str) end end -function game_scene() - local score = am.translate(win.left + 10, win.top - 20) ^ am.text("", "left"):tag"score" - local coords = am.translate(win.right - 10, win.top - 20) ^ am.text("", "right"):tag"coords" - local hex_cursor = am.circle(vec2(-6969), HEX_SIZE, COLORS.TRANSPARENT, 6):tag"hex_cursor" +local function toolbelt() + local toolbelt_height = hex_height(HEX_SIZE) * 2 + local toolbelt = am.group{ + am.rect(WIN.left, WIN.bottom, WIN.right, WIN.bottom + toolbelt_height, COLORS.TRANSPARENT) + } + + --[[ + local padding = 22 + local size = toolbelt_height - padding + for i = 0, 0 do + toolbelt:append( + am.translate(vec2(size + padding, 0) * i + vec2(WIN.left + padding/3, WIN.bottom + padding/3)) + ^ am.rect(0, 0, size, size, COLORS.BLACK) + ) + end + ]] + + return toolbelt +end + +local function game_scene() + local score = am.translate(WIN.left + 10, WIN.top - 20) ^ am.text("", "left"):tag"score" + local coords = am.translate(WIN.right - 10, WIN.top - 20) ^ am.text("", "right"):tag"coords" + local hex_cursor = am.circle(OFF_SCREEN, HEX_SIZE, COLORS.TRANSPARENT, 6):tag"hex_cursor" - local curtain = am.rect(win.left, win.bottom, win.right, win.top, COLORS.TRUEBLACK) + local curtain = am.rect(WIN.left, WIN.bottom, WIN.right, WIN.top, COLORS.TRUE_BLACK) curtain:action(coroutine.create(function() am.wait(am.tween(curtain, 3, { color = vec4(0) }, am.ease.out(am.ease.hyperbola))) - win.scene:remove(curtain) + WIN.scene:remove(curtain) end)) local world @@ -87,8 +112,9 @@ function game_scene() world, curtain, hex_cursor, + toolbelt(), score, - coords + coords, } scene:action(game_action) @@ -96,10 +122,10 @@ function game_scene() return scene end -function init() +local function init() require "texture" load_textures() - win.scene = am.scale(1) ^ game_scene() + WIN.scene = am.scale(1) ^ game_scene() end init() diff --git a/src/mob.lua b/src/mob.lua index 734f9a0..87cf6d9 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -1,36 +1,44 @@ -MOBS = {} +local MOBS = {} --[[ mob structure: { - TOB - float -- time stamp in seconds of when the mob when spawned + TOB - float -- time stamp in seconds of when the tower was spawned hex - vec2 -- hexagon the mob is on position - vec2 -- true pixel coordinates node - node -- the root graph node for this mob update - function -- function that gets called every frame with itself as an argument + path - 2d table -- map of hexes to other hexes, forms a path + speed - number -- multiplier on distance travelled per frame, up to the update function to use correctly } ]] require "extra" require "sound" -MOB_UPDATES = { + +local MOB_UPDATES = { BEEPER = function(mob, index) mob.hex = pixel_to_hex(mob.position) local frame_target = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y] if frame_target then - mob.position = math.lerpv2(mob.position, hex_to_pixel(frame_target.hex), 0.91) + mob.position = mob.position + math.normalize(hex_to_pixel(frame_target.hex) - mob.position) * mob.speed mob.node.position2d = mob.position - else -- can't find path, or dead - 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) - table.remove(MOBS, index) - win.scene"world":remove(mob.node) + else + if mob.hex == HEX_GRID_CENTER then + WIN.scene"world":action( + am.play(am.sfxr_synth(SOUNDS.EXPLOSION1), false, math.random() + 0.5) + ) + + table.remove(MOBS, index) + WIN.scene"world":remove(mob.node) + else + log("stuck") + end end -- passive animation @@ -43,13 +51,32 @@ MOB_UPDATES = { } -- check if a the tile at |hex| is passable by |mob| -function can_pass_through(mob, hex) +local function mob_can_pass_through(mob, hex) local tile = HEX_MAP.get(hex.x, hex.y) return tile and tile.elevation < 0.5 and tile.elevation > -0.5 end +local function get_mob_path(map, start, goal, mob) + return Astar(map, goal, start, -- goal and start are switched intentionally + -- neighbour function + function(map, hex) + return table.filter(grid_neighbours(map, hex), function(_hex) + return mob_can_pass_through(mob, _hex) + end) + end, + + -- heuristic function + math.distance, + + -- cost function + function(from, to) + return math.abs(map.get(to.x, to.y).elevation) + end + ) +end + -- @FIXME there's a bug here where the position of the spawn hex is sometimes 1 closer to the center than we want -function get_spawn_hex(mob) +local function get_spawn_hex(mob) local spawn_hex repeat -- ensure we spawn on an random tile along the map's edges @@ -73,51 +100,40 @@ function get_spawn_hex(mob) spawn_hex = evenq_to_hex(vec2(x, -y)) local tile = HEX_MAP[spawn_hex.x][spawn_hex.y] - until can_pass_through(mob, spawn_hex) + until mob_can_pass_through(mob, spawn_hex) return spawn_hex end --- -function make_mob() +local function make_mob() local mob = {} mob.TOB = TIME mob.update = MOB_UPDATES.BEEPER mob.hex = get_spawn_hex(mob) mob.position = hex_to_pixel(mob.hex) - mob.path = Astar(HEX_MAP, HEX_GRID_CENTER, mob.hex, - - -- neighbour function - function(hex) - return table.filter(hex_neighbours(hex), function(_hex) - return can_pass_through(mob, _hex) - end) - end, - - -- heuristic function - function(source, target) - return math.distance(source, target) - end, - - -- cost function - function(hex) - return math.abs(HEX_MAP.get(hex.x, hex.y).elevation) - end - ) + mob.path = get_mob_path(HEX_MAP, mob.hex, HEX_GRID_CENTER, mob) + mob.speed = 10 mob.node = am.translate(mob.position) ^ am.scale(2) ^ am.rotate(mob.TOB) ^ pack_texture_into_sprite(TEX_MOB1_1, 20, 20) - win.scene"world":append(mob.node) + WIN.scene"world":append(mob.node) return mob end +function mob_on_hex(hex) + return table.find(MOBS, function(mob) + return mob.hex == hex + end) +end + local SPAWN_CHANCE = 50 function do_mob_spawning() + --if WIN:key_pressed"space" then if math.random(SPAWN_CHANCE) == 1 then table.insert(MOBS, make_mob()) end diff --git a/src/sound.lua b/src/sound.lua index 29ae28c..bbc67b7 100644 --- a/src/sound.lua +++ b/src/sound.lua @@ -1,14 +1,14 @@ SOUNDS = { - EXPLOSION1 = 49179102, -- this slowed sounds metal as fuck - EXPLOSION2 = 19725402, - LASER1 = 79859301, - PUSH1 = 30455908, - BIRD1 = 50838307, - RANDOM1 = 85363309, - RANDOM2 = 15482409, - RANDOM3 = 58658009, - RANDOM4 = 89884209, - RANDOM5 = 36680709 + EXPLOSION1 = 49179102, -- this slowed sounds metal as fuck + EXPLOSION2 = 19725402, + LASER1 = 79859301, + PUSH1 = 30455908, + BIRD1 = 50838307, + RANDOM1 = 85363309, + RANDOM2 = 15482409, + RANDOM3 = 58658009, + RANDOM4 = 89884209, + RANDOM5 = 36680709 } diff --git a/src/texture.lua b/src/texture.lua index 56fa299..296ac99 100644 --- a/src/texture.lua +++ b/src/texture.lua @@ -1,6 +1,13 @@ function load_textures() - TEX_MOB1_1 = am.texture2d("../res/mob1_1.png") + TEX_MARQUIS = am.texture2d("../res/marquis.png") + + TEX_ARROW = am.texture2d("../res/arrow.png") + + TEX_WALL_CLOSED = am.texture2d("../res/wall_closed.png") + TEX_TOWER1 = am.texture2d("../res/tower1.png") + + TEX_MOB1_1 = am.texture2d("../res/mob1_1.png") end function pack_texture_into_sprite(texture, width, height) @@ -12,5 +19,3 @@ function pack_texture_into_sprite(texture, width, height) } end - - diff --git a/src/tower.lua b/src/tower.lua index 79c1ca7..17e6ec3 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -1,15 +1,43 @@ -TOWERS = {} +local TOWERS = {} +--[[ + tower structure: + { + TOB - float -- time stamp in seconds of when the tower was spawned + hex - vec2 -- hexagon the tower is on + position - vec2 -- true pixel coordinates + node - node -- the root graph node for this tower + update - function -- function that gets called every frame with itself as an argument + } +]] + +function is_buildable(hex, tile, tower) + local blocked = mob_on_hex(hex) + return not blocked and is_passable(tile) +end -function is_buildable(tile, tower) +function make_tower(hex) + local tower = {} -end + tower.TOB = TIME + tower.hex = hex + tower.position = hex_to_pixel(tower.hex) + tower.node = am.translate(tower.position) + ^ pack_texture_into_sprite(TEX_TOWER1, 55, 55) + + tower.update = function(_tower) end -function make_tower() + -- make this cell impassable + --HEX_MAP.get(hex.x, hex.y).elevation = 2 + WIN.scene"world":append(tower.node) + + return tower end function do_tower_updates() - + for i,tower in pairs(TOWERS) do + tower.update(tower, i) + end end