前言
在《代码本色》的第4章 粒子系统 中,主要讲到了粒子系统的实现、多态和继承实现面向对象以及通过力的作用体现自然系统。以下为第4章的内容目录:
针对粒子系统的实现、多态和继承实现面向对象以及通过力的作用体现自然系统,我展开了自己的习作。
关于习作
学习了《代码本色》第4章 粒子系统 的内容之后,我想要在我的习作中表现的元素有:
- 鼠标的交互
- 粒子系统的生成
- 随机点的生成
- 排斥力的体现
其中,鼠标的交互和粒子系统的生成,体现在我鼠标在界面中移动即在我鼠标位置生成粒子系统;随机点的生成体现在界面中随机生成点圈圈;排斥力体现在界面中的大圆,所有的点(包括随机生成的和粒子系统生成的)经过界面时都会绕开大圆(排斥)。
下面是效果图和具体代码实现:
可以看到,排斥力很明显。
Particle.pde
class Particle {
PVector position;
PVector velocity;
PVector acceleration;
float lifespan;
float r = 6;
float mass = 1; // Let's do something better here!
Particle(PVector l) {
acceleration = new PVector(0,0);
velocity = new PVector(random(-1,1),random(-2,0));
position = l.get();
lifespan = 255.0;
}
Particle(float x, float y) {
acceleration = new PVector();
velocity = PVector.random2D();
position = new PVector(x, y);
lifespan = 255.0;
}
void run() {
update();
display();
}
void applyForce(PVector force) {
PVector f = force.get();
f.div(mass);
acceleration.add(f);
}
// Method to update position
void update() {
velocity.add(acceleration);
position.add(velocity);
acceleration.mult(0);
lifespan -= 2.0;
}
// Method to display
void display() {
stroke(0,lifespan);
strokeWeight(2);
fill(127,lifespan);
ellipse(position.x,position.y,12,12);
}
// Is the particle still useful?
boolean isDead() {
if (lifespan < 0.0) {
return true;
} else {
return false;
}
}
void intersects(ArrayList<Particle> particles) {
for (Particle other : particles) {
if (other != this) {
PVector dir = PVector.sub(position, other.position);
if (dir.mag() < r*2) {
dir.setMag(0.5);
applyForce(dir);
}
}
}
}
}
ParticleSystem.pde
class ParticleSystem {
ArrayList<Particle> particles;
PVector origin;
ParticleSystem(PVector position) {
origin = position.get();
particles = new ArrayList<Particle>();
}
void addParticle() {
particles.add(new Particle(origin));
}
void addParticle(float x, float y) {
particles.add(new Particle(x, y));
}
// A function to apply a force to all Particles
void applyForce(PVector f) {
for (Particle p: particles) {
p.applyForce(f);
}
}
void applyRepeller(Repeller r) {
for (Particle p: particles) {
PVector force = r.repel(p);
p.applyForce(force);
}
}
void run() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
particles.remove(i);
}
}
}
void intersection() {
for (Particle p : particles) {
p.intersects(particles);
}
}
void display() {
for (Particle p : particles) {
p.display();
}
}
void update() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.update();
if (p.isDead()) {
particles.remove(i);
}
}
}
}
Repeller.pde
class Repeller {
// Gravitational Constant
float G = 100;
// position
PVector position;
float r = 20;
Repeller(float x, float y) {
position = new PVector(x,y);
}
void display() {
stroke(0);
strokeWeight(2);
fill(175);
ellipse(position.x,position.y,48,48);
}
// Calculate a force to push particle away from repeller
PVector repel(Particle p) {
PVector dir = PVector.sub(position,p.position); // Calculate direction of force
float d = dir.mag(); // Distance between objects
dir.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
d = constrain(d,5,100); // Keep distance within a reasonable range
float force = -1 * G / (d * d); // Repelling force is inversely proportional to distance
dir.mult(force); // Get force vector --> magnitude * direction
return dir;
}
}
sketch_4.pde
ParticleSystem[] parsys = new ParticleSystem[2];
Repeller[] repellers = new Repeller[12];
void setup() {
size(800,600);
for (int i = 0; i < parsys.length; i++){
parsys[i] = new ParticleSystem(new PVector(width/2,50));
}
for (int i = 0; i < repellers.length; i++){
repellers[i] = new Repeller(25+75*i,height/3);
i++;
repellers[i] = new Repeller(25+75*i,height/3*2);
}
}
void draw() {
background(200);
parsys[0].addParticle(mouseX,mouseY);
parsys[1].addParticle(random(width),random(height));
// Apply gravity force to all Particles
//PVector gravity = new PVector(0,0.2);
//parsys[0].applyForce(gravity);
for (int i = 0; i < repellers.length; i++){
parsys[0].applyRepeller(repellers[i]);
repellers[i].display();
parsys[1].applyRepeller(repellers[i]);
repellers[i].display();
}
parsys[0].run();
parsys[1].update();
parsys[1].intersection();
parsys[1].display();
}
关于代码
本次习作利用了面向编程的继承性和多态性。
在Particle类和ParticleSystem类中实现了粒子系统的定点生成与随机生成;在Repeller类中实现了排斥物的实现。
主程序sketch_4.pde实现了界面的绘制,在程序中生成多个repeller和particle以及particleSystem。
其中,移动的鼠标点生成粒子系统其实就是在定点生成粒子的基础上,加上了一个鼠标坐标的mouseX和mouseY即可。
比较想说一下的是排斥力的实现,排斥力是在引力的基础上,将引力的大小乘以-1,公式是:force = -1 * G / (d * d);
这样就实现了排斥力,在图中效果比较明显。
来源:CSDN
作者:产品经理顾清宇
链接:https://blog.csdn.net/A_Ainley/article/details/103484650