书名:代码本色:用编程模拟自然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
目录
2.9 引力
6、引力示例
示例代码2-6 引力
- Mover类没有发生任何改变,
- 所以我们可以把主程序和Attractor类看成一个整体,把万有引力常量加入其中。
(源代码中,还可以用鼠标移动Attractor对象。)
1)主程序
Mover m;
Attractor a;
void setup() {
size(640,360);
m = new Mover();
a = new Attractor();
}
void draw() {
background(255);
PVector force = a.attract(m); //计算Attractor对象对Mover对象的引力
m.applyForce(force);
m.update();
a.drag();
a.hover(mouseX,mouseY);
a.display();
m.display();
}
void mousePressed() {
a.clicked(mouseX,mouseY);
}
void mouseReleased() {
a.stopDragging();
}
2)Attractor.pde(吸引器类)
class Attractor {
float mass; // Mass, tied to size
float G; // Gravitational Constant
PVector position; // position
boolean dragging = false; // Is the object being dragged?
boolean rollover = false; // Is the mouse over the ellipse?
PVector dragOffset; // holds the offset for when object is clicked on
Attractor() {
position = new PVector(width/2,height/2);
mass = 20;
G = 1;
dragOffset = new PVector(0.0,0.0);
}
PVector attract(Mover m) {
PVector force = PVector.sub(position,m.position); // Calculate direction of force
float d = force.mag(); // Distance between objects
d = constrain(d,5.0,25.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
force.mult(strength); // Get force vector --> magnitude * direction
return force;
}
// Method to display
void display() {
ellipseMode(CENTER);
strokeWeight(4);
stroke(0);
if (dragging) fill (50);
else if (rollover) fill(100);
else fill(175,0,0);
ellipse(position.x,position.y,mass*2,mass*2);
}
// The methods below are for mouse interaction
void clicked(int mx, int my) {
float d = dist(mx,my,position.x,position.y);
if (d < mass) {
dragging = true;
dragOffset.x = position.x-mx;
dragOffset.y = position.y-my;
}
}
void hover(int mx, int my) {
float d = dist(mx,my,position.x,position.y);
if (d < mass) {
rollover = true;
}
else {
rollover = false;
}
}
void stopDragging() {
dragging = false;
}
void drag() {
if (dragging) {
position.x = mouseX + dragOffset.x;
position.y = mouseY + dragOffset.y;
}
}
}
3)Mover.pde(Mover类)
class Mover {
PVector position;
PVector velocity;
PVector acceleration;
float mass;
color c;
Mover() {
position = new PVector(400,50);
velocity = new PVector(1,0);
acceleration = new PVector(0,0);
mass = 1;
//c = color(random(255),random(255),random(255));
c = color(0,random(255),random(255));
}
void applyForce(PVector force) {
PVector f = PVector.div(force,mass);
acceleration.add(f);
}
void update() {
velocity.add(acceleration);
position.add(velocity);
acceleration.mult(0);
}
void display() {
stroke(0);
strokeWeight(2);
//fill(127);
fill(c);
ellipse(position.x,position.y,16,16);
}
void checkEdges() {
if (position.x > width) {
position.x = 0;
} else if (position.x < 0) {
position.x = width;
}
if (position.y > height) {
velocity.y *= -1;
position.y = height;
}
}
}