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 函数来逐渐减少它,但你可以想出任何类型的函数。

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

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

于 2011-01-21T06:03:55.757 回答
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();
    //..
}
于 2011-01-24T12:34:21.357 回答
0

像往常一样,如果是 XNA,Shawn 可能已经解决了您的问题。在几篇文章中,他解释了使用Lerp、SmoothStep 和其他数学运算以及基于物理的方法的转换。这些示例使用游戏状态管理项目,但这些想法可以在任何地方使用。

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

于 2011-01-25T02:14:28.047 回答