[ v1.1.0 ] || Curve Module || Makes Tweening Advanced

:chart_with_upwards_trend: || Curve Module ||

ModuleScript that makes tweening advanced


:link: Useful Links :


:ribbon: Why to use?

It is useful in various cases :

  • Creating your own Easing Styles
  • Making smooth Difficulty change
  • Making drastic Zoom animation
  • Creating Paths
  • Creating custom and flexible Leveling system
  • Creating your own Curve Editor
  • Making Run Acceleration
  • Learning more about Bezier curve

:safety_vest: How to use?

Functions

CreateBezierCurve(CurvePointsHolder, Smoothness) → Curve

It’s a function that returns a Curve from CurvePointsHolder and Smoothness. Smoothness determines the distance between points. In this case, CurvePointsHolder can be represented as an AudioEmitter, a ModuleScript or a table. ModuleScript must return any of those values on requiring it.

CreateLinearCurve(CurvePointsHolder) → Curve

It’s a function that returns a Curve from CurvePointsHolder. In this case, CurvePointsHolder can be represented as an AudioEmitter, a ModuleScript, a function or a table. ModuleScript must return any of those values on requiring it. Function must return the Value on graph when it’s given Time (also can return Smoothness as the second variable).

TweenObjectWithCurve(Object, TweenInfo, Properties, Curve) → {Play= func(), Stop = func()}

It’s a function that returns a table of functions which can Stop or Play the animation of an Object. It also requires TweenInfo and Curve. Curve should be represented as a returned value from functions at the top but isn’t necessary.

GetValueFromCurve(Curve, Time, Start, End) → number

It’s a function that returns the value on a Curve with the given Time when it has specific Start and End. It can also work when the start is lower than the end.

GetValueFromCurve({
{Time = 0, Value = 0}, 
{Time = 1, Value = 1}
}, 0.5, 100, 200) -> 150

I highly recommend you visit the Testing Place for better understanding


Curves

Linear curve

The main advantage of Linear curves is their flexibility. You can create them using AudioEmitter’s Distance Attenuation, table, function or ModuleScript as shown below.
:bulb:[Tip] When using functions make sure it returns 0 when it’s given 0 and returns 1 when it’s given 1

Table
{
	{Time = 0, Value = 0},
	{Time = 0.2, Value = 0.4},
	{Time = 0.5, Value = 0.8},
	{Time = 0.7, Value = -0.2},
	{Time = 1, Value = 1}
}
Function
function (time : number)
	return time^2
end
function (time : number)
	return time^3, 1000 -- the second variable is the Smoothness of curve
end

ModuleScript
return {
	{Time = 0, Value = 0},
	{Time = 0.4, Value = 0.3},
	{Time = 0.7, Value = -0.2},
	{Time = 1, Value = 1}
}
return function (time : number)
	return math.sin(math.rad(time*(90+360)))
end
AudioEmitter

Bezier curve

Main advantages of Bezier curves are their endless possibility and easiness of use. Although Linear curves use every point to create a curve, Bezier curves use anchor points. You can create them using AudioEmitter’s Distance Attenuation, table or ModuleScript as shown below.
:bulb:[Tip] AudioEmitters aren’t really reliable for Bezier curves so for more flexibility, you should use tables instead

Table
{
	{Time = 0, Value = 0},
	{Time = 0.2, Value = -0.2},
	{Time = 0.3, Value = -0.15},
	{Time = 1, Value = 1}
}
ModuleScript
return {
	{Time = 0, Value = 0},
	{Time = 0.5, Value = 0},
	{Time = 0.6, Value = 1},
	{Time = 1, Value = 1}
}
AudioEmitter




:yarn: Code samples

Example #1
local Path = game.ReplicatedStorage.CurveModule

local CurveModule = require(Path)
local presets = Path.Presets

--

function previewCurve (curve : {}, smoothness : number, startPos : Vector3)
	local folder = Instance.new("Folder")
	folder.Name = "Curve"
	folder.Parent = workspace
	
	for i = 1, smoothness do
		local t = i/smoothness
		local point = CurveModule.GetValueFromCurve(curve, t, 0, 1) -- gets the Y value of a Curve with the given Time and Range
		
		
		local part = Instance.new("Part")
		part.Position = Vector3.new(0, point*30, t*30) + startPos
		part.Anchored = true
		part.CanCollide = false
		part.Size = Vector3.new(1,1,1)
		part.Shape = "Ball"
		part.Material = "Neon"
		part.Parent = folder
		part.BrickColor = BrickColor.new("Bright red")
		part.Name = "Point"
		
		
		task.wait()
	end
end

--

