2017-11-29 6 views
0

私はjavascriptのゲームを作っています。そして、私はこの基本的なgameloopエンジンを持っています。ゲームループの速度は、異なるコンピュータで異なります

var left = 0, 
    speed = documentHeight/300; 

var keyState = {}; 
window.addEventListener('keydown',function(e){ 
    keyState[e.keyCode || e.which] = true; 
},true);  
window.addEventListener('keyup',function(e){ 
    keyState[e.keyCode || e.which] = false; 
},true); 

function gameLoop() { 
    if (keyState[39]) { 
    left -= speed; 
    move(); 
    } 
    if (keyState[37]){ 
    left += speed; 
    move(); 
    } 

    function move() { 
    element.style.left = left + 'px'; 
    } 

    setTimeout(gameLoop, 20); 
} 
gameLoop(); 

私はすべて100%の高さにしていますので、ドキュメントの高さに合わせて速度を設定しました。それは私のPC上でうまく動作し、サイズを変更しても一貫しています。しかし、私がiMacでテストしたところ、要素の動きははるかに遅くなりました。私もwindow.requestAnimationFrame(gameLoop)を試しましたが、同じことが起こります。

これはいくつかの画面でより多くのfpsを処理することと関連していますか?すべてのコンピュータ/スクリーンで一貫した速度を達成する最良の方法は何でしょうか?

+0

requestAnimationFrameをご覧ください(例:https://stackoverflow.com/questions/19764018/controlling-fps-with-requestanimationframe) – keja

+0

物理学とフレームレートを結合しないでください。 – zero298

+0

将来の訪問者の明快さのために、zero298のコメントは、私の答えが説明していることを言うための素敵で簡潔な方法です。 – samanime

答えて

2

フレームあたり20ミリ秒で、それは50 fpsです。それは超高ではありませんが、遅いコンピュータでは遅くなる可能性があります(それは追いつくことができないためです)。

より安全なアプローチは、希望のフレームレートで実行することですが、一定のFPSを仮定するのではなく、実際の経過時間に基づいてフレーム間の時間の差分をチェックして動きを行います。

だけで、その後、最後の時間に各ループを記録した時間の量に基づいて、いくつかの要因により、現在の時間と規模から減算されることを行う簡単な方法、何かのように:

だから私は作ってるんですジャバスクリプトゲーム。そして、私はこの基本的なgameloopエンジンを持っています。

var left = 0, 
    speed = documentHeight/300, 
    lastTime = Date.now(); 

var keyState = {}; 
window.addEventListener('keydown',function(e){ 
    keyState[e.keyCode || e.which] = true; 
},true);  
window.addEventListener('keyup',function(e){ 
    keyState[e.keyCode || e.which] = false; 
},true); 

function gameLoop() { 
    const currentTime = Date.now(); 
    const delta = currentTime - lastTime; 
    lastTime = currentTime; 

    if (keyState[39]) { 
    left -= speed * delta; 
    move(); 
    } 
    if (keyState[37]){ 
    left += speed * delta; 
    move(); 
    } 

    function move() { 
    element.style.left = left + 'px'; 
    } 

    setTimeout(gameLoop, 20); 
} 
gameLoop(); 

そして、ちょうど(ミリ秒ごとに5pxの、またはミリ秒画面の高さの0.00033パーセントなど)ミリ秒ごとに何かを「高速」の相対値を設定します。これを実行し、経過時間を掛けることで、実際にループ速度が一貫していなくてもスムーズな動きが得られます。

その他の注意:アプリケーションによっては、残りの部分も追跡したい場合があります。 「10px /秒」のようなことをしているのに、20msが経過している場合は、10/1000 * 20 = 0.2pxです。実際に.2pxを移動することはできないので、残りの部分を追跡して、次のループでそれを追加することができます。

また、位置を小数点にしてdraw()フェーズで解決することもできます。これは、よりクリーンなアプローチであり、通常は代わりに使用します。

+0

ねえ、ありがとう!私はms部分の設定速度で少し失われました。もう少し説明できますか?ミリ秒ごとにどれくらい正確に設定するのですか? –

+0

あなたの 'delta'は「最後のループからのミリ秒数」になるので、その量に基づいてすべてを拡大縮小したいと思うでしょう。だから、もともと "500px /秒"を動かすことを意図していた場合、それを1000分の1秒(ミリ秒に変換)で割って ".5px per millisecond"にします。次に、「5ミリ秒毎ミリ秒」を「最後のループから5ミリ秒」で複数回移動する場合は、移動したい量を移動します。この例では、速度変数を '.5'に設定します。それは助けますか? – samanime

+0

パーフェクト!どうもありがとうございます!素晴らしい説明とスピードは両方のコンピュータで一貫しています。 –

関連する問題