Scaling elements without stretch ?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Gogbayls
Prole
Posts: 3
Joined: Fri Aug 14, 2020 12:35 pm

Scaling elements without stretch ?

Post 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.
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to scaling children elements without stretch ?

Post 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
...
Gogbayls
Prole
Posts: 3
Joined: Fri Aug 14, 2020 12:35 pm

Re: How to scaling children elements without stretch ?

Post 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?
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to scaling children elements without stretch ?

Post 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
Gogbayls
Prole
Posts: 3
Joined: Fri Aug 14, 2020 12:35 pm

Re: How to scaling children elements without stretch ?

Post 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.
sphyrth
Party member
Posts: 260
Joined: Mon Jul 07, 2014 11:04 am
Contact:

Re: Scaling elements without stretch ?

Post 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.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 3 guests