Object on the screen trembles if rendered with viewport coords

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
dusoft
Party member
Posts: 676
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Object on the screen trembles if rendered with viewport coords

Post by dusoft »

Well, it's clear that you are not rounding *vy* to nearest integer and that's why the "trembling" occurs.
lysandre
Prole
Posts: 9
Joined: Sun Sep 01, 2024 3:31 pm

Re: Object on the screen trembles if rendered with viewport coords

Post by lysandre »

But when I tried to round with:

Code: Select all

function MathHelper.round(n)
    if n >= 0 then
        return math.floor(n + 0.5)
    else
        return math.ceil(n - 0.5)
    end
end
as I answered back in the thread, the trembling still occurred, only a little bit decreased
User avatar
dusoft
Party member
Posts: 676
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Object on the screen trembles if rendered with viewport coords

Post by dusoft »

It's still possible that rounding causes changes between integers, so the vy location is not stable. You can check via similar debug log to see if your integers change, when the original position is stable. If so, there is an issue in either your coordinate transformation or the push library.
lysandre
Prole
Posts: 9
Joined: Sun Sep 01, 2024 3:31 pm

Re: Object on the screen trembles if rendered with viewport coords

Post by lysandre »

Code: Select all

if showLocationSign then
    local ox, oy = love.graphics.inverseTransformPoint(0, 0)
    local vx, vy = MathHelper.round(viewport.getX()), MathHelper.round(viewport.getY())
    print(('ox: %s, vx: %s, delta: %s, oy: %s, vy: %s, delta: %s'):format(ox, vx, ox - vx, oy, vy, oy - vy))
    locationSignPanel.render(ox + 2, oy + 2)
    locationSignText.render(ox + 4, oy + 6)
end
Output:

Code: Select all

