diff --git a/color.lua b/color.lua index 1c60a36..b1c1072 100644 --- a/color.lua +++ b/color.lua @@ -10,7 +10,7 @@ COLORS = { TRUE_BLACK = vec4(0, 0, 0, 1), -- non-standard hues - WATER = vec4(0.12, 0.3, 0.3, 1), + WATER = vec4(0.12, 0.25, 0.3, 1), GRASS = vec4(0.10, 0.25, 0.10, 1), DIRT = vec4(0.22, 0.20, 0.10, 1), MOUNTAIN = vec4(0.95, 0.30, 0.20, 1), diff --git a/main.lua b/main.lua index 77b7069..5bfb59a 100644 --- a/main.lua +++ b/main.lua @@ -27,7 +27,7 @@ WIN = am.window{ title = "hexyz", highdpi = true, letterbox = true, - clear_color = color_at(0) + --clear_color = color_at(0) } OFF_SCREEN = vec2(WIN.width * 2) -- arbitrary pixel position that is garunteed to be off screen @@ -71,7 +71,6 @@ local function game_action(scene) TIME = TIME + am.delta_time SCORE = SCORE + am.delta_time MOUSE = WIN:mouse_position() - local mwd = WIN:mouse_wheel_delta() local hex = pixel_to_hex(MOUSE - WORLDSPACE_COORDINATE_OFFSET) local rounded_mouse = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET @@ -93,9 +92,9 @@ local function game_action(scene) if WIN:mouse_pressed"middle" then WIN.scene"scale".scale2d = vec2(1) else - local small_mwd = vec2(mwd.y / 1000) - WIN.scene"scale".scale = WIN.scene"scale".scale + small_mwd - WIN.scene"scale".scale = WIN.scene"scale".scale + small_mwd + local mwd = vec2(WIN:mouse_wheel_delta().y / 1000) + WIN.scene"scale".scale2d = WIN.scene"scale".scale2d + mwd + WIN.scene"scale".scale2d = WIN.scene"scale".scale2d + mwd end if WIN:key_pressed"escape" then @@ -154,7 +153,7 @@ function game_end() delete_all_entities() SCORE = 0 - WIN.scene = game_scene() + WIN.scene = am.scale(1) ^ game_scene() end function update_score(diff) diff --git a/src/grid.lua b/src/grid.lua index 70610fe..8469914 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -45,10 +45,6 @@ function is_interactable(tile, evenq) }) end -function is_passable(tile, mob) - return tile.elevation > -0.5 and tile.elevation < 0.5 -end - -- map elevation to appropriate color function color_at(elevation) if elevation < -0.5 then -- lowest elevation @@ -65,14 +61,18 @@ function color_at(elevation) end end -local function grid_heuristic(source, target) +function grid_heuristic(source, target) return math.distance(source, target) end -local function grid_cost(map, from, to) +function grid_cost(map, from, to) local t1, t2 = map.get(from.x, from.y), map.get(to.x, to.y) - if t2.elevation < -0.5 or t2.elevation >= 0.5 - or t1.elevation < -0.5 or t1.elevation >= 0.5 then return 999 end + + -- moving from a non-water, non-mountain tile to a water or mountain tile is very expensive + if math.abs(t1.elevation) < 0.5 and math.abs(t2.elevation) > 0.5 then + return 999 + end + return math.abs(math.abs(t1.elevation)^0.5 - math.abs(t2.elevation)^0.5) end diff --git a/src/mob.lua b/src/mob.lua index 4a00d03..794e1d9 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -30,6 +30,15 @@ function mob_on_hex(hex) end) end +function mob_can_pass_through(mob, hex) + local tile = HEX_MAP.get(hex.x, hex.y) + if tile and tile.elevation < -0.5 or tile.elevation >= 0.5 then + return false + else + return true + end +end + function mob_die(mob, mob_index) WORLD:action(vplay_sound(SOUNDS.EXPLOSION1)) delete_entity(MOBS, mob_index) @@ -61,37 +70,30 @@ end -- try reducing map size by identifying key nodes (inflection points) -- there are performance hits everytime we spawn a mob and it's Astar's fault function get_mob_path(mob, map, start, goal) - --return Astar(map, goal, start, grid_heuristic, grid_cost) + return Astar(map, goal, start, grid_heuristic, grid_cost) end -- @FIXME there's a bug here where the position of the spawn hex is sometimes 1 closer to the center than we want local function get_spawn_hex() - local spawn_hex - repeat - -- ensure we spawn on an random tile along the map's edges - local roll = math.random(HEX_GRID_WIDTH * 2 + HEX_GRID_HEIGHT * 2) - 1 - local x, y + -- ensure we spawn on an random tile along the map's edges + local roll = math.random(HEX_GRID_WIDTH * 2 + HEX_GRID_HEIGHT * 2) - 1 + local x, y - if roll < HEX_GRID_HEIGHT then - x, y = 0, roll + if roll < HEX_GRID_HEIGHT then + x, y = 0, roll - elseif roll < (HEX_GRID_WIDTH + HEX_GRID_HEIGHT) then - x, y = roll - HEX_GRID_HEIGHT, HEX_GRID_HEIGHT - 1 + elseif roll < (HEX_GRID_WIDTH + HEX_GRID_HEIGHT) then + x, y = roll - HEX_GRID_HEIGHT, HEX_GRID_HEIGHT - 1 - elseif roll < (HEX_GRID_HEIGHT * 2 + HEX_GRID_WIDTH) then - x, y = HEX_GRID_WIDTH - 1, roll - HEX_GRID_WIDTH - HEX_GRID_HEIGHT - - else - x, y = roll - (HEX_GRID_HEIGHT * 2) - HEX_GRID_WIDTH, 0 - end + elseif roll < (HEX_GRID_HEIGHT * 2 + HEX_GRID_WIDTH) then + x, y = HEX_GRID_WIDTH - 1, roll - HEX_GRID_WIDTH - HEX_GRID_HEIGHT - -- @NOTE negate 'y' because hexyz algorithms assume south is positive, in amulet north is positive - spawn_hex = evenq_to_hex(vec2(x, -y)) - local tile = HEX_MAP[spawn_hex.x][spawn_hex.y] - - until is_passable(tile) + else + x, y = roll - (HEX_GRID_HEIGHT * 2) - HEX_GRID_WIDTH, 0 + end - return spawn_hex + -- @NOTE negate 'y' because hexyz algorithms assume south is positive, in amulet north is positive + return evenq_to_hex(vec2(x, -y)) end local function mob_update(mob, mob_index) @@ -104,17 +106,21 @@ local function mob_update(mob, mob_index) return true end - --local frame_target = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y] local frame_target = nil - local neighbours = HEX_MAP.neighbours(mob.hex) - if #neighbours ~= 0 then - local first_entry = HEX_MAP.get(neighbours[1].x, neighbours[1].y) + if mob.path then + -- we have an explicitly stored hex that this mob wants to move towards. + frame_target = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y] - local best_hex = neighbours[1] - local best_cost = first_entry and first_entry.priority or HEX_MAP.get(last_frame_hex.x, last_frame_hex.y).priority + else + -- make a dumb guess where we should go. + local neighbours = HEX_MAP.neighbours(mob.hex) + if #neighbours ~= 0 then + local first_entry = HEX_MAP.get(neighbours[1].x, neighbours[1].y) - for _,h in pairs(neighbours) do - --if h ~= last_frame_hex then + local best_hex = neighbours[1] + local best_cost = first_entry and first_entry.priority or HEX_MAP.get(last_frame_hex.x, last_frame_hex.y).priority + + for _,h in pairs(neighbours) do local map_entry = HEX_MAP.get(h.x, h.y) local cost = map_entry.priority @@ -122,9 +128,15 @@ local function mob_update(mob, mob_index) best_cost = cost best_hex = h end - --end + end + frame_target = best_hex end - frame_target = best_hex + end + + if frame_target == last_frame_hex or not mob_can_pass_through(mob, frame_target) then + -- we are trying to go somewhere dumb. make a better path. + mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER) + return -- don't move this frame. too much time thinking end if frame_target then @@ -150,7 +162,7 @@ local function make_and_register_mob() mob_update ) - mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER) + mob.path = false --get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER) mob.health = 10 mob.speed = 1 mob.bounty = 5