🚙️
基本的なイージング用計算式まとめ
等速
f = -> t { t }
(0..1).step(0.1) do |e|
f[e].floor(1) # => 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0
end
加速
f = -> t { t**2 }
(0..1).step(0.1) do |e|
f[e].floor(1) # => 0.0, 0.0, 0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8, 1.0
end
減速
f = -> t { -t**2 + 2 * t }
(0..1).step(0.1) do |e|
f[e].floor(1) # => 0.0, 0.1, 0.3, 0.5, 0.6, 0.7, 0.8, 0.9, 0.9, 0.9, 1.0
end
加速+減速
f = -> t { -2 * t**3 + 3 * t**2 }
(0..1).step(0.1) do |e|
f[e].floor(1) # => 0.0, 0.0, 0.1, 0.2, 0.3, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0
end
超速+減速 (計算量低め)
相手との差分の半分を自分に足していく方法で掛け算を使わないので非常に速い。
a = 0
b = 100
a += (b - a) >> 1 # => 50
a += (b - a) >> 1 # => 75
a += (b - a) >> 1 # => 87
a += (b - a) >> 1 # => 93
a += (b - a) >> 1 # => 96
a += (b - a) >> 1 # => 98
a += (b - a) >> 1 # => 99
a += (b - a) >> 1 # => 99
a += (b - a) >> 1 # => 99
a += (b - a) >> 1 # => 99
ただし、いくら足しても目的地に着かないため、一定の距離まで近づいたら移動し終わったことにしないといけない。
if (b - a).abs < 5
a = b # => 100
end
コード
class App < Base
def initialize
super
@counter = 0
end
def button_down(id)
super
if id == Gosu::KB_Z
@counter = 0
end
end
def draw
super
duration = 60.0 * 2
if @counter >= duration + 60 * 0.5
@counter = 60 * -0.5
end
t = @counter.fdiv(duration).clamp(0, 1)
list = [
{ name: "linear", f: -> t { t }, },
{ name: "ease-in", f: -> t { t**2 }, },
{ name: "ease-out", f: -> t { -t**2 + 2 * t }, },
{ name: "ease", f: -> t { -2 * t**3 + 3 * t**2 }, },
]
radius = window_wh.y / list.count * 0.5
rr = V[radius, radius]
list.each.with_index do |e, i|
y = i * 1.0 / list.count
a = window_wh * V[0.0, y] + rr
b = window_wh * V[1.0, y] - V[radius * 2, 0] + rr
point_draw(a.lerp(b, e[:f][t]), radius: radius * 0.8)
end
@counter += 1
end
def window_size_default
V[800, 320]
end
show
end
参照
-
https://www.youtube.com/watch?v=I6GxFRtZcNE
計算式を導く過程も紹介されている -
https://gizma.com/easing/
助走やバウンドなどあらゆるパターンが網羅されている
Discussion