基於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();
}
}