我在C#中使用了一些缓动函数,它们会产生Ease In
和Ease out
效果。但是,我试图用这些缓动函数实现的效果并没有产生可观察到的效果。
例如:
int x=2;
while(x<200)
SetSomething(x = EaseIn(x, 1, EasingType.Quadratic));
SetSomething执行的速度没有足够的时间来注意SetSomething
的效果。例如:值从2开始 - > 4 - &gt; 16 - &gt; 256
我试图获得以下类型的图表,但值较小(不大于200):
http://theinstructionlimit.com/wp-content/uploads/2009/07/easing.png
Easing功能实现在这里:http://theinstructionlimit.com/wp-content/uploads/2009/07/Easing.cs
即使我得到较小范围内的二次值&lt; 200,我需要在循环的每次迭代中至少有一个非常小的暂停效果,以注意效果缓和。这个小暂停也可以遵循二次曲线(即缓和:暂停持续时间可能更先,然后是更短的暂停持续时间)
我该怎么做?如何获得范围内的二次图形&lt; 200,这个暂停效果在每次迭代中都有效?
答案 0 :(得分:1)
您将Easing的结果视为新的x
。这很奇怪!
此外,x
应该是linearStep
。 linearStep
是double
,但您的x
是int
。将x
设为double
并按适当的数量递增。
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
- 语句完全删除方法。您可以使用
var curve = new PowerCurve(3);
for (double x = 2.0; x <= 200.0; x += step) {
double y = Ease(x, 1.0f, curve);
SetSomething(y);
}
答案 1 :(得分:0)
我有三种方法可以帮助你做任何你想做的事情(我不是100%确定我完全理解你想要达到的目的):)
使用更大的间隔然后在绘制时缩放。例如,不是让x在0-200范围内,而是在0-200 00范围内,然后在绘制时按0,01进行缩放。
使用睡眠功能。 sleep函数将暂停当前线程的执行一段时间。
使用计时器。我建议使用计时器线程,但您也可以使用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