What are arbitrary angles? and how would i use them for a smooth turn

Was making a tower defence game when I came across a post made by atrazine over on twitter, about how he used arbitrary angles to make smooth turns, he also states the fact that you can use them to make smooth turns for any type of angle. I would just like to know if anyone could help with with a few questions based on them:

• What even are they?
• How could you use them / how are they helpful?
• How could you use them to make smooth turns?

I have no idea of how I would make it.

Post : https://twitter.com/AtrazineC/status/1519014455090196481

2 Likes

Pretty sure they are just random angles, but how would I create a smooth turn. He says that he uses one node to smooth it out, probably just using math to move the position of it

2 Likes

I would try using a spline module

1 Like

However it still doesn’t create a perfect turn, rather more of a weird one.

1 Like

Not too certain about this topic but I do know you can control the shape of the curve of splines.

I would try adjust the curve using the tension value in the constructor.

1 Like

Arbitrary angles are simply angles that can be any value. In game designing, this usually refers to the orientation of game objects.

Here’s a breakdown:

  1. What are arbitrary angles?
    Arbitrary angles are angles that aren’t fixed to one value. They can be any angle really, which allows for a lot more flexibility when designing games. For example, if you’re designing a racing game, you could use these angles to create tracks with curves that aren’t just a sudden 90 or 180 degree turn.

  2. How can you use these angles?
    Arbitrary angles can be used in a lot of ways when designing games. They can be used to create more realistic/fluid movements. If you’re designing a game where the player a vehicle, you can use arbitrary angles to make the movements feel more natural and less rigid. (as shown in atrazine’s post)

  3. How can you make smooth turns?
    To make smooth turns using arbitrary angles, you would gradually change the angle of the turn over time, rather than instantly changing it. This can be done by incrementally increasing or decreasing the angle value over a set period of time. For example, if you wanted to make a smooth 90-degree turn, you could start by turning 1 degree, then 2 degrees, then 3 degrees, and so on until you’ve turned 90 degrees. This will create a smooth turn.

Creating a custom curve algorithm that works with arbitrary angles involves the use of vector math and interpolation techniques. Here’s a basic example of how you might do it:

local function lerp(a, b, t)
    return a + (b - a) * t
end

local function createCurve(startPoint, endPoint, controlPoint, resolution)
    local curve = {}
    for t = 0, 1, 1/resolution do
        local A = lerp(startPoint, controlPoint, t)
        local B = lerp(controlPoint, endPoint, t)
        local C = lerp(A, B, t)
        table.insert(curve, C)
    end
    return curve
end

local startPoint = Vector3.new(0, 0, 0)
local endPoint = Vector3.new(10, 0, 10)
local controlPoint = Vector3.new(5, 0, 20)
local resolution = 100

local curve = createCurve(startPoint, endPoint, controlPoint, resolution)

The example above represent a Bezier curve

However the exact implementation really varies. Atrazine might be using a more complex curve algorithm.

I haven’t specifically developed anything that require the usage of arbitrary angles. What I gave is just a basic understanding on creating smooth turns with arbitrary angles. You might need to experiment if to get the movement you want.

2 Likes

Thanks for the code, not to be a pain, but would you know how I could create this with just the start and end value, and create the control point based on the 2 values, as since I want it to be a linear curve all along the path, surely with a bit of math you could technically use the start and end position to figure it out. Please correct me if I’m wrong

Example:
For a 90° Turn
image

For a 45° Turn (not super sure)
image

But then if I wanted to make a strange turn, but by just adjusting the Start and end position, I wouldn’t really know where to put the control point position.

2 Likes

you could calculate the control point as the midpoint between the start and end points, and then offset it by a certain distance in the direction perpendicular to the line between the start and end points.

Here’s a simple example:

local function calculateControlPoint(startPoint, endPoint, offset)
    local midpoint = (startPoint + endPoint) / 2
    local direction = (endPoint - startPoint).Unit
    local perpendicular = Vector3.new(-direction.Z, 0, direction.X) -- this gives a vector perpendicular to the direction vector
    local controlPoint = midpoint + perpendicular * offset
    return controlPoint
end

local startPoint = Vector3.new(0, 0, 0)
local endPoint = Vector3.new(10, 0, 10)
local offset = 5 -- adjust this value to change the "sharpness" of the turn

local controlPoint = calculateControlPoint(startPoint, endPoint, offset)

This script calculates the control point as the midpoint between the start and end points, and then offsets it by a certain distance in the direction perpendicular to the line between the start and end points. The offset variable determines how “sharp” the turn is.

You can then use this control point to create your curve as before:

local curve = createCurve(startPoint, endPoint, controlPoint, resolution)

So this it how it would look like:

local function lerp(a, b, t)
    return a + (b - a) * t
end

local function createCurve(startPoint, endPoint, controlPoint, resolution)
    local curve = {}
    for t = 0, 1, 1/resolution do
        local A = lerp(startPoint, controlPoint, t)
        local B = lerp(controlPoint, endPoint, t)
        local C = lerp(A, B, t)
        table.insert(curve, C)
    end
    return curve
end

local function calculateControlPoint(startPoint, endPoint, offset)
    local midpoint = (startPoint + endPoint) / 2
    local direction = (endPoint - startPoint).Unit
    local perpendicular = Vector3.new(-direction.Z, 0, direction.X) -- this gives a vector perpendicular to the direction vector
    local controlPoint = midpoint + perpendicular * offset
    return controlPoint
end

local startPoint = Vector3.new(0, 0, 0)
local endPoint = Vector3.new(10, 0, 10)
local offset = 5 -- adjust this value to change the "sharpness" of the turn
local resolution = 100

local controlPoint = calculateControlPoint(startPoint, endPoint, offset)
local curve = createCurve(startPoint, endPoint, controlPoint, resolution)

local part = game.Workspace.Part

for i, point in ipairs(curve) do
    part.CFrame = CFrame.new(point)
    wait(0.1) 
end

This will calculate the control point based on the start and end points and the offset. Then it creates a curve using these points, and to visualize it, it will move a part along this curve

Still take note that this is a basic example.

Still isn’t perfect but thank you very much for the example. I will try to change it to my best liking, and reply to this post when I have found out the perfect solution

1 Like

just going to put in the control point in manually due to it having a chance of breaking.

1 Like

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