Browse Source

astar

master
Nicholas Hayashi 4 years ago
parent
commit
bc161ce8b0
  1. 32
      src/grid.lua
  2. 2
      src/hexyz.lua
  3. 6
      src/main.lua
  4. 94
      src/mob.lua
  5. 14
      src/table.lua
  6. 18
      src/util.lua

32
src/grid.lua

@ -7,7 +7,7 @@ HEX_GRID_WIDTH = 65
HEX_GRID_HEIGHT = 33
HEX_GRID_DIMENSIONS = vec2(HEX_GRID_WIDTH, HEX_GRID_HEIGHT)
-- @NOTE no idea why the y coordinate doesn't need to be transformed here
-- this is in hex coordinates
HEX_GRID_CENTER = vec2(math.floor(HEX_GRID_DIMENSIONS.x/2), 0)
-- index is hex coordinates [x][y]
@ -50,6 +50,32 @@ function color_at(elevation)
end
end
function generate_flow_field(start)
local frontier = { start }
local came_from = {}
came_from[start.x] = {}
came_from[start.x][start.y] = true
while not (#frontier == 0) do
local current = table.pop(frontier)
log(current)
for _,neighbour in pairs(hex_neighbours(current)) do
if get_tile(neighbour.x, neighbour.y) then
if not (came_from[neighbour.x] and came_from[neighbour.x][neighbour.y]) then
log("hi")
if true then return came_from end
table.insert(frontier, neighbour)
came_from[neighbour.x] = {}
came_from[neighbour.x][neighbour.y] = current
end
end
end
end
return came_from
end
function random_map(seed, do_seed_rng)
local elevation_map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y, seed)
@ -92,3 +118,7 @@ function random_map(seed, do_seed_rng)
^ world:tag"world"
end
function grid_neighbours(hex)
return table.filter(hex_neighbours(hex), function(_hex) return get_tile(_hex.x, _hex.y) end)
end

2
src/hexyz.lua

@ -97,7 +97,7 @@ function hex_direction(direction)
-- Return Hexagon Adjacent to |hex| in Integer Index |direction|
function hex_neighbour(hex, direction)
return hex + HEX_DIRECTIONS[(direction % 6) % 6 + 1] end
return hex + HEX_DIRECTIONS[(direction % 6) % 6 + 1] end
-- Collect All 6 Neighbours in a Table
function hex_neighbours(hex)

6
src/main.lua

@ -37,12 +37,9 @@ function game_action(scene)
local _off = hex_to_evenq(hex)
local off = _off{ y = -_off.y } - vec2(math.floor(HEX_GRID_WIDTH/2)
, math.floor(HEX_GRID_HEIGHT/2))
local off2 = evenq_to_hex(_off)
local tile = get_tile(hex.x, hex.y)
if tile and win:mouse_pressed"left" then
log(tile)
--invoke_tile_menu(hex.x, hex.y, tile)
end
if win:key_pressed"f1" then end
@ -60,13 +57,11 @@ function game_action(scene)
win.scene"hex_cursor".center = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET
win.scene"score".text = string.format("SCORE: %.2f", time)
win.scene"coords".text = string.format("%d,%d", off.x, off.y)
win.scene"rev".text = string.format("%d,%d", off2.x, off2.y)
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 coords2 = am.translate(win.right - 10, win.top - 40) ^ am.text("", "right"):tag"rev"
local hex_cursor = am.circle(vec2(-6969), HEX_SIZE, COLORS.TRANSPARENT, 6):tag"hex_cursor"
local curtain = am.rect(win.left, win.bottom, win.right, win.top, COLORS.TRUEBLACK)
@ -81,7 +76,6 @@ function game_scene()
hex_cursor,
score,
coords,
coords2
}
scene:action(game_action)

94
src/mob.lua

