- Joined
- Apr 24, 2012
- Messages
- 5,113
Been using this on my profession, and so I wrote this as a library on the map I am making on my spare time.
Sample:
If you want to visualize your bezier easings, you can use this web tool:
cubic-bezier.com
This library also includes preset BezierEasing functions provided by Easing Functions Cheat Sheet
JASS:
library BezierEasing /* 1.0.0
*************************************************************************************
*
* Build Cubic Bezier-based Easing functions
*
* Instead of solving for the point on the cubic bezier curve, BezierEasing
* solves for output Y where X is the input.
*
* Useful for adjusting animation rate smoothness
*
*************************************************************************************
*
* struct BezierEasing extends array
*
* static method create takes real ax, real ay, real bx, real by returns thistype
* - points (ax, ay) and (bx, by) are cubic bezier control points on 2D plane.
* - cx = cubic(0, ax, bx, 1)
* - cy = cubic(0, ay, by, 1)
* method operator [] takes real t returns real
* - real "t" is the given time progression whose value in [0..1] range
*
*************************************************************************************/
globals
/*
* Adjust precision of epsilon's value
* higher precision = lower performance
*
* May cause infinite loop if the
* precision is too high.
*/
private constant real EPSILON = 0.00001
endglobals
private function Abs takes real a returns real
if(a < 0) then
return -a
endif
return a
endfunction
private function Max takes real a, real b returns real
if(a < b) then
return b
endif
return a
endfunction
/*
* Float Equality Approximation
* Accuracy is influenced by EPSILON's value
*/
private function Equals takes real a, real b returns boolean
return Abs(a - b) <= EPSILON*Max(1., Max(Abs(a), Abs(b)))
endfunction
private function Bezier3 takes real a, real b, real c, real d, real t returns real
local real x = 1. - t
return x*x*x*a + 3*x*x*t*b + 3*x*t*t*c + t*t*t*d
endfunction
private module Init
private static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
struct BezierEasing extends array
private static thistype array r
private real x1
private real y1
private real x2
private real y2
static method create takes real ax, real ay, real bx, real by returns thistype
local thistype this = r[0]
if(r[this] == 0) then
set r[0] = this + 1
else
set r[0] = r[this]
endif
set r[this] = -1
set x1 = ax
set y1 = ay
set x2 = bx
set y2 = by
return this
endmethod
method operator [] takes real t returns real
/*
* Perform binary search for the equivalent points on curve
* by using the t factor of cubic beziers, where the input
* is equal to the bezier point's x, and the output is the
* point's y, respectively.
*/
local real lo = 0.
local real hi = 1.
local real mid
local real tx
local real ty
local real ax = x1
local real ay = y1
local real bx = x2
local real by = y2
/*
* Since bezier points lies within
* the [0, 1] bracket, just return
* the bound values.
*/
if(Equals(t, 0.)) then
return 0.
elseif(Equals(t, 1.)) then
return 1.
endif
/*
* Binary Search
*/
loop
set mid = (lo + hi)*0.5
set tx = Bezier3(0, ax, bx, 1, mid)
set ty = Bezier3(0, ay, by, 1, mid)
if(Equals(t, tx))then
return ty
elseif(t < tx) then
set hi = mid
else
set lo = mid
endif
endloop
return 0.
endmethod
method destroy takes nothing returns nothing
if(r[this] == -1) then
set r[this] = r[0]
set r[0] = this
set x1 = 0.
set y1 = 0.
set x2 = 0.
set y2 = 0.
endif
endmethod
private static method init takes nothing returns nothing
set r[0] = 1
endmethod
implement Init
endstruct
struct BezierEase extends array
readonly static BezierEasing inQuad
readonly static BezierEasing outQuad
readonly static BezierEasing inOutQuad
readonly static BezierEasing inCubic
readonly static BezierEasing outCubic
readonly static BezierEasing inOutCubic
readonly static BezierEasing inQuart
readonly static BezierEasing outQuart
readonly static BezierEasing inOutQuart
readonly static BezierEasing inQuint
readonly static BezierEasing outQuint
readonly static BezierEasing inOutQuint
readonly static BezierEasing inSine
readonly static BezierEasing outSine
readonly static BezierEasing inOutSine
readonly static BezierEasing inBack
readonly static BezierEasing outBack
readonly static BezierEasing inOutBack
readonly static BezierEasing inCirc
readonly static BezierEasing outCirc
readonly static BezierEasing inOutCirc
readonly static BezierEasing inExpo
readonly static BezierEasing outExpo
readonly static BezierEasing inOutExpo
private static method init takes nothing returns nothing
set inSine = BezierEasing.create(0.47, 0, 0.745, 0.715)
set outSine = BezierEasing.create(0.39, 0.575, 0.565, 1)
set inOutSine = BezierEasing.create(0.445, 0.05, 0.55, 0.95)
set inQuad = BezierEasing.create(0.55, 0.085, 0.68, 0.53)
set outQuad = BezierEasing.create(0.25, 0.46, 0.45, 0.94)
set inOutQuad = BezierEasing.create(0.455, 0.03, 0.515, 0.955)
set inCubic = BezierEasing.create(0.55, 0.055, 0.675, 0.19)
set outCubic = BezierEasing.create(0.215, 0.61, 0.355, 1)
set inOutCubic = BezierEasing.create(0.645, 0.045, 0.355, 1)
set inQuart = BezierEasing.create(0.895, 0.03, 0.685, 0.22)
set outQuart = BezierEasing.create(0.165, 0.84, 0.44, 1)
set inOutQuart = BezierEasing.create(0.77, 0, 0.175, 1)
set inQuint = BezierEasing.create(0.755, 0.05, 0.855, 0.06)
set outQuint = BezierEasing.create(0.23, 1, 0.32, 1)
set inOutQuint = BezierEasing.create(0.86, 0, 0.07, 1)
set inExpo = BezierEasing.create(0.95, 0.05, 0.795, 0.035)
set outExpo = BezierEasing.create(0.19, 1, 0.22, 1)
set inOutExpo = BezierEasing.create(1, 0, 0, 1)
set inCirc = BezierEasing.create(0.6, 0.04, 0.98, 0.335)
set outCirc = BezierEasing.create(0.075, 0.82, 0.165, 1)
set inOutCirc = BezierEasing.create(0.785, 0.135, 0.15, 0.86)
set inBack = BezierEasing.create(0.6, -0.28, 0.735, 0.045)
set outBack = BezierEasing.create(0.175, 0.885, 0.32, 1.275)
set inOutBack = BezierEasing.create(0.68, -0.55, 0.265, 1.55)
endmethod
implement Init
endstruct
endlibrary
Sample:
JASS:
library Tester requires BezierEasing
private struct T
private static constant real TIMEOUT = 0.031250000
private static constant real DURATION = 2.0
private static constant real SPEED = 500.
private static constant timer timer = CreateTimer()
private thistype next
private thistype prev
private real t
private real dx
private real dy
private real x
private real y
private unit u
/*
* For the custom Easing function, Easing InOut Back
*/
private static BezierEasing IOBack
private static method update takes nothing returns nothing
local thistype this = thistype(0).next
local real tmp
loop
exitwhen 0 == this
if(t > 0.) then
/*
* Since easing functions have results within the [0, 1] bracket
* we need to divide t to the max cap as a scaled progress.
*
* subtract from 1 since t is in regression
*/
set tmp = IOBack[1 - t/DURATION]
/*
* Apply progress of distance
*/
call SetUnitX(u, x + dx*tmp)
call SetUnitY(u, y + dy*tmp)
set t = t - TIMEOUT
else
set next.prev = prev
set prev.next = next
set dx = 0.
set dy = 0.
set t = 0.
if(thistype(0).next == 0) then
call PauseTimer(timer)
endif
call deallocate()
endif
set this = next
endloop
endmethod
private static method E takes nothing returns boolean
local thistype this = allocate()
local unit tu = GetFilterUnit()
local real angle = GetUnitFacing(tu)*bj_DEGTORAD
/*
* Original unit coords
* Used for setting the polar offset
*/
set x = GetUnitX(tu)
set y = GetUnitY(tu)
/*
* Direction Vectors
*/
set dx = Cos(angle)*SPEED
set dy = Sin(angle)*SPEED
set u = tu
set t = DURATION
if(thistype(0).next == 0) then
call TimerStart(timer, TIMEOUT, true, function thistype.update)
endif
set next = 0
set prev = thistype(0).prev
set thistype(0).prev.next = this
set thistype(0).prev = this
return false
endmethod
private static method init takes nothing returns nothing
call TriggerRegisterPlayerUnitEvent(CreateTrigger(), Player(1), EVENT_PLAYER_UNIT_SELECTED, function thistype.E)
/*
* Create the easing function
* The values provided creates
* the known easeInOutBack function
*/
set IOBack = BezierEasing.create(0.68, -0.55, 0.265, 1.55)
endmethod
implement Init
endstruct
endlibrary
If you want to visualize your bezier easings, you can use this web tool:
cubic-bezier.com
This library also includes preset BezierEasing functions provided by Easing Functions Cheat Sheet
Last edited: