If you're seeing this message, it means we're having trouble loading external resources on our website.

如果你被网页过滤器挡住,请确保域名*.kastatic.org*.kasandbox.org 没有被阻止.

主要内容

振荡振幅和周期

惊艳到了吗?在角运动截面上,我们看到了正切 (用于查找矢量的角度)、正弦和余弦 (从极性转换为笛卡尔坐标) 的一些非常好的用处。我们可以停在这里, 满足一下。但我们不会这么做的,这只是个开始。正弦和余弦可以为你做的不止是数学公式和直角三角形。
让我们看一下正弦函数的图像, y = sine(x)
您会注意到正弦函数的输出是一个在–1和 1之间交替的平滑曲线。这种类型的行为被称为 振荡,这是两点之间的周期性运动。拨动吉他弦,摆动钟摆,在一个弹球杆上弹球——这些都是振荡运动的例子。
我们很高兴地发现,我们可以通过将正弦函数的输出赋值给对象的位置在 ProcessingJS 程序中模拟振荡。请注意,这将依照我们在噪声部分中应用在 Perlin 噪声上的同一方法。
让我们从一个非常基本的类型开始。我们希望有一个圆圈从画布的左侧振荡到右侧。
这就是所谓的 简谐运动 (或者, 更花哨的,"物体的周期性正弦振荡")。编写这个程序很简单,但在我们进入代码之前,让我们先来熟悉一些振荡(和波)的术语。
简谐运动可以表示为任何位置(在我们的情况下,x 位置)作为时间的函数,其具有一下两个元素:
  • 振幅:从运动中心到极值的距离
  • 周期:一个完整的运动循环所需要的时间
在上面嵌入的正弦图中,我们可以看到振幅为 1,周期为 TWO_PI;正弦的输出永远不会上升到1以上或低于-1;每一个 TWO_PI 弧度(或 360 度),波模式重复。
现在, 在我们生活的 ProcessingJS 世界中,什么是振幅,什么是周期?振幅可以很容易地以像素为单位衡量。在窗口200像素宽的情况下,我们会从中心往右100像素向往左100像素振荡。因此:
// 以像素为单位衡量的振幅
var amplitude = 100;
周期是一个完整的运动循环所需要的时间,但在我们的 ProcessingJS 世界中,时间是多少?我们当然可以说,希望圆圈每三秒振荡一次。我们可以跟踪程序中过去的毫秒(使用 millis()),提出一个复杂的根据现实时间的振荡对象算法。
但是,我们还有另一个选择:我们可以依靠 ProcessingJS 程序的一个特性。它具有 "帧" 的概念,并且默认情况下,程序尝试运行 30 “帧/每秒”。ProcessingJS 为我们提供了 frameCount 变量,以找出我们当前所在的帧,以及 frameRate() 函数来更改首选的帧/每秒。30 FPS(帧/每秒) 是默认的帧率,因为这是一个很好地产生平滑动画以欺骗人脑的速率,但它有时,如在调试时,减慢帧率会有帮助。
因此,我们决定根据经过的帧数来确定我们的周期,因为我们已经看到它与现实时间的密切联系——我们可以说,振荡运动应该每30帧、或50帧、或1000帧等等重复。
// 我们的周期用帧衡量(我们的动画时间单位)
var period = 120;
一旦我们知道了振幅和周期,就可以写出一个公式来计算 x 作为时间的函数,我们将用它来代替当前的帧数。
var x = amplitude * sin(TWO_PI * frameCount / period);
让我们更详细地剖析一下公式,并尝试了解每个部分。第一个可能是最简单的。无论正弦函数产生什么,我们都会乘以振幅。我们知道正弦将在-1 和 1 之间振荡。如果我们取这个值,并将其乘以振幅,那么我们将得到所需的结果:在-振幅和振幅之间振荡的值。(注意: 这也是我们可以使用 ProcessingJS 的 map() 函数将正弦输出映射到自定义范围的地方。)
现在,让我们来看看正弦函数里边有什么:
TWO_PI * frameCount / period
这是怎么回事呢?让我们从我们所知道的开始。我们已知正弦函数在每个2*PI 弧度后重复一次—也就是说它将从0开始,并在2*PI, 4*PI, 6*PI等重复。如果周期为120帧,那么当 frameCount 为120帧,240帧,360帧等时,我们会让这个振荡运动重复。frameCount 实际上是唯一的变量,它从0开始,并向上计数。让我们一起来看看这个公式用这些值所产生的结果。
frameCountframeCount / periodTWO_PI * frameCount / period
000
600.5PI
1201TWO_PI
24022 * TWO_PI (or 4 * PI)
etc.  
frameCount 除以周期告诉我们已经完成了多少个循环——我们是在第一个循环的一半?我们完成两个循环了吗?通过将该数字乘以 TWO_PI, 我们得到了所需的结果,因为 TWO_PI 是一个正弦函数完成一个周期所需的弧度数。
总结起来看,这是一个程序正在振荡一个圆的 x 轴坐标,它的振幅为100像素,周期为120帧。
还有一个值得一提的术语频率:周期数/每个时间单位。频率等于1除以周期。如果周期为120帧,在一个帧内只完成一个循环的1/120,因此频率 = 1/120 周期/帧。在上面的示例中,因为我们选择用周期来定义振荡频率,所以不需要一个变量来代表频率。
请注意,我们使用 ProcessingJS 中的正弦函数 (sin()) 完成了所有这些工作,但同样的想法也适用于使用余弦函数。两者的周期是相同的,主要的区别只是振幅的开始是从1还是从0。

“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享 著名-非商用性 3.0 本地化许可协议

想加入讨论吗?

尚无帖子。
你会英语吗?单击此处查看更多可汗学院英文版的讨论.