-2

Can the following code be refactored to be more concise or more clear? I have also attached a picture below to help illustrate what I have in mind.

    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

The aim of this function is to teleport enemies from posTable to playerAreaPos while ensuring they teleport within the corresponding line, which means if they are 3 squares north from main character they will be teleported to 1 square north of main character

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Jay
  • 41
  • 9

2 Answers2

0
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
Egor Skriptunoff
  • 906
  • 1
  • 8
  • 23
  • Thank you, even the beam_length :) I understand everything except the if statement but I will get the hang of it once I will apply it next time myself! – Jay Jun 08 '18 at 10:56
0

There's a many way to implementation your question but I'm going try to use some math and after I'm going do some considerations about them.

Look at the next diagram there's a minimum distance between our hero and enemy when enemy fall into range it'll be teleport to hero's radius and after, foe can not teleport unless our hero throw it far its radius.

When these consideration, I made this implementation

-- 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

The previous implementation, require a lot calculation if you put a lot foes on the landscape my suggestion is use C API or Box2D this last use a sensor fixture when a collision occur and is very useful for this sort situations. Currently there's many Lua SDK with these features so you can kickstart.

HubertRonald
  • 101
  • 4