Bézier curves are curves defined by a starting point, one or more control points and an end point. They are often used for vector graphics, animations and art. There are many types of Bézier curves. The main ones are Cubic and Quadratic. Those terms define the amount of control points the curve has. For example, a Cubic curve has 1 control point, for a total of 3 points. A Quadratic curve has 2 control points, for a total of 4 points. The more control points a curve has, the more detailed you can make your curve.
This is really simple.
Lerping (short for linear interpolation) is a simple function that takes in the inputs a, b and t and returns a value that's somewhere between a and b. That somewhere in between is determined by t, a value between 0 and 1.
function lerp(a,b,t)
return a + (b - a) * t
end
This line:
print(lerp(10,20,0.5))
Would output this:
15
This will be very important later on.
Now for the fun part! Firstly, we'll describe a simple Cubic Bézier Curve on Geogebra. You can follow along on Geogebra yourself if you want.
Firstly, we'll define the start and end points, as well as one control point:
Then, we'll add a variable t and two intermediary points (D and E). The point's positions will be determined by a lerp function between their two neighbouring points, like this:
And finally, we'll make one last point, F, who's position will be determined by a Lerp function between D and E, with argument t. This point will draw our curve:
If you're following along, you can press the play button on t. If you look at F, you'll see it trace a line. The line F traces is our Bézier Curve!
Okay, if you've made it this far, congratulations! I told you it'd be easy. Let's see how to program them into Luau. We'll do this in a 2D plane. By the way, if you want to use this for GUI's, make sure to use UDim2 and not Vector2!
function lerp(a,b,t)
return a+(b-a)*t
end
local fps = 60 -- Useful for later. This value should be 60 since it's Roblox's FPS value.
local t = 0 -- Time
local A = Vector2.new(0,0) -- Starting position
local B = Vector2.new(0,0) -- End position
local C = Vector2.new(0,0) -- Control Point position
local D = Vector2.new(0,0) -- Median point between A and C
local E = Vector2.new(0,0) -- Median point between C and B
local F = Vector2.new(0,0) -- Curve tracer
function start(length, startPos, endPos, controlPos)
A = startPos
B = endPos
C = controlPos
local dT = (1/length)/fps -- Delta time. This is how much time will pass between each loop iteration.
for i = 0,length*fps do -- This is length*fps because we want to iterate enough times so that dT ends at 1.
t += dT
D = Vector2.new(lerp(A.x,C.x,t), lerp(A.y,C.y,t)) -- Update D
E = Vector2.new(lerp(C.x,B.x,t), lerp(C.y,B.y,t)) -- Update E
F = Vector2.new(lerp(D.x,E.x,t), lerp(D.y,E.y,t)) -- Update F
print(F)
end
end
Whew, that was lengthy. Basically, what we've done is define the points, create a function that loops until t = 1, printing F every iteration. This is useful for many applications, but may need to adapted. You can also do this for 3D planes, just substitute the Vector2s for Vector3s.
As stated before, Bézier curves can be used for many animation and general UI/UX implementations. Here are a few examples:
- Smoothing values
- Cool graphics
- Paths for animation
In this lesson, you learned what linear interpolation is and how to do it, as well as what Bézier curves are, some applications and how to create and animate them. Thank you for reading, and I hope you use this knowledge in very cool ways.
Happy creating!