[Help] Techniques for scaling

General discussion about LÖVE, Lua, game development, puns, and unicorns.
glass2d
Prole
Posts: 14
Joined: Thu Apr 18, 2024 11:40 pm

[Help] Techniques for scaling

Post by glass2d »

Background
I'm new to LOVE and could use some guidance on navigating certain aspects. Currently, I'm developing a top-down pixel art game with a 16:9 aspect ratio. The native resolution of the game is set to 480 x 270, and I've implemented the HUMP library for creating a camera that tracks the player. To maintain a consistent visual experience, I've opted for a camera scale of 4/3. When upscaling the game, such as to 1920x1080, I multiply both the camera scale and window dimensions by 4, ensuring proper scaling.

Issue
After scaling up, I've encountered tearing in the visuals. My game map is constructed using Tiled with a 16x16 tile set. Researching on forums, I found suggestions to use math.floor on the camera's x and y coordinates to address tearing. However, implementing this solution causes the player to appear jittery as the camera snaps to integer values. The player's movement is continuous in both x and y directions, while the camera's coordinates are floored. Additionally, I prefer to maintain the decimal scaling for the 4/3 camera scale, as it provides the best visual aesthetics. Some sources also recommend extruding the tiles to alleviate tearing, but I'm hesitant to undertake that task for every tile without certainty of its necessity.

I'm seeking insights into effective techniques to mitigate these issues while preserving the desired visual presentation.
User avatar
pgimeno
Party member
Posts: 3572
Joined: Sun Oct 18, 2015 2:58 pm

Re: [Help] Techniques for scaling

Post by pgimeno »

What do you mean by jittery? Do you mean it snaps to virtual 480x270 pixels, and you want it to have screen-pixel movement as opposed to virtual-pixel movement? I find it hard to imagine what can be producing the tearing with the data you've provided.

If you can, posting a .gif animation would help understanding what you mean exactly. Certainly, posting a .love file with a minimal test case would help even more - it doesn't even have to use the same assets as your production, just something basic that exhibits the problem.
User avatar
dusoft
Party member
Posts: 518
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: [Help] Techniques for scaling

Post by dusoft »

Well, not flooring player movement, while camera movement is floored might cause some mismatch. Video or GIF would help as would the code as pgimeno said.
Last edited by dusoft on Tue May 07, 2024 10:58 pm, edited 1 time in total.
RNavega
Party member
Posts: 269
Joined: Sun Aug 16, 2020 1:28 pm

Re: [Help] Techniques for scaling

Post by RNavega »

I think the inexact 4/3 camera scale at such a low fidelity will mess things up.
If your native canvas is really 480 x 270 then you should be able to draw the game screen at that size, without upscaling anything, and having it appear perfectly -- take a screenshot, go to some paint program and paste it and zoom in to see if the native graphics are coming out alright.
If you can get this native canvas / the ground truth looking fine (which you haven't exactly confirmed to have done yet), then you know that the problem is definitely coming only from the upscaling part.
glass2d
Prole
Posts: 14
Joined: Thu Apr 18, 2024 11:40 pm

Re: [Help] Techniques for scaling

Post by glass2d »

I've added videos of the behavior I am describing.

1. 480_270 -> Cam at 4/3 zoom no tearing, not character blur
2. 1440_810 -> Cam at 4/3 zoom * 4 with tearing, no character blur
3. floor_cam_player_blur -> Cam at 4/3 zoom * 4 with tearing, math.floor cam x, y `self:lockPosition(math.floor(camX), math.floor(camY))` player blur in motion
Attachments
examples.zip
(26.99 MiB) Downloaded 18 times
glass2d
Prole
Posts: 14
Joined: Thu Apr 18, 2024 11:40 pm

Re: [Help] Techniques for scaling

Post by glass2d »

Here is an example of what I'm seeing when I math.floor both the player and the camera movement. I see snapping in the background tiles during movement especially diagonal movement (FYI I scale the movement vector when the player is moving along the diagonal to limit the max speed)
Attachments
floor_player_and_cam.gif
floor_player_and_cam.gif (62.85 MiB) Viewed 410 times
glass2d
Prole
Posts: 14
Joined: Thu Apr 18, 2024 11:40 pm

Re: [Help] Techniques for scaling

Post by glass2d »

I'm open to sharing my project publicly since I'm currently using placeholder assets. You can find the repository for the top-down game I'm developing here [https://github.com/znimon/alchemist]. I'm still encountering issues understanding the root cause of tearing when I scale up both the window and the camera. Any insights into what might be causing this problem would be greatly appreciated!
User avatar
_JM_
Prole
Posts: 17
Joined: Thu Mar 30, 2023 9:06 pm
Contact:

Re: [Help] Techniques for scaling

Post by _JM_ »

I think I resolved the problem flooring player and camera position (maybe you did it the wrong way?)

Anyway, I attached a .love file with the fixes

These were my changes:
  • add a global "Round" method get from lua programming book;
  • use that function to round the camera position on playercamera:update;
  • rounding the player position when drawing the sprite on player:draw
See if this was how it was supposed to work.
Attachments
alchemist_fix.love
(600.52 KiB) Downloaded 13 times
glass2d
Prole
Posts: 14
Joined: Thu Apr 18, 2024 11:40 pm

Re: [Help] Techniques for scaling

Post by glass2d »

I tried what you're describing but I get the same "vibration" behavior as shown in the gif above. Observe how the fountain asset moves back and forth as the player moves along the diagonal. Here is my code...

utils.lua (Fn from Programming_in_Lua,_4th_ed._(2017))

Code: Select all

function round(x)
    local f = math.floor(x)
    if (x == f) or (x % 2.0 == 0.5) then
        return f
    else
        return math.floor(x + 0.5)
    end
end

playercamera.lua

Code: Select all

function PlayerCamera:update(dt)
    local camX = Player.x
    local camY = Player.y
    local mapW = Map.width * Map.tilewidth
    local mapH = Map.height * Map.tileheight
    camX, camY = self:setBorders(camX, camY, mapW, mapH)
    local rcamX = round(camX)
    local rcamY = round(camY)
    self:lockPosition(rcamX, rcamY)
end
player.lua

Code: Select all

function Player:draw()
    local rpx = round(self.x)
    local rpy = round(self.y)
    self.anim:draw(self.spriteSheet, rpx, rpy, nil, nil, nil, 8, 16)
end
User avatar
_JM_
Prole
Posts: 17
Joined: Thu Mar 30, 2023 9:06 pm
Contact:

Re: [Help] Techniques for scaling

Post by _JM_ »

Hmm... try round the position of the player's body on syncPhysics method. Like this:

Code: Select all

function Player:syncPhysics()
    local bd = self.physics.body
    bd:setPosition(
        round(bd:getX()),
        round(bd:getY())
    )
    self.x, self.y = self.physics.body:getPosition()
    self.physics.body:setLinearVelocity(self.vx, self.vy)
end
Post Reply

Who is online

Users browsing this forum: Semrush [Bot] and 5 guests