Тут одним методом не обойдешься, тут все гораздо сложнее.
Вот тебе класс, избегай движения строго по вертикали и все будет хорошо (если нужно будет по вертикали, придется поменять кое-что местами, там сообразишь уже):
public class ControlMoveAnimator
{
private Control TargetControl;
private Point TargetPos;
private int FrameCount;
private double FrameDelay;
double Scale = 1;
public ControlMoveAnimator(Control _TargetBox, Point _TargetPos, int _TargetAnimationTimeMs, int _FrameCount = 0)
{
TargetControl = _TargetBox;
TargetPos = _TargetPos;
int dx = TargetControl.Left - TargetPos.X;
int dy = TargetControl.Top - TargetPos.Y;
double TravelDistance = Math.Sqrt(dx * dx + dy * dy);
if (_FrameCount > 0)
FrameCount = _FrameCount;
else
FrameCount = (int)TravelDistance;
Scale = TravelDistance / FrameCount;
FrameDelay = Convert.ToDouble(_TargetAnimationTimeMs) / FrameCount;
}
private void ApplyPos(Point _Target)
{
TargetControl.Location = _Target;
}
public Thread Animate()
{
Thread t = new Thread(() =>
{
Point StartPos = new Point(TargetControl.Left, TargetControl.Top);
double Angle = Math.Atan(Convert.ToDouble(TargetPos.Y - StartPos.Y) / (TargetPos.X - StartPos.X));
for (int i = 0; i < FrameCount; i ++)
{
double x = StartPos.X + (i * Scale * Math.Cos(Angle));
double y = StartPos.Y + (i * Scale * Math.Sin(Angle));
TargetControl.Invoke(delegate { ApplyPos(new Point((int)x, (int)y)); });
Thread.Sleep((int)FrameDelay);
}
TargetControl.Invoke(delegate { ApplyPos(TargetPos); });
}
);
t.Start();
return t;
}
}
Еще такой момент. Рисование картинки в новом месте и передача управления в главный поток и обратно занимают время. Поэтому достичь какого-то маленького времени анимации достаточно сложно, надо подбирать параметры эмпирически.