0

我一直在尝试平滑地为某些 Windows 窗体位置设置动画,但如果我希望速度可变,我会遇到一些问题。换句话说,如果我想让用户选择动画的首选速度。

我发现以下文章对我执行我正在寻找的动画有很大帮助,对于我的表单。它似乎在各方面都比我过去尝试过的 BackgroundWorker 或 Threads 方法更好: http ://www.vcskicks.com/animated-windows-form.html

我现在唯一的问题是,如果我想让动画有不同的速度,要保持流畅的动画。我的代码中有两个重要的值,FPSPX。FPS 表示每秒帧数(还有什么),PX 表示移动表格的像素数。

问题 1)为了获得最流畅的动画,我希望表单一次移动 1px,但我认为我不能像我想要的那样快速移动表单。将 FPS 值增加到一个非常高的值似乎没有任何效果,就像有一个限制,超过该限制,将不会有明显的差异。我确信对此有一个很好的解释。

我的问题是:如果我想要更快的移动,你有什么好的解决方案或者唯一的解决方案是更改 PX 值并将表单移动超过 1px?

问题 2)如果上述问题的解决方案是相应地更改 PX 值,我发现(通过测试不同的值)等于 300 的 FPS 值足以满足我的需要它到。然后,如果我想要 10 种速度,将表单移动 1、2、3、4、5、6、7、8、9 和 10 像素可提供慢速和快速平滑动画,正如我想要的那样。如果我想要 5 种速度,例如,我可以使用 2、4、6、8、10。

我的问题是:将 300 之类的值用于 FPS 有什么问题吗?这样的值有什么不好的后果吗?

这是我当前的代码:

public partial class Form1 : Form {

    bool dir = true;

    public Form1() {
        InitializeComponent();

        Location = new Point(1280/2 - Width, 800/2 - Height/2);
    }

    private void button1_Click(object sender, EventArgs e) {
        double FPS = 300;
        int PX = 1;
        long lastTicks = 0;
        long currentTicks = 0;
        double interval = (double)Stopwatch.Frequency / FPS;

        while(dir ? Left <= 1280/2 : Left >= 1280/2 - Width) {
            Application.DoEvents();

            currentTicks = Stopwatch.GetTimestamp();

            if(currentTicks >= lastTicks + interval) {
                lastTicks = Stopwatch.GetTimestamp();

                this.Location = new Point(dir ? Left + PX : Left - PX, Top);

                this.Invalidate(); //refreshes the form
            }

            Thread.Sleep(1); //frees up the cpu
        }

        dir = !dir;
    }

}

注意:这只是示例代码,用于测试目的,不是真实代码,如果您想指出一些非常重要的事情,我应该在将其移植到真实应用程序时考虑这些事情。

4

4 回答 4

4

尝试执行我之前的建议(不考虑 FPS):

public partial class Form1 : Form
{
    private bool go;
    private int dx = 1;
    public Form1()
    {
        InitializeComponent();
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (go)
        {
            this.Location = new Point(this.Location.X + dx, this.Location.Y);
            if (Location.X < 10 || Location.X > 1200)
            {
                go = false;
                dx = -dx;
            }
            else
            {
                this.Invalidate();
            }
        }
    }
    private void button1_Click(object sender, EventArgs e)
    {
        go = true;
        this.Invalidate();
    }
}

我认为您可能不得不走出 winforms 以获得更高的 FPS。

于 2009-06-10T20:28:40.857 回答
1

我认为 Windows 限制了重绘率,所以如果你把 FPS 调到疯狂的值也没关系;如果您想看到更高的帧速率,您可能不得不使用 XNA/DirectX 动画之类的东西。

您可以使用计时器,并编写一个经过的事件处理程序,该处理程序既可以移动又可以使您的表单无效。为此,您不必执行 Thread.Sleep 或使用最后的滴答声和间隔计算进行簿记,并且它会以有规律的节奏发生。此外,当你想改变方向时,你可以否定 PX 值,而不是围绕“dir”布尔值的条件代码(并且只做加法而不是 dir 上的三元运算符);这是可能的,因为减法与加负数相同。

这应该使您的动画更容易扩展以执行其他操作。为了好玩,您还可以创建一个 PY 来垂直移动。不管怎样,我希望你玩得开心。:)

于 2009-06-09T04:04:21.363 回答
0

如果您以 300 的 FPS 值获得所需的结果,那么我会接受。WinForms 的每秒帧数的概念与图形密集型视频游戏不同,因此高值不会成为问题。这里的 FPS 值只是调整代码执行的频率。

于 2009-06-10T21:37:46.583 回答
-1

超级杀戮解决方案

摘要:制作窗口移动的动画,然后播放(可能全屏)

详细信息:
假设您的窗口是 100x100,并且是 @0,0
对屏幕截图:(0,0)-(200,200)。
使用屏幕截图创建一个剪辑,描述将您的窗口从 0,0 移动到 100,100
然后创建一个无边框窗口 (0,0)-(200,200),并在其上放置一个视频播放器,并重播你的窗户在里面移动。

不用说您的窗口将是静态的。但是你可以获得最好的动画。您甚至可以为窗口移动添加一些效果,例如矩阵中的子弹或 Necromunga 飞船。

于 2009-06-10T20:35:50.717 回答