ox: 192, vx: 192, delta: 0, oy: 532, vy: 532, delta: 0
ox: 192, vx: 192, delta: 0, oy: 531, vy: 532, delta: -1
ox: 192, vx: 192, delta: 0, oy: 531, vy: 531, delta: 0
ox: 192, vx: 192, delta: 0, oy: 530, vy: 530, delta: 0
ox: 192, vx: 192, delta: 0, oy: 530, vy: 530, delta: 0
ox: 192, vx: 192, delta: 0, oy: 529, vy: 529, delta: 0
ox: 192, vx: 192, delta: 0, oy: 529, vy: 529, delta: 0
ox: 192, vx: 192, delta: 0, oy: 528, vy: 528, delta: 0
ox: 192, vx: 192, delta: 0, oy: 528, vy: 528, delta: 0
ox: 192, vx: 192, delta: 0, oy: 527, vy: 527, delta: 0
ox: 192, vx: 192, delta: 0, oy: 527, vy: 527, delta: 0
ox: 192, vx: 192, delta: 0, oy: 526, vy: 526, delta: 0
ox: 192, vx: 192, delta: 0, oy: 525, vy: 526, delta: -1
ox: 192, vx: 192, delta: 0, oy: 525, vy: 525, delta: 0
ox: 192, vx: 192, delta: 0, oy: 524, vy: 524, delta: 0
ox: 192, vx: 192, delta: 0, oy: 524, vy: 524, delta: 0
ox: 192, vx: 192, delta: 0, oy: 523, vy: 523, delta: 0
ox: 192, vx: 192, delta: 0, oy: 522, vy: 522, delta: 0
ox: 192, vx: 192, delta: 0, oy: 522, vy: 522, delta: 0
ox: 192, vx: 192, delta: 0, oy: 521, vy: 521, delta: 0
ox: 192, vx: 192, delta: 0, oy: 521, vy: 521, delta: 0
ox: 192, vx: 192, delta: 0, oy: 520, vy: 520, delta: 0
ox: 192, vx: 192, delta: 0, oy: 520, vy: 520, delta: 0
ox: 192, vx: 192, delta: 0, oy: 519, vy: 519, delta: 0
ox: 192, vx: 192, delta: 0, oy: 519, vy: 519, delta: 0
ox: 192, vx: 192, delta: 0, oy: 518, vy: 518, delta: 0
ox: 192, vx: 192, delta: 0, oy: 518, vy: 518, delta: 0
ox: 192, vx: 192, delta: 0, oy: 517, vy: 517, delta: 0
ox: 192, vx: 192, delta: 0, oy: 516, vy: 517, delta: -1
ox: 192, vx: 192, delta: 0, oy: 516, vy: 516, delta: 0
ox: 192, vx: 192, delta: 0, oy: 516, vy: 516, delta: 0
ox: 192, vx: 192, delta: 0, oy: 515, vy: 515, delta: 0
ox: 192, vx: 192, delta: 0, oy: 514, vy: 515, delta: -1
ox: 192, vx: 192, delta: 0, oy: 514, vy: 514, delta: 0
ox: 192, vx: 192, delta: 0, oy: 513, vy: 513, delta: 0
ox: 192, vx: 192, delta: 0, oy: 513, vy: 513, delta: 0
ox: 192, vx: 192, delta: 0, oy: 512, vy: 512, delta: 0
ox: 192, vx: 192, delta: 0, oy: 511, vy: 511, delta: 0
ox: 192, vx: 192, delta: 0, oy: 511, vy: 511, delta: 0
ox: 192, vx: 192, delta: 0, oy: 510, vy: 510, delta: 0
ox: 192, vx: 192, delta: 0, oy: 510, vy: 510, delta: 0
ox: 192, vx: 192, delta: 0, oy: 509, vy: 509, delta: 0
ox: 192, vx: 192, delta: 0, oy: 509, vy: 509, delta: 0
ox: 192, vx: 192, delta: 0, oy: 508, vy: 508, delta: 0
ox: 192, vx: 192, delta: 0, oy: 508, vy: 508, delta: 0
ox: 192, vx: 192, delta: 0, oy: 507, vy: 507, delta: 0
ox: 192, vx: 192, delta: 0, oy: 506, vy: 507, delta: -1
ox: 192, vx: 192, delta: 0, oy: 506, vy: 506, delta: 0
ox: 192, vx: 192, delta: 0, oy: 505, vy: 506, delta: -1
ox: 192, vx: 192, delta: 0, oy: 505, vy: 505, delta: 0
ox: 192, vx: 192, delta: 0, oy: 504, vy: 504, delta: 0
ox: 192, vx: 192, delta: 0, oy: 504, vy: 504, delta: 0
ox: 192, vx: 192, delta: 0, oy: 503, vy: 503, delta: 0
ox: 192, vx: 192, delta: 0, oy: 503, vy: 503, delta: 0
ox: 192, vx: 192, delta: 0, oy: 502, vy: 502, delta: 0
ox: 192, vx: 192, delta: 0, oy: 502, vy: 502, delta: 0
ox: 192, vx: 192, delta: 0, oy: 501, vy: 501, delta: 0
ox: 192, vx: 192, delta: 0, oy: 501, vy: 501, delta: 0
ox: 192, vx: 192, delta: 0, oy: 500, vy: 500, delta: 0
User avatar
dusoft
Party member
Posts: 676
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Object on the screen trembles if rendered with viewport coords

Post by dusoft »

It seems there is an issue in your MathHelper.round function or its parameters (getX/getY functions). If both values in are 192,192, you can not get random results out. The results out need to be stable as well, thus the function or its params/functions are the issue.
lysandre
Prole
Posts: 9
Joined: Sun Sep 01, 2024 3:31 pm

Re: Object on the screen trembles if rendered with viewport coords

Post by lysandre »

Well but the x doesn't change since the movement of the player is on the y axis (up). If instead I'd move it left or right the x will change and the y will not.

The getX/getY are getters: they simply return the value of the x/y field of the viewport object. The implementation of the MathHelper.round method is the same of the "Rounds towards zero" of the example you provided.
User avatar
dusoft
Party member
Posts: 676
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Object on the screen trembles if rendered with viewport coords

