2

私は Javascript (HTML5 Canvas) でゲームに取り組んでいます。オブジェクトが別のオブジェクトをたどることを可能にする単純なアルゴリズムを実装しました。これは、基本的な物理学が混在しています (オブジェクトを正しい方向に駆動する力ベクトルと、速度が運動量を積み上げますが、一定の抗力によって減速されます)。現時点では、マウス (x, y) 座標に沿った長方形として設定しています。コードは次のとおりです。

// rectangle x, y position
var x = 400; // starting x position
var y = 250; // starting y position
var FPS = 60; // frames per second of the screen
// physics variables:
var velX = 0; // initial velocity at 0 (not moving)
var velY = 0; // not moving
var drag = 0.92; // drag force reduces velocity by 8% per frame
var force = 0.35; // overall force applied to move the rectangle
var angle = 0; // angle in which to move

// called every frame (at 60 frames per second):
function update(){
    // calculate distance between mouse and rectangle
    var dx = mouseX - x;
    var dy = mouseY - y;
    // calculate angle between mouse and rectangle
    var angle = Math.atan(dy/dx);
    if(dx < 0)
        angle += Math.PI;
    else if(dy < 0)
        angle += 2*Math.PI;

    // calculate the force (on or off, depending on user input)
    var curForce;
    if(keys[32]) // SPACE bar
        curForce = force; // if pressed, use 0.35 as force
    else
        curForce = 0; // otherwise, force is 0

    // increment velocty by the force, and scaled by drag for x and y
    velX += curForce * Math.cos(angle);
    velX *= drag;
    velY += curForce * Math.sin(angle);
    velY *= drag;

    // update x and y by their velocities
    x += velX;
    y += velY;

そして、それは毎秒60フレームでうまく機能します. さて、難しい部分: 私の質問は、これを別のフレームレート (たとえば 30 FPS) に変更した場合、力とドラッグの値を変更して動きを一定に保つにはどうすればよいかということです。

つまり、現在、私の長方形 (位置は x 変数と y 変数によって決定されます) は、毎秒約 4 ピクセルの最大速度で移動し、約 1 秒で最大速度まで加速します。しかし、フレームレートを変更すると、動きが遅くなります (たとえば、30 FPS はフレームあたりわずか 2 ピクセルに加速します)。

では、入力として FPS (フレーム/秒) を受け取り、リアルタイムで同じように動作する正しい「ドラッグ」値と「フォース」値を吐き出す方程式を作成するにはどうすればよいでしょうか?

難しい質問であることは承知していますが、おそらくゲーム デザインの経験があるか、物理学のプログラミングの知識がある人が助けてくれるでしょう。ご尽力いただきありがとうございます。

jsFiddle: http://jsfiddle.net/BadDB

4

4 に答える 4

3

実時間測定を紹介します。次に、実際の経過時間と目的の最大速度の関数になるように方程式を作り直す必要があります。実際の経過時間を使用する利点は、プログラムされた FPS で動作しない (負荷やその他の理由により) システムでも方程式がうまく機能することです。

余談ですが、Math.atan2(dy, dx)の代わりに使用する必要がありMath.atan(dy/dx)ます。(いつ何が起こるか考えてみてくださいdx == 0。)

于 2012-09-12T03:00:04.007 に答える
1

理想的には、前のフレームからの経過時間としてタイムフレームを取得し、実際のデルタに基づいてスケール係数を計算し、それを時間ベースの計算に使用する必要があります。

理想的には、ゲームが 60 fps で実行されていると考えてください。また、ゲームプレイのすべての単一フレームで正確に 1000ms/60f でゲームが実行されることはめったにないことも考慮してください。

だからあなたの理想は1000/60. あなたの実際はcurrent_timestamp - previous_timestamp. あなたの時間枠のスケールはactual/ideal.

あとは、スケールを使用して、時間に敏感な値を変換するだけです。

時間の関数であるすべてのものは、その「フレームあたりの理想値」( magnitude = 8; current_magnitude = magnitude * scale; vec.x *= current_magnitude; vec.y *= current_magnitude; vec.z *= current_magnitude;) を使用できます。

いつ乗算し、いつ乗算しないかを理解するように注意する必要があります。計算が時間ベースの場合は、事前に乗算します。そうでない場合は、しないでください。

ゲームが 15 fps で実行されている場合、時間スケールは 4 倍になりますよね? それは何かの力に影響を与えるべきではありません。たとえば、車のトルク、つまりエンジンが蓄積しているエネルギーに影響を与えることはありません。それ影響するのは、その正確な時間内にどれだけの加速(線形またはその他)が発生するかです。

車が 0.5m/s^2 の速度で加速する必要がある場合、または何を決定しようとしても、その加速の一部 (現在の速度に加算される) だけを見ていることになります。これは、秒の特定の部分に適用されます。次の更新では、車は設定した速度で移動し、現在のフレームとその時点での前のフレームとの差として計算した時間スケールを掛けます。

回転も同じ方法で計算する必要があります。

これにより、一貫性のないフレームレートを実際のアクションから切り離すことができます。これは、常にハード ナンバー (時間が関係する場合) ではなくパーセンテージに基づいて操作しているためです。

これにより、バレットタイムのようなことをばかげて簡単に行うこともできます. 照準を除くすべてに追加のバレットタイム ファクターを追加します。または、忍者反射を作成したい場合は、プレイヤーと敵に異なる時間スケールを適用します。

凍結時間については、次の 2 つのオプションがあります。

  1. すべてを 0 に設定し、以前の値を忘れます (再開時に、すべてが 0 から勢いを増すようにします)
  2. すべてを 0 に設定しますが、以前のすべての値の「フレーム」を保持します。後で 0 を忘れますが、一時停止が発生してから 1 フレームだけが経過したかのように、次の期間を扱います。

あなたが何をすべきかについて話しているときdrag- あなたはそれを自分で言いました:あなたのシミュレーションでdragは. constant話している期間がどれだけ長くても短くてもかまいません。その期間にオブジェクトにドラッグが与えた効果は、他のオブジェクトにどのように影響するかと一貫しています。一定の期間。

于 2012-09-12T03:24:42.870 に答える
0

力を 2 倍にし、抗力はそのままにします。

編集:

数学:

運動は、初期加速度と終末速度の 2 つのパラメーターによって完全に記述できます。この2つが正しければ、モーションも正しく見えます。

初期加速の場合、抗力 (この種の抗力) は関係ありません。は加速度であるためforce、1 秒分の加速度を得るには、1 秒間に多くのフレームを追加するだけです。

30 * 30 = 力60 * 60
30 = 力60 * 60/30 = 2.0 * 力60 = 2.0 (0.35) = 0.7

終末速度は、力と抗力が釣り合ったときに発生します。

V* 抗力 = 力
抗力 = 力 / V

Vをスケーリングしたいのですが、 もスケーリングforceしているため、スケール項はキャンセルされます。drag変更する必要はありません。

于 2012-09-12T03:01:48.640 に答える
0

時間で積分すると、力の積分が速度、速度の積分が位置になります。タイム ステップを 2 つのフレーム間の時間と等しくすると、ポスト コリジョン ディテクターがある場合に弾丸物理学が機能します。

2 つのフレーム間の時間は、FPS に反比例します。

FPS = 合計フレーム数 / 合計時間

タイム ステップ = ( 1.0/(float)FPS 秒 )*K。K は、タイムステップを十分に小さくして、物理が十分に安定するようにするための定数です。

于 2012-09-12T16:40:38.123 に答える