0

Windows フォームの場所をスムーズにアニメーション化しようとしましたが、速度を可変にしたい場合に問題が発生します。つまり、ユーザーがアニメーションの優先速度を選択できるようにしたい場合です。

次の記事を見つけたので、フォームで探していたアニメーションを実行するのにかなり役立ちました。過去に試した BackgroundWorker または Threads アプローチよりもあらゆる点で優れているようです: http://www.vcskicks.com/animated-windows-form.html

私の唯一の問題は、アニメーションの速度を変えたい場合にスムーズなアニメーションを維持することです。私のコードにはFPSPXという 2 つの重要な値があります。FPS は 1 秒あたりのフレーム数 (その他) を表し、PX はフォームを移動するピクセル数を表します。

問題 1)可能な限りスムーズなアニメーションを実現するには、フォームを一度に 1 ピクセルずつ移動したいのですが、フォームをそのように速く移動できるとは思いません。FPS 値を非常に高い値に上げても効果はないようです。限界があるようで、その限界を超えると目に見える違いはありません。私はそれについての良い説明があると確信しています。

ここでの私の質問は次のとおりです。この問題に対する適切な解決策はありますか、それとも PX 値を変更してフォームを 1 ピクセル以上移動するのが唯一の解決策ですか?

問題 2)上記の質問の解決策がそれに応じて PX 値を変更することである場合、(さまざまな値をテストすることによって) 300 に等しい FPS 値で、フォームを必要なだけゆっくりと速く動かす必要があることがわかりました。それをする。次に、10 の速度が必要な場合は、フォームを 1、2、3、4、5、6、7、8、9、および 10 ピクセルずつ移動すると、必要に応じて低速および高速の滑らかなアニメーションが得られます。たとえば、5 つの速度が必要な場合は、2、4、6、8、10 を使用できます。

ここでの私の質問は次のとおりです: FPS に 300 のような値を使用することに問題はありますか? そのような値に悪い結果はありますか?

そして、ここに私の現在のコードがあります:

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();
    }
}

より高い FPS を得るには、おそらく winforms の外に出る必要があると思います。

于 2009-06-10T20:28:40.857 に答える
1

Windows は再描画率を制限していると思うので、FPS を非常識な値まで上げても問題ありません。より高いフレーム レートを見たい場合は、おそらく XNA/DirectX アニメーションのようなものにする必要があります。

タイマーを使用して、フォームの移動と無効化の両方を行う経過イベント ハンドラーを作成できます。そのためには、Thread.Sleep を実行したり、最後のティックと間隔の計算を記録したりする必要はなく、通常のリズムで実行されます。さらに、「dir」ブール値の周りの条件付きコードの代わりに、方向を変更したいときに PX 値を否定することができます (そして、dir の三項演算子の代わりに加算のみを行います)。減算はマイナスを加算することと同じであるため、これが可能です。

これにより、アニメーションを拡張して他のことを実行しやすくなります。楽しみのために、PY を作成して垂直方向にも移動させることもできます。いずれにせよ、楽しんでいただければ幸いです。:)

于 2009-06-09T04:04:21.363 に答える
0

300 の FPS 値で必要な結果が得られた場合は、それを使用します。WinForms の 1 秒あたりのフレーム数の概念は、グラフィックを多用するビデオ ゲームと同じではないため、高い値が問題になることはありません。ここでの FPS 値は、コードが実行される頻度を調整するだけです。

于 2009-06-10T21:37:46.583 に答える
-1

スーパーオーバーキルソリューション

まとめ:ウィンドウが動くアニメーションを作成し、それを再生します (おそらく全画面表示)。

詳細:
ウィンドウが 100x100 で、@0,0 であると仮定します

スクリーンショットを使用して、ウィンドウを 0,0 から 100,100 に移動することを示すクリップを作成します。
次に、ボーダレス ウィンドウ (0,0)-(200,200) を作成し、その上にビデオ プレーヤーを置き、アニメーションを再生します。あなたの窓が内側に移動します。

言うまでもなく、ウィンドウは静的になります。しかし、最高のアニメーションを手に入れることができます。マトリックスの弾丸やネクロムンガの船など、ウィンドウの動きにいくつかの効果を追加することもできます.

于 2009-06-10T20:35:50.717 に答える