Search code examples
luasynchronizationgame-physicslove2d

LOVE2D, Desync movement of follower-object


I've got a problem in my code. (Love2D framework) I'm making small follower-object, that follows coordinates in realtime. The problem is that speed of movement is changing, depending on the vector. Like move forward is slightly faster, than moving to up-left. Can somebody help me? Mark my mistake please. The code:

    function love.load()
    player = love.graphics.newImage("player.png")
    local f = love.graphics.newFont(20)
    love.graphics.setFont(f)
    love.graphics.setBackgroundColor(75,75,75)
    x = 100
    y = 100
    x2 = 600
    y2 = 600
    speed = 300
    speed2 = 100
end

function love.draw()
    love.graphics.draw(player, x, y)
    love.graphics.draw(player, x2, y2)
end

function love.update(dt)
print(x, y, x2, y2)
   if love.keyboard.isDown("right") then
      x = x + (speed * dt)
   end
   if love.keyboard.isDown("left") then
      x = x - (speed * dt)
   end

   if love.keyboard.isDown("down") then
      y = y + (speed * dt)
   end
   if love.keyboard.isDown("up") then
      y = y - (speed * dt)
   end

   if x < x2 and y < y2 then
    x2 = x2 - (speed2 * dt)
    y2 = y2 - (speed2 * dt)
   end

   if x > x2 and y < y2 then
    x2 = x2 + (speed2 * dt)
    y2 = y2 - (speed2 * dt)
   end

   if x > x2 and y > y2 then
    x2 = x2 + (speed2 * dt)
    y2 = y2 + (speed2 * dt)
   end

   if x < x2 and y > y2 then
    x2 = x2 - (speed2 * dt)
    y2 = y2 + (speed2 * dt)
   end
end

Solution

  • This

       if x < x2 and y < y2 then
        x2 = x2 - (speed2 * dt)
        y2 = y2 - (speed2 * dt)
       end
    
       if x > x2 and y < y2 then
        x2 = x2 + (speed2 * dt)
        y2 = y2 - (speed2 * dt)
       end
    
       if x > x2 and y > y2 then
        x2 = x2 + (speed2 * dt)
        y2 = y2 + (speed2 * dt)
       end
    
       if x < x2 and y > y2 then
        x2 = x2 - (speed2 * dt)
        y2 = y2 + (speed2 * dt)
       end
    

    has a bunch of problems.

    The one that's causing your speed differences is this: if (x<x2), but x>(x2+speed2*dt), you will run through the first branch (if x < x2 and y < y2 then …). This will change the values so that you will also hit the second branch (if x > x2 and y < y2 then …), which means you move twice in the y direction. Change to if x < x2 and y < y2 then … elseif x > x2 and y < y2 then … so that you cannot fall through into the other branches, or do the math and avoid the whole if-chain.

    A thing that you may or may not want and currently have is that it either walks in a certain direction, or it doesn't. Which means there are 8 possible directions that the follower can travel. (Axis-aligned or diagonally – the 4 cases you have plus the situation when dx or dy is (approximately) zero.)

    If you want it to move "directly towards you", the follower should be able to move in any direction.

    You will have to use the relative distances along the x- and y-direction. There are many common choices of distance definitions, but you probably want the euclidean distance. (The "shape" of the unit circle under that norm / distance definition determines how fast it's moving in either direction, only the euclidean distance is "the same in all directions".)

    So replace the above block with

       local dx, dy = (x2-x), (y2-y)    -- difference in both directions
       local norm = 1/(dx^2+dy^2)^(1/2) -- length of the distance
       dx, dy = dx*norm, dy*norm        -- relative contributions of x/y parts
       x2, y2 = x2 - dx*speed*dt, y2 - dy*speed*dt
    

    and you'll get the "normal" notion of distance, which gets you the normal notion of movement speed, which gets you identical-looking speeds when moving towards the player.