-
Notifications
You must be signed in to change notification settings - Fork 1
/
example.lua
96 lines (78 loc) · 2.33 KB
/
example.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
local PathFinder = require 'flow_field'
local map = { w = 40, h = 32 }
local cached_nodes = {}
local function get_node(x, y)
local row = cached_nodes[y]
if not row then row = {}; cached_nodes[y] = row end
local node = row[x]
if not node then node = { x = x, y = y, cost = 0 }; row[x] = node end
return node
end
local neighbors_offset = {
{ -1, -1 }, { 0, -1 }, { 1, -1 },
{ -1, 0 }, { 1, 0 },
{ -1, 1 }, { 0, 1 }, { 1, 1 },
}
-- Return all neighbor nodes. Means a target that can be moved from the current node
function map:get_neighbors(node)
local nodes = {}
local x, y = node.x, node.y
for i, offset in ipairs(neighbors_offset) do
local tnode = get_node(x + offset[1], y + offset[2])
if self:is_valid_node(tnode) and self:is_valid_neighbor(node, tnode) then
nodes[#nodes + 1] = tnode
end
end
return nodes
end
function map:is_valid_node(node)
return node.cost >= 0 and node.x >= 0 and node.x < map.w and node.y >= 0 and node.y < map.h
end
function map:is_valid_neighbor(from, node)
if node.x == from.x or node.y == from.y then return true end
local dx, dy = node.x - from.x, node.y - from.y
return self:is_valid_node(get_node(from.x + dx, from.y)) and self:is_valid_node(get_node(from.x, from.y + dy))
end
-- Cost of two adjacent nodes
function map:get_cost(from_node, to_node)
local dx, dy = from_node.x - to_node.x, from_node.y - to_node.y
return math.sqrt(dx * dx + dy * dy) + (from_node.cost + to_node.cost) * 0.5
end
----------------------
local finder = PathFinder.new(map)
local st = os.clock()
local goal = get_node(5, 5)
local field = finder:build(goal)
local start = get_node(1, 1)
while start ~= goal do
if not start then break end
local info = field[start]
if info then
print(start.x, start.y, info.score)
start = get_node(start.x + info.ox, start.y + info.oy)
else
start = nil
end
end
local direction_char = {
'↖', '↑', '↗',
'←', 'o', '→',
'↙', '↓', '↘'
}
local str = ''
for y = 0, map.h do
for x = 0, map.w do
local cnode = get_node(x, y)
local tinfo = field[cnode]
if not tinfo then
str = str..' '
else
local ox, oy = tinfo.ox + 1, tinfo.oy + 1
local idx = oy * 3 + ox + 1
str = str..' '..direction_char[idx]
end
end
str = str..'\n'
end
print(str)
print('Used ', (os.clock() - st) * 1000, 'ms')