9

私は2Dゲームを書いていますが、カメラスペースに鳥がいます。飛ばしたいです。だから、私は3つの〜ランダムなポイントを生成します。1つ目は左上、2つ目は中下、3つ目は右上です。

その結果、180度回転した三角形になりました。

鳥をカーブのパスに沿って移動させるために、各フレーム(レンダリングループ)でデルタごとに増加するtパラメーターがあります。

問題は、異なる曲線では鳥の速度が異なることです。三角形が「幅広」(1)の場合は遅くなり、Y座標(2)で引き伸ばされた場合は、速度が非常に速くなります。

ここに画像の説明を入力してください

しかし、私は異なるカーブで速度を等しくしたいと思っています。論理的にはdelta、各曲線の各フレームに追加されるものを変更する必要があります。


私はそれを次のように解決しようとしました:

2つのベクトルの長さを合計して曲線の〜長さを求めます:P1P2P2P3

フレームごとに1つの仮想メーターの速度を定義したよりも。少しの擬似コード:

float pixelsInMeter = 92.f; // One virtual meter equals to this number of pixels
float length = len(P1P2) + len(P2P3)
float speed  = 0.0003f; // m/frame

// (length * speed) / etalon_length
float speedForTheCurve = toPixels( (toMeters(length) * speed) / 1.f);

// ...
// Each frame code:
t += speedForTheCurve;
Vector2 newPos = BezierQuadratic(t, P1, P2, P3);

しかし、とにかく鳥は異なる速度を持っています。どうしたの?あるいは、もっと良い方法があるかもしれません。

4

1 に答える 1

2

使用しているベジエ関数は、境界 [0...1] を持つパラメーター化された関数です。あなたはステップサイズをいじっています。それがあなたが狂った速度を得ている理由です。一般的に言えば、距離dは方程式の従属変数であり、曲線の長さに基づいて速度が異なることを示しています。

速度は従属変数であるため、ステップ サイズを計算して関数をベクトル化します。

この疑似コードをチェックしてください:

P1 = (x1, y1)

P2 = (x2, y2)

P3 = (x3, y3)

int vec[100][2]

int getPoint(int p1, int p2, float stepSize) {
   return p1 + (p2 - p1)*stepSize;
}

for (float i = 0.0; i < 1.0; i += 0.01 ) {
   int newX = getPoint(getPoint(x1, x2, i), getPoint(x2, x3, i), i);
   int newY = getPoint(getPoint(y1, y2, i), getPoint(y2, y3, i), i);
   vec[iter++][0] = newX;
   vec[iter][1] = newY;
}

最初の差分を実行することでデルタ値を取得できますが、それは必要ではないと思います。ステップの反復に基づいてすべての鳥を適切な距離だけ移動させる限り、すべての鳥は異なる距離を移動しますが、軌道の開始と終了は同じになります。

式から、ピクセル デルタ ステップ サイズを計算できます。

int pixelsToMove = toMeter(sqrt((x2 - x1)^2 + (y2 - y1)^2))/pixelsInMeter;

これにより、鳥を動かすのに適切な量のピクセルが得られます。そうすれば、それらはすべて異なるステップ サイズで移動しますが、速度は異なります。それは理にかなっていますか?


または、次のようなことを試してください (はるかに難しい):

  1. 選択した 3 点の実際の 2 次関数を取得します。
  2. xy2 つの直角座標間の 2 次を積分する
  3. 計算された長さをピクセルまたは使用しているものに変換します
  4. すべてのカーブが同時に終了するように、従属可変速度を取得します。

二次的なものから始めましょう:

y = Ax^2 + Bx + CここでA != 0、3 つの点があるので、3 つの方程式が必要になります。代数を使用すると、定数を解くことができます。

A = (y3 - y2)/((x3 - x2)(x3 - x1)) - (y1 - y2)/((x1 - x2)(x3 - x1))

B = (y1 - y2 + A(x2^2 - x1^2))/(x1 - x2)

C = y1 - Ax1^2 - Bx1

次に、上記の式を使用して、閉じた形式の弧の長さを取得できます。この Web サイトをチェックしてください。wolfram が統合してくれるので、次のように入力するだけです。

二次積分の閉形式ソリューション

円弧の長さを計算したらactualArcLength、速度または使用している単位に変換します。

float speedForTheCurve = toPixels( (toMeters(actualArcLength) * speed) / 1.f);
于 2013-02-09T21:00:56.050 に答える