我正在处理一些代码,其中我有一个Time
带有 member 的对象time
。Time.time
给我自我的应用程序启动以来的时间(以秒为单位)(浮点值)。现在我想在 0 和 1 之间创建一个脉动值,然后再次从 1 到 0,它会继续变薄,直到应用程序停止。
我正在考虑使用 sin() 但不知道将什么作为参数传递给它来创建这个脉冲值。
我将如何创造这种脉动的价值?
亲切的问候, Pollux
我正在处理一些代码,其中我有一个Time
带有 member 的对象time
。Time.time
给我自我的应用程序启动以来的时间(以秒为单位)(浮点值)。现在我想在 0 和 1 之间创建一个脉动值,然后再次从 1 到 0,它会继续变薄,直到应用程序停止。
我正在考虑使用 sin() 但不知道将什么作为参数传递给它来创建这个脉冲值。
我将如何创造这种脉动的价值?
亲切的问候, Pollux
您提到使用 sin(),所以我想您希望它在 0 和 1 之间连续脉冲。
这样的事情会做:
float pulse(float time) {
const float pi = 3.14;
const float frequency = 10; // Frequency in Hz
return 0.5*(1+sin(2 * pi * frequency * time));
}
1/frequency = 0.1 second
是周期,即 1 之间的时间。
x = 1 - x 怎么样?或者,如果您希望它基于时间,请使用 Timer % 2
哦,你也想要 0 到 1 之间的值。Math.Abs(100 - (Timer % 200)) / 100 怎么样,其中计时器类似于 DateTime.Now.TimeOfDay.TotalMilliseconds
编辑: 我的测试表明这比 Sin 方法快两倍多。对于 100 万次迭代,sin 方法需要 0.048 秒,而 Abs 方法大约需要 0.023 秒。此外,当然,您会从两者中得到不同的波形。Sin 产生正弦波,而 Abs 产生三角波。
static void Main(string[] args)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
const int count = 1000000;
float[] results = new float[count];
for (int i = 0; i < count; i++)
{
results[i] = AbsPulse(i/1000000F);
//results[i] = SinPulse(i / 1000000F);
}
sw.Stop();
Console.WriteLine("Time Elapsed: {0} seconds", sw.Elapsed.TotalSeconds);
char[,] graph = new char[80, 20];
for (int y = 0; y <= graph.GetUpperBound(1); y++)
for (int x = 0; x <= graph.GetUpperBound(0); x++)
graph[x, y] = ' ';
for (int x = 0; x < count; x++)
{
int col = x * 80 / count;
graph[col, (int)(results[x] * graph.GetUpperBound(1))] = 'o';
}
for (int y = 0; y <= graph.GetUpperBound(1); y++)
{
for (int x = 0; x < graph.GetUpperBound(0); x++)
Console.Write(graph[x, y]);
Console.WriteLine();
}
}
static float AbsPulse(float time)
{
const int frequency = 10; // Frequency in Hz
const int resolution = 1000; // How many steps are there between 0 and 1
return Math.Abs(resolution - ((int)(time * frequency * 2 * resolution) % (resolution * 2))) / (float)resolution;
}
static float SinPulse(float time)
{
const float pi = 3.14F;
const float frequency = 10; // Frequency in Hz
return 0.5F * (1 + (float)Math.Sin(2 * pi * frequency * time));
}
我认为正弦函数是理想的,但您需要调整周期和比例。
正弦函数产生介于 -1 和 1 之间的结果,但您希望介于 0 和 1 之间。要正确缩放它,您需要(sin(x)+1)/2
.
正弦函数从零开始,在 pi/2 处变为 1,在 pi 处再次归零,在 3*pi/2 处为 -1,在 2*pi 处返回零。缩放后,第一个零将出现在 3*pi/2 处,之后的第一个最大值将出现在 5/2*pi 处。所以x
在前面的公式中是(2*time + 3) * pi/2
。
把它们放在一起: (sin((2*time.time + 3) * pi/2) + 1) / 2
你希望它多久跳一次?
假设您想在 10 秒内从 0 变为 1。
float pulseValueForTime(int sec) {
int pulsePoint = sec % 10;
float pulsePercent = (float)pulsePoint / (float)10;
float pulseInTermsOfPI = (pulsePercent * 2 * PI) - PI;
float sinVal = MagicalSinFunction(pulseInTermsOfPI); // what framework you use to compute sin is up to you... I'm sure you can google that!
return (sinVal + 1) / 2; // sin is between 1 and -1, translate to between 0 and 1
}
查看缓动功能。他们以各种方式做这种事情——线性、多边形、exp、sin等。