71 lines
1.7 KiB
Lua
71 lines
1.7 KiB
Lua
|
-- A Spring class. This is extremely useful for juicing things up.
|
||
|
-- See this article https://github.com/a327ex/blog/issues/60 for more details.
|
||
|
-- The argument passed in are: the initial value of the spring, its stiffness and damping.
|
||
|
Spring = Object:extend()
|
||
|
function Spring:init(x, k, d)
|
||
|
self.x = x or 0
|
||
|
self.k = k or 100
|
||
|
self.d = d or 10
|
||
|
self.target_x = self.x
|
||
|
self.v = 0
|
||
|
end
|
||
|
|
||
|
|
||
|
function Spring:update(dt)
|
||
|
local a = -self.k*(self.x - self.target_x) - self.d*self.v
|
||
|
self.v = self.v + a*dt
|
||
|
self.x = self.x + self.v*dt
|
||
|
end
|
||
|
|
||
|
|
||
|
-- Pull the spring with a certain amount of force. This force should be related to the initial value you set to the spring.
|
||
|
function Spring:pull(f, k, d)
|
||
|
if k then self.k = k end
|
||
|
if d then self.d = d end
|
||
|
self.x = self.x + f
|
||
|
end
|
||
|
|
||
|
|
||
|
-- Animates the spring such that it reaches the target value in a smoothy springy motion.
|
||
|
-- Unlike pull, which tugs on the spring so that it bounces around the anchor, this changes that anchor itself.
|
||
|
function Spring:animate(x, k, d)
|
||
|
if k then self.k = k end
|
||
|
if d then self.d = d end
|
||
|
self.target_x = x
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
--[[
|
||
|
NSpring = Object:extend()
|
||
|
|
||
|
|
||
|
function NSpring:new(x, z, o)
|
||
|
self.x = x or 0
|
||
|
self.z = z or 0.5
|
||
|
self.o = o or 2*math.pi
|
||
|
self.target_x = self.x
|
||
|
self.v = 0
|
||
|
end
|
||
|
|
||
|
|
||
|
function NSpring:update(dt)
|
||
|
local f = 1 + 2*dt*self.z*self.o
|
||
|
local oo = self.o*self.o
|
||
|
local hoo = dt*oo
|
||
|
local hhoo = dt*hoo
|
||
|
local det_inv = 1/(f+hhoo)
|
||
|
local det_x = f*self.x + dt*self.v + hhoo*self.target_x
|
||
|
local det_v = self.v + hoo*(self.target_x - self.x)
|
||
|
self.x = det_x*det_inv
|
||
|
self.v = det_v*det_inv
|
||
|
end
|
||
|
|
||
|
|
||
|
function NSpring:animate(target_x, pd, td)
|
||
|
self.z = math.log(pd)/(self.o*td)
|
||
|
self.target_x = target_x
|
||
|
end
|
||
|
]]--
|