Making A Line Between Two GUI Points

I’ve been trying to create a line that goes between two of my GUI objects to create sort of a trail. Each of my GUIs have an AnchorPoint of 0.5, 0.5, to make the line connect them by the middle points.

The resizing and positioning of the line seems fine, but the rotation seems to be a bit wonky and out of place. Here’s a GIF showing my problem.
https://gyazo.com/714d8e5ec01fb1b4be9ba68c68e077b6

Here’s the code i’m running from the command bar:

local gui = game.StarterGui.Main.Fight
local line = gui.Line 
local c1 = gui.C1 
local c2 = gui.C2
local c1v = Vector2.new(c1.Position.X.Scale, c1.Position.Y.Scale)
local c2v = Vector2.new(c2.Position.X.Scale, c2.Position.Y.Scale) 
local mid = c1v:lerp(c2v, 0.5) 
line.Position = UDim2.new(mid.X, 0, mid.Y, 0) 
line.Rotation = math.deg(math.atan((mid.Y - c2v.Y) / (mid.X - c2v.X))) 
line.Size = UDim2.new((mid - c2v).magnitude * 2, 0, 0.01, 0)
6 Likes

You should calculate the slope based on their absolute position instead of their scales. A screen that’s 2000x1000 pixels wide would throw your math off.

2 Likes

In addition, to what @XAXA said, use math.atan2 to calculate the angle. It’s a life-saver. From the Wiki:

math.atan2

number math.atan2(number y, number x)

Description: Returns the arc tangent of y/x (in radians), but uses the signs of both parameters to find the quadrant of the result. It also handles correctly the case of x being zero.

(in your case, the quadrant part of math.atan2 doesn’t affect much, but the handling x being zero part is nice)

4 Likes

Someone had a similar issue. My response can be found here and may help you:

1 Like

Your code doesn’t seem to be functioning correctly

Not Working.rbxl (175.3 KB)

Unless I did something wrong, can you check it out?

I tried using both already, I just didn’t bother switching back to it because I realized that’s not the problem here anyways.

Yes, the code I provided explicitly uses offsets. Your example uses scales. As someone already pointed out, using scales would not be effective as most screens are not squares and 1.0 across the X wouldn’t be the same as 1.0 across the Y.

local function DrawLine(from: Vector2, to: Vector2, options: { color: Color3 | nil, width: number | nil }): (Frame)
    if not options then options = {} end

    local distance = to - from

	local line = Instance.new("Frame", script.Parent)
	line.AnchorPoint = Vector2.new(0.5, 0.5)
	line.BackgroundColor3 = options.color or Color3.fromRGB(255, 0, 0)
	line.Rotation = math.atan2(distance.Y, distance.X) * (180 / math.pi)
	line.Position = UDim2.fromOffset((to + from).X / 2, (to + from).Y / 2)
	line.Size = UDim2.fromOffset((distance.X ^ 2 + distance.Y ^ 2) ^ 0.5, options.width == nil and 1 or options.width)
	return line
end

local function DrawLineUI(guiObject1: GuiBase2d, guiObject2: GuiBase2d, options: { color: Color3 | nil, width: number | nil }): (Frame)
	local from = guiObject1.AbsolutePosition + (guiObject1.AbsoluteSize * Vector2.new(0.5, 0.5))
	local to = guiObject2.AbsolutePosition + (guiObject2.AbsoluteSize * Vector2.new(0.5, 0.5))

	return DrawLine(from, to, options)
end

DrawLine(Vector2.new(100, 100), Vector2.new(200, 200), {color = Color3.fromRGB(0, 255, 0)}) -- Create a green line from (x: 100, y: 100) to (x: 200, y: 200)
-- Updated at 29/11/2023 
-- typing added
-- 'options' added
8 Likes

The math algorithms were created by @RuizuKun_Dev, I just fixed some errors

For some odd reason, when I used this algorithm, it appeared as though the one line was not working as intended.

It wasn’t an error of arguments either, if I removed an instance causing the issue in the for loop, another line would be glitched in the same way. If you could help me understand what was causing the issue, it would be rather helpful. Here’s a screenshot of what it looks like.

I use this in my script

local a = Mainframe.UDim2.toVector2(teamPositions[team1])
local b = Mainframe.UDim2.toVector2(teamPositions[team2])

if b.X < a.X then --a is always on left
	local temp = a
	a=b
	b=temp
end
local barx,bary = Mainframe.midpoint(a.X, a.Y, b.X, b.Y)
bar.Size = UDim2.fromOffset(bar.Size.X.Offset, (a-b).Magnitude)
bar.Position = UDim2.new(0.5,barx,0.5,bary)
bar.Rotation = math.deg(math.atan2(bar.Position.Y.Offset,bar.Position.X.Offset))

This way of creating lines is a workaround, you must create a “correct” shape with the start position, the end position, and the size of the line, so you can do all the possible calculations (for example, calculate the intersection point)

(Take the CanvasContextRendering2D[web api] as an example)

You would also need to create a way to render the data ‘-’