你是正確的。如果幀速率不同,你的時間步長是不同的,所以加速度會有點不可預測。這就是爲什麼許多遊戲使用與遊戲幀率分開運行的固定時間步長的原因。這是確保遊戲在每臺設備上都完全相同的一種方式。
如果這是一個簡單的遊戲,競爭力不強,那麼你只需要確保它保持準確,不一定確定性。如果是這樣的話,我認爲你可以作弊一點,並使用最大時間步而不是固定的時間步。遊戲在任何時候都不會完全一樣,但它足夠準確,沒有人會注意到。爲此,請設置一些最大增量時間。在遊戲的每一幀中,重複調用更新,直到所有增量時間用完,但總增量時間仍然準確。例如:
public static final float MAX_DELTA = 1/50f;
public static final int MAX_UPDATES_PER_FRAME = 3;
private float elapsedTime;
public void render (float deltaTime){
elapsedTime += deltaTime;
int updates = 0;
while (elapsedTime > 0 && updates < MAX_UPDATES_PER_FRAME){
update(Math.min(MAX_DELTA, elapsedTime));
elapsedTime = Math.max(0, elapsedTime - MAX_DELTA);
updates++;
}
// drawing
}
所以發生了什麼事是在while循環,反覆更新物理,直到與當前時間趕上,使用MAX_DELTA
或更小的時間步驟。你只需要確保MAX_DELTA
足夠小,以確保你的物理看起來正確,你不能隧穿薄壁。變量MAX_UPDATES_PER_FRAME
是爲了確保當CPU峯值過高導致delta時間越來越遠並且落後時,您不會進入「死亡螺旋」。相反,你的遊戲會進入一個緩慢的模式,直到它迎頭趕上。
這是比固定時間步驟(famously explained here)更簡單的原因是,您不必存儲兩個模擬之間進行內插以進行渲染。具有固定時間步長,上面的代碼變爲:
public static final float FIXED_TIMESTEP = 1/50f;
public static final int MAX_UPDATES_PER_FRAME = 3;
private float elapsedTime;
public void render (float deltaTime){
elapsedTime += deltaTime;
int updates = 0;
while (elapsedTime >= FIXED_TIMESTEP = && updates < MAX_UPDATES_PER_FRAME){
update(FIXED_TIMESTEP);
elapsedTime -= FIXED_TIMESTEP;
updates++;
}
// drawing
}
這導致難看口吃,並且只能通過保持所有的位置數據的兩個副本進行遊戲,每幀在它們之間交替,並進行內插來固定在剩餘的elapsedTime
之間的兩個值之間得到適合繪製平滑動畫的值。非常複雜!
這就是我在我的問題中所做的,我將速度乘以增量時間並將其添加到當前位置。但是,當速度不是恆定的並且在每一幀中都會減少時,那麼fps較低的玩家會比高fps的玩家進一步移動,不是嗎? – androlama
是的,他在每一幀都進一步移動,但fps較高的玩家比fps較低的玩家移動的次數多。因此,每個人移動的距離差不多相同 – Fefux
根據我在1秒後的計算結果,如果他們都向前按一次按鈕,則1fps的玩家將比30fps的玩家進一步增加約40個單位。 40是相當大的差異,我不希望用戶利用這一點,並得到較低的fps分數較高 – androlama