I'm creating a gamepass for my game - this gamepass will allow users to purchase a 2D box ESP [only during frenzy mode], giving them an advantage over players who only have access to the radar (which I plan to have all users visible on at all times, during something I'm calling "frenzy mode" in my FPS).
To do this, I've created a simple implementation. When players leave, join, whatnot, I create a GUI for them which has 4 frames contained within it on each client that has purchased the 2d box esp. When its frenzy mode, I parent the gui's to the playergui. When it isn't, I parent it to replicatedstorage [note: I'm aware this isn't that secure, I'm just trying to get it >working< before worrying about that. I have ideas in mind].
Anyhow, to make my idea a reality - I need to draw a line 2 pixels thick [I'd settle for one if its too hard to take width into account, but I prefer 2 as 1 isn't very visible] between point A and point B.
This is fairly simple if I didn't have to account for rotation, if it's going up/down or left/right, etc. Just subtract to get the distance, use math.abs() to make it absolute, and resize the frame + position it accordingly.
However, I'm stuck when accounting for the fact that I need to be going both up/down and left/right for two lines each, AND accounting for rotation and whatnot.
I've already calculated the 2d position of the player, the topleft, topright, bottomleft, bottomright, all of that jazz - so I have the base coordinates.
The only thing left is to fill in this function, and it will be 100% functional - everything else is done, literally, including calling this function once calculating all of the math.
local function AdjustLine(LineHandle, PointOneX, PointOneY, PointTwoX, PointTwoY, Color, Thickness) --\\Fill in my line here... smh I suck at math... end;
This is the function I'm trying to fill in. Now to make it clear here, -I'M NOT asking for a spoonfeed or fully written code. I'd just like to know if someone can shed some light on the math/implementation behind this (preferably explaining it like I'm 5, because I can barely comprehend algebra tbh).
And I hope this question is found relevant to others and not deleted/downvoted - because I'm sure while the reason behind it isn't exactly the same, SOMEONE else has to be or will be or has been wondering how to draw a line between 2 points.
You want to position LineHandle
such that it connects two points. First for the sake of simplicity, it will make it much easier if the anchor points of all gui elements involved in the positioning of this line have their AnchorPoint
set to 0.5 , 0.5
. In addition, we're going to be using Vector2
s for this problem as it's much easier to work with in this scenario.There are three things that need to be calculated: position, size, and rotation.
Position is the easiest as it's literally just the middle of the two points. The position can be calculated by adding the two vectors up and then dividing it by two. This is exactly the same as finding the middle of two regular numbers because it uses the same logic. The position part would look like this:
--Position local position = (PointOne + PointTwo) / 2
Size can be calculated by finding the displacement vector between the two points and getting the magnitude of that. A displacement vector can be thought of as a line connecting two points (kind of like what we're doing right now). A displacement vector can be calculated by subtracting one vector from another. For example if you wanted to find the displacement between a vector called v1
and another one called v2
, the displacement would be v2 - v1
. The magnitude of a vector is its length. The formula for calculating magnitude is irrelevant here because it is already done for us and can be accessed by doing vector.Magnitude
. By getting the magnitude of the displacement vector, we are essentially getting the distance between the two points (remember that we will be converting all our vectors in to UDim2
s later).
--Size local size = Vector2.new((PointOne - PointTwo).Magnitude , Thickness)
This seems like the trickiest part because it requires a tad of trigonometry but it's not all that hard. First, we get the displacement vector again (explained in the prior section). In order to get our rotation, we will need to find the angle this vector makes with the x axis. If we think of this vector like the hypotenuse a triangle, we find that the x
value of this vector is the adjacent side and the y
value of this vector is the opposite side. In order to get our angle, we simply need to take the inverse tangent of opposite divided by adjacent or in this case, our y
component divided by the x
component of our vector. This is how it looks like:
--Rotation local displacement = PointTwo - PointOne local rotation = math.atan(direction.Y / direction.X)
Now, all that's left is to change the color of our line handle and convert our position and size into UDim2
s. We also need to convert our rotation from radians into degrees. This is how the final function would look like:
function adjustLine(LineHandle , PointOne , PointTwo , Color , Thickness) --Position local position = (PointOne + PointTwo) / 2 --Size local size = Vector2.new((PointOne - PointTwo).Magnitude , Thickness) --Rotation local displacement = PointTwo - PointOne local rotation = math.atan(direction.Y / direction.X) LineHandle.Size = UDim2.new(0 , size.X , 0 , size.Y) LineHandle.Position = UDim2.new(0 , position.X , 0 , position.Y) LineHandle.Rotation = math.deg(rotation) LineHandle.BackgroundColor3 = Color end
Example Usage:
local line = ... local frame1 = ... local frame2 = ... adjustLine(line , frame1.AbsolutePosition , frame2.AbsolutePosition , Color3.fromRGB(61, 128, 252) , 2)