0

私は前後に試してきましたが、フリックジェスチャを使用するときにビューをスクロールする(またはすべてのオブジェクトをオフセットする)方法についての数学を理解できません。スクロールになんらかのイーズアウトを持たせたいです。

    public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
    {
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

        //Some math to change 'matrixOffsetY'
        //I use 'matrixOffsetY' to offset my objects in Draw()

        base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
    }

これがジェスチャーイベントです

    public override void HandleInput(InputState input)
    {
        if (input == null)
            throw new ArgumentNullException("input");

        while (TouchPanel.IsGestureAvailable)
        {
            GestureSample gesture = TouchPanel.ReadGesture();

            switch (gesture.GestureType)
            {
                case GestureType.Flick:
                    {
                        //Set a variable with some math? Using:
                        //gesture.Delta

                        //gesture.Delta gives us pixels/sec
                        break;
                    }
                default: return;
            }
        }
    }

これはそれほど難しいことではないはずですが、私は脳が凍っています:)助けてください!

4

3 に答える 3

3

「イーズアウト」とは、想定されていることを徐々に実行することを意味していると思います(これについてはよくわかりません(タッチパネルとジェスチャーについてはよくわかりません))。

これを行うにはいくつかの方法があります。物理的なアプローチを取り、ニュートンの法則を使用して、微分方程式を単純に解くことができます。

私が一般的にこのようなことを行う方法 (マウスでウィンドウをスクロールするときに徐々に停止するなど) は、必要な感覚を得るために変更できるパラメーターを持つ関数を使用して、速度を徐々に下げることです。

あなたの場合、私はあなたがやろうとしていることを理解しました。単に速度に基づいて位置を更新したいだけです。

水平方向に実行するとします(通常は 2D で実行します)。

X_new = X_old + 速度*dt 速度 = max(0, 速度*0.95 - 0.2)

これが行うことは、x座標を徐々に移動することです(X_oldはループを通過するたびにX_newになります(通常はスレッドで行います))、完全に停止するのではなく、速度がゼロに達するまで移動し続けます。単純な pow 関数を使用して徐々に減らしますが、任意のタイプの関数を考え出すことができます。

また、ポインターからエッジまでの距離を実際に考慮することもできます。私は自分のプログラムの 1 つでこれを行って、マウス カーソルが端から離れたときにスクロールする速度がどれくらいの距離に依存するようにします (したがって、少しスクロールしたい場合は、少し移動し、多く移動すると多く移動します)。

これはスレッドで処理する必要があることに注意してください。おそらく、これは引き続き発生するためです。また、加速度を計算し、単純な物理学を使用してそれに基づいて位置を計算することもできます。x = x0 + x'*t + 1/2*x''*t^2 タイプのもの。

于 2011-01-21T06:03:55.757 に答える
3

2 つの値の間を "lerp" (線形補間) して、徐々に近づけることができます (最初は速く、最後はゆっくり)。

2Dでスクロールしていると思います。したがって、位置は Vector2 です。

次のようなことを試してください:

position; //current position of the object.
targetPosition; //set by scrolling, position should gradually come close to this
float weigth; //how much the weight is of the targetPosition compared to the position
//practically this means how fast position approaches targetPosition. 
//First try values between 0 and 1, for example 0.8f for starters.
public void Scroll(Vector2 ammount)
{
   //We assume scrolling the scrollbar 1 pixel down, means the object should go 1 pixel up.
   //So the targetPosition should move the same ammount opposite.
   //If you don't want scrolling to correspond 1:1, you can multiply ammount by a float.
   targetPosition -= ammount;   
}

public void Update(GameTime gameTime)
{
    //..
    //Executed every update, position closes in on targetPosition pretty fast.     
    position = Vector2.Lerp(position, targetPosition, weigth);

    //Because we Lerp position will only get extremely close to targetPosition. Never exactly at it.
    //most of the time this is good enough, if this isnt use the following code

    float omega = 0.05f; // the minimum dinstance between position and targetPosition before we clamp
    if(Vector2.Distance(position, targetPosition) < omega)
    {
        position = targetPosition;
    }
    //..
}

public void Draw(GameTime gameTime)
{
    //..
    spriteBatch.Begin();
    spriteBatch.Draw(texture, position, Color.White);
    spriteBatch.End();
    //..
}
于 2011-01-24T12:34:21.357 に答える
0

いつものように、それが XNA の場合、Shawn はおそらく既に問題を解決しています。いくつかの投稿で、彼はLerp、SmoothStep およびその他の数学演算を使用した遷移と、物理ベースのアプローチについて説明しています。例では Game State Management プロジェクトを使用していますが、アイデアはどこでも使用できます。

ところで、すべてのオブジェクトをカメラに対して相対的に動かさないことを検討することをお勧めします。vector2 または vector3 cameraOffset をどこかに保存し、SpriteBatch.Begin で transformMatrix を使用できます。もちろん、これは、1 つまたは 2 つのスプライトバッチ サイクルを使用してすべてのワールド オブジェクトをペイントする場合に最も役立ちます。

于 2011-01-25T02:14:28.047 に答える