How to convert a circular pattern of UI Frames into scale from offset?

As explained by the title, I have a script which creates UI Frames and puts them into a circular pattern, I’ve already converted their position and scale to offset, but I don’t know how to convert the radius (Their distance from the center of the screen) to offset. What do I have to do and where do I begin in order to convert radius (A number) and influence it with the screen size to create a scaled radius?

Any help would be much appreciated.

local function CreateCircles(SpellName)
	Active = true
	ActiveSpell = SpellName

	for _, v in ipairs(MainFrame:GetChildren()) do
		if v:IsA("Frame") and v.Name ~= "LinesFrame" then
			v:Destroy()
		end
	end

	for _, v in ipairs(LineFolder:GetChildren()) do
		v:Destroy()
	end

	Circles = {}
	CurrentIndex = 1

	local Config = SpellCastingInfo:FindSpellInfo(SpellName)
	if not Config then return end

	local TimeLimit = Config.TimeLimit
	local ManaCircleCount = Config.ManaCircleCount
	local ManaCircleSize = Config.ManaCircleSize
	local Radius = Config.Radius

	local angleStep = (2 * math.pi) / ManaCircleCount
	for i = 1, ManaCircleCount do
		local newCircle = TemplateCircle:Clone()
		newCircle.Visible = true
		newCircle.Name = "Circle_" .. i
		newCircle.Size = UDim2.fromScale(ManaCircleSize / GuiObj.AbsoluteSize.Y, ManaCircleSize / GuiObj.AbsoluteSize.Y)

		if i == 1 then
			newCircle.ManaImage.ImageColor3 = Color3.new(1, 0.827451, 0.396078)
		end

		if i == ManaCircleCount then
			newCircle.ManaImage.ImageColor3 = Color3.new(0.729412, 0, 0.0117647)
		end

		local angle = (i - 1) * angleStep

		local x = math.cos(angle) * Radius
		local y = math.sin(angle) * Radius
		local OffsetPos = UDim2.fromOffset(MainFrame.AbsoluteSize.X/2.1 + x - ManaCircleSize/2, MainFrame.AbsoluteSize.Y/2.1 + y - ManaCircleSize/2)
		newCircle.Position = UDim2.fromScale(OffsetPos.X.Offset / GuiObj.AbsoluteSize.X, OffsetPos.Y.Offset / GuiObj.AbsoluteSize.Y)
		newCircle.Parent = MainFrame
		table.insert(Circles, newCircle)
	end
end

I’m mainly focusing on this part of the function:

local Radius = Config.Radius

	local angleStep = (2 * math.pi) / ManaCircleCount
	for i = 1, ManaCircleCount do
		local newCircle = TemplateCircle:Clone()
		newCircle.Visible = true
		newCircle.Name = "Circle_" .. i
		newCircle.Size = UDim2.fromScale(ManaCircleSize / GuiObj.AbsoluteSize.Y, ManaCircleSize / GuiObj.AbsoluteSize.Y)

		if i == 1 then
			newCircle.ManaImage.ImageColor3 = Color3.new(1, 0.827451, 0.396078)
		end

		if i == ManaCircleCount then
			newCircle.ManaImage.ImageColor3 = Color3.new(0.729412, 0, 0.0117647)
		end

		local angle = (i - 1) * angleStep

		local x = math.cos(angle) * Radius
		local y = math.sin(angle) * Radius
		local OffsetPos = UDim2.fromOffset(MainFrame.AbsoluteSize.X/2.1 + x - ManaCircleSize/2, MainFrame.AbsoluteSize.Y/2.1 + y - ManaCircleSize/2)
		newCircle.Position = UDim2.fromScale(OffsetPos.X.Offset / GuiObj.AbsoluteSize.X, OffsetPos.Y.Offset / GuiObj.AbsoluteSize.Y)
		newCircle.Parent = MainFrame
		table.insert(Circles, newCircle)
	end

Your code looks fine to me. You’re converting the polar coordinates Radius and angle into x and y. When you convert the UDim2 from offset to scale the radius should already be taken into account.

Could you provide an example of what Circles ends up being after you run this? In particular the Positions that are assigned on the parts.

1 Like

Oh! Sorry, I posted this at 1 in the morning and fell asleep afterwards, sure thing. This is the end result of the circles and the result I want:

Half Screen (Split screen on windows)

Full Screen (Standard)

I want it so that on the Half Screen (Like when split-screening), the circles move closer to the center of the screen to avoid the distance between each of them being too big
Like this:


Green = Wanted behaviour
Red = Actual behaviour

I think if you modify the Radius to take account of the screen size then it will adjust like you want. Rather than simply reading the radius from the config.

local Radius = Config.Radius

Make the config value a percentage value or a UDim and then use ScreenGui.AbsoluteSize to determine the result.

local screenGui = ...current screen gui...
local radiusFactor = UDim.fromScale(0.5) -- Config.Radius
local minScreenSize = math.min(screenGui.AbsoluteSize.X, screenGui.AbsoluteSize.Y)
local Radius = radiusFactor.Scale * minScreenSize + radiusFactor.Offset

And then you can detect changes in the screen size by watching the AbsoluteSize property and adjust the positions of all the circles.

function resizeScreen()
  ... redo the position calculations to move the circles...
end
screenGui:GetPropertyChangedSignal("AbsoluteSize"):Connect(resizeScreen)
1 Like

Sure, thank you! I can’t work on it right now but I’ll update as soon as I can on whether this solves the problem.

Again, thank you for taking the time to reply and answer!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.