主要内容
多个对象的运动
在现实世界中(我们经常从中寻求灵感),我们有不止一个移动的物体——我们被许多具有不同质量和位置的物体所包围。让我们来看看如何让我们的
Mover
更好地模拟真实世界的物体。为此,我们需要快速复习一下面向对象编程。同样,我们不会在这里介绍面向对象编程的全部基础知识。然而。因为创建一个充满对象的世界的思想是本单元所有内容的基础,花些时间介绍从只有一个对象到有多个对象的步骤还是值得的。
提醒一下,这是我们现在
Mover
的样子。它跟我们首次引用向量时创建的弹球
对象相同,但是有两处添加——mass(质量)
和一个新的applyForce()
(应用力)方法:现在我们的对象已经设置好了,我们可以用一个循环,用数组创建二十个
Mover
实例。var movers = [];
for (var i = 0; i < 20; i++) {
movers[i] = new Mover();
}
但是现在我们有一个小问题,如果我们引用
Mover
对象的构造函数……var Mover = function() {
this.mass = 1;
this.position = new PVector(30, 30);
this.velocity = new PVector(0, 0);
this.acceleration = new PVector(0, 0);
};
……我们发现每个
Mover
对象都会是完全一样的。我们想要的是有 不同 质量和初始位置的 Mover
对象。现在我们需要通过添加参数来提高构造函数的复杂性。var Mover = function(m, x, y) {
this.mass = m;
this.position = new PVector(x, y);
this.velocity = new PVector(0, 0);
this.acceleration = new PVector(0, 0);
};
注意质量和位置不再被设置为硬编码数字,而是通过构建函数传递的参数进行初始化。这意味着我们可以创建各种
Mover
对象:大的,小的,初始位置在屏幕左端的,初始位置在屏幕右端的。// 窗口左侧的一个大弹球
var m1 = new Mover(10, 0, height/2);
// 窗口右侧的一个小弹球
var m2 = new Mover(0.1, width, height/2);
但是,我们希望使用循环初始化数组里的所有对象。
for (var i = 0; i < 20; i++) {
movers[i] = new Mover(random(0.1, 5), 0, 0);
}
对于每一个生成的弹球,它的质量会被设成0.1到5之间的一个随机数,起始 x 和 y 位置都设为0。当然,我们可以选择各种方法来初始化对象:这只是提供一种可能性。
当对象数组被声明、创建和初始化之后,剩余的代码就很简单了。我们调整每一个对象,给它们设置环境中的力,然后我们可以欣赏它们的表演了。
draw = function() {
background(50, 50, 50);
for (var i = 0; i < movers.length; i++) {
var wind = new PVector(0.01, 0);
var gravity = new PVector(0, 0.1);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
};
下面是程序实际的样子。注意在程序中较小的圆圈比较大的圆圈更快到达屏幕右侧。这是因为我们的公式:加速度 = 力除以质量。质量越大,加速度越小。
“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享 著名-非商用性 3.0 本地化许可协议。