3

GDI+ でスムーズなアニメーションを作成するのに問題があります。私がグーグルで理解している問題は、マルチコア プロセッサ上の .NET のクロック ティックに何らかのバグがあることです。これが私がやっていることの簡略化されたバージョンです:

class Animation
{
  System.Diagnostics.Stopwatch sw = new Stopwatch();
  float AnimationTime = 1000; //time it takes the animation to complete

  public bool IsComplete
  { get { return sw.ElapsedMilliseconds > AnimationTime; } }

  public void StartAnimation()
  {
     sw.Reset();
     sw.Start();
  }

  public void DoFrame()
  {
     float PercentComplete = (float)sw.ElapsedMilliseconds / AnimationTime;
     //draw the animation based on PercentComplete
  }
}

DoFrame() は次のように呼び出されます。

Animation.Start();
do
{
  Animation.DoFrame();
  Application.DoEvents();
} while (!Animation.IsComplete);

問題は、アニメーションが約 15 フレームの間非常に滑らかで、それからぎくしゃくし、実際には後方に移動することです (sw.ElapsedMilliseconds は、前のクエリよりも小さい値を返します)。これは非常に面倒で、Core 2 Duo でも見栄えのするスムーズなアニメーションが台無しになります (Microsoft はこれをマルチコアのバグだと言っていますが)。私は i7 を持っていますが、アニメーションは毎秒 2 ~ 3 フレームが「ぎくしゃく」する以外はスムーズです。

これは既知の問題であり、マイクロソフトはそれをプロセッサのせいにしていることを理解しています。私の質問は、これに対する解決策を知っている人はいますか? カルマン フィルターを使用してみましたが、うまくいきました。これには確立された「正しい」解決策があるのではないかと思っていましたか?

ところで、ストップウォッチの代わりに DateTime を使用してみましたが、同じ結果が得られました。

私も試しました:

double PercentComplete = (double)sw.ElapsedTicks / (double)Stopwatch.Frequency * 1000 / AnimationTime

同じ結果が得られます。

4

1 に答える 1

1

それはおそらくあなたが呼び出す方法に関係していますDoFrame()。次の Windows フォーム/GDI+ ベースのアルゴリズムを使用すると、常に非常に滑らかなアニメーションが得られます。

const double desiredFps = 500.0;
long ticks1 = 0;
var interval = Stopwatch.Frequency / desiredFps;
while (true)
{
    Application.DoEvents();
    var ticks2 = Stopwatch.GetTimestamp();
    if (ticks2 >= ticks1 + interval)
    {
        ticks1 = Stopwatch.GetTimestamp();

        // do the drawing here
    }
}
于 2012-10-10T09:51:54.933 に答える