这个lua的代码能不能写的更好?
Can this lua code be written better?
下面的代码可以重构得更简洁或者更清晰吗?我还在下面附上了一张图片,以帮助说明我的想法。
local playerAreaPos = {
{x = playerPos.x, y = playerPos.y - 1, z = playerPos.z}, -- NORTH
{x = playerPos.x, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH
{x = playerPos.x + 1, y = playerPos.y, z = playerPos.z}, -- EAST
{x = playerPos.x - 1, y = playerPos.y, z = playerPos.z}, -- WEST
{x = playerPos.x - 1, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH-WEST
{x = playerPos.x + 1, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH-EAST
{x = playerPos.x - 1, y = playerPos.y - 1, z = playerPos.z}, -- NORTH-WEST
{x = playerPos.x + 1, y = playerPos.y - 1, z = playerPos.z} -- NORTH-EAST
}
local posTable = {
{x = playerPos.x, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH"},
{x = playerPos.x, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH"},
{x = playerPos.x, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH"},
{x = playerPos.x, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH"},
{x = playerPos.x + 2, y = playerPos.y, z = playerPos.z, dir = "EAST"},
{x = playerPos.x + 3, y = playerPos.y, z = playerPos.z, dir = "EAST"},
{x = playerPos.x - 2, y = playerPos.y, z = playerPos.z, dir = "WEST"},
{x = playerPos.x - 3, y = playerPos.y, z = playerPos.z, dir = "WEST"},
{x = playerPos.x - 2, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH_WEST"},
{x = playerPos.x - 3, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH_WEST"},
{x = playerPos.x + 2, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH_EAST"},
{x = playerPos.x + 3, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH_EAST"},
{x = playerPos.x - 2, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH_WEST"},
{x = playerPos.x - 3, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH_WEST"},
{x = playerPos.x + 2, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH_EAST"},
{x = playerPos.x + 3, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH_EAST"}
}
for i = 1, #posTable do
if targetPos == Position(posTable[i]) then
if posTable[i].dir == "NORTH_EAST" then
print("TELEPORT TO: ", playerAreaPos[8].x, playerAreaPos[8].y)
elseif posTable[i].dir == "NORTH_WEST" then
print("TELEPORT TO: ", playerAreaPos[7].x, playerAreaPos[7].y)
elseif posTable[i].dir == "NORTH" then
print("TELEPORT TO: ", playerAreaPos[1].x, playerAreaPos[1].y)
elseif posTable[i].dir == "SOUTH_WEST" then
print("TELEPORT TO: ", playerAreaPos[5].x, playerAreaPos[5].y)
elseif posTable[i].dir == "SOUTH_EAST" then
print("TELEPORT TO: ", playerAreaPos[6].x, playerAreaPos[6].y)
elseif posTable[i].dir == "SOUTH" then
print("TELEPORT TO: ", playerAreaPos[2].x, playerAreaPos[2].y)
elseif posTable[i].dir == "EAST" then
print("TELEPORT TO: ", playerAreaPos[3].x, playerAreaPos[3].y)
elseif posTable[i].dir == "WEST" then
print("TELEPORT TO: ", playerAreaPos[4].x, playerAreaPos[4].y)
end
end
end
这个函数的目的是将敌人从 posTable 传送到 playerAreaPos,同时确保他们在相应的线内传送,这意味着如果他们在主角以北 3 个方格,他们将被传送到主角以北 1 个方格
local enemyPos = {x = 11, y = 22, z = 33}
local playerPos = {x = 10, y = 20, z = 30}
local beam_length = 3
if enemyPos.z == playerPos.z then
local dx = enemyPos.x - playerPos.x
local dy = enemyPos.y - playerPos.y
local ax, ay = math.abs(dx), math.abs(dy)
local len_max, len_min = math.max(ax, ay), math.min(ax, ay)
if len_max >= 2 and len_max <= beam_length and len_min % len_max == 0 then
print("TELEPORT TO: ", playerPos.x + dx / len_max, playerPos.y + dy / len_max)
end
end
有很多方法可以解决您的问题,但我将尝试使用一些数学知识,然后再对它们进行一些考虑。
看下一个diagram我们的英雄和敌人之间有一个最小距离当敌人落入射程时它会传送到英雄的半径然后,敌人不能传送除非我们的英雄把它扔到它的远处半径.
当这些考虑的时候,我做了这个实现
-- returns math functions as local functions
local deg = math.deg
local sin = math.sin
local cos = math.cos
local atan2 = math.atan2
-- returns the distance between two points
local lengthOf = function ( dots )
local dx, dy = dots.x[2]-dots.x[1], dots.y[2]-dots.y[1]
return (dx*dx + dy*dy)^.5
end
-- returns the degrees between two points
-- note: 0 degrees is 'east'
local angleBetweenPoints = function ( dots )
local x, y = dots.x[2]-dots.x[1], dots.y[2]-dots.y[1]
local radian = atan2(x, y)
local angle = deg(radian)
angle = angle < 0 and (360 + angle) or angle
return angle
end
--config your hero
local hero = {}
hero.posX, hero.posY = 0, 0
hero.radius = 10
-- config enemy
local foe = {}
foe.posX, foe.posY = 0, 18
foe.radius = 8
foe.theta = 0
foe.teleported = false
foe.distToHero = 18
foe.points = {}
foe.curDist = 0
-- this part will be a sort like frame
foe.points = {x={hero.posX,foe.posX}, y={hero.posY,foe.posY}}
foe.curDist = lengthOf( foe.points )
if foe.distToHero<=foe.curDist and not foe.teleported then
foe.theta = angleBetweenPoints ( foe.points )
foe.posX = hero.radius*sin( foe.theta ) -- yes it's reverse
foe.posY = hero.radius*cos( foe.theta ) -- yes it's reverse
foe.teleported = true
else
foe.teleported = false -- if enemy is hit far of the hero
end
print(foe.posX,foe.posY)
-- printed output: 0, 10
以前的实现,如果你在地形上放了很多敌人,需要大量计算我的建议是在发生碰撞时使用 C API or Box2D this last use a sensor fixture,这对这种情况非常有用。目前有许多 Lua 具有这些功能的 SDK,因此您可以快速启动。
下面的代码可以重构得更简洁或者更清晰吗?我还在下面附上了一张图片,以帮助说明我的想法。
local playerAreaPos = {
{x = playerPos.x, y = playerPos.y - 1, z = playerPos.z}, -- NORTH
{x = playerPos.x, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH
{x = playerPos.x + 1, y = playerPos.y, z = playerPos.z}, -- EAST
{x = playerPos.x - 1, y = playerPos.y, z = playerPos.z}, -- WEST
{x = playerPos.x - 1, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH-WEST
{x = playerPos.x + 1, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH-EAST
{x = playerPos.x - 1, y = playerPos.y - 1, z = playerPos.z}, -- NORTH-WEST
{x = playerPos.x + 1, y = playerPos.y - 1, z = playerPos.z} -- NORTH-EAST
}
local posTable = {
{x = playerPos.x, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH"},
{x = playerPos.x, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH"},
{x = playerPos.x, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH"},
{x = playerPos.x, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH"},
{x = playerPos.x + 2, y = playerPos.y, z = playerPos.z, dir = "EAST"},
{x = playerPos.x + 3, y = playerPos.y, z = playerPos.z, dir = "EAST"},
{x = playerPos.x - 2, y = playerPos.y, z = playerPos.z, dir = "WEST"},
{x = playerPos.x - 3, y = playerPos.y, z = playerPos.z, dir = "WEST"},
{x = playerPos.x - 2, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH_WEST"},
{x = playerPos.x - 3, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH_WEST"},
{x = playerPos.x + 2, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH_EAST"},
{x = playerPos.x + 3, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH_EAST"},
{x = playerPos.x - 2, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH_WEST"},
{x = playerPos.x - 3, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH_WEST"},
{x = playerPos.x + 2, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH_EAST"},
{x = playerPos.x + 3, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH_EAST"}
}
for i = 1, #posTable do
if targetPos == Position(posTable[i]) then
if posTable[i].dir == "NORTH_EAST" then
print("TELEPORT TO: ", playerAreaPos[8].x, playerAreaPos[8].y)
elseif posTable[i].dir == "NORTH_WEST" then
print("TELEPORT TO: ", playerAreaPos[7].x, playerAreaPos[7].y)
elseif posTable[i].dir == "NORTH" then
print("TELEPORT TO: ", playerAreaPos[1].x, playerAreaPos[1].y)
elseif posTable[i].dir == "SOUTH_WEST" then
print("TELEPORT TO: ", playerAreaPos[5].x, playerAreaPos[5].y)
elseif posTable[i].dir == "SOUTH_EAST" then
print("TELEPORT TO: ", playerAreaPos[6].x, playerAreaPos[6].y)
elseif posTable[i].dir == "SOUTH" then
print("TELEPORT TO: ", playerAreaPos[2].x, playerAreaPos[2].y)
elseif posTable[i].dir == "EAST" then
print("TELEPORT TO: ", playerAreaPos[3].x, playerAreaPos[3].y)
elseif posTable[i].dir == "WEST" then
print("TELEPORT TO: ", playerAreaPos[4].x, playerAreaPos[4].y)
end
end
end
这个函数的目的是将敌人从 posTable 传送到 playerAreaPos,同时确保他们在相应的线内传送,这意味着如果他们在主角以北 3 个方格,他们将被传送到主角以北 1 个方格
local enemyPos = {x = 11, y = 22, z = 33}
local playerPos = {x = 10, y = 20, z = 30}
local beam_length = 3
if enemyPos.z == playerPos.z then
local dx = enemyPos.x - playerPos.x
local dy = enemyPos.y - playerPos.y
local ax, ay = math.abs(dx), math.abs(dy)
local len_max, len_min = math.max(ax, ay), math.min(ax, ay)
if len_max >= 2 and len_max <= beam_length and len_min % len_max == 0 then
print("TELEPORT TO: ", playerPos.x + dx / len_max, playerPos.y + dy / len_max)
end
end
有很多方法可以解决您的问题,但我将尝试使用一些数学知识,然后再对它们进行一些考虑。
看下一个diagram我们的英雄和敌人之间有一个最小距离当敌人落入射程时它会传送到英雄的半径然后,敌人不能传送除非我们的英雄把它扔到它的远处半径.
当这些考虑的时候,我做了这个实现
-- returns math functions as local functions
local deg = math.deg
local sin = math.sin
local cos = math.cos
local atan2 = math.atan2
-- returns the distance between two points
local lengthOf = function ( dots )
local dx, dy = dots.x[2]-dots.x[1], dots.y[2]-dots.y[1]
return (dx*dx + dy*dy)^.5
end
-- returns the degrees between two points
-- note: 0 degrees is 'east'
local angleBetweenPoints = function ( dots )
local x, y = dots.x[2]-dots.x[1], dots.y[2]-dots.y[1]
local radian = atan2(x, y)
local angle = deg(radian)
angle = angle < 0 and (360 + angle) or angle
return angle
end
--config your hero
local hero = {}
hero.posX, hero.posY = 0, 0
hero.radius = 10
-- config enemy
local foe = {}
foe.posX, foe.posY = 0, 18
foe.radius = 8
foe.theta = 0
foe.teleported = false
foe.distToHero = 18
foe.points = {}
foe.curDist = 0
-- this part will be a sort like frame
foe.points = {x={hero.posX,foe.posX}, y={hero.posY,foe.posY}}
foe.curDist = lengthOf( foe.points )
if foe.distToHero<=foe.curDist and not foe.teleported then
foe.theta = angleBetweenPoints ( foe.points )
foe.posX = hero.radius*sin( foe.theta ) -- yes it's reverse
foe.posY = hero.radius*cos( foe.theta ) -- yes it's reverse
foe.teleported = true
else
foe.teleported = false -- if enemy is hit far of the hero
end
print(foe.posX,foe.posY)
-- printed output: 0, 10
以前的实现,如果你在地形上放了很多敌人,需要大量计算我的建议是在发生碰撞时使用 C API or Box2D this last use a sensor fixture,这对这种情况非常有用。目前有许多 Lua 具有这些功能的 SDK,因此您可以快速启动。