0

我在 C# 中使用了一些缓动函数,它们给出了Ease In效果Ease out。但是,我试图通过这些缓动函数实现的目标并没有产生明显的效果。

例如:

int x=2;
while(x<200)
SetSomething(x = EaseIn(x, 1, EasingType.Quadratic));

SetSomething 的执行速度并没有给我们足够的时间来注意到SetSomething. 例如:值从 2 -> 4 -> 16 -> 256 开始

我试图实现以下类型的图表,但值较小(不大于 200): http ://theinstructionlimit.com/wp-content/uploads/2009/07/easing.png

缓动函数的实现在这里:http ://theinstructionlimit.com/wp-content/uploads/2009/07/Easing.cs

即使我在小于 200 的较小范围内得到二次值,我也需要在循环的每次迭代中至少有一个非常小的类似暂停的效果,以注意到效果缓和。这个小暂停也可以遵循二次曲线(即对于缓动:暂停持续时间可能会更多,然后暂停持续时间更短)

我应该怎么做?如何在 < 200 的范围内获得二次图,并且在每次迭代中都有这种暂停效果?

4

2 回答 2

1

您将 Easing 的结果视为 new x。这很奇怪!

另外,x应该是linearStep. linearStep是一个double,但你x是一个int。制作您x的 adouble并将其增加适当的数量。

const double step = 1.5; // Choose an appropriate value here!

for (double x = 2.0; x <= 200.0; x += step) {
    double y = Ease(x, 1.0f, EasingType.Quadratic);
    SetSomething(y); 
}

更新

你的设计非常程序化。我更喜欢面向对象的方法。switch-语句通常可以用多态(面向对象)方法代替。

public abstract class Curve 
{
    public float EaseIn(double s);
    public float EaseOut(double s);
    public static float EaseInOut(double s);
}

public class StepCurve : Curve
{
    public override float EaseIn(double s)
    {
        return s < 0.5 ? 0.0f : 1.0f;
    }

    public override float EaseOut(double s)
    {
        return s < 0.5 ? 0.0f : 1.0f;
    }

    public override float EaseInOut(double s)
    {
        return s < 0.5 ? 0.0f : 1.0f;
    }
}

public class LinearCurve : Curve
{
    public override float EaseIn(double s)
    {
        return (float)s;
    }

    public override float EaseOut(double s)
    {
        return (float)s;
    }

    public override float EaseInOut(double s)
    {
        return (float)s;
    }
}

public class SineCurve : Curve
{
    public override float EaseIn(double s)
    {
        return (float)Math.Sin(s * MathHelper.HalfPi - MathHelper.HalfPi) + 1;
    }

    public override float EaseOut(double s)
    {
        return (float)Math.Sin(s * MathHelper.HalfPi);
    }

    public override float EaseInOut(double s)
    {
        return (float)(Math.Sin(s * MathHelper.Pi - MathHelper.HalfPi) + 1) / 2;
    }
}

public class PowerCurve : Curve
{
    int _power;

    public PowerCurve(int power)
    {
        _power = power;
    }

    public override float EaseIn(double s)
    {
        return (float)Math.Pow(s, _power);
    }

    public override float EaseOut(double s)
    {
        var sign = _power % 2 == 0 ? -1 : 1;
        return (float)(sign * (Math.Pow(s - 1, _power) + sign));
    }

    public override float EaseInOut(double s)
    {
        s *= 2;
        if (s < 1) return EaseIn(s, _power) / 2;
        var sign = _power % 2 == 0 ? -1 : 1;
        return (float)(sign / 2.0 * (Math.Pow(s - 2, _power) + sign * 2));

    }
}

使用这些定义,您可以将Ease方法更改为

public static float Ease(double linearStep, float acceleration, Curve curve)
{
    float easedStep = acceleration > 0 ? curve.EaseIn(linearStep) :
                      acceleration < 0 ? curve.EaseOut(linearStep) :
                      (float)linearStep;
    return MathHelper.Lerp(linearStep, easedStep, Math.Abs(acceleration));
}

您可以使用switch-statements 完全删除方法。你会画一条三次曲线

var curve = new PowerCurve(3);
for (double x = 2.0; x <= 200.0; x += step) {
    double y = Ease(x, 1.0f, curve);
    SetSomething(y); 
}
于 2012-06-24T20:00:21.467 回答
0

我能想到 3 种方法可以帮助你做任何你想做的事情(我不是 100% 确定我完全理解你想要达到的目标):)

  1. 在绘图时使用更大的间隔然后缩放。例如,不要让 x 在 0-200 范围内,而是将其设置在 0-200 00 范围内,然后在绘图时按 0,01 缩放。

  2. 使用睡眠功能。sleep 函数将暂停当前线程的执行给定的时间。

  3. 使用计时器。我建议使用计时器线程,但您也可以使用 winform 计时器。这是不确定您给出的示例中几乎恒定的 FPS 的最简单方法。

http://msdn.microsoft.com/en-us/library/system.threading.thread.sleep(v=vs.71).aspx

http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

于 2012-06-24T17:40:42.863 回答