Плавное увеличение/уменьшение числа
Нужна помощь математиков, ибо я, как говорится, не бум-бум
Покадрово рисую гифку на 180 кадров, в гифке колесо, которое по задумке изначально крутится быстро, и по итогу плавно останавливается, но я не понимаю, как сделать плавное замедление
Накидал минимальный-упрощённый пример того, как это происходит сейчас. Делаю какое-то подобие ускорения вращения, а по завершению цикла беру выходные картинки из папки и переворачиваю список, но остановка сейчас слишком резкая
int totalFrames = 180;
float lastAngle = 0;
for (int frame = 0; frame < totalFrames; frame++) {
Image img = Image.FromFile(...);
Image main = new Bitmap(img.Width, img.Height);
float angle = 0;
if (frame > 15)
angle = (lastAngle + frame / 5f) % 360; << вот тут нужна плавность
lastAngle = angle;
using (Graphics g = Graphics.FromImage(main)) {
g.DrawImage(RotateImage(img, angle), new Rectangle(0, 0, img.Width, img.Height));
main.Save($"out/{frame}.jpg", ImageFormat.Jpeg);
}
}
Ответы (1 шт):
Плавное торможение достигается за счет уменьшения скорости вращения колеса (или угловой скорости). Скорость вращения колеса (в формулах и коде буду применять обозначение vAngular) - это угол, на который поворачивается колесо за единицу времени. В вашем случае - это поворот на x градусов за 1 кадр.
Эту скорость vAngular необходимо плавно уменьшать со значения vAngularStart до значения vAngularEnd = 0 за определенный промежуток времени. Чтобы уменьшать скорость в цикле - необходимо найти некоторую vDelta - изменение скорости вращения за 1 кадр. Она вычисляется по формуле:
vDelta = (vAgularEnd - vAngularStart) / deltaT
где deltaT - время торможения.
Поскольку скорость в вашем случае уменьшается, то vDelta будет отрицательная.
Применяя все выше сказанное к вашему коду, получаем следующее:
int totalFrames = 180;
int frameStartBraking = 15; // Фрейм, с которого начинаем торможение
float deltaT = totalFrames - frameStartBraking;
float vAngularStart = 30; // Скорость вращения колеса при начале торможения.
float vAngularCurrent = vAngularStart; // Считаем, что до торможения скорость колеса вращения не изменялась
float vAgularEnd = 0; // Конечная скорость вращения колеса
float vDelta = (vAgularEnd - vAngularStart) / (totalFrames - frameStartBraking);
float angle = 0;
for (int frame = 0; frame < totalFrames; frame++) {
//...
if (frame > frameStartBraking) {
vAngularCurrent += deltaV;
}
angle += vAngularCurrent;
//...
}
Регулируется плавность торможения за счет изменения величин vAngularStart и deltaT.
Единственный нюанс: этот расчет не гарантирует того, что в последнем фрейме ваше колесо будет повернуто на angle = 0.