diff --git a/color.lua b/color.lua index 6f62ab3..37d5eaa 100644 --- a/color.lua +++ b/color.lua @@ -2,6 +2,7 @@ COLORS = { TRANSPARENT = vec4(0.6), + TRANSPARENT1 = vec4(0.4), -- tones WHITE = vec4(1, 1, 0.95, 1), diff --git a/res/thing.aseprite b/res/thing.aseprite new file mode 100644 index 0000000..1e74467 Binary files /dev/null and b/res/thing.aseprite differ diff --git a/res/thing.png b/res/thing.png new file mode 100644 index 0000000..1f33b03 Binary files /dev/null and b/res/thing.png differ diff --git a/src/game.lua b/src/game.lua index dc1a084..8340c2b 100644 --- a/src/game.lua +++ b/src/game.lua @@ -83,6 +83,16 @@ local function get_top_right_display_text(hex, evenq, centered_evenq, display_ty return str end +function alert(message) + WIN.scene:append( + am.scale(3) ^ am.text(message) + :action(coroutine.create(function(self) + am.wait(am.tween(self, 1, { color = vec4(0) })) + WIN.scene:remove(self) + end)) + ) +end + -- initialized later, as part of the init of the toolbelt local function select_tower_type(tower_type) end local function select_toolbelt_button(i) end @@ -170,19 +180,21 @@ local function game_action(scene) if WIN:mouse_pressed"left" then if interactable then if buildable then - local broken, flow_field = making_hex_unwalkable_breaks_flow_field(hex, tile) + local broken, flow_field = building_tower_breaks_flow_field(state.selected_tower_type, hex) local cost = get_tower_cost(state.selected_tower_type) if broken then local node = WIN.scene("cursor"):child(2) node.color = COLORS.CLARET node:action(am.tween(0.1, { color = COLORS.TRANSPARENT })) + alert("breaks flow field") play_sfx(SOUNDS.BIRD2) elseif cost > state.money then local node = WIN.scene("cursor"):child(2) node.color = COLORS.CLARET node:action(am.tween(0.1, { color = COLORS.TRANSPARENT })) + alert("not enough $$$$") play_sfx(SOUNDS.BIRD2) else @@ -259,16 +271,7 @@ end local function make_game_toolbelt() local function toolbelt_button(size, half_size, tower_texture, padding, i, offset, key_name) - local x1 = (size + padding) * i + offset.x - local y1 = offset.y - local x2 = (size + padding) * i + offset.x + size - local y2 = offset.y + size - - register_button_widget("toolbelt_tower_button" .. i - , am.rect(x1, y1, x2, y2) - , function() select_toolbelt_button(i) end) - - return am.translate(vec2(size + padding, 0) * i + offset) + local button = am.translate(vec2(size + padding, 0) * i + offset) ^ am.group{ am.translate(0, half_size) ^ pack_texture_into_sprite(TEXTURES.BUTTON1, size, size), @@ -283,6 +286,20 @@ local function make_game_toolbelt() ^ am.text(key_name, COLORS.BLACK) } } + + local x1 = (size + padding) * i + offset.x - half_size + local y1 = offset.y + local x2 = (size + padding) * i + offset.x + size - half_size + local y2 = offset.y + size + local rect = { x1 = x1, y1 = y1, x2 = x2, y2 = y2 } + + button:action(function(self) + if WIN:mouse_pressed"left" and point_in_rect(WIN:mouse_position(), rect) then + select_toolbelt_button(i) + end + end) + + return button end local toolbelt_height = hex_height(HEX_SIZE) * 2 @@ -362,6 +379,7 @@ local function make_game_toolbelt() end select_tower_type = function(tower_type) + log(tower_type) state.selected_tower_type = tower_type if get_tower_spec(tower_type) then diff --git a/src/grid.lua b/src/grid.lua index 6237e5b..8ce13a8 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -50,6 +50,14 @@ function evenq_is_in_interactable_region(evenq) }) end +function is_water_elevation(elevation) + return elevation < -0.5 +end + +function is_mountain_elevation(elevation) + return elevation >= 0.5 +end + function tile_is_medium_elevation(tile) return tile.elevation >= -0.5 and tile.elevation < 0.5 end @@ -121,18 +129,30 @@ function apply_flow_field(map, flow_field, world) end end -function making_hex_unwalkable_breaks_flow_field(hex, tile) - if not mob_can_pass_through(nil, hex, tile) then - return false - end +function building_tower_breaks_flow_field(tower_type, hex) + local hexes = spiral_map(hex, get_tower_size(tower_type)) + local original_elevations = {} + for _,h in pairs(hexes) do + local tile = state.map.get(h.x, h.y) + + if not mob_can_pass_through(nil, h, tile) then + return false + end + + table.insert(original_elevations, tile.elevation) - local original_elevation = tile.elevation - -- making the tile's elevation very large *should* make it unwalkable - tile.elevation = 999 + -- making the tile's elevation very large *should* make it unwalkable + tile.elevation = 999 + end local flow_field = generate_flow_field(state.map, HEX_GRID_CENTER) local result = not hex_map_get(flow_field, 0, 0) - tile.elevation = original_elevation + log(result) + + for i,h in pairs(hexes) do + state.map.get(h.x, h.y).elevation = original_elevations[i] + end + return result, flow_field end diff --git a/src/tower.lua b/src/tower.lua index b9c5c19..af6e185 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -26,6 +26,7 @@ TOWER_SPECS = { range = 0, fire_rate = 2, size = 0, + height = 1, }, [TOWER_TYPE.HOWITZER] = { name = "Howitzer", @@ -37,6 +38,7 @@ TOWER_SPECS = { range = 10, fire_rate = 4, size = 1, + height = 1, }, [TOWER_TYPE.REDEYE] = { name = "Redeye", @@ -48,6 +50,7 @@ TOWER_SPECS = { range = 12, fire_rate = 1, size = 1, + height = 1, }, [TOWER_TYPE.MOAT] = { name = "Moat", @@ -59,6 +62,7 @@ TOWER_SPECS = { range = 0, fire_rate = 2, size = 0, + height = -1, }, [TOWER_TYPE.RADAR] = { name = "Radar", @@ -70,6 +74,7 @@ TOWER_SPECS = { range = 0, fire_rate = 1, size = 1, + height = 1, }, [TOWER_TYPE.LIGHTHOUSE] = { name = "Lighthouse", @@ -81,6 +86,7 @@ TOWER_SPECS = { range = 8, fire_rate = 1, size = 1, + height = 1, }, } @@ -100,7 +106,7 @@ function get_tower_texture(tower_type) return TOWER_SPECS[tower_type].texture end function get_tower_icon_texture(tower_type) - return TOWER_SPECS[tower_type] and TOWER_SPECS[tower_type].icon_texture + return TOWER_SPECS[tower_type].icon_texture end function get_tower_cost(tower_type) return TOWER_SPECS[tower_type].cost @@ -119,14 +125,15 @@ local function make_tower_sprite(tower_type) return pack_texture_into_sprite(get_tower_texture(tower_type), HEX_PIXEL_WIDTH, HEX_PIXEL_HEIGHT) end +local HEX_FLOWER_DIMENSIONS = vec2(115, 125) local function make_tower_node(tower_type) if tower_type == TOWER_TYPE.REDEYE then return make_tower_sprite(tower_type) elseif tower_type == TOWER_TYPE.HOWITZER then return am.group{ - make_tower_sprite(tower_type), - am.rotate(0) ^ am.sprite("res/cannon1.png") + pack_texture_into_sprite(TEXTURES.HEX_FLOWER, HEX_FLOWER_DIMENSIONS.x, HEX_FLOWER_DIMENSIONS.y), + am.rotate(0) ^ pack_texture_into_sprite(TEXTURES.CANNON1, 100, 100) } elseif tower_type == TOWER_TYPE.LIGHTHOUSE then return am.group{ @@ -168,7 +175,7 @@ end do local tower_cursors = {} for _,i in pairs(TOWER_TYPE) do - local tower_sprite = make_tower_sprite(i) + local tower_sprite = make_tower_node(i) tower_sprite.color = COLORS.TRANSPARENT local coroutine_ = coroutine.create(function(node) @@ -240,23 +247,37 @@ function tower_type_is_buildable_on(hex, tile, tower_type) local blocking_towers = {} local blocking_mobs = {} + local has_water = false + local has_mountain = false + local has_ground = false for _,h in pairs(spiral_map(hex, get_tower_size(tower_type))) do - table.append(blocking_towers, towers_on_hex(hex)) - table.append(blocking_mobs, mobs_on_hex(hex)) - end + table.merge(blocking_towers, towers_on_hex(h)) + table.merge(blocking_mobs, mobs_on_hex(h)) + + local tile = state.map.get(h.x, h.y) + -- this should always be true, unless it is possible to place a tower + -- where part of the tower overflows the edge of the map + if tile then + if is_water_elevation(tile.elevation) then + has_water = true - if WIN:key_down"space" then - log(table.tostring(blocking_towers)) + elseif is_mountain_elevation(tile.elevation) then + has_mountain = true + + else + has_ground = true + end + end end local towers_blocking = table.count(blocking_towers) ~= 0 local mobs_blocking = table.count(blocking_mobs) ~= 0 - local blocked = mobs_blocking or towers_blocking if tower_type == TOWER_TYPE.HOWITZER then if not mobs_blocking and towers_blocking then + -- you can build howitzers on top of walls. blocked = false for _,tower in pairs(blocking_towers) do if tower.type ~= TOWER_TYPE.WALL then @@ -265,10 +286,11 @@ function tower_type_is_buildable_on(hex, tile, tower_type) end end end - return not blocked and tile.elevation >= -0.5 + return not (blocked or has_water) elseif tower_type == TOWER_TYPE.REDEYE then if not mobs_blocking and towers_blocking then + -- you can build redeyes on top of walls blocked = false for _,tower in pairs(blocking_towers) do if tower.type ~= TOWER_TYPE.WALL then @@ -277,7 +299,10 @@ function tower_type_is_buildable_on(hex, tile, tower_type) end end end - return not blocked and tile.elevation > 0.5 + return not blocked + and not has_water + and not has_ground + and has_mountain elseif tower_type == TOWER_TYPE.LIGHTHOUSE then local has_water_neighbour = false @@ -289,7 +314,10 @@ function tower_type_is_buildable_on(hex, tile, tower_type) break end end - return not blocked and tile_is_medium_elevation(tile) and has_water_neighbour + return not blocked + and not has_mountain + and not has_water + and has_water_neighbour elseif tower_type == TOWER_TYPE.WALL then return not blocked and tile_is_medium_elevation(tile) @@ -406,7 +434,6 @@ function update_tower_lighthouse(tower, tower_index) end end -local TOWER_HEIGHT = 1 function make_and_register_tower(hex, tower_type) local tower = make_basic_entity( hex, @@ -423,30 +450,15 @@ function make_and_register_tower(hex, tower_type) tower.last_shot_time = -spec.fire_rate tower.size = spec.size tower.hexes = spiral_map(tower.hex, tower.size) + tower.height = spec.height - if tower_type == TOWER_TYPE.REDEYE then - local tile = state.map.get(hex.x, hex.y) - tile.elevation = tile.elevation + TOWER_HEIGHT - - elseif tower_type == TOWER_TYPE.HOWITZER then - local tile = state.map.get(hex.x, hex.y) - tile.elevation = tile.elevation + TOWER_HEIGHT - tower.props.z = tile.elevation - - elseif tower_type == TOWER_TYPE.LIGHTHOUSE then - tower.perimeter = ring_map(tower.hex, tower.range) - local tile = state.map.get(hex.x, hex.y) - tile.elevation = tile.elevation + TOWER_HEIGHT - - elseif tower_type == TOWER_TYPE.WALL then - state.map.get(hex.x, hex.y).elevation = TOWER_HEIGHT - - elseif tower_type == TOWER_TYPE.MOAT then - state.map.get(hex.x, hex.y).elevation = -TOWER_HEIGHT + for _,h in pairs(tower.hexes) do + local tile = state.map.get(h.x, h.y) + tile.elevation = tile.elevation + tower.height + end - elseif tower_type == TOWER_TYPE.RADAR then - local tile = state.map.get(hex.x, hex.y) - tile.elevation = tile.elevation + TOWER_HEIGHT + if tower.type == TOWER_TYPE.HOWITZER then + tower.props.z = tower.height end register_entity(TOWERS, tower) diff --git a/texture.lua b/texture.lua index 64fd963..070a5a1 100644 --- a/texture.lua +++ b/texture.lua @@ -33,6 +33,8 @@ TEXTURES = { TOWER_LIGHTHOUSE = load_texture("res/tower_lighthouse.png"), TOWER_LIGHTHOUSE_ICON = load_texture("res/tower_lighthouse_icon.png"), + HEX_FLOWER = load_texture("res/thing.png"), + -- mob stuff MOB_BEEPER = load_texture("res/mob_beeper.png"), MOB_SPOODER = load_texture("res/mob_spooder.png"),