I've been trying to smoothly animate some Windows Form location but I'm having some issues if I want the speed to be variable. In other words, if I want to allow the user to select the preferred speed for animation.
I've found the following article that helped me quite a bit to perform the animation I was looking for, for my form. It seems better in every way than a BackgroundWorker or Threads approach I tried in the past: http://www.vcskicks.com/animated-windows-form.html
My only problem now, is to maintain a smooth animation if I want o have different speeds for the animation. There are two values that are important in my code, FPS and PX. FPS represents frames per second (what else) and PX represents the number of pixels to move the form.
Problem 1) To have the smoothest possible animation, I would prefer to have the form move 1px at a time but I don't think that I will be able to move the form as fast as I want like that. Increasing the FPS value to a very high value doesn't seem to take any effect, it's like there's a limit and above that limit, there will be no visible differences. I'm sure there's a good explanation for that.
My question here is: Do you have any good solution for this problem or the only solution is to change the PX value and move the form by more than 1px if I want a faster movement?
Problem 2) If the solution for the question above is to change the PX value accordingly, I found out (by testing different values) that a FPS value equal to 300 would suffice my needs to move the form as slow and as fast as I want it to. Then, if I wanted 10 speeds, moving the form by 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10 pixels provides slow and fast smooth animations, just as I want it. If I wanted 5 speeds, I could use 2, 4, 6, 8, 10, for instance.
My question here is: Is there any problem to use a value like 300 for FPS? Are there any bad consequences for such a value?
And here's my current code:
public partial class Form1 : Form {
bool dir = true;
public Form1() {
InitializeComponent();
Location = new Point(1280/2 - Width, 800/2 - Height/2);
}
private void button1_Click(object sender, EventArgs e) {
double FPS = 300;
int PX = 1;
long lastTicks = 0;
long currentTicks = 0;
double interval = (double)Stopwatch.Frequency / FPS;
while(dir ? Left <= 1280/2 : Left >= 1280/2 - Width) {
Application.DoEvents();
currentTicks = Stopwatch.GetTimestamp();
if(currentTicks >= lastTicks + interval) {
lastTicks = Stopwatch.GetTimestamp();
this.Location = new Point(dir ? Left + PX : Left - PX, Top);
this.Invalidate(); //refreshes the form
}
Thread.Sleep(1); //frees up the cpu
}
dir = !dir;
}
}
Note: This is just sample code, for testing purposes, not real code but be my guest if you want to point out some very important things that I should consider when porting this to the real application.