Post by dusoft »

If this code causes the output as logged above, there is a covert issue somewhere that I can not see in the code provided. You can try more simple print statements in your other functions including getters and the round helper itself.
RNavega
Party member
Posts: 404
Joined: Sun Aug 16, 2020 1:28 pm

Re: Object on the screen trembles if rendered with viewport coords

Post by RNavega »

(Acknowledging that this is OCD from this point on, since the problem is already solved.)
Looking at the code in the first post again, there are many uses of math.floor() including inside functions which I imagine run frequently.
Do you guys think this might be causing the difference?

Code: Select all

    local x = math.floor(params.x) or 0
    local y = math.floor(params.y) or 0
    local width = math.floor(params.width) or virtualWidth
    local height = math.floor(params.height) or virtualHeight

Code: Select all

    local function setCenter()
        center = {
            x = math.floor(x + (width / 2)),
            y = math.floor(y + (height / 2))
        }
    end

Code: Select all

    function self.update()
        if object then
            x = math.floor(object.x - virtualWidth * 0.5)
            y = math.floor(object.y - virtualHeight * 0.5)
        end
    end

Code: Select all

    function self.render()
        if object then
            love.graphics.translate(
                math.floor(-object.x + virtualWidth * 0.5),
                math.floor(-object.y + virtualHeight * 0.5)
            )
        end
    end

Code: Select all

    function self.setOrigin()
        x = math.floor(center.x - (width / 2))
        y = math.floor(center.y - (height / 2))
    end
User avatar
dusoft
Party member
Posts: 676
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Object on the screen trembles if rendered with viewport coords

Post by dusoft »

Yes, I would recommend rounding only in the output/process function, nowhere else (e.g. render function should be getting properly rounded values and not to do additional round of rounding, pun intended). This might eliminate many points where rounding changes the result.
lysandre
Prole
Posts: 9
Joined: Sun Sep 01, 2024 3:31 pm

Re: Object on the screen trembles if rendered with viewport coords

Post by lysandre »

Update: I simplify the code this way:

Code: Select all

-- file viewport.lua
function self.update()
    if object then
        x = object.x - halfVirtualWidth
        y = object.y - halfVirtualHeight
    end
end

function self.render()
    if object then
        -- trembling if translating to not integer positions
        -- pass only integer values
        love.graphics.translate(
            -object.x + halfVirtualWidth,
            -object.y + halfVirtualHeight
        )
    end
end

-- file Entity.lua
function self.setX(value) x = MathHelper.round(value) end
function self.setY(value) y = MathHelper.round(value) end
function self.setRenderX(value) renderX = MathHelper.round(value) end
function self.setRenderY(value) renderY = MathHelper.round(value) end

-- file EntityBaseState.lua (where the rendering of the entity happens)
---@param params {x: integer, y: integer}
function self.render(params)
    local x, y = params.x, params.y
    local anim = entity.getCurrentAnimation()
    for _, texture in ipairs(anim.getTexture()) do
        love.graphics.draw(
            texture.getImage(),
            texture.getQuads()[anim.getCurrentFrame()],
            x,
            y
        )
    end
end

-- file World.lua
local ox, oy = love.graphics.inverseTransformPoint(0, 0)
locationSignPanel.render(ox + 2, oy + 2)
locationSignText.render(ox + 4, oy + 6)
Now the x, y, renderX and renderY of the entity are always integer values, as they should.

The major effect of this refactor is that the entity movement is now even cleaner. If I try to reference directly the viewport while rendering the location sign, as I did in the initial code, the rendering is still not optimal, due to the fact that the value of viewport.getX() and viewport.getY() are different from the ox and the oy that love.graphics.inverseTransformPoint(0, 0) gaves me (if i print them there's always a difference of 1 or -1 depending on the direction of the movement).

Sincerly I went on with other features of the game, since for me the problem is fully addressed and I don't want to go any further investigation, but I thought it would be nice to give an update.

Many thanks.
Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests