如何使动画看起来一致和流畅

时间:2017-04-29 15:28:37

标签: c# winforms animation

`所以我总共有6张图像,当动画时,会产生一个人行走的错觉。问题是它不顺畅,refresh(),invalidate(),update()都失败了。我该怎么做呢。

namespace Runner
{
    public partial class Form1 : Form 
    {
        Keys moveRight;
        Keys moveLeft;
    public static bool isMovingR = false;
    public static bool isMovingL = false;

    Bitmap stnd = new Bitmap(Properties.Resources.Standing);
    static Bitmap wlk_1_RL = new Bitmap(Properties.Resources.Walk_1_RL);
    static Bitmap wlk_2_RL = new Bitmap(Properties.Resources.Walk_2_RL);
    static Bitmap wlk_3_RL = new Bitmap(Properties.Resources.Walk_3_RL);
    static Bitmap wlk_4_LL = new Bitmap(Properties.Resources.Walk_4_LL);
    static Bitmap wlk_5_LL = new Bitmap(Properties.Resources.Walk_5__LL);
    static Bitmap wlk_6_LL = new Bitmap(Properties.Resources.Walk_6_LL);

    Graphics gfx;
    Animation animate = new Animation(new Bitmap[] { wlk_1_RL, wlk_2_RL, wlk_3_RL,
        wlk_4_LL, wlk_5_LL, wlk_6_LL });


    Timer timer = new Timer();

    int imageX = 5;
    int imageY = 234;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        moveRight = Keys.D;
        moveLeft = Keys.A;

        if (Keys.D == moveRight)
        {
            isMovingR = true;
            timer.Enabled = true;
            timer.Interval = 50;
            timer.Tick += timer1_Tick;                
            //imageX += 5;
            Refresh();
        } else if (Keys.A == moveLeft)
        {
            isMovingL = true;
            imageX -= 5;
            Refresh();
        }

    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        gfx = this.CreateGraphics();
        gfx.DrawImage(animate.Frame2Draw(), imageX, imageY);
        //Refresh(); Invalidate(); Update();
    }
} 

}

现在,问题是能够使动画保持一致和流畅

更新...动画类

 public class Animation
{
    int slctdImg = 0;
    public static Bitmap[] images;
    Bitmap frame2Draw;

    public Animation(Bitmap[] frames)
    {
        foreach (Bitmap btm in frames)
        {
            btm.MakeTransparent();
        }
        images = frames;
    }

    public Bitmap Frame2Draw()
    {

        if (slctdImg < images.Length)
        {
            frame2Draw = images[slctdImg];
            slctdImg++;
        }
        if (slctdImg >= images.Length)
        {
            slctdImg = 0;
            frame2Draw = images[slctdImg];
        }
        return frame2Draw;
    }
}

1 个答案:

答案 0 :(得分:2)

许多问题:

  • 我想知道你为什么要在每个Tick上拨打MakeTransparent?我怀疑它是否符合您的预期......它正在改变像素,相当昂贵;你应该缓存图像。

  • 也不是为什么要在每个Tick上创建一个位图数组???并且因为它始终以与始终仅显示第一张图像相同的方式创建 ..这应该回答您的问题。

其他问题:

  • 使用this.CreateGraphics();将无法创建持久性结果,但在尝试设置动画时可能不是您的目标。

  • 请注意,Timer.Interval的运行速度不能超过15-30 ms;另外,winforms在动画方面是出色的糟糕

  • 请记住,c#是从零开始的,因此slctdImg > images.Length应该是slctdImg >= images.Length

这是你应该做的事情:

  • 将实例化移动到表单加载或可能移动到键事件。

  • 将绘图移动到表单的Paint事件。

  • Tick计算帧数和/或位置,并通过调用表单上的Paint触发Invalidate

更新:

另外一个问题是每次按下右键时挂钩Tick事件的方式。 连接事件多次会导致多次运行;这将创建动画中的间隙/跳跃..

要么每次在连接之前添加取消挂钩(它会在第一次安静地失败)

timer.Tick -= timer1_Tick;
timer.Tick += timer1_Tick; 

(更好)在原始设置中仅将一次连接起来!