Page 1 of 1

Scaling elements without stretch ?

Posted: Fri Aug 14, 2020 1:25 pm
by Gogbayls
I found the code for scaling elements by window size and convert him to lua but i have a problem with scaling rectangles, they stretch when the window is resized but i want save original form. How to fix this problem ?
My code:

Code: Select all

local objects = {
    {x = g_x + 0, y = g_y, w = 50, h = 50},
    {x = g_x + 55, y = g_y, w = 50, h = 50},
    {x = g_x + 110, y = g_y, w = 50, h = 50},
    {x = g_x + 165, y = g_y, w = 50, h = 50},
    {x = g_x + 220, y = g_y, w = 50, h = 50}
}

function love.load()
    love.window.setMode(800, 600, {resizable=true, vsync=false, minwidth=400, minheight=300})
    local n = {x = love.graphics.getWidth() / 2 - 25,y = love.graphics.getHeight() / 2 - 25,w = 50,h = 50}
    table.insert(objects, n)
end

local default_w = love.graphics.getWidth()
local default_h = love.graphics.getHeight()

function love.draw()
    for i = 1, #objects do
        local obj = objects[i]
        love.graphics.setColor(42, 42, 42)
        love.graphics.rectangle("fill", obj.x, obj.y, obj.w, obj.h)
    end
end

function love.resize( new_w, new_h )

	local scale_Width = new_w / default_w
	local scale_Height = new_h / default_h

	for i = 1, #objects do

	    local obj = objects[i]

	    obj.x = obj.x * scale_Width
	    obj.y = obj.y * scale_Height

		obj.w = obj.w * scale_Width
		obj.h = obj.h * scale_Height

	end

    default_w = new_w
    default_h = new_h

end
Without change window size : https://love2d.org/imgmirrur/zWKNoou.png
Example of problem : https://love2d.org/imgmirrur/MIIbkGW.png
What i want make : https://love2d.org/imgmirrur/2la4Bye.png - Blue rects was save original proportionals is what i want make but currently in my case white rects is stretched like in second screenshot.
Ok so, if you don't want help me with code, give me any examples with the same, because i not found any information with that problem.

Re: How to scaling children elements without stretch ?

Posted: Sun Aug 16, 2020 12:39 am
by pgimeno
There are some ways to preserve the aspect ratio, but I don't think we have enough context.

But something like this might help:

Code: Select all

	local scale_Width = new_w / default_w
	local scale_Height = new_h / default_h
	scale_Width = math.min(scale_Width, scale_Height)
	scale_Height = scale_Width
...

Re: How to scaling children elements without stretch ?

Posted: Sun Aug 16, 2020 3:13 pm
by Gogbayls
pgimeno wrote: Sun Aug 16, 2020 12:39 am There are some ways to preserve the aspect ratio, but I don't think we have enough context.
I tested your version, but it has position problems and with changing size.
Problems :https://files.catbox.moe/f3271r.mp4
What do you mean by context?

Re: How to scaling children elements without stretch ?

Posted: Sun Aug 16, 2020 3:44 pm
by pgimeno
Gogbayls wrote: Sun Aug 16, 2020 3:13 pm I tested your version, but it has position problems and with changing size.
Problems :https://files.catbox.moe/f3271r.mp4
What do you mean by context?
Exactly that. You haven't mentioned how you want to deal with the issues inherent to scaling. And you haven't given enough code to allow us to run it.

The basic idea to preserve the aspect ratio is to keep the horizontal and vertical scale always the same. Beyond that, there's lots of variations: trim the part that overflows; zoom out to fit everything, leaving an empty stripe; keep an intermediate size with a smaller empty stripe and a smaller part trimmed; let more of the background be visible as the screen stretches; move certain objects to occupy the larger area; align left, right, top, down, or centre. Maybe you can imagine your own variation.

Edit: OK, it seems you edited your post to add more code; after defining g_x and g_y the program works. Well, scaling the coordinates of the objects is a recipe for disaster, so it's no wonder that you're having trouble. You need to apply the scale to the original objects, not to the already scaled objects. Your default_w and default_h should not change and should be your design size (800, 600 according to the program). That way, the original objects work for your design size, so scaling these sizes by the ratio between the actual size and the design size works.

Bottom line: just do the scaling when drawing, do not store the scaled values back into the object, and do not update default_w and default_h. You can get rid of love.resize altogether.

Alignment aside, this works:

Code: Select all

