2009-06-09 68 views
0

我一直在嘗試平滑地動畫一些Windows窗體位置,但如果我想讓速度變化,我遇到了一些問題。換句話說,如果我想讓用戶選擇動畫的首選速度。如何平滑地以不同的速度動畫化Windows窗體位置?

我發現以下文章,幫助我執行我正在尋找的動畫,對於我的表單。看起來好像比過去我嘗試過的BackgroundWorker或Threads方法更好: http://www.vcskicks.com/animated-windows-form.html

我現在唯一的問題是如果我想爲動畫提供不同的速度,請保持流暢的動畫。在我的代碼中有兩個重要的值,FPSPX。 FPS表示每秒幀數(還有什麼),PX表示移動表單的像素數量。

問題1)爲了獲得最平滑的動畫,我寧願讓表單一次移動1px,但我不認爲我能夠像那樣快地移動表單。將FPS值提高到一個非常高的值似乎沒有任何影響,就像有一個限制,超過這個限制,將不會有明顯的差異。我確信有一個很好的解釋。

我在這裏的問題是:你有這個問題的任何好的解決方案或唯一的解決方案是更改PX值,並移動窗體超過1px,如果我想要更快的移動?

問題2)如果上述問題的解決方案是相應地更改PX值,我發現(通過測試不同的值)FPS值等於300就足以滿足我需要將窗體移動爲緩慢並儘可能快地達到我的要求。然後,如果我想要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; 
    } 

} 

注:這只是示例代碼,用於測試目的,不是真正的代碼,但如果你想指出一些非常重要的事情是我的客人,我應該考慮將其移植到實際應用程序中。

+1

該限制應該是您的顯示器的刷新率:典型TFT的60Hz,實際上是60 FPS。 – VVS 2009-06-10 20:33:58

回答

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。

1

我認爲Windows限制重繪速度,所以如果您將FPS提升到瘋狂的值就沒有關係;如果你想看到更高的幀速率,你可能不得不導致像XNA/DirectX動畫。

你可以使用一個Timer,並且寫一個已經過去的事件處理程序,它既會移動&使表單失效。爲此,您不必執行Thread.Sleep或使用最後一個滴答和間隔計算器進行記錄,並且會以常規節奏進行。此外,而不是圍繞'dir'布爾值的條件代碼,當你想改變方向時,你可以否定PX值(並且在dir上添加 - 只能代替三元運算符)。這是可能的,因爲減法與增加一個負數相同。

這應該會使您的動畫更容易延伸到做其他事情。爲了好玩,你也可以創建一個PY來垂直移動。無論如何,我希望你有一些樂趣。:)

+0

計時器不允許我正在查找的準確性。而且我確定你甚至沒有閱讀我發佈的鏈接,因爲Thread.Sleep()僅僅是出於某種原因,並且原因不是爲了控制動畫速度,而是像評論所說的那樣,釋放CPU。沒有這條線,在動畫處理時CPU的使用率將是100%。 – 2009-06-09 15:16:45

-1

超過殺死解決方案

摘要:讓你的窗口移動的動畫,並進行播放(全屏幕,也許)

詳情:
假設你窗口爲100x100,並且@ 0,0
拍攝屏幕:嗯,屏幕:(0,0) - (200,200)。
使用屏幕截圖創建一個剪輯,描述了將窗口從0,0移動到100,100
然後創建一個無邊界窗口(0,0) - (200,200),並在其上放置一個視頻播放器,然後重播您的窗戶在裏面移動的動畫。

不用說,你的窗口將是靜態的。但是你可以獲得最好的動畫。你甚至可以爲移動的窗口添加一些效果,如矩陣中的子彈或Necromunga船。

0

如果你得到你想要的結果,並且FPS值爲300,那麼我會選擇這個結果。 WinForms每秒幀數的概念與圖形密集型視頻遊戲不同,因此高價值不會成爲問題。這裏的FPS值只是調整代碼的執行頻率。