Issues

Issue #499 invalid

love.physics glitch while dragging window with mouse

Anonymous avatarAnonymous created an issue

When I make a body go very fast (80-100 m/s) and then drag the window, the body instantly loses speed. The glitch occurs even when minimizing the window or just clicking on the title bar with the mouse.

The bug exists even at much lower speeds, the window needs to be grabbed with the mouse for a longer period of time.

When testing a 2d racing game, the loss of speed from the body occurs even without dragging the window. At high speeds (again 80-100 m/s or 250 km/h) the car randomly instantly loses 100 km/h of it's speed. The issue is bigger with additional apps being open (e.g. Chrome browser, video player).

Example:

function love.load()
    m = 10; love.physics.setMeter(m)
    world = love.physics.newWorld(0, 0, true)
    body = love.physics.newBody(world, 100, 300, "dynamic")
    shape = love.physics.newRectangleShape(5 * m, 2 * m)
    fixture = love.physics.newFixture(body, shape, 100)
end

function love.update(dt)
    world:update(dt)
    if love.keyboard.isDown("right") then body:applyForce(body:getMass() * 50 * m, 0) end
end

function love.draw()
    love.graphics.setLine(1, "smooth")
    love.graphics.polygon("line", body:getWorldPoints(shape:getPoints()))
    vx, vy = body:getLinearVelocity()
    love.graphics.print(string.format("%d %d", vx / m, vy / m), 0, 0)
end

Comments (8)

  1. substitute541

    Actually, this bug applies to everything. For example, when I move my ball then drag my window for 10 seconds, it ends up faster, and changes the position.

  2. Przemator

    Hi, I created this ticket. I also created a forum topic: https://love2d.org/forums/viewtopic.php?f=4&t=11621

    From the discussion we have established, that for the best simulation, a constant dt is needed to be passed to world:update. When I call world:update(1/60) in each cycle of the loop, everything runs smooth.

    It has been suggested on the forum to split a large dt into a series of smaller updates, (e.g. 1 second would mean 60 updates of 1/60). The advantage is that this method will catch up for all the time that was lost when the game was out of focus. However, when I implement this, the game becomes laggy, it's not so smooth anymore.

    So, to conclude, using a fixed dt for world:update "solves" this problem.

    One final word: On a few machines that I tried, there seems to be no frame limit despite having vsync enabled, so a fixed dt causes the simulation to be insanely accelerated.

  3. Boolsheet

    The issue of DispatchMessage blocking on Windows is usually handled with a different thread that keeps drawing. It should be possible with the current LÖVE, but I don't know if that's worth the extra work.

    However, when I implement this, the game becomes laggy, it's not so smooth anymore.

    As we discussed on the other thread, it's very likely this comes from the fact that the buffer swap frequency is slightly different from the chosen physics simulation update frequency. The timer slowly accumulates until it can do two physics updates and then does none in the following frame. This causes a noticeable artifact and is perceived as stutter. Here's a modified version of your code that visualizes this. The green line is the value of the timer. Press space to toggle milli- and microsecond precision, this actually had an effect on my system.

    local last
    local step = 1/60
    local timer = 0
    
    local lines = {}
    local cur = 0
    for i = 1, 200 do
        lines[i*2-1] = i*4-1
        lines[i*2] = 300
    end
    
    function love.load()
        love.graphics.setLineStyle("rough")
    
        m = 1; love.physics.setMeter(m)
        world = love.physics.newWorld(0, 0, true)
        body = love.physics.newBody(world, 100, 300, "dynamic")
        shape = love.physics.newRectangleShape(5 * m, 2 * m)
        fixture = love.physics.newFixture(body, shape, 100)
    
        last = love.timer.getMicroTime()
    end
    
    function love.update(dt)
        local now = love.timer.getMicroTime()
        if high_precision then
            dt = now - last
        end
        last = now
    
        timer = timer + dt
    
        if timer > 1 then
            timer = 0
        end
    
        while timer >= step do
            world:update(step)
            timer = timer - step
        end
    
        lines[cur*2+2] = 300 + -timer*10000
        cur = (cur + 1)%200
    
        if love.keyboard.isDown("right") then body:applyForce(body:getMass() * 50 * m, 0) end
    end
    
    function love.draw()
        local p = {body:getWorldPoints(shape:getPoints())}
        for i = 1, #p, 2 do
            p[i] = p[i]%800
        end
        love.graphics.polygon("line", p)
        vx, vy = body:getLinearVelocity()
        love.graphics.print(string.format("Velocity: %d %d", vx / m, vy / m), 0, 0)
        love.graphics.setColor(0, 255, 0, 150)
        love.graphics.line(lines)
        love.graphics.setColor(255, 255, 255)
    end
    
    
    function love.keypressed(k)
        if k == "escape" then
            love.event.quit()
        elseif k == " " then
            high_precision = not high_precision
        end
    end
    
  4. Przemator

    Incredible input, Boolsheet. I tried your code and this is what I got:

    http://grebocin.com/upload/chainsaw.png

    I think the shaky graphics experience appears when the chainsaw effect is displayed on the graph. When I change to microsecond precision, the line is smooth and the chainsaw does not occur. I will have to analyse it thoroughly but it's a great food for thought.

  5. Boolsheet

    Oh, I also wanted to say that this is not an issue with LÖVE; the lover has to handle this in his code with interpolation or whatever.

  6. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.