XNA中的滚动屏幕 - 缓解数学(轻弹手势)

时间:2011-01-20 21:59:42

标签: math xna gesture easing

我一直在来回尝试,但是当我使用轻弹手势时,我无法弄清楚如何滚动我的视图(或者更确切地说是偏移所有对象)。我希望滚动有一些缓和。

    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;
            }
        }
    }

这应该不是那么难,但我有一个大脑冻结:)请帮帮我!

3 个答案:

答案 0 :(得分:3)

我认为你的意思是“缓和”它逐渐做出它想要做的事情(我不太清楚(我对触摸屏和手势不太了解)。

有几种方法可以做到这一点。您可以采用物理方法并使用牛顿定律并简单地求解微分方程。

我通常做这样的事情(例如用鼠标滚动窗口时逐渐停止),就是使用一些我可以修改的参数来逐渐降低速度,以获得我想要的感觉。 / p>

在你的情况下,我得到了你想做的事情,你只想根据速度更新位置。

假设你是水平地做(通常你会为2D做),

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

这样做是逐渐移动x坐标(X_old每次通过循环变为X_new(你通常在一个线程中做))这样它不是完全停止而是继续移动直到速度达到零。我使用一个简单的pow功能逐渐减少它,但你可以提出任何类型的功能。

您还可以实际考虑指针​​到边缘的距离。我在我的一个程序中执行此操作,以便当鼠标光标移出边缘时,它滚动的速度取决于多远(所以如果你想滚动一点,你移动一点点,你移动了很多)。

请注意,您必须在线程中处理此问题,因为它可能会继续发生。您还可以计算加速度并使用简单物理来计算基于它的位置。 x = x0 + x'* t + 1/2 * x''* t ^ 2类型的东西。

答案 1 :(得分:3)

你可以在两个值之间“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();
    //..
}

答案 2 :(得分:0)

像往常一样,如果它是XNA,Shawn可能已经解决了你的问题。在几篇文章中,他使用Lerp, SmoothStep and other math operationsphysics based approach来解释过渡。这些示例使用了游戏状态管理项目,但这些想法可以在任何地方使用。

顺便说一句,你可能想要考虑不要相对于相机移动所有物体。您可以在某处存储vector2或vector3 cameraOffset,并在SpriteBatch.Begin中使用transformMatrix。当然,如果您使用一个或两个spritebatch循环来绘制所有世界对象,这将非常有用。