diff --git a/lib/texture.lua b/lib/texture.lua index 0628236..67a497c 100644 --- a/lib/texture.lua +++ b/lib/texture.lua @@ -44,6 +44,8 @@ TEXTURES = { SELECT_BOX = load_texture("select_box.png"), + TOWER_WALL0 = load_texture("wall0.png"), + -- tower stuff TOWER_WALL = load_texture("tower_wall.png"), TOWER_WALL_ICON = load_texture("tower_wall_icon.png"), diff --git a/main.lua b/main.lua index 2caeec5..26da753 100644 --- a/main.lua +++ b/main.lua @@ -45,6 +45,7 @@ TRDTS = { PERF = 5, SEED = 6, TILE = 7, + MOUSE = 8 } function make_top_right_display_node() diff --git a/res/img/wall0.png b/res/img/wall0.png new file mode 100644 index 0000000..2bf5ef8 Binary files /dev/null and b/res/img/wall0.png differ diff --git a/src/game.lua b/src/game.lua index c5c025d..6f361ef 100644 --- a/src/game.lua +++ b/src/game.lua @@ -120,6 +120,9 @@ local function get_top_right_display_text(hex, evenq, centered_evenq, display_ty elseif display_type == TRDTS.TILE then str = table.tostring(hex_map_get(game_state.map, hex)) + + elseif display_type == TRDTS.MOUSE then + str = win:mouse_position() end return str end @@ -682,7 +685,7 @@ local function game_scene() -- dangling actions run before the main action scene:late_action(game_action) - play_track(SOUNDS.MAIN_THEME) + --play_track(SOUNDS.MAIN_THEME) return scene end @@ -727,7 +730,7 @@ function game_end() gui_alert(string.format( "\nmobs spawned: %d\ntowers built: %d\nprojectiles spawned: %d\n", - hmob, htower, hprojectile + hmob or 0, htower or 0, hprojectile or 0 ), COLORS.WHITE, 1000) game_state = {} diff --git a/src/hexyz.lua b/src/hexyz.lua index a121483..fcaae73 100644 --- a/src/hexyz.lua +++ b/src/hexyz.lua @@ -19,25 +19,28 @@ HEX_ORIENTATION = { 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), - angle = 0.0 + angle = 30 -- degrees }, -- Forward & Inverse Matrices used for the Pointy Orientation 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), - angle = 0.5 + angle = 0 -- degrees } } -- whenever |orientation| appears as an argument, if it isn't provided, this is used instead. -- this is useful because most of the time you will only care about one orientation local HEX_DEFAULT_ORIENTATION = HEX_ORIENTATION.FLAT +-- if you need to dynamically calculate the default hexagon orientation (or use a non-standard one), you can pass it here +function hex_set_default_orientation(orientation) + HEX_DEFAULT_ORIENTATION = orientation +end -- whenever |size| for a hexagon appears as an argument, if it isn't provided, use this -- 'size' here is distance from the centerpoint to any vertex in pixel local HEX_DEFAULT_SIZE = vec2(26) - --- if you need to dynamically calculate the default hexagon size, you can pass it here after +-- if you need to dynamically calculate the default hexagon size, you can pass it here function hex_set_default_size(size) HEX_DEFAULT_SIZE = size end @@ -170,21 +173,21 @@ function pixel_to_hex(pix, size, orientation) return hex_round(x, y, -x - y) end --- TODO test, learn am.draw -function hex_corner_offset(corner, size, orientation) +-- you should provide |center| in pixels, not hexes, or any other coordinate system +function hex_corner_offset(center, corner, size, orientation) local orientation = orientation or HEX_DEFAULT_ORIENTATION - local angle = 2.0 * math.pi * orientation.angle + corner / 6 - return vec2(size[1] * math.cos(angle), size[2] * math.sin(angle)) + local size = size or HEX_DEFAULT_SIZE + local angle_rad = math.rad((60 * corner) - orientation.angle) + return vec2(center[1] + size[1] * math.cos(angle_rad), center[2] + size[2] * math.sin(angle_rad)) end --- TODO test this thing -function hex_corners(hex, size, orientation) +function hex_corners(hex, center, size, orientation) local orientation = orientation or HEX_DEFAULT_ORIENTATION + local size = size or HEX_DEFAULT_SIZE local corners = {} - local center = hex_to_pixel(hex, size, orientation) - for i = 0, 5 do - local offset = hex_corner_offset(i, size, orientation) - table.insert(corners, center + offset) + for i = 1, 6 do + local offset = hex_corner_offset(center, i, size, orientation) + table.insert(corners, offset) end return corners end diff --git a/src/tower.lua b/src/tower.lua index ae53ec2..9e676ae 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -75,8 +75,47 @@ function init_tower_specs() range = 0, fire_rate = 2, update_f = false, - make_node_f = function(self) - return am.circle(vec2(0), HEX_SIZE, COLORS.TAN1{a=0.6}, 6) + make_node_f = function(self, hex, cause_repaint) + local group = am.group(am.circle(vec2(0), HEX_SIZE, COLORS.VERY_DARK_GRAY, 6)) + if not hex then + -- should only happen when making the hex-cursor for the wall + return group + end + + local wall_neighbours = {} + local lines = am.rotate(math.rad(-30)) ^ am.group() + for i,n in pairs(hex_neighbours(hex)) do + local no_towers_adjacent = true + for _,t in pairs(towers_on_hex(n)) do + no_towers_adjacent = false + break + end + + if no_towers_adjacent then + local center = hex_to_pixel(hex, vec2(HEX_SIZE)) + lines:append(am.circle(center, 4, COLORS.WATER)) + local p1 = hex_corner_offset(center, i) + local j = i == 6 and 1 or i + 1 + local p2 = hex_corner_offset(center, j) + lines:append( + am.line(p1, p2, 3, vec4(1, 0, 0, 1)) + ) + end + end + + group:append(lines) + + if cause_repaint then + -- building a wall could change the adjacency between other walls, so we have to re-render them + -- (or atleast check if we need to) + for _,t in pairs(game_state.towers) do + if not t.completed_render and t.type == TOWER_TYPE.WALL then + t.node:replace("group", t.make_node_f(t, t.hex, false)) + end + end + end + + return group end }, { @@ -451,6 +490,8 @@ function tower_deserialize(json_string) return tower end +-- note that the table returned has towers at their index into the global towers table, +-- so #t will often not work correctly (the table will often be sparse) function towers_on_hex(hex) local t = {} for tower_index,tower in pairs(game_state.towers) do @@ -524,7 +565,7 @@ function make_and_register_tower(hex, tower_type) table.merge(tower, spec) tower.type = tower_type - tower.node = am.translate(tower.position) ^ tower.make_node_f(tower) + tower.node = am.translate(tower.position) ^ tower.make_node_f(tower, hex, true) -- initialize each weapons' last shot time to the negation of the fire rate - -- this lets the tower fire immediately upon being placed @@ -539,18 +580,19 @@ function make_and_register_tower(hex, tower_type) tower.hexes = hex_spiral_map(tower.hex, tower.size - 1) end - -- should we be permuting the map here? - for _,h in pairs(tower.hexes) do - local tile = hex_map_get(game_state.map, h.x, h.y) - tile.elevation = tile.elevation + tower.height - end - register_entity(game_state.towers, tower) return tower end function build_tower(hex, tower_type) local tower = make_and_register_tower(hex, tower_type) + + -- modify the hexes the tower sits atop to be impassable (actually just taller by the tower's height value) + for _,h in pairs(tower.hexes) do + local tile = hex_map_get(game_state.map, h.x, h.y) + tile.elevation = tile.elevation + tower.height + end + vplay_sfx(SOUNDS.EXPLOSION4) return tower