@ -3,49 +3,55 @@ MOBS = {}
-- check if a |tile| is passable by |mob|
function can_pass_through(mob, tile)
return tile and tile.elevation and tile.elevation < 0.5 and tile.elevation > -0.5
return tile.elevation < 0.5 and tile.elevation > -0.5
end
function get_path(mob, starting_hex, goal_hex)
local moves = {}
function get_movement_cost(mob, start_hex, goal_hex)
return 1
end
local visited = {}
visited[starting_hex.x] = {}
visited[starting_hex.x][starting_hex.y] = true
repeat
local neighbours = hex_neighbours(pixel_to_hex(mob.position))
local candidates = {}
-- get list of candidates: hex positions to consider moving to.
for _,neighbour in pairs(neighbours) do
if can_pass_through(mob, get_tile(neighbour.x, neighbour.y)) then
if not (visited[neighbour.h] and visited[neighbour.x][neighbour.y]) then
table.insert(candidates, neighbour)
else
--table.insert(candidates, neighbour)
end
end
end
-- choose where to move
local move = candidates[1]
for _,hex in pairs(candidates) do
if math.distance(hex, goal_hex) < math.distance(move, goal_hex) then
move = hex
end
end
function Astar(mob, start_hex, goal_hex)
local function heuristic(start_hex, goal_hex)
return math.distance(start_hex, goal_hex)
end
local came_from = {}
came_from[start_hex.x] = {}
came_from[start_hex.x][start_hex.y] = false
local frontier = {}
frontier[1] = { position = start_hex, priority = 0 }
local cost_so_far = {}
cost_so_far[start_hex.x] = {}
cost_so_far[start_hex.x][start_hex.y] = 0
while not (#frontier == 0) do
local current = table.remove(frontier, 1)
if move then
table.insert(moves, move)
visited[move.x] = {}
visited[move.x][move.y] = true
end
--if move == goal then log('made it!') return end
until move == goal_hex
if current.position == goal_hex then log('found it!') break end
return moves
for _,_next in pairs(hex_neighbours(current.position)) do
local tile = get_tile(_next.x, _next.y)
if tile then
local new_cost = cost_so_far[current.position.x][current.position.y]
+ get_movement_cost(mob, current.position, _next)
if not twoD_get(cost_so_far, _next.x, _next.y) or new_cost < twoD_get(cost_so_far, _next.x, _next.y) then
twoD_set(cost_so_far, _next.x, _next.y, new_cost)
local priority = new_cost + heuristic(goal_hex, _next)
table.insert(frontier, { position = _next, priority = priority })
twoD_set(came_from, _next.x, _next.y, current)
end
end
end
end
return came_from
end
function get_spawn_hex(mob)
@ -81,12 +87,26 @@ function make_mob()
local mob = {}
local spawn_hex = get_spawn_hex(mob)
log(spawn_hex)
local spawn_position = hex_to_pixel(spawn_hex) + WORLDSPACE_COORDINATE_OFFSET
mob.position = spawn_position
--mob.path = get_path(mob, spawn_hex, HEX_GRID_CENTER)
mob.path = Astar(mob, spawn_hex, HEX_GRID_CENTER)
mob.sprite = am.circle(spawn_position, 18, COLORS.WHITE, 4)
win.scene:action(coroutine.create(function()
local goal = spawn_hex
local current = mob.path[HEX_GRID_CENTER.x][HEX_GRID_CENTER.y].position
log(current)
while current ~= goal do
if current then
win.scene:append(am.circle(hex_to_pixel(current) + WORLDSPACE_COORDINATE_OFFSET, 4, COLORS.MAGENTA))
current = mob.path[current.x][current.y].position
end
am.wait(am.delay(0.01))
end
end))
win.scene:append(mob.sprite)
return mob

14
src/table.lua

@ -0,0 +1,14 @@
function table.shift(t, count)
local e = t[1]
t[1] = nil
for i,e in pairs(t) do
if e then
t[i - 1] = e
end
end
return e
end

18
src/util.lua

@ -1,14 +1,14 @@
function table.shift(t, count)
local e = t[1]
t[1] = nil
function twoD_get(t, x, y)
return t[x] and t[x][y]
end
for i,e in pairs(t) do
if e then
t[i - 1] = e
end
function twoD_set(t, x, y, v)
if t[x] then
t[x][y] = v
else
t[x] = {}
t[x][y] = v
end
return e
end
Loading…
Cancel
Save