Animation timing
-
Hi All, i'm trying to implement animation in an app. The frame rate of the animation needs to be variable. To implement this, i have a thread which sleeps for 1/fps seconds, and when it wakes it invalidates the window. Then, the onpaint handler draws the next frame. Whilst this approach works ok at low frame rates, when things speed up, the animation gets choppy (due to the way in which the message queue is processed). Is there a better approach? I want to be able to draw at reasonably precise times. Would DirectDraw help? i've never looked at directx, but would be prepared to if it offered a solution to my problem. Thanks slip
using System.Beer;
-
Hi All, i'm trying to implement animation in an app. The frame rate of the animation needs to be variable. To implement this, i have a thread which sleeps for 1/fps seconds, and when it wakes it invalidates the window. Then, the onpaint handler draws the next frame. Whilst this approach works ok at low frame rates, when things speed up, the animation gets choppy (due to the way in which the message queue is processed). Is there a better approach? I want to be able to draw at reasonably precise times. Would DirectDraw help? i've never looked at directx, but would be prepared to if it offered a solution to my problem. Thanks slip
using System.Beer;
Hi, you may find some suggestions in my timer article... :)
Luc Pattyn [My Articles] [Forum Guidelines]
-
Hi All, i'm trying to implement animation in an app. The frame rate of the animation needs to be variable. To implement this, i have a thread which sleeps for 1/fps seconds, and when it wakes it invalidates the window. Then, the onpaint handler draws the next frame. Whilst this approach works ok at low frame rates, when things speed up, the animation gets choppy (due to the way in which the message queue is processed). Is there a better approach? I want to be able to draw at reasonably precise times. Would DirectDraw help? i've never looked at directx, but would be prepared to if it offered a solution to my problem. Thanks slip
using System.Beer;
Hi Slip I have recently worked on a solution that is similar to your needs. I used threads that animated a user control containing other controls, in fact I had multiple user controls being animated on the same form, with different threads. I used delegates to access a number of variables on the form from my threads. Also in the form I declared a volatile integer like this:-
private volatile int componentOnPaint
And a public method which will be used by a delegate to return the above value. Then in your override method for OnPaint in the form, increment the componentOnPaint integer, this way you know how many times the form has been re-painted. Before your thread has invalidated the form get the componentOnPaint value, invalidate the form and then sleep for a short time using Thread.Sleep(30) (this allows the thread to be re-painted). At the next line of execution check the componentOnPaint value again, if it is greater than before, then continue. Otherwise loop and sleep again, until the value is greater and the form is repainted. Then you would use Thread.Sleep again for a fixed time depending on the animations frame length. To make the animation smoother, use another delegate to get the delay time (milliseconds) required in between animation cycles. Use DateTime.Now to get the time before you invalidated your form, and use DateTime.Now to get the time after componentOnPaint was greater. Subtract the first value from last eg...TimeSpan drawTime = AnimateLastStart - AnimateLastDrawn;
Then reduce your delay time by the time it took to refresh your form... ie...Thread.Sleep(standardTime-drawTime.Milliseconds)
This worked for me, using volatile earlier means the variable can act as a semaphore accessible from any thread (hence volatile), so you know if the form has been drawn and you shouldn't miss any frames. The time manipulation should just make your animation smoother. I hope this helps :-) Jason -- modified at 7:04 Wednesday 4th July, 2007 -
Hi, you may find some suggestions in my timer article... :)
Luc Pattyn [My Articles] [Forum Guidelines]
Thanks, but I understand why the animation is jerky - the kernels scheduler runs on a similar timer to what you describe. I'm just wondering how other apps which animate do it so smoothly - eg windows media player.
using System.Beer;
-
Thanks, but I understand why the animation is jerky - the kernels scheduler runs on a similar timer to what you describe. I'm just wondering how other apps which animate do it so smoothly - eg windows media player.
using System.Beer;
Hi, I dont know how WMP does what it does. This comes to mind: - use the right kind of timer - use double-buffering - make sure everything you need is in memory before you need it - precalculate the next frame, so the only real-time thing to do is show it - possibly work with thread priorities (not recommended if you are not familiar with it). :)
Luc Pattyn [My Articles] [Forum Guidelines]
-
Hi All, i'm trying to implement animation in an app. The frame rate of the animation needs to be variable. To implement this, i have a thread which sleeps for 1/fps seconds, and when it wakes it invalidates the window. Then, the onpaint handler draws the next frame. Whilst this approach works ok at low frame rates, when things speed up, the animation gets choppy (due to the way in which the message queue is processed). Is there a better approach? I want to be able to draw at reasonably precise times. Would DirectDraw help? i've never looked at directx, but would be prepared to if it offered a solution to my problem. Thanks slip
using System.Beer;
I think you should first factor in how complicated is the animation you are trying to execute. Drawing in .NET is not the fastest solution by any means, and usually its as slow as you can get. So your issue might be more related to .NET's drawing performance more than to timing issues...when you demand high frame rates maybe .NET's drawing performance just can't keep up more than the message queue not processing the paint messages (as a matter of fact Invalidate messages skip the application queue and are processed immeadiately, so queueing is not the issue). For any kind of serious animation I would rely on DirectX or OpenGL. NET Drawing namespace does and adequate job when it comes to what it was meant to do, but animation was not in the list IMHO. hope this helps P.D.1: First off, before plunging into new technology, I'd try optimising the code. Even if .NET is slow, it might be enough in your case but maybe your drawing routines are not coded well enough. Make sure you are disposing all disposable objects you "own" in your drawing implementation, you're releasing correctly any unmanaged resources you might be using, etc. Also check if maybe its worthwhile to cache any of objetcs you might be using and that way avoid creating and releasing them on every drawn frame, etc. P.D.2: If you have to rely on some other solution then you dont have to plunge into 100% native code...check out Managed DirectX. -- modified at 4:42 Thursday 5th July, 2007