基于processing实现
效果演示
10个粒子
30个粒子
60个粒子
Processing实现
可拖拽震荡粒子(参考)
class Bob {
PVector location;
PVector velocity;
PVector acceleration;
float mass = 24;
// Arbitrary damping to simulate friction / drag
float damping = 0.98;
// For mouse interaction
PVector dragOffset;
boolean dragging = false;
// Constructor
Bob(float x, float y) {
location = new PVector(x,y);
velocity = new PVector();
acceleration = new PVector();
dragOffset = new PVector();
}
// Standard Euler integration
void update() {
velocity.add(acceleration);
velocity.mult(damping);
location.add(velocity);
acceleration.mult(0);
}
// Newton's law: F = M * A
void applyForce(PVector force) {
PVector f = force.get();
f.div(mass);
acceleration.add(f);
}
// Draw the bob
void display() {
stroke(0);
strokeWeight(2);
fill(175);
if (dragging) {
fill(50);
}
ellipse(location.x,location.y,mass*2,mass*2);
}
// The methods below are for mouse interaction
// This checks to see if we clicked on the mover
void clicked(int mx, int my) {
float d = dist(mx,my,location.x,location.y);
if (d < mass) {
dragging = true;
dragOffset.x = location.x-mx;
dragOffset.y = location.y-my;
}
}
void stopDragging() {
dragging = false;
}
void drag(int mx, int my) {
if (dragging) {
location.x = mx + dragOffset.x;
location.y = my + dragOffset.y;
}
}
}
固定位移振荡(参考)
class Oscillator {
PVector angle;
PVector velocity;
PVector amplitude;
Oscillator() {
angle = new PVector();
velocity = new PVector(random(-0.05, 0.05), random(-0.05, 0.05));
amplitude = new PVector(random(20,width/2), random(20,height/2));
}
void oscillate() {
angle.add(velocity);
}
void display() {
float x = sin(angle.x)*amplitude.x;
float y = sin(angle.y)*amplitude.y;
pushMatrix();
translate(width/2, height/2);
stroke(0);
strokeWeight(2);
fill(127,127);
line(0, 0, x, y);
ellipse(x, y, 32, 32);
popMatrix();
}
}
固定位移可拖拽振荡粒子
优化1
在Oscillator类中添加clicked,stopDragging,drag函数,分别进行点击相应,拖拽响应与停止拖拽响应。
void clicked(int mx, int my) {
print(1);
float x = sin(angle.x)*amplitude.x;
float y = sin(angle.y)*amplitude.y;
mx = mx - width/2;
my = my - height/2;
float d = dist(mx,my,x,y);
if (d < mass) {
dragging = true;
dragOffset.x = x-mx - width/2;
dragOffset.y = y-my - height/2;
}
}
void stopDragging() {
dragging = false;
}
void drag(int mx, int my) {
if (dragging) {
//float x = sin(angle.x)*amplitude.x;
//float y = sin(angle.y)*amplitude.y;
float x = mx + dragOffset.x;
float y = my + dragOffset.y;
float new_x = asin(x/amplitude.x);
if(!Double.isNaN(new_x)){
angle.x = new_x;
}
float new_y = asin(y/amplitude.y);
if(!Double.isNaN(new_y)){
angle.y = new_y;
}
print(angle.x,angle.y);
pushMatrix();
translate(width/2, height/2);
stroke(0);
strokeWeight(2);
fill(this.c);
line(0, 0, x, y);
if(type==1){
ellipse(x, y, 32, 32);
}
else if(type==2){
rect(x, y, 32, 32);
}
else if(type==3){
triangle(x+10, y+10, x-20, y-20, x-20, y+20);
}
popMatrix();
}
}
- 修改其显示函数,使其与被拖拽时效果不同,不显示边框;
- 添加随机数type用来随机选择粒子的样式;
- 随机生成每个粒子的颜色
int type = 1;
Oscillator() {
...
int max=4,min=1;
type = (int) (Math.random()*(max-min)+min);
}
void display() {
if (!dragging) {
float x = sin(angle.x)*amplitude.x;
float y = sin(angle.y)*amplitude.y;
pushMatrix();
translate(width/2, height/2);
noStroke();
//stroke(0);
strokeWeight(2);
fill(this.c);
line(0, 0, x, y);
if(type==1){
ellipse(x, y, 32, 32);
}
else if(type==2){
rect(x, y, 32, 32);
}
else if(type==3){
triangle(x+10, y+10, x-20, y-20, x-20, y+20);
}
popMatrix();
}
}
效果
粒子系统
粒子系统就是一系列独立对象的集合, 这些对象通常用简单的图形或者点来表示。 为什么我们要学习粒子系统呢? 毫无疑问, 粒子系统可以用于模拟各种自然现象( 比如爆炸) 。 实际上, 它的作用不局限于此。如果我们要用代码对自然界的各种事物建模, 要接触的系统肯定并不是由单个物体组成的, 系统内部会有很多物体, 而粒子系统非常适合对复数系统进行建模。 比如一堆弹球的弹跳运动、 鸟群的繁殖, 以及生态系统的演化, 这些研究对象都是由复数组成的系统。本书的后续章节都会涉及对一组对象的处理。 在前面向量和力的示例程序中, 我们简单地用数组表示一组对象, 但从本章开始, 我们要用一种更强大的方式表示它们。首先, 列表中物体的数量应该是可变的: 可能没有物体, 可能只有1个物体, 也可能有10个物体或成千上万的物体。 其次, 除了定义粒子类, 我们还会定义一个类表示粒子的集合——也就是粒子系统( ParticleSystem) 类。
详见我之前写的博客创意编程——粒子与细胞分裂
效果
改进2
在每个粒子被拖拽时都使粒子系统生效
void drag(int mx, int my) {
if (dragging) {
...
P.origin = new PVector(x, y);
P.run();
P.addParticle(this.c);
popMatrix();
}
}