local curve1 = CurveModule.CreateLinearCurve(presets.Linear.Momentum)
previewCurve(curve1, 100, Vector3.new(0, 5, 5))

local curve2 = CurveModule.CreateBezierCurve(presets.Bezier.Back)
previewCurve(curve2, 100, Vector3.new(0, 5, -35))
Example #2
local Path = game.ReplicatedStorage.CurveModule

local CurveModule = require(Path)
local presets = Path.Presets

--

local part = Instance.new("Part")
part.Anchored = true
part.Material = Enum.Material.Concrete
part.BrickColor = BrickColor.new("Dark stone grey")
part.Position = Vector3.new(0, 7, 0)
part.Size = Vector3.zero
part.Shape = "Ball"
part.Parent = workspace

local image = Instance.new("Decal")
image.Texture = "rbxasset://textures/face.png"
image.Face = Enum.NormalId.Front
image.Parent = part

--

local curveA = CurveModule.CreateLinearCurve(presets.Linear.Quad)
local curveB = CurveModule.CreateBezierCurve(presets.Bezier.Back)

task.wait(3)
CurveModule.TweenObjectWithCurve(part, TweenInfo.new(2), {Size = Vector3.new(10,10,10)}, curveA):Play()
task.wait(3)
CurveModule.TweenObjectWithCurve(part, TweenInfo.new(2), {Size = Vector3.new(0,0,0)}, curveB):Play()
Example #3
local Path = game.ReplicatedStorage.CurveModule

local CurveModule = require(Path)
local presets = Path.Presets

--

local part = Instance.new("Part")
part.Position = Vector3.new(0, 10, 0)
part.Parent = workspace
part.Anchored = true
part.Size = Vector3.new(1,1,1)
part.Shape = "Ball"

--

local CurvePreset = presets.Bezier.Expo -- Path to Curve Preset
local Curve = CurveModule.CreateBezierCurve(CurvePreset, 100) -- Creates a Curve using a Preset and Smoothness value

local Tween = CurveModule.TweenObjectWithCurve(part, TweenInfo.new(5), {Size = Vector3.new(10,10,10)}, Curve)
Tween:Play()

--

task.wait(2)
Tween:Stop()
task.wait(1)
Tween:Play()

You can see other code samples when editing the Testing Place.
(The scripts are located in StarterGui)


:bulb: Ideas/Bugs

If you have any ideas, improvements and/or found bugs, feel free to share it down below!


:question: What updates are planned?

In the near future it is planned to implement InOut EasingDirection to TweenObjectWithCurve and function that allows to Tween Object CFrame along a Curve. Also, it’s planned to release more Examples involving Repeats.

Update #1 || v1.1.0

Repeat

Basically, TweenObjectWithCurve now supports more TweenInfo parameters :

  • Reverses
  • RepeatCount
  • DelayTime
They work the same as for regular Tween, so for more info check out this Documentation

EasingDirection

TweenObjectWithCurve now supports In, Out EasingDirections! They can be set when creating new TweenInfo for the function.

They work the same as for regular Tween, so for more info check out this Documentation
v1.1.0

:sparkles: Distribution

Feel free to use and/or modify the script how you want! If you use it in experiences, please mention me in credits.


:star2: Thanks

@Den_vers
@ltsRealJr
@bhristt

(Took huge inspiration from them :P)


Thank you for your patience :sparkling_heart:
Peace


Have you found this ModuleScript useful?
  • Yes
  • Maybe
  • No
0 voters

Is the information clear enough?
  • Yes
  • Maybe
  • No
0 voters

Do you think visiting Testing Place was useful?
  • Yes
  • Maybe
  • No
  • Haven’t tried
0 voters
10 Likes

This appears to be a great way to make smooth camera motion along a curve that may change at runtime. Nice module, has many use-cases

That’s a great idea! I’m gonna implement this as a function in future updates because it wasn’t intended lol

Update #1 || v1.1.0


Repeat

Basically, TweenObjectWithCurve now supports more TweenInfo parameters :

  • Reverses
  • RepeatCount
  • DelayTime
They work the same as for regular Tween, so for more info check out this Documentation

EasingDirection

TweenObjectWithCurve now supports In, Out EasingDirections! They can be set when creating new TweenInfo for the function.

They work the same as for regular Tween, so for more info check out this Documentation

v1.1.0

Talk about making a demo game to show some science…

Can I play this game?

I don’t quite understand what you’ve meant so feel free to correct me. This example is supposed to show how you can configure game difficulty for the players (in this case, the chance of death) using curves. This scenario can be used in Room type of games (ex. Doors) so with every room player unlocks, the more harder it gets. Sure, you can use it in many games.