diff --git a/.DS_Store b/.DS_Store index 643d1f3..fb090b4 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/NOTES.md b/NOTES.md index d4a32c3..06a58e1 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1,36 +1,34 @@ SEEED 1835 has bad start -todoooos & notes @TODO test optimizing pathfinding via breadth first search/djikstra -i think i want more or less no such thing as 'impassable' terrain - -all mobs always can always traverse everything, though they initially will give the impression that certain tiles are impassable by prefering certain tiles. - -the illusion is likely to be broken when you attempt to fully wall-off an area, and mobs begin deciding to climb over mountains or swim through lakes. this will come at great cost to them, but they will be capable of it - MAP RESOURCES - spawn diamonds or special floating resources that give you bonuses for building on, whether it's score, money, or boosting the effectiveness of the tower you place on top, etc. - killing certain mobs may cause these resources to spawn on the hex they died on towers: -0 - wall +1 - redeye + long-range laser tower + only buildable on mountains and upgraded walls + + upgrades: + ??? + +-1 - wall some fraction of the height of the tallest mountain makes mob pathing more difficult upgrades: - - +height - making the tower taller makes it more difficult/costly for mobs to climb over it - - spikes - mobs take damage when climbing + - fortifications - lets you build some qualifying towers on top of this tower + - spikes - mobs take damage when climbing -1 - moat +-2 - moat some fraction of the depth of the deepest lake makes mob pathing more difficult upgrades: - - +depth - making the moat deeper makes it more difficult/costly for mobs to swim through it - alligators - mobs take damage while swimming - diff --git a/main.lua b/main.lua index 0942906..81eb49f 100644 --- a/main.lua +++ b/main.lua @@ -27,7 +27,7 @@ WIN = am.window{ title = "hexyz", highdpi = true, letterbox = true, - clear_color = COLORS.TRUE_BLACK + clear_color = color_at(0) } OFF_SCREEN = vec2(WIN.width * 2) -- arbitrary pixel position that is garunteed to be off screen @@ -61,8 +61,15 @@ local TRDTS = { } local TRDT = TRDTS.SEED --- a function - get sets later inside toolbelt ---local select_tower_type +local function select_hex(hex) + local tower = tower_on_hex(hex) + local tile = HEX_MAP.get(hex.x, hex.y) + log(tile) +end + +local function can_do_build(hex, tile, tower_type) + return tower_is_buildable_on(hex, tile, SELECTED_TOWER_TYPE) +end local function game_action(scene) if SCORE < 0 then game_end() end @@ -78,13 +85,13 @@ local function game_action(scene) 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 }) + local hot = evenq_is_interactable(evenq{ y = -evenq.y }) do_entity_updates() do_mob_spawning() if WIN:mouse_pressed"left" then - if hot and is_buildable(hex, tile, nil) then + if hot and can_do_build(hex, tile, SELECTED_TOWER_TYPE) then build_tower(hex, SELECTED_TOWER_TYPE) end end @@ -105,6 +112,19 @@ local function game_action(scene) elseif WIN:key_pressed"tab" then select_tower_type((SELECTED_TOWER_TYPE) % #table.keys(TOWER_TYPE) + 1) + + elseif WIN:key_pressed"1" then select_tower_type(TOWER_TYPE.REDEYE) + elseif WIN:key_pressed"2" then select_tower_type(2) + elseif WIN:key_pressed"3" then select_tower_type(3) + elseif WIN:key_pressed"4" then --select_tower_type(4) + elseif WIN:key_pressed"5" then --select_tower_type(5) + elseif WIN:key_pressed"6" then --select_tower_type(6) + elseif WIN:key_pressed"7" then --select_tower_type(7) + elseif WIN:key_pressed"8" then --select_tower_type(8) + elseif WIN:key_pressed"9" then --select_tower_type(9) + elseif WIN:key_pressed"0" then --select_tower_type(10) + elseif WIN:key_pressed"-" then --select_tower_type(1) + elseif WIN:key_pressed"=" then --select_tower_type(1) end if tile and hot then @@ -142,7 +162,7 @@ local function game_action(scene) WIN.scene"coords".text = str end - do_day_night_cycle() + --do_day_night_cycle() end function do_day_night_cycle() @@ -151,11 +171,13 @@ function do_day_night_cycle() end function game_end() - WIN.scene.paused = true -- de-initialize stuff delete_all_entities() + TIME = 0 SCORE = 0 + MONEY = 0 + WORLD = false WIN.scene = am.scale(1) ^ game_scene() end @@ -168,7 +190,6 @@ local function toolbelt() local toolbelt_height = hex_height(HEX_SIZE) * 2 local tower_tooltip = am.translate(WIN.left + 10, WIN.bottom + toolbelt_height + 20) ^ am.text(tower_type_tostring(SELECTED_TOWER_TYPE), "left"):tag"tower_tooltip" - local toolbelt = am.group{ tower_tooltip, am.rect(WIN.left, WIN.bottom, WIN.right, WIN.bottom + toolbelt_height, COLORS.TRANSPARENT) @@ -176,34 +197,53 @@ local function toolbelt() local padding = 15 local size = toolbelt_height - padding - local offset = vec2(WIN.left + padding/3, WIN.bottom + padding/3) + local half_size = size/2 + local offset = vec2(WIN.left + padding*3, WIN.bottom + padding/3) - local keys = { - '1', '2', '3', '4', '5', '6', '7', '9', '0', '-', '=' - } + local tab_button = am.translate(vec2(0, half_size) + offset) + ^ am.group{ + pack_texture_into_sprite(TEX_WIDER_BUTTON1, 54, 32), + pack_texture_into_sprite(TEX_TAB_ICON, 25, 25) + } + toolbelt:append(tab_button) local tower_select_square = ( - am.translate(vec2(size + padding, size/2) + offset) + am.translate(vec2(size + padding, half_size) + offset) ^ am.rect(-size/2-3, -size/2-3, size/2+3, size/2+3, COLORS.SUNRAY) ):tag"tower_select_square" - toolbelt:append(tower_select_square) - local tower_type_values = table.values(TOWER_TYPE) + local tower_type_values = table.values(TOWER_TYPE) + local keys = { '1', '2', '3', '4', '5', '6', '7', '9', '0', '-', '=' } for i = 1, #keys do if tower_type_values[i] then toolbelt:append( am.translate(vec2(size + padding, 0) * i + offset) ^ am.group{ - am.translate(0, size/2) + am.translate(0, half_size) ^ pack_texture_into_sprite(TEX_BUTTON1, size, size), - am.translate(0, size/2) + am.translate(0, half_size) ^ pack_texture_into_sprite(get_tower_texture(tower_type_values[i]), size, size), - am.translate(vec2(size/2)) + am.translate(vec2(half_size)) + ^ am.group{ + pack_texture_into_sprite(TEX_BUTTON1, half_size, half_size), + am.scale(2) + ^ am.text(keys[i], COLORS.BLACK) + } + } + ) + else + toolbelt:append( + am.translate(vec2(size + padding, 0) * i + offset) + ^ am.group{ + am.translate(0, half_size) + ^ pack_texture_into_sprite(TEX_BUTTON1, size, size), + + am.translate(vec2(half_size)) ^ am.group{ - pack_texture_into_sprite(TEX_BUTTON1, size/2, size/2), + pack_texture_into_sprite(TEX_BUTTON1, half_size, half_size), am.scale(2) ^ am.text(keys[i], COLORS.BLACK) } diff --git a/res/.DS_Store b/res/.DS_Store new file mode 100644 index 0000000..a777cea Binary files /dev/null and b/res/.DS_Store differ diff --git a/res/radar.aseprite b/res/radar.aseprite new file mode 100644 index 0000000..3c87221 Binary files /dev/null and b/res/radar.aseprite differ diff --git a/res/radar.png b/res/radar.png new file mode 100644 index 0000000..723affa Binary files /dev/null and b/res/radar.png differ diff --git a/res/tab_icon.png b/res/tab_icon.png new file mode 100644 index 0000000..6849880 Binary files /dev/null and b/res/tab_icon.png differ diff --git a/res/tab_icon.zip b/res/tab_icon.zip new file mode 100644 index 0000000..4169fc7 Binary files /dev/null and b/res/tab_icon.zip differ diff --git a/res/tab_icon/Tab-02.eps b/res/tab_icon/Tab-02.eps new file mode 100644 index 0000000..772c3a5 Binary files /dev/null and b/res/tab_icon/Tab-02.eps differ diff --git a/res/tab_icon/Tab-02.jpg b/res/tab_icon/Tab-02.jpg new file mode 100644 index 0000000..2eb1b4a Binary files /dev/null and b/res/tab_icon/Tab-02.jpg differ diff --git a/res/tab_icon/Tab-02.png b/res/tab_icon/Tab-02.png new file mode 100644 index 0000000..6849880 Binary files /dev/null and b/res/tab_icon/Tab-02.png differ diff --git a/res/tab_icon/Tab-02.svg b/res/tab_icon/Tab-02.svg new file mode 100644 index 0000000..7373085 --- /dev/null +++ b/res/tab_icon/Tab-02.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/res/wider_button1.png b/res/wider_button1.png new file mode 100644 index 0000000..18f51c1 Binary files /dev/null and b/res/wider_button1.png differ diff --git a/sound.lua b/sound.lua index 556262c..4fe595e 100644 --- a/sound.lua +++ b/sound.lua @@ -5,7 +5,8 @@ SOUNDS = { EXPLOSION2 = 19725402, EXPLOSION3 = 69338002, EXPLOSION4 = 92224102, - HIT1 = 25811004, + COIN1 = 10262800, + HIT2 = 25811004, LASER1 = 79859301, LASER2 = 86914201, PUSH1 = 30455908, diff --git a/src/entity.lua b/src/entity.lua index 47b94ec..16b8aa2 100644 --- a/src/entity.lua +++ b/src/entity.lua @@ -21,7 +21,8 @@ function make_basic_entity(hex, node, update, position) -- usually you'll provide a hex and not a position, and the entity will spawn in the center -- of the hex. if you want an entity to exist not at the center of a hex, you can provide a - -- pixel position instead + -- pixel position instead, then the provided hex is ignored and instead we calculate what hex + -- corresponds to the provided pixel position if position then entity.position = position entity.hex = pixel_to_hex(entity.position) @@ -30,8 +31,8 @@ function make_basic_entity(hex, node, update, position) entity.position = hex_to_pixel(hex) end - entity.update = update - entity.node = am.translate(entity.position) ^ node + entity.update = update + entity.node = am.translate(entity.position) ^ node return entity end diff --git a/src/grid.lua b/src/grid.lua index 23370cf..fec3656 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -37,9 +37,9 @@ end -- transform coordinates by this to pretend 0,0 is elsewhere WORLDSPACE_COORDINATE_OFFSET = -HEX_GRID_PIXEL_DIMENSIONS/2 --- the outer edges of the map are not interactable, most action occurs in the center +-- the outer edges of the map are not interactable, most action occurs in the center-ish HEX_GRID_INTERACTABLE_REGION_PADDING = 4 -function is_interactable(tile, evenq) +function evenq_is_interactable(evenq) return point_in_rect(evenq, { x1 = HEX_GRID_INTERACTABLE_REGION_PADDING, x2 = HEX_GRID_WIDTH - HEX_GRID_INTERACTABLE_REGION_PADDING, @@ -48,6 +48,14 @@ function is_interactable(tile, evenq) }) end +local function tile_is_medium_elevation(tile) + return tile.elevation >= -0.5 and tile.elevation < 0.5 +end + +function tilehex_is_buildable(tile, hex) + return tile_is_medium_elevation(tile) and hex ~= HEX_GRID_CENTER +end + -- map elevation to appropriate color function color_at(elevation) if elevation < -0.5 then -- lowest elevation @@ -92,9 +100,15 @@ function random_map(seed) or -evenq.y == 0 or -evenq.y == (HEX_GRID_HEIGHT - 1) then noise = 0 + -- also terraform the center of the grid to be passable + -- very infrequently, but still sometimes it is not medium elevation + elseif i == HEX_GRID_CENTER.x and j == HEX_GRID_CENTER.y then + noise = 0 + else -- scale noise to be closer to 0 the closer we are to the center -- @NOTE i don't know if this 100% of the time makes the center tile passable, but it seems to 99.9+% of the time + -- @NOTE it doesn't. seed: 1835 local nx, ny = evenq.x/HEX_GRID_WIDTH - 0.5, -evenq.y/HEX_GRID_HEIGHT - 0.5 local d = (nx^2 + ny^2)^0.5 / 0.5^0.5 noise = noise * d^0.125 -- arbitrary, seems to work good @@ -124,7 +138,8 @@ function random_map(seed) end end - world:append(am.circle(hex_to_pixel(HEX_GRID_CENTER), HEX_SIZE/2, COLORS.MAGENTA, 4)) + world:append(am.translate(hex_to_pixel(HEX_GRID_CENTER)) + ^ pack_texture_into_sprite(TEX_RADAR1, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y)) return map, am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world end diff --git a/src/hexyz.lua b/src/hexyz.lua index 1bc1c3d..a960a35 100644 --- a/src/hexyz.lua +++ b/src/hexyz.lua @@ -551,9 +551,6 @@ function Astar(map, start, goal, heuristic, cost_f) end end end - if not made_it then - log('aaaa') - end return path, made_it end diff --git a/src/mob.lua b/src/mob.lua index c196af6..1c0935a 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -92,13 +92,11 @@ local function mob_update(mob, mob_index) local frame_target = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y] -- frame_target will be false when we are one hex away from the center, -- or nil if something went wrong - if frame_target == false then + if not frame_target then frame_target = { hex = HEX_GRID_CENTER, priority = 0 } + end - elseif frame_target == nil then - log("bad") - - elseif mob_can_pass_through(mob, frame_target.hex) then + if mob_can_pass_through(mob, frame_target.hex) then -- this is supposed to achieve frame rate independence, but i have no idea if it actually does local rate = 1 + mob.speed * (1/frame_target.priority) / PERF_STATS.avg_fps diff --git a/src/tower.lua b/src/tower.lua index 4ca658e..4df3acf 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -41,8 +41,8 @@ local function make_tower_sprite(tower_type) return pack_texture_into_sprite(texture, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y) elseif tower_type == TOWER_TYPE.WALL then - --return pack_texture_into_sprite(TEX_WALL_CLOSED, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y) - return am.circle(vec2(0), HEX_SIZE, COLORS.VERY_DARK_GRAY, 6) + return pack_texture_into_sprite(TEX_WALL_CLOSED, HEX_PIXEL_SIZE.x + 1, HEX_PIXEL_SIZE.y + 1) + --return am.circle(vec2(0), HEX_SIZE, COLORS.VERY_DARK_GRAY, 6) elseif tower_type == TOWER_TYPE.MOAT then --return pack_texture_into_sprite(TEX_MOAT1, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y) @@ -50,9 +50,26 @@ local function make_tower_sprite(tower_type) end end -function is_buildable(hex, tile, tower) +function tower_on_hex(hex) + return table.find(TOWERS, function(tower) + return tower.hex == hex + end) +end + +function tower_is_buildable_on(hex, tile, tower_type) + if hex == HEX_GRID_CENTER then return false end + local blocked = #mobs_on_hex(hex) ~= 0 - return not blocked and tile.elevation <= 0.5 and tile.elevation > -0.5 + + if tower_type == TOWER_TYPE.REDEYE then + return not blocked and tile.elevation > 0.5 + + elseif tower_type == TOWER_TYPE.WALL then + return not blocked and tile.elevation <= 0.5 and tile.elevation > -0.5 + + elseif tower_type == TOWER_TYPE.MOAT then + return not blocked and tile.elevation <= 0.5 and tile.elevation > -0.5 + end end function update_tower_redeye(tower, tower_index) @@ -94,7 +111,7 @@ function make_and_register_tower(hex, tower_type) get_tower_update_function(tower_type) ) - tower.range = 10 + tower.range = 7 tower.last_shot_time = tower.TOB tower.target_index = false diff --git a/src/tower_spec.lua b/src/tower_spec.lua new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/tower_spec.lua @@ -0,0 +1 @@ + diff --git a/src/tower_spec.luaa b/src/tower_spec.luaa new file mode 100644 index 0000000..5985dd6 --- /dev/null +++ b/src/tower_spec.luaa @@ -0,0 +1,12 @@ + + +REDEYE = { + + + + + + +} + + diff --git a/texture.lua b/texture.lua index 468c6cd..34b051d 100644 --- a/texture.lua +++ b/texture.lua @@ -4,9 +4,12 @@ function load_textures() TEX_MARQUIS = am.texture2d("res/marquis.png") TEX_BUTTON1 = am.texture2d("res/button1.png") + TEX_WIDER_BUTTON1 = am.texture2d("res/wider_button1.png") + TEX_TAB_ICON = am.texture2d("res/tab_icon.png") TEX_ARROW = am.texture2d("res/arrow.png") + TEX_RADAR1 = am.texture2d("res/radar.png") TEX_WALL_CLOSED = am.texture2d("res/wall_closed.png") TEX_MOAT1 = am.texture2d("res/moat1.png") TEX_TOWER1 = am.texture2d("res/tower1.png")