Search code examples
c#formstimerintervalspong

C# low timer interval = slow drawtime?


I'm trying to make a simple pong game but I encountered this problem, each timer1 tick (with the interval set to 1ms) should move of 1 pixel the white paddle rectangle if the 'S' or 'W' button is pressed, this means theorically that the white rectangle inside my 400px in height picturebox should be moving from y = 0 to y = 400 in 0.4 - 0.8 seconds, but apparently it takes more than 4 full seconds.

I understand that timer tick events may be "skipped" if the cpu is already busy or by processing speed problems but I tried to make a snake game way more complex than these 50 lines of code and the speed of the drawn snake was actually accurate with low-time intervals

Why does it takes that much?

 public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        pictureBox1.BackColor = Color.Black;

        timer1.Interval = 1;
        timer1.Start();
    }


    private void timer1_Tick(object sender, EventArgs e)
    {
        PongGame.CheckIfMoving();
        PongGame.DrawIt(pictureBox1);
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyData == Keys.S)
        { PongGame.movesDown = true; }

        if (e.KeyData == Keys.W)
        { PongGame.movesUp = true; }
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyData == Keys.S)
        { PongGame.movesDown = false; }

        if (e.KeyData == Keys.W)
        { PongGame.movesUp = false; }
    }
}



public class PongGame
{
    public static Rectangle paddle1 = new Rectangle(14, 370, 20, 100);
    public Rectangle paddle2;
    public static bool movesUp;
    public static bool movesDown;
    public static Graphics Draw;

    public static void DrawIt(PictureBox pb1)
    {
        Draw = pb1.CreateGraphics();
        SolidBrush sb = new SolidBrush(Color.White);

        Draw.Clear(Color.Black);
        Draw.FillRectangle(sb, paddle1);
    }

    public static void CheckIfMoving()
    {
        if (movesUp == true)
        {
            paddle1.Y -= 1;
        }

        if (movesDown == true)
        {
            paddle1.Y += 1;
        }
    }
}

Thanks in advance for the answers (:


Solution

  • First of all, setting the Timer's interval to 1 produces an unnecessary overhead in this case. That's 1000 fps (well, it would be, if you could actually trust the Timer).

    In DrawIt:

    Draw = pb1.CreateGraphics();
    SolidBrush sb = new SolidBrush(Color.White);
    

    This, since DrawIt is called by the Timer's tick, recreates the Graphics, and the Brush, 1000 times, every second. Be careful about what you put in there.

    Furtheremore, you shouldn't use the Picturebox's CreateGraphics method. Instead, override its OnPaint method, and call Refresh on it.

    You can read more about this on Bob Powell's Website