Click here to Skip to main content
15,889,863 members
Articles / Programming Languages / C#
Article

FlickerFree - Creating flicker-free graphics with GDI+

Rate me:
Please Sign up or sign in to vote.
4.25/5 (13 votes)
14 Nov 20021 min read 82.4K   667   42   3
Sample code on how to create flicker-free graphics with GDI+.

Sample Image - FlickerFree.jpg

Introduction

First I want to say: "Sorry about my spelling - but I'll try to become better!"

When you create moving objects/graphics using GDI+, you have to refresh the screen every time the timer ticks :-) But then the graphics begin to flicker - to avoid this you can use Double-Buffering. In this sample, I'll show what you need for flicker-free-graphics and also how to use KeyEvents.

Using the code

I've used a timer with an interval of 40 milliseconds because we need about 25 frames per second (1000 milliseconds / 25 frames = 40). To demonstrate how to move the graphics-object I have also built in KeyEvents.

At first you have to set Double-Buffering in the constructor of your class:

SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);

Then we use a timer to refresh the form every 40 milliseconds:

private System.Windows.Forms.Timer t;
t = new Timer();
t.Interval = 40;
t.Tick += new System.EventHandler(TimerOnTick);
t.Enabled = true;

private void TimerOnTick(object sender, System.EventArgs e)
{
  this.Refresh(); // #### 84: Refresh the form
  this.Text = DateTime.Now.ToString();
  this.Text += " " + this.PlayerPosition.ToString();
}

Next we "listen" to our keyboard:

this.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKeyPress);

private void OnKeyPress(object sender, System.Windows.Forms.KeyEventArgs e)
{
  // #### 84: When the Left-Cursor has been pressed
  if(e.KeyValue == 37)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X
                                - this.playerSize.Width,
                                    this.PlayerPosition.Y);
  }

  // #### 84: When the Up-Cursor has been pressed
  if(e.KeyValue == 38)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X,
                                    this.PlayerPosition.Y
                                    - this.playerSize.Width);
  }

  // #### 84: When the Right-Cursor has been pressed
  if(e.KeyValue == 39)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X
                                    + this.playerSize.Height,
                                    this.PlayerPosition.Y);
  }

  // #### 84: When the Down-Cursor has been pressed
  if(e.KeyValue == 40)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X,
                                    this.PlayerPosition.Y
                                    + this.playerSize.Height);
  }
}

And we have to overwrite the OnPaint event to draw our object:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
  e.Graphics.FillRectangle(new SolidBrush(Color.Red),
               this.PlayerPosition.X,
                   this.PlayerPosition.Y,
               this.playerSize.Width,
               this.playerSize.Height);
}

To calculate if the new position of our graphics-object is in the client area and what to do if not, I've used a property:

private Point PlayerPosition
{
  get
  {
    return this.playerPosition;
  }
  set
  {
    if(value.X < 0)
    {
      this.playerPosition.X = this.ClientSize.Width - this.playerSize.Width;
    }
    else if(value.X + this.playerSize.Width > this.ClientSize.Width)
    {
      this.playerPosition.X = 0;
    }
    else
    {
      this.playerPosition.X = value.X;
    }

    if(value.Y < 0)
    {
      this.playerPosition.Y = this.ClientSize.Height - 
                                    this.playerSize.Height;
    }
    else if(value.Y + this.playerSize.Height > this.ClientSize.Height)
    {
      this.playerPosition.Y = 0;
    }
    else
    {
      this.playerPosition.Y = value.Y;
    }
  }
}

Now we have a flicker-free animation ;-)

Points of interest

In the first version of my sample I used if() - else if() for the KeyEvent. But then one key worked at a time. Using if() for every key makes it possible to combine the keys for a diagonal movement. It's also important to use this.Client.Width and this.Client.Height instead of this.Width and this.Height - because the graphics-object can only be moved in the client-area and so you can calculate areas for the movement.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
1978-I was born
1989-My parents (++me, ++myBrother) moved to Germany
1990-I've got my first Computer (Amstrad CPC-464)
1991-I've bought a Commodore C64 by myself
1992-I've bought my first PC (486sx25)
1993-My first Website (static HTML) was ready
1993-PHP, ASP, SQL, C++, JavaScript, Python
2001-eightfour goes csharp

Comments and Discussions

 
Generalalso applicable to VB Pin
Fabian Tamp25-Sep-06 14:30
Fabian Tamp25-Sep-06 14:30 
GeneralCollision Pin
Hayat26-May-03 15:40
Hayat26-May-03 15:40 
;PIts a very nice and effective way of creating a flicker free motion .I am trying to develop a simple pinball game in c# .The rest of the work has been done.But the problem for me is that how to check that whether the ellipse(ball)
has collided with the line(player) or not so that i can proceed.

Any help.
Thanks in advance.Laugh | :laugh:

GeneralCollision Pin
Hayat26-May-03 15:37
Hayat26-May-03 15:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.