local g_x = 0
local g_y = 0
local objects = {
    {x = g_x + 0, y = g_y, w = 50, h = 50},
    {x = g_x + 55, y = g_y, w = 50, h = 50},
    {x = g_x + 110, y = g_y, w = 50, h = 50},
    {x = g_x + 165, y = g_y, w = 50, h = 50},
    {x = g_x + 220, y = g_y, w = 50, h = 50}
}

local default_w, default_h = 800, 600

function love.load()
    love.window.setMode(default_w, default_h, {resizable=true, vsync=false, minwidth=400, minheight=300})
    local n = {x = love.graphics.getWidth() / 2 - 25,y = love.graphics.getHeight() / 2 - 25,w = 50,h = 50}
    table.insert(objects, n)
end

function love.draw()
    local new_w, new_h = love.graphics.getDimensions()
    local s = math.min(new_w / default_w, new_h / default_h)

    for i = 1, #objects do
        local obj = objects[i]
        love.graphics.setColor(42, 42, 42)
        love.graphics.rectangle("fill", obj.x * s, obj.y * s, obj.w * s, obj.h * s)
    end
end

Re: How to scaling children elements without stretch ?

Posted: Mon Aug 17, 2020 9:01 am
by Gogbayls
pgimeno wrote: Sun Aug 16, 2020 3:44 pm
Gogbayls wrote: Sun Aug 16, 2020 3:13 pm I tested your version, but it has position problems and with changing size.
Problems :https://files.catbox.moe/f3271r.mp4
What do you mean by context?
Exactly that. You haven't mentioned how you want to deal with the issues inherent to scaling. And you haven't given enough code to allow us to run it.

The basic idea to preserve the aspect ratio is to keep the horizontal and vertical scale always the same. Beyond that, there's lots of variations: trim the part that overflows; zoom out to fit everything, leaving an empty stripe; keep an intermediate size with a smaller empty stripe and a smaller part trimmed; let more of the background be visible as the screen stretches; move certain objects to occupy the larger area; align left, right, top, down, or centre. Maybe you can imagine your own variation.

Edit: OK, it seems you edited your post to add more code; after defining g_x and g_y the program works. Well, scaling the coordinates of the objects is a recipe for disaster, so it's no wonder that you're having trouble. You need to apply the scale to the original objects, not to the already scaled objects. Your default_w and default_h should not change and should be your design size (800, 600 according to the program). That way, the original objects work for your design size, so scaling these sizes by the ratio between the actual size and the design size works.

Bottom line: just do the scaling when drawing, do not store the scaled values back into the object, and do not update default_w and default_h. You can get rid of love.resize altogether.

Alignment aside, this works:

Code: Select all

local g_x = 0
local g_y = 0
local objects = {
    {x = g_x + 0, y = g_y, w = 50, h = 50},
    {x = g_x + 55, y = g_y, w = 50, h = 50},
    {x = g_x + 110, y = g_y, w = 50, h = 50},
    {x = g_x + 165, y = g_y, w = 50, h = 50},
    {x = g_x + 220, y = g_y, w = 50, h = 50}
}

local default_w, default_h = 800, 600

function love.load()
    love.window.setMode(default_w, default_h, {resizable=true, vsync=false, minwidth=400, minheight=300})
    local n = {x = love.graphics.getWidth() / 2 - 25,y = love.graphics.getHeight() / 2 - 25,w = 50,h = 50}
    table.insert(objects, n)
end

function love.draw()
    local new_w, new_h = love.graphics.getDimensions()
    local s = math.min(new_w / default_w, new_h / default_h)

    for i = 1, #objects do
        local obj = objects[i]
        love.graphics.setColor(42, 42, 42)
        love.graphics.rectangle("fill", obj.x * s, obj.y * s, obj.w * s, obj.h * s)
    end
end
Thank you for helping, but I changed your code a little for myself because the position doesn't work the way I wanted it to.
I was made two videos for you can see difference.
Your example: https://files.catbox.moe/h38enr.mp4
My: https://files.catbox.moe/4hnaqq.mp4

Code: Select all

local ratioX = new_w / default_w
local ratioY = new_h / default_h
love.graphics.rectangle("fill", obj.x * ratioX, obj.y * ratioY, obj.w * s, obj.h * s)
I think now a position should be correct.

Re: Scaling elements without stretch ?

Posted: Mon Aug 17, 2020 1:09 pm
by sphyrth
By the behavior that you want. It seems that you're trying to make a "Toolbar Menu" of some sort. It makes sense to imagine those squares as icons.