new circleVectors (midpoint circle algorithm) and pathToClosestCharacter
function
This commit is contained in:
parent
7526e3064f
commit
b77c07eef0
@ -25,45 +25,85 @@ local function closestCharacter(char)
|
|||||||
return charTarget
|
return charTarget
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Возвращает все точки в радиусе в виде векторов
|
-- --- Возвращает все точки в радиусе в виде векторов (должен по крайней мере)
|
||||||
|
-- --- @param radius integer
|
||||||
|
-- --- @param center Vec3
|
||||||
|
-- --- @return Vec3[]
|
||||||
|
-- local function circleVectors(center, radius)
|
||||||
|
-- local vecs = {}
|
||||||
|
-- local res = {}
|
||||||
|
-- for t = 0, 2 * math.pi, EPSILON do
|
||||||
|
-- local x = math.cos(t) * radius + center.x
|
||||||
|
-- local y = math.sin(t) * radius + center.y
|
||||||
|
-- table.insert(vecs, Vec3 { math.floor(x), math.floor(y) })
|
||||||
|
-- end
|
||||||
|
-- for _, v in pairs(vecs) do
|
||||||
|
-- local i = 1
|
||||||
|
-- while i <= #res and (res[i].x ~= v.x or res[i].y ~= v.y) do
|
||||||
|
-- i = i + 1
|
||||||
|
-- end
|
||||||
|
-- if i == #res + 1 or #res == 0 then
|
||||||
|
-- table.insert(res, v)
|
||||||
|
-- print('[AI]: circle vecs:', v)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- return res
|
||||||
|
-- end
|
||||||
|
|
||||||
|
--- Возвращает все точки в радиусе в виде векторов (должен по крайней мере)
|
||||||
--- @param radius integer
|
--- @param radius integer
|
||||||
local function circleVectors(radius)
|
--- @param center Vec3
|
||||||
local cam = Tree.level.camera
|
--- @return Vec3[]
|
||||||
local vecs = {}
|
local function circleVectors(center, radius)
|
||||||
for t = 0, 2 * math.pi, EPSILON do
|
local dx, dy, err = radius, 0, 1 - radius
|
||||||
local x = math.sin(t) * radius
|
local vecs, res = {}, {}
|
||||||
local y = math.cos(t) * radius
|
while dx >= dy do
|
||||||
vecs[cam:toWorldPosition(Vec3 { x, y })] = true
|
table.insert(vecs, Vec3 { center.x + dx, center.y + dy })
|
||||||
|
table.insert(vecs, Vec3 { center.x - dx, center.y + dy })
|
||||||
|
table.insert(vecs, Vec3 { center.x + dx, center.y - dy })
|
||||||
|
table.insert(vecs, Vec3 { center.x - dx, center.y - dy })
|
||||||
|
table.insert(vecs, Vec3 { center.x + dy, center.y + dx })
|
||||||
|
table.insert(vecs, Vec3 { center.x - dy, center.y + dx })
|
||||||
|
table.insert(vecs, Vec3 { center.x + dy, center.y - dx })
|
||||||
|
table.insert(vecs, Vec3 { center.x - dy, center.y - dx })
|
||||||
|
dy = dy + 1
|
||||||
|
if err < 0 then
|
||||||
|
err = err + 2 * dy + 1
|
||||||
|
else
|
||||||
|
dx, err = dx - 1, err + 2 * (dy - dx) + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return utils.keys(vecs)
|
for _, v in pairs(vecs) do
|
||||||
|
local i = 1
|
||||||
|
while i <= #res and (res[i].x ~= v.x or res[i].y ~= v.y) do
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
if i == #res + 1 or #res == 0 then
|
||||||
|
table.insert(res, v)
|
||||||
|
print('[AI]: circle vecs:', v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return vecs
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param owner Character
|
--- @param owner Character
|
||||||
--- @param space integer здесь мы должны сами определять, сколько должны не доходить до персонажа (1 <= n)
|
--- @param radius integer здесь мы должны сами определять, сколько должны не доходить до персонажа (1 <= n)
|
||||||
--- @return Vec3|nil
|
--- @return Vec3|nil
|
||||||
local function pathToClosestCharacter(owner, space)
|
local function pathToClosestCharacter(owner, radius)
|
||||||
local charTarget = closestCharacter(owner)
|
local charTarget = closestCharacter(owner)
|
||||||
local targetPosition, ownerPosition = charTarget:has(Tree.behaviors.positioned), owner:has(Tree.behaviors.positioned)
|
local targetPosition, ownerPosition = charTarget:has(Tree.behaviors.positioned), owner:has(Tree.behaviors.positioned)
|
||||||
if not targetPosition or not ownerPosition then return end
|
if not targetPosition or not ownerPosition then return end
|
||||||
local target = Vec3 {}
|
|
||||||
print(ownerPosition.position, targetPosition.position)
|
local circleVecs = circleVectors(targetPosition.position, radius)
|
||||||
local path = pf(ownerPosition.position, targetPosition.position)
|
local target = circleVecs[#circleVecs]
|
||||||
for c in path:values() do
|
local path = pf(ownerPosition.position, target)
|
||||||
print(c)
|
for i, c in ipairs(circleVecs) do
|
||||||
|
local newPath = pf(ownerPosition.position, c)
|
||||||
|
if newPath:size() < path:size() then
|
||||||
|
path = newPath
|
||||||
|
target = c
|
||||||
|
end
|
||||||
end
|
end
|
||||||
print(path)
|
|
||||||
space = math.min(space, path:size())
|
|
||||||
print(space, path:size())
|
|
||||||
for _ = 0, space - 1 do
|
|
||||||
path:pop_back()
|
|
||||||
end
|
|
||||||
if path:size() ~= 0 then
|
|
||||||
target = path:pop_back()
|
|
||||||
else
|
|
||||||
target = ownerPosition.position
|
|
||||||
end
|
|
||||||
print(target, targetPosition.position)
|
|
||||||
--- @todo тут захардкожено + 1, но мы должны как-то хитро определять с какой стороны обойти
|
|
||||||
return target
|
return target
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -72,7 +112,7 @@ local aiNature = {
|
|||||||
["dev_warrior"] = function(self)
|
["dev_warrior"] = function(self)
|
||||||
return function(callback) -- почему так, описано в Task
|
return function(callback) -- почему так, описано в Task
|
||||||
self.owner:try(Tree.behaviors.spellcaster, function(spellB)
|
self.owner:try(Tree.behaviors.spellcaster, function(spellB)
|
||||||
self.target = pathToClosestCharacter(self.owner, 2)
|
self.target = pathToClosestCharacter(self.owner, 1)
|
||||||
local task1 = spellB.spellbook[1]:cast(self.owner, self.target)
|
local task1 = spellB.spellbook[1]:cast(self.owner, self.target)
|
||||||
if task1 then
|
if task1 then
|
||||||
task1(
|
task1(
|
||||||
|
|||||||
9
main.lua
9
main.lua
@ -41,7 +41,7 @@ function love.load()
|
|||||||
:addBehavior {
|
:addBehavior {
|
||||||
Tree.behaviors.residentsleeper.new(),
|
Tree.behaviors.residentsleeper.new(),
|
||||||
Tree.behaviors.stats.new(nil, nil, 3),
|
Tree.behaviors.stats.new(nil, nil, 3),
|
||||||
Tree.behaviors.positioned.new(Vec3 { 7, 1 }),
|
Tree.behaviors.positioned.new(Vec3 { 7, 2 }),
|
||||||
Tree.behaviors.tiled.new(),
|
Tree.behaviors.tiled.new(),
|
||||||
Tree.behaviors.sprite.new(Tree.assets.files.sprites.character),
|
Tree.behaviors.sprite.new(Tree.assets.files.sprites.character),
|
||||||
Tree.behaviors.shadowcaster.new(),
|
Tree.behaviors.shadowcaster.new(),
|
||||||
@ -128,9 +128,14 @@ function love.draw()
|
|||||||
love.graphics.setColor(1, 1, 1)
|
love.graphics.setColor(1, 1, 1)
|
||||||
|
|
||||||
love.graphics.setFont(Tree.fonts:getTheme("Roboto_Mono"):getVariant("small"))
|
love.graphics.setFont(Tree.fonts:getTheme("Roboto_Mono"):getVariant("small"))
|
||||||
|
local mousePosX, mousePosY = love.mouse.getPosition()
|
||||||
|
local mousePos = Tree.level.camera:toWorldPosition(Vec3 { mousePosX, mousePosY }):floor()
|
||||||
local stats = "fps: " ..
|
local stats = "fps: " ..
|
||||||
love.timer.getFPS() ..
|
love.timer.getFPS() ..
|
||||||
" lt: " .. lt .. " dt: " .. dt .. " mem: " .. string.format("%.2f MB", collectgarbage("count") / 1000)
|
" lt: " .. lt ..
|
||||||
|
" dt: " .. dt ..
|
||||||
|
" mem: " .. string.format("%.2f MB", collectgarbage("count") / 1000) ..
|
||||||
|
" mouse pos: " .. tostring(mousePos)
|
||||||
love.graphics.print(stats, 10, 10)
|
love.graphics.print(stats, 10, 10)
|
||||||
|
|
||||||
local t2 = love.timer.getTime()
|
local t2 = love.timer.getTime()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user