2011-10-03 551 views
2

爲了實現動畫,我只是在循環中重繪東西。如何用OpenGL/glut暫停動畫

但是,我需要能夠暫停,當一個鍵被按下。我知道我現在這樣做的方式是錯誤的,因爲它會在循環進行時吃掉我所有的週期。

哪種方式更好,並允許關鍵暫停和恢復?

我試過使用布爾標誌,但顯然它沒有改變標誌,直到循環完成。

+0

你的意思是說你的整個遊戲運行在一個循環中,或者動畫本身是小循環? –

回答

7

你有正確的非常基本的體系結構,所有東西都需要循環更新,但是你需要讓遊戲(或其他需要OpenGL動畫的應用程序)變得更加智能。

但是,我需要能夠暫停當一個按鍵被按下。

這樣做的一個基本方法是讓布爾值爲paused並將遊戲包裝成一個循環。

while(!finished) { 
    while(!paused) { 
     update(); 
     render(); 
    } 
} 

通常但是你仍然希望在本場比賽的暫停做的事情,如看您的庫存,手藝東西等,而你的遊戲暫停,很多遊戲仍然可以運行自己的主循環,他們只是不」讓演員們知道任何時間都過去了。例如,它聽起來像你的動畫幀只有許多可以看到的遊戲幀。這是一個糟糕的主意,因爲如果動畫速度在不同的計算機上增加或減少,則動畫速度在這些計算機上看起來是錯誤的。您可以考慮我的回答here以及鏈接的示例,瞭解如何通過以毫秒持續時間指定動畫幀並在更新循環中傳遞幀時間來實現與幀率無關的動畫。例如,你的主遊戲,然後變成這個樣子:

float previousTime = 0.0f; 
float thisTime = 0.0f; 
float framePeriod = 0.0f; 

while(!finished) { 
    thisTime = getTimeInMilliseconds(); 
    framePeriod = previousTime - thisTime; 

    update(framePeriod); 
    render(); 

    previousTime = thisTime; 
} 

現在,一切都在遊戲中得到更新會知道,因爲前一幀多少時間已經過去了。這對所有物理計算都有幫助,因爲我們所有的物理公式都是以時間+起始因子+衰減因子(例如SUVAT方程)爲單位的。相同的信息可以用於您的動畫,使它們獨立於幀率,正如我已經介紹過的一些鏈接指向例子here

要回答這個問題的下一個部分:

it eats all of my cycles when the loop is going on. 

這是因爲你使用的CPU的100%,並且永遠不會睡覺。如果我們考慮在目標設備上需要例如30fps(並且我們知道這是可能的),那麼我們知道一幀的週期是1/30秒。我們剛剛計算出需要更新和渲染我們的遊戲的時候,所以我們可以睡上任何的空餘時間:

float previousTime = 0.0f; 
float thisTime = 0.0f; 
float framePeriod = 0.0f; 
float availablePeriod = 1/30.0f; 

while (!finished) { 
    thisTime = getTimeInMilliseconds(); 
    framePeriod = previousTime - thisTime; 

    update(framePeriod); 
    render(); 

    previousTime = thisTime; 

    if (framePeriod < availablePeriod) 
     sleep(availablePeriod - framePeriod); 
} 

這種技術被稱爲要手動控制率幀率治理上,你正在渲染和更新。

+0

現在我有類似的東西,比如if(complete)...但由於某種原因,MouseEvent在我的循環中並不改變我的標誌。我在yoru代碼上看到的唯一不同是我的更新函數在更新(函數)中被隔離,我的代碼在我的循環中。你的代碼解決了CPU吃飯問題,但我需要一些關於鼠標事件(或鍵盤)的幫助。你可以擴大一點嗎? – Andre

+0

@Andre你確定你的鼠標事件處理程序被調用?你用一個調試器檢查過它改變了暫停布爾*,並且這個改變在你的主循環中可見*?這裏可能有一個範圍問題。 –

+0

它確實改變了標誌,但不是當它做我的主動畫循環時。我可能是因爲它使用所有的循環做循環,並沒有得到做我的mousevent。這聽起來像是一個合理的演繹? – Andre