移动对象

时间:2015-11-19 20:03:39

标签: c# winforms 2d-games

我试图为Windows窗体中的作业制作一个突破性的游戏,之前我已经制作过游戏,但我之前没有使用过winforms。我发现了一些应该有助于OnPaint()(你应该覆盖的),DoubleBuffered and Invalidate`的内容。但我只是在努力将其应用到我的代码

以下是我所拥有的:

 int xSpeed, ySpeed;

    Graphics display;
    Brush brush;

    Rectangle ballRect;

    public Form1()
    {
        InitializeComponent();



        timer1.Enabled = true;
        timer1.Interval = 1;

        xSpeed = 5;
        ySpeed = 5;
        ballRect = new Rectangle(10, 10, 20, 20);

        display = this.CreateGraphics();

        brush = new SolidBrush(Color.Red);


    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        DoubleBuffered = true;

        ballRect.X += xSpeed;
        ballRect.Y += ySpeed;

        if (ballRect.X >= 469)
            xSpeed = -xSpeed;

        if (ballRect.Y >= 457)
            ySpeed = -ySpeed;

        if (ballRect.X <= 0)
            xSpeed = -xSpeed;

        if (ballRect.Y <= 0)
            ySpeed = -ySpeed;

        display.Clear(Color.White);
        display.FillEllipse(brush, ballRect);

    }

我在Update方法(timer1_tick)中画球,但我觉得我不应该这样做。 谢谢:))

2 个答案:

答案 0 :(得分:1)

您可以创建自定义ControlForm和:

  • 在构造函数中为无闪烁绘画设置样式OptimizedDoubleBufferUserPaintAllPaintingInWmPaint
  • 在构造函数中如果大小更改ResizeRedraw
  • ,则设置重绘样式
  • Tick事件中,只需更新球的位置,然后Invalidate控件
  • 覆盖您的控件的OnPaint方法并将绘制逻辑放在那里
  • 此外,您应该使用速度或球大小的属性,以便在这些值发生更改时使控件无效。 (我没有在下面的代码中实现属性。)此外,您可以稍微增加间隔。

例如:

public partial class CustomControl1 : Control
{
    public CustomControl1()
    {
        InitializeComponent();

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

        timer1.Enabled = true;
        timer1.Interval = 1;

        xSpeed = 5;
        ySpeed = 5;

        ballRect = new Rectangle(10, 10, 20, 20);
        brush = new SolidBrush(Color.Red);
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        pe.Graphics.FillEllipse(brush, ballRect);
    }

    int xSpeed, ySpeed;
    Brush brush;
    Rectangle ballRect;
    private void timer1_Tick(object sender, EventArgs e)
    {
        ballRect.X += xSpeed;
        ballRect.Y += ySpeed;

        if (ballRect.X + ballRect.Width >= this.Width)
            xSpeed = -xSpeed;

        if (ballRect.Y + ballRect.Height >= this.Height)
            ySpeed = -ySpeed;

        if (ballRect.X <= 0)
            xSpeed = -xSpeed;

        if (ballRect.Y <= 0)
            ySpeed = -ySpeed;

        this.Invalidate();
    }

}

答案 1 :(得分:0)

闪烁正在发生,因为您正在直接绘制到显示屏。首先清除用户将在瞬间看到的显示,然后在其上绘制一个圆圈,该圆圈仅在重复该过程之前显示一小段时间。 “透支”是闪烁的来源。

摆脱它的一种方法是将所有绘图都绘制到内存位图,一旦完成,将整个位图移动到显示器。

我在代码中看到的其他问题是您在构造函数中创建了一个Graphics实例,并在程序的生命周期中保留它。这是你应该避免的模式。相反,您应该创建一个新的Graphics对象,最好是在每个“框架”的using语句中。这将确保一切都得到妥善清理。