Экран прокрутки в XNA - Легкая математика (жест щелчка) - PullRequest
0 голосов
/ 21 января 2011

Я пробовал взад и вперед, но я не могу понять, как прокрутить мое представление (или, скорее, сместить все объекты) при использовании жеста щелчка.Я бы хотел, чтобы у прокрутки было какое-то облегчение.

    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 ]

3 голосов
/ 24 января 2011

Вы можете "lerp" (линейная интерполяция) между двумя значениями, чтобы постепенно приблизиться (начиная быстро, заканчивая медленно).

Я предполагаю, что вы прокручиваете в 2D.Таким образом, позиция - это вектор 2.

Попробуйте что-то вроде этого:

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();
    //..
}
3 голосов
/ 21 января 2011

Я предполагаю, что вы подразумеваете под "облегчением", что он постепенно делает то, что должен делать (что мне не совсем понятно (я мало знаю о сенсорных панелях и жестах).

ТамЕсть несколько способов сделать это. Вы можете использовать физический подход и использовать закон Ньютона и просто решить дифференциальное уравнение.

Способ, которым я обычно делаю такие вещи (например, постепенная остановка при прокрутке окна с помощьюмышь), просто постепенно уменьшать скорость, используя некоторую функцию с параметрами, которые я могу изменить, чтобы получить ощущение, которое я хочу.

В вашем случае, я получил то, что вы пытаетесь сделать, вы просто хотитеобновить позицию, основываясь на скорости.

Предположим, вы делаете это горизонтально (обычно вы будете делать это для 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 типа материала.

0 голосов
/ 25 января 2011

Как обычно, если это XNA, Шон, вероятно, уже решил вашу проблему. В нескольких постах он объясняет переходы, используя Lerp, SmoothStep и другие математические операции и физический подход . В примерах используется проект Game State Management, но идеи можно использовать где угодно.

И, кстати, вы можете подумать о том, чтобы не перемещать все объекты вокруг камеры. Вы можете где-то хранить вектор2 или вектор3 cameraOffset и использовать transformMatrix в SpriteBatch.Begin. Конечно, это наиболее полезно, если вы используете один или два цикла spritebatch для рисования всех объектов вашего мира.

...