Simple animation using C#/Windows Forms

Posted by clintp on Stack Overflow See other posts from Stack Overflow or by clintp
Published on 2008-10-09T17:39:11Z Indexed on 2010/05/30 2:02 UTC
Read the original article Hit count: 666

Filed under:
|
|
|

I need to knock out a quick animation in C#/Windows Forms for a Halloween display. Just some 2D shapes moving about on a solid background. Since this is just a quick one-off project I really don't want to install and learn an entire new set of tools for this. (DirectX dev kits, Silverlight, Flash, etc..) I also have to install this on multiple computers so anything beyond the basic .Net framework (2.0) would be a pain in the arse.

For tools I've got VS2k8, 25 years of development experience, a wheelbarrow, holocaust cloak, and about 2 days to knock this out. I haven't done animation since using assembler on my Atari 130XE (hooray for page flipping and player/missile graphics!)

Advice? Here's some of the things I'd like to know:

  • I can draw on any empty widget (like a panel) by fiddling with it's OnPaint handler, right? That's how I'd draw a custom widget. Is there a better technique than this?
  • Is there a page-flipping technique for this kind of thing in Windows Forms? I'm not looking for a high frame rate, just as little flicker/drawing as necessary.

Thanks.

Post Mortem Edit ... "a couple of coding days later"

Well, the project is done. The links below came in handy although a couple of them were 404. (I wish SO would allow more than one reply to be marked "correct"). The biggest problem I had to overcome was flickering, and a persistent bug when I tried to draw on the form directly.

  • Using the OnPaint event for the Form: bad idea. I never got that to work; lots of mysterious errors (stack overflows, or ArgumentNullExceptions). I wound up using a panel sized to fill the form and that worked fine.
  • Using the OnPaint method is slow anyway. Somewhere online I read that building the PaintEventArgs was slow, and they weren't kidding. Lots of flickering went away when I abandoned this. Skip the OnPaint/Invalidate() and just paint it yourself.
  • Setting all of the "double buffering" options on the form still left some flicker that had to be fixed. (And I found conflicting docs that said "set them on the control" and "set them on the form". Well controls don't have a .SetStyle() method.) I haven't tested without them, so they might be doing something (this is the form):

        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    

So the workhorse of the code wound up looking like (pf is the panel control):

    void PaintPlayField()
    {
        Bitmap bufl = new Bitmap(pf.Width, pf.Height);
        using (Graphics g = Graphics.FromImage(bufl))
        {
            g.FillRectangle(Brushes.Black, new Rectangle(0, 0, pf.Width, pf.Height));
            DrawItems(g);
            DrawMoreItems(g);
            pf.CreateGraphics().DrawImageUnscaled(bufl, 0, 0);
        }
    }

And I just called PaintPlayField from the inside of my Timer loop. No flicker at all.

© Stack Overflow or respective owner

Related posts about c#

Related posts about .NET