Линейная интерполяция (Linear interpolation, которую ещё называют ‘lerp’ или ‘mix’) — очень удобная функция при разработке игр, которая интерполирует в диапазоне [от..до] на основе параметра t, где t обычно находится в диапазоне [0..1].
Короткая, но полезная заметка от Matt DesLauriers про интерполяцию.
1 2 3 4 5 6 7 8 9 |
function lerp(start, end, t) { return start * (1 - t) + end * t; } console.log(lerp(0, 100, 0.5)); // 50 console.log(lerp(20, 80, 0)); // 20 console.log(lerp(30, 5, 1)); // 5 console.log(lerp(-1, 1, 0.5)); // 0 console.log(lerp(0.5, 1, 0.5)); // 0.75 |
К примеру, разделите время цикла на продолжительность цикла, и вы получите значение t между 0,0 и 1,0. Теперь вы можете отобразить это значение t в новый диапазон, например, lerp (20, 50, t)
, чтобы постепенно увеличить радиус круга, или lerp (20, 10, t)
, чтобы постепенно уменьшить толщину линии.
Другой пример: вы можете использовать линейную интерполяцию, чтобы плавно анимировать движение из одной точки в другую. Определите начальную точку (x1, y1) и конечную точку (x2, y2), затем интерполируйте измерения x и y отдельно, чтобы найти итоговую точку.
Или используйте линейную интерполяцию, чтобы прыгнуть к движущейся цели. Каждый кадр интерполировать от текущего значения к целевому значению с небольшим шагом t, к примеру, 0,05. Это всё равно, что сказать: приблизиться на 5% к цели за каждый кадр.
Пример посложнее — интерполирует один цвет (красный) в другой (синий). Чтобы сделать это, мы интерполируем (R, G, B) или (H, S, L) каналы цвета по отдельности, по аналогии с тем, как мы делали для 2D или 3D координат.
Все сорсы: https://gist.github.com/mattdesl/3675c85a72075557dbb6b9e3e04a53d9
В комментариях заметили, что пример с телепортированием очень зависит от фреймрейта. Лучше учитывать deltaTime
:
1 2 3 4 5 6 7 |
// Return a lerp factor for the given frame time which will result in // the value getting convergenceFraction of the way to the target in // smoothTime time units. I usually just use 0.9 or 0.95 for the fraction // and vary the smoothTime to get the effect I want. function smoothOver(dt, smoothTime, convergenceFraction) { return 1 - Math.pow(1 - convergenceFraction, dt / smoothTime) } |
На эту тему можно посмотреть интересный докла от Squirrel Eiserloh’s «Fast and Funky 1D Non-linear Transformations» на GDC: