太陽の動きのための機能?


9

したがって、地平線に設定された太陽スプライト(x = 0、y = worldheight / 2)が与えられた場合、太陽を昇らせてから降らせる関数を考案しようとしています。

これを行う最良の方法はsin関数ですが、それを使用する方法はわかりません。

y = sin(x)を使用する場合、完全な曲線の場合、xの速度は一定であるのに対し、xは0からpiの範囲でなければなりません。

考えや提案はありますか?

編集:みんなありがとう!

太陽が働いています!

回答:


7

0からpiの問題については、一般的に、Xを乗数でスケーリングするだけです。例:

y = sin(x * pi / worldWidth)

http://www.wolframalpha.com/input/?i=Plot%5BSin%5Bx%5D%2C+%7Bx%2C+0%2C+Pi%7D%5D

しかし、これはおそらくあなたが探している曲線を完全には得ていません。次のパラメトリック形式を使用する必要があります。

t = 0 -> pi over the course of a day
y = sin(t)   -> goes from 0 up to 1 at noon, then down to 0 again
x = (1-cos(t))/2 -> starts at 0 goes up to 1 by sundown.

http://www.wolframalpha.com/input/?i=ParametricPlot%5B%7B1+-+Cos%5Bt%5D%2C+Sin%5Bt%5D%7D%2C+%7Bt%2C+0%2C+Pi% 7D%5D

YのsinとXのcosのこの組み合わせは、楕円をトレースします。


おかげで、これは素晴らしいです。私は数学中心ではありません。私の数学のスキルは、ほとんど初歩的な計算です。
ロス

12

ジミーが言ったように、楕円はおそらくこの動きにより適しています。興味のある人のために、もう少し詳細に実際にそれを実装する方法に関するいくつかのアイデアがあります。

時間をかけて

まず、ゲームの世界で時間を追跡するための変数が必要です。好きなように実装できますが、ここに例を示します。私はhours0から24まで変化すると呼ばれる変数を使用します(ただし、24に達すると0に戻ります)。

しかし、実際の生活とは異なり、その日は0時間から始まり、夜は12時間から始まると考えます。これにより、一部の計算が容易になります。

また、リアルタイムとの関係でゲーム時間の変化率も定義します。この例では、リアルタイムの2分ごとがゲームの1時間に相当します。

float hours = 0.0f;                       // From 0 to 24 wrapping around
const float HoursPerSecond = 1f / 120f;   // E.g. 2 minutes = 1 hour ingame

public void Update(float elapsed)
{
    hours += elapsed * HoursPerSecond;    // Advance clock
    if(hours >= 24f) hours -= 24f;        // Wrap around 24 hours
}

構成

太陽の動きを設定する前に、いくつかのパラメータを指定する必要があります。特に、どのX値で地平線から上昇し、どのX値で地平線に落ちます。また、Yは地平線に対応し、その線より上に上昇すると想定される高さを示します。

float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;

太陽の座標を計算する

それでは、1日の特定の時間における太陽の位置を計算します。私はジミーが使用したのと同じパラメトリック関数を使用しますが、代わりに[0..2PI]の範囲のドメインを使用します(夜明けまでに太陽を元の位置に戻すため):

x =(1-cos(t))/ 2

y = sin(t)

X値は0から1に変化し、その後再び0に戻り(太陽の開始と終了のX値にマッピングされます)、Y値は0から始まり、1に戻り、1に戻るため、これは適切な関数です。再び0(これは私たちの日の部分になります)と元の位置に戻る前に負の側でまったく同じことを繰り返します(この時点では太陽は描かれませんが、夜になります)。

最初のステップは、時間を[0..24)の範囲から関数の範囲[0..2PI)にスケーリングします。

float t = (hours / 24f) * MathHelper.TwoPi;          // Scale: [0..24) to [0..2PI)

次に、関数を適用して、前述の0と1の間の値を取得します。

float horizontal = (float)((1-Math.Cos(t)) / 2f);    // Changes: 0 1 0
float vertical = (float)(Math.Sin(t));               // Changes: 0 1 0 -1 0

そして最後に、太陽のパラメータを使用してこれらの値をスケーリングします。

float sunX = startX + (endX - startX) * horizontal;    // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical;         // Up and down around horizonY

驚異の+1、私の唯一の後悔は、2つの答えをマークできないことです!
ロス

とにかく、私はジミーと同じ基本式を使用しました。:)
David Gouveia
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.