1

每次我尝试在此游戏中添加新线或移动桨时,屏幕都会闪烁。

移动拨片或添加线条时如何防止屏幕闪烁?

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
public partial class GameTest : Form
{
    int dx=3, dy=3, i =500, o = 100;

   int rex = 400, rey = 450 ;
       double c =0;


    public GameTest()
    {

        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Graphics g = this.CreateGraphics();
        Invalidate();
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        Graphics g = this.CreateGraphics();
        if (e.KeyCode == Keys.Left)
        {

            //Graphics g = this.CreateGraphics();


            Invalidate();
            Brush black = new SolidBrush(Color.White);
            g.FillRectangle(black, rex, rey, 200, 20);

            rex -= 40;
            Brush red = new SolidBrush(Color.Green);
            g.FillRectangle(red, rex, rey, 200, 20);




        }
        if (e.KeyCode == Keys.Right)
        {


            //Graphics g = this.CreateGraphics();



            Brush white = new SolidBrush(Color.White);
            g.FillRectangle(white, rex, rey, 200, 20);

            rex += 40;
            Brush red = new SolidBrush(Color.Green);
            g.FillRectangle(red, rex, rey, 200, 20);

        }
    }



    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        DoubleBuffered = false;

         Graphics g = this.CreateGraphics();
         //  Bitmap bmp1 = new Bitmap("G:\c#\Bouncing ball\Pic.jpg");
        //TextureBrush tb2 = new TextureBrush(bmp1);

        Brush green = new SolidBrush(Color.Green);
            g.FillRectangle(green, rex, rey, 200, 20);

            Graphics b= this.CreateGraphics();

            Brush red = new SolidBrush(Color.Red);

            b.FillEllipse(red, i, o, 20, 20);



       Pen p = new Pen(Color.Black, 10);
        //
           g.DrawLine(p, 1000, 480,0,480);
          g.DrawLine(p, 1000, 485, 1000, 0);

        g .DrawLine(p, 0,480, 0, 0);
    }


    private void timer1_Tick(object sender, EventArgs e)
    {
        DoubleBuffered = false;
        //  int dx=3, dy=3, i = 300, o = 50;

        i += dx;


        if (i < 0)
        {
            dx = -dx;
        }

        else if (i + 50 > 1000)
        {
            dx = -dx;
        }



        o += dy;

        if ((o +20>= rey) &&(i+20<=rex+200)&&(i+20>=rex))
        {
            //int rex = 400, rey = 450; RECTANGLE
            // int dx=3, dy=3, i(x) = 500, o(y) = 100;

            dy =-dy;
            //c++;
            //label1.Text = c.ToString();
        }


            // Misgeret\\
            if (o < 0)
            {
                dy = -dy;
            }
            // Misgeret\\
            else if (o + 50 > 600)
            {
                dy = -dy;
            }
           this.Invalidate();



    }

    private void label1_Click(object sender, EventArgs e)
    {
        label1.Text = c.ToString();
    }
}
}
4

1 回答 1

3

我注意到您DoubleBuffered在程序的多个区域中设置为 false 。这绝对没有帮助,因为使用双缓冲的全部原因是为了防止闪烁。

另一件事是您正在创建图形上下文并在应用程序的多个位置进行绘图。尝试重构您的代码以仅在OnPaint()表单的事件处理程序中进行绘制,并且不要创建新的 Graphics 上下文。使用事件中提供的PaintEventArgs那个OnPaint()

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;

    using(Brush green = new SolidBrush(Color.Green))
    {
         g.FillRectangle(green, rex, rey, 200, 20);
    }

    // .. etc, etc..        
}

然后,当您需要重新绘制表单时,您只需调用该Invalidate()方法来告诉 GDI 您的表单或其中的一部分需要重新绘制。这反过来会导致Paint事件被触发并被OnPaint()调用。

作为旁注,正如@HighCore 在评论中所建议的那样,WinForms 绝对不是创建游戏的正确框架。对于游戏,请尝试 XNA 框架,或者网络上可用的几个开源框架之一,例如Unity

更新

为了防止闪烁,您可以对表单使用自动双缓冲。这可以在表单构造函数中启用,在调用 之后InitializeComponent(),使用调用SetStyle

 SetStyle( ControlStyles.AllPaintingInWmPaint
         | ControlStyles.UserPaint
         | ControlStyles.DoubleBuffer , true);
于 2013-11-12T21:27:35.373 回答