U3 如何构建粒子系统

文章介绍了如何使用面向对象编程方法构建粒子系统,包括创建自定义的Polygon和Button类,实现图形的动态变化和鼠标交互。此外,还展示了如何使用数组和ArrayList管理粒子,以及如何通过生命值和边界检测来复杂化粒子系统的逻辑。最后,提到了Firework类的实现,用于模拟烟花效果的粒子动画。
摘要由CSDN通过智能技术生成

U3 如何构建粒子系统

面向对象编程(OOP)

①面向过程编程(POP)的思路
请添加图片描述

②面向对象编程(OOP)的思路
把不同类型的对象之间的互动逻辑建立起来
请添加图片描述
③自定义类
类首字母用大写,方法用小写

④类的属性和方法
在这里插入图片描述

⑤声明,建立并调用属于自定义类的对象
在这里插入图片描述

  • 面向对象实例

屏幕录制2023-05-3010.55.01

Polygon triangle,square,pentage,hexagon;//声明建立调用自身类

void setup(){
  size(800,800);
  smooth(8);
  //初始化,建立三角形
  triangle = new Polygon(3,80,width*0.2,height*0.2);
  square = new Polygon(4,80,width*0.4,height*0.4);
  pentage = new Polygon(5,80,width*0.6,height*0.6);
  hexagon = new Polygon(6,80,width*0.8,height*0.8);
}

void draw(){
  triangle.update();//更新多边形
  square.update();
  pentage.update();
  hexagon.update();
  
  background(255);
  triangle.display();//呈现多边形
  square.display();
  pentage.display();
  hexagon.display();
}

//鼠标点击事件
void mousePressed(){
  triangle.randomize();
  square.randomize();
  pentage.randomize();
  hexagon.randomize();
}
class Polygon{
  int sideCount;//边数
  float radius,radiusT;//半径
  color c,cT;//颜色
  float rtt;//旋转角度 rotation
  float [] x,y; //顶点
  float ctrX,ctrY; //中心位置k
  float lerpStep;//控制插值的步数
  float thetabfst,thetabfstT;//旋转偏差量
  
  //构造方法
  Polygon(int _sideCount, float _radius,float _ctrX,float _ctrY){
    //用传入参数给自身属性赋值
    sideCount = _sideCount; 
    radius = radiusT = _radius;
    ctrX = _ctrX;
    ctrY = _ctrY;
    //初始化
    x = new float[sideCount];
    y = new float[sideCount];
    
    c = cT = color(random(255),random(255),random(255));
    thetabfst = thetabfstT = random(TWO_PI); 
  }
    //声明一个方法
   void update(){
     radius = lerp(radius,radiusT,lerpStep);
     c = lerpColor(c,cT,lerpStep);
     thetabfst = lerp(thetabfst,thetabfstT,lerpStep);
     //用for循环计算一下多边形顶点的位置,有多少条边就有多少个顶点
     for(int i=0;i<sideCount;i++){
       float theta = map(i,0,sideCount,thetabfst,thetabfst + TWO_PI);
       x[i] = cos(theta)*radius+ctrX;
       y[i] = sin(theta)*radius+ctrY;
     }
   }
   void randomize(){  //随机参数
     lerpStep = random(0.0325,0.2); //随机插值,使大小、颜色变化速度不一致
     radiusT = random(60,100); //随机大小
     cT = color(random(255),random(255),random(255)); //随机颜色
     thetabfst += random(PI*0.25,PI*0.75);
   }
   
   
   void display(){
     noStroke();
     fill(c);
     beginShape();
     for(int i=0;i<sideCount;i++){
       vertex(x[i],y[i]);
     }
     endShape();
   }
}

⑥课程作业
实现:

屏幕录制2023-05-3013.43.21

int amt = 10; //图形数量
Button [] btns; //建立对象数组

void setup(){
  size(800, 800, P3D);
  smooth(8);
  rectMode(CENTER);

  btns = new Button[amt];
  for(int i=0;i<amt;i++){
    float theta = map(i,0,amt,0,TWO_PI);
    btns[i] = new Button(theta,320,i%2,80,randColor()); //i%2,0和1周期性变化
    //float _theta,float _radius,int _mode,float _diam,color _c
  }

}
color randColor(){
  return color(random(255),random(255),random(255));
  
}

void draw(){
  for(int i=0;i<amt;i++){
    btns[i].update();
  }
  background(0);
  for(int i=0;i<amt;i++){
    btns[i].display();
  }
}
class Button{
  int mode; //0-rectangular;1-circular
  float x,y;
  float theta,thetaIncre,radius;
  float diam,diamT,diamSelf,w,wT,h,hT;
  color c,cT,cSelf;
  Button(float _theta,float _radius,int _mode,float _diam,color _c){
    mode = _mode;
    theta = _theta;
    radius = _radius; 
    //用来画矩形
    w = wT = _diam*1.25;
    h = hT = _diam*0.75;
    
    diam = diamT = diamSelf = _diam;
    c = cT = cSelf = _c;
    thetaIncre = .0025; 
  }
  void update(){ //数据更新
    theta += thetaIncre; //theta递增,实现转动
    x = cos(theta)*radius + width * 0.5;
    y = sin(theta)*radius + height * 0.5;
    
    if(inRange()){  //鼠标在范围内外的事件
      wT = diamSelf * 1.25 * 1.5;
      hT = diamSelf * 0.75 * 1.5;
      diamT = diamSelf*1.5;
      cT = color(255);
    }else{
       wT = diamSelf * 1.25;
       hT = diamSelf * 0.75;
       diamT = diamSelf;
       cT = cSelf;
    }
  
    diam = lerp(diam,diamT,0.0625);
    w = lerp(w,wT,0.125);
    h = lerp(h,hT,0.125);
    c = lerpColor(c,cT,0.125);
  }
  
  boolean inRange(){  //判断鼠标是否在范围内
    if(mode == 0){ //矩形范围判定
      float boundL = x - w * .5;
      float boundR = x + w * .5;
      float boundT = y + h * .5;
      float boundB = y - h * .5;
      if(mouseX > boundL && mouseX < boundR && mouseY < boundT && mouseY > boundB) return true;
      else return false;
    }else{ //圆形范围判定
      float d = dist(mouseX,mouseY,x,y);
      if(d<diam*.5) return true;
      else return false;
    }
    
  }
  
  void display(){ //数据呈现
    fill(c);
    if(mode == 0) rect(x,y,w,h);
    else circle(x,y,diam);
  }
}

粒子系统(一)

①对象数组
请添加图片描述
实例:
请添加图片描述

Polygon [] polys;
int cols = 10,rows = 10;


void setup(){
  size(800,800,P3D);
  smooth(8);
  
  polys = new Polygon[cols * rows];
  for(int i=0;i<polys.length;i++){
    int col = i % cols;
    int row = i / cols;
    
    int sideCount = round(random(3,6));//取随机数再取整
    float radius = random(20,40);
    float x = map(col,0,cols-1,width*0.1,width*0.9);
    float y = map(row,0,rows-1,height*0.1,height*0.9);
    polys[i] = new Polygon(sideCount,radius,x,y);
    //int _sideCount, float _radius,float _ctrX,float _ctrY
  }
}

void draw(){
  for(int i=0;i<polys.length;i++){
    polys[i].update();
  }
  background(255);
  for(int i=0;i<polys.length;i++){
    polys[i].display();
  }
}

//鼠标点击事件
void mousePressed(){
  for(int i=0;i<polys.length;i++){
    polys[i].randomize();
  }
}
class Polygon{
  int sideCount;//边数
  float radius,radiusT;//半径
  color c,cT;//颜色
  float rtt;//旋转角度 rotation
  float [] x,y; //顶点
  float ctrX,ctrY; //中心位置k
  float lerpStep;//控制插值的步数
  float thetabfst,thetabfstT;//旋转偏差量
  
  //构造方法
  Polygon(int _sideCount, float _radius,float _ctrX,float _ctrY){
    //用传入参数给自身属性赋值
    sideCount = _sideCount; 
    radius = radiusT = _radius;
    ctrX = _ctrX;
    ctrY = _ctrY;
    //初始化
    x = new float[sideCount];
    y = new float[sideCount];
    
    c = cT = color(random(255),random(255),random(255));
    thetabfst = thetabfstT = random(TWO_PI); 
  }
    //声明一个方法
   void update(){
     radius = lerp(radius,radiusT,lerpStep);
     c = lerpColor(c,cT,lerpStep);
     thetabfst = lerp(thetabfst,thetabfstT,lerpStep);
     //用for循环计算一下多边形顶点的位置,有多少条边就有多少个顶点
     for(int i=0;i<sideCount;i++){
       float theta = map(i,0,sideCount,thetabfst,thetabfst + TWO_PI);
       x[i] = cos(theta)*radius+ctrX;
       y[i] = sin(theta)*radius+ctrY;
     }
   }
   void randomize(){  //随机参数
     lerpStep = random(0.0325,0.2); //随机插值,使大小、颜色变化速度不一致
     //radiusT = random(60,100); //随机大小
     cT = color(random(255),random(255),random(255)); //随机颜色
     thetabfst += random(PI*0.25,PI*0.75);
   }
   
   
   void display(){
     noStroke();
     fill(c);
     beginShape();
     for(int i=0;i<sideCount;i++){
       vertex(x[i],y[i]);
     }
     endShape();
   }
}

在此基础上可实现间隔分布:
请添加图片描述

Polygon [] polys;
int cols = 10,rows = 10;


void setup(){
  size(800,800,P3D);
  smooth(8);
  
  polys = new Polygon[cols * rows / 2];  //***
  int polyIdx = 0;  //***
  //for(int i=0;i<polys.length;i++){
    for(int i=0;i<cols * rows;i++){   //***
    int col = i % cols;
    int row = i / cols;
    if(col%2==0 && row%2==0) continue;   //跳过循环*** 
    else if(col%2==1 && row%2==1) continue;   //***
    int sideCount = round(random(3,6));//取随机数再取整
    float radius = random(20,40);
    float x = map(col,0,cols-1,width*0.1,width*0.9);
    float y = map(row,0,rows-1,height*0.1,height*0.9);
    polys[polyIdx] = new Polygon(sideCount,radius,x,y);  //***
    polyIdx++;  //***
    //int _sideCount, float _radius,float _ctrX,float _ctrY
  }
}

void draw(){
  for(int i=0;i<polys.length;i++){
    polys[i].update();
  }
  background(255);
  for(int i=0;i<polys.length;i++){
    polys[i].display();
  }
}

//鼠标点击事件
void mousePressed(){
  for(int i=0;i<polys.length;i++){
    polys[i].randomize();
  }
}
class Polygon{
  int sideCount;//边数
  float radius,radiusT;//半径
  color c,cT;//颜色
  float rtt;//旋转角度 rotation
  float [] x,y; //顶点
  float ctrX,ctrY; //中心位置k
  float lerpStep;//控制插值的步数
  float thetabfst,thetabfstT;//旋转偏差量
  
  //构造方法
  Polygon(int _sideCount, float _radius,float _ctrX,float _ctrY){
    //用传入参数给自身属性赋值
    sideCount = _sideCount; 
    radius = radiusT = _radius;
    ctrX = _ctrX;
    ctrY = _ctrY;
    //初始化
    x = new float[sideCount];
    y = new float[sideCount];
    
    c = cT = color(random(255),random(255),random(255));
    thetabfst = thetabfstT = random(TWO_PI); 
  }
    //声明一个方法
   void update(){
     radius = lerp(radius,radiusT,lerpStep);
     c = lerpColor(c,cT,lerpStep);
     thetabfst = lerp(thetabfst,thetabfstT,lerpStep);
     //用for循环计算一下多边形顶点的位置,有多少条边就有多少个顶点
     for(int i=0;i<sideCount;i++){
       float theta = map(i,0,sideCount,thetabfst,thetabfst + TWO_PI);
       x[i] = cos(theta)*radius+ctrX;
       y[i] = sin(theta)*radius+ctrY;
     }
   }
   void randomize(){  //随机参数
     lerpStep = random(0.0325,0.2); //随机插值,使大小、颜色变化速度不一致
     //radiusT = random(60,100); //随机大小
     cT = color(random(255),random(255),random(255)); //随机颜色
     thetabfst += random(PI*0.25,PI*0.75);
   }
   
   
   void display(){
     noStroke();
     fill(c);
     beginShape();
     for(int i=0;i<sideCount;i++){
       vertex(x[i],y[i]);
     }
     endShape();
   }
}

屏幕录制2023-05-3016.25.18

②运用OOP思路的粒子系统
向量:请添加图片描述
边缘侦测:
请添加图片描述
如何实现下面的效果?

屏幕录制2023-05-3113.53.56

Particle [] pts;
void setup(){
  size(800,800,P3D);
  smooth(8);
  
  pts = new Particle[300];
  for(int i=0;i<pts.length;i++){ //建立每一个小粒子
    pts[i] = new Particle(random(width),random(height),random(5,20));
    //float initX,float initY,float _diam
  }
  background(0);
}

void draw(){
  
  for(int i=0;i<pts.length;i++){ 
    pts[i].update();
  }
  //每次叠加一个半透明的矩形,实现残影效果
  noStroke();
  fill(0,64);
  rect(0,0,width,height);
  
  for(int i=0;i<pts.length;i++){ 
    pts[i].display();
  }  
}
class Particle{
  PVector pos,vel;//向量
  float diam;
  float rtt; //rotation
  color c;
  Particle(float initX,float initY,float _diam){ //构造方法
    pos = new PVector(initX,initY);
    vel = PVector.random2D(); //让速度向量随机取一个任意方向的单位向量,但此时速度一致
    vel.mult(random(0.25,5)); //随机乘一个数值,使速度不同
    diam = _diam;
    c = color(random(255),random(255),random(255));
    rtt = random(-0.025,0.025)*PI;
  }
  
  void update(){
    vel.rotate(rtt);
    pos.add(vel);//v += vx;y += vy;
    boundaryTest();
  }
  
  void boundaryTest(){  //碰撞检测
    float leftBound = diam * .5;
    float rightBound = width - diam * .5;
    float topBound = diam * .5;
    float bottomBound = height - diam * .5;
    if(pos.x <= leftBound){
      pos.x = leftBound;
      vel.x *= -1;
    }
    else if(pos.x >= rightBound){
      pos.x = rightBound;
      vel.x *= -1;
    }
    if(pos.y <= topBound){
      pos.y = topBound;
      vel.y *= -1;
    }
    else if(pos.y >= bottomBound){
      pos.y = bottomBound;
      vel.y *= -1;
    }
  }
  
  void display(){
    strokeWeight(diam);
    stroke(c);
    point(pos.x,pos.y);
  }
}

③课程作业
实现下方的实时互动效果

屏幕录制2023-06-0113.00.55

Spiral [] sGrid;
int cols = 10,rows = 10,amt = cols * rows;
float unitW;
void setup(){
  size(800,800,P3D);
  smooth(8);
  unitW = width * 1.0 / cols;  //*0.1是为了让width带小数,使之后计算数值更准确
  sGrid = new Spiral[amt]; 
  for(int i=0;i<amt;i++){
    int col = i % cols;
    int row = i / cols;
    float x = map(col,0,cols-1,unitW * .5,width - unitW * .5);
    float y = map(row,0,rows-1,unitW * .5,height - unitW * .5);
    sGrid[i] = new Spiral(100,x,y,unitW * .5,i * TWO_PI * 0.25);
    //int _res,float _ctrX,float _ctrY,float _radius,float _thetaOdst
    
  }
}
void draw(){
  for(int i=0;i<amt;i++){
    sGrid[i].update();
  }
  background(255);
   for(int i=0;i<amt;i++){
    sGrid[i].display();
  }
}
class Spiral{
  int res; //resolution 精度,即分辨率
  float thetaMax,thetaMaxT,thetaOdst;  //弯曲程度,,,角度偏移值
  float ctrX,ctrY; //中心位置
  float radius;  //半径
  Spiral(int _res,float _ctrX,float _ctrY,float _radius,float _thetaOdst){
    res = _res;
    ctrX = _ctrX;
    ctrY = _ctrY;
    radius = _radius;
    thetaOdst = _thetaOdst;
  }
  void update(){
    float d = dist(mouseX,mouseY,ctrX,ctrY);
    d = constrain(d,0,width*0.5);
    thetaMaxT = map(d,0,width*0.5,TWO_PI*4,0);
    thetaMax = lerp(thetaMax,thetaMaxT,0.0625);
  }
  void display(){
    noFill();
    stroke(0);
    strokeWeight(5);
    beginShape();
    for(int i=0;i<res;i++){
      float theta = map(i,0,res-1,0,thetaMax) + thetaOdst;
      float r = map(i,0,res-1,radius,0);
      float x = cos(theta) * r + ctrX;
      float y = sin(theta) * r + ctrY;
      vertex(x,y);
    }
    endShape();
  }
}

粒子系统(二)

①数组列表
数组列表与数组的差异请添加图片描述
请添加图片描述

②使用数组改写上一节的粒子系统实例
请添加图片描述

ArrayList <Particle>ptcs; //Particle [] pts;
void setup(){
  size(800,800,P3D);
  smooth(8);
  background(0);
  ptcs = new ArrayList<Particle>(); //pts = new Particle[300];
  for(int i=0;i<120;i++){  //for(int i=0;i<pts.length;i++){ 
    Particle ptc = new Particle(random(width),random(height),random(5,20));
    //pts[i] = new Particle(random(width),random(height),random(5,20));
    ptcs.add(ptc);
  }
}

void draw(){
  for(int i=0;i<ptcs.size();i++){  //for(int i=0;i<pts.length;i++){ 
    Particle ptc = ptcs.get(i);
    ptc.update();
    //pts[i].update();
    
  }
  noStroke();
  fill(0,64);
  rect(0,0,width,height);
  for(int i=0;i<ptcs.size();i++){ //for(int i=0;i<pts.length;i++){ 
    Particle ptc = ptcs.get(i);
    ptc.display();
    //pts[i].display();
  }  
}
class Particle{
  PVector pos,vel;//向量
  float diam;
  float rtt; //rotation
  color c;
  Particle(float initX,float initY,float _diam){ //构造方法
    pos = new PVector(initX,initY);
    vel = PVector.random2D(); //让速度向量随机取一个任意方向的单位向量,但此时速度一致
    vel.mult(random(0.25,5)); //随机乘一个数值,使速度不同
    diam = _diam;
    c = color(random(255),random(255),random(255));
    rtt = random(-0.025,0.025)*PI;
  }
  
  void update(){
    vel.rotate(rtt);
    pos.add(vel);//v += vx;y += vy;
    boundaryTest();
  }
  
  void boundaryTest(){  //碰撞检测
    float leftBound = diam * .5;
    float rightBound = width - diam * .5;
    float topBound = diam * .5;
    float bottomBound = height - diam * .5;
    if(pos.x <= leftBound){
      pos.x = leftBound;
      vel.x *= -1;
    }
    else if(pos.x >= rightBound){
      pos.x = rightBound;
      vel.x *= -1;
    }
    if(pos.y <= topBound){
      pos.y = topBound;
      vel.y *= -1;
    }
    else if(pos.y >= bottomBound){
      pos.y = bottomBound;
      vel.y *= -1;
    }
  }
  
  void display(){
    strokeWeight(diam);
    stroke(c);
    point(pos.x,pos.y);
  }
}

③进一步复杂化粒子系统的逻辑,以及深化细节

  • 添加与移除元素实例

请添加图片描述
添加都是添加在最后,索引不会发生变更
请添加图片描述
移除如果是移除中间的元素,后边的索引会发生相应的变化

  • 生命值映射到视觉形态
    在这里插入图片描述
  • 两种规避规避移除元素过程中跳过后一个元素方法
    1.索引控制
    请添加图片描述
    2.倒序遍历请添加图片描述
  • 粒子系统实例

粒子系统

ArrayList <Particle>ptcs;  //声明
boolean emitting;
void setup(){
  size(800,800,P3D);
  smooth(8);
  background(0);
  blendMode(ADD);  //颜色叠加效果
  ptcs = new ArrayList<Particle>();  // 初始化
  
}
void draw(){
  if(emitting){ //为true时,初始化元素,不断释放
    for(int i=0;i<25;i++){  //for增加数量
      Particle ptc = new Particle(mouseX,mouseY,mouseX-pmouseX,mouseY-pmouseY,random(3,8));
      ptcs.add(ptc);
    }    
  }
  for(int i=0;i<ptcs.size();i++){  //调用元素
    Particle ptc = ptcs.get(i);
    if(ptc.dead){  //如果是死亡状态则移除
      ptcs.remove(ptc);
      i--;  //规避移除元素过程中跳过后一个元素
    }
     else{  //否则继续更新
      ptc.update();
    }
  }
  background(0);
  for(int i=0;i<ptcs.size();i++){ //调用元素
    Particle ptc = ptcs.get(i);
    ptc.display();
  }  
  fill(#00ff00);
  text("ptcs.size():" + ptcs.size() ,50,50); //显示数组列表元素数量
}


void mousePressed(){  
  if(mouseButton == LEFT){  //初始化元素 //监听鼠标左键按下事件
    Particle ptc = new Particle(mouseX,mouseY,mouseX-pmouseX,mouseY-pmouseY,random(25,50));
    ptcs.add(ptc);
  }else if(mouseButton == RIGHT){//监听鼠标右键按下事件
    emitting = true;
  }
}

void mouseReleased(){
  if(mouseButton == RIGHT){
    emitting = false;
  }
}
class Particle{
  boolean dead;
  int life,lifeSpan;//生命与寿命
  PVector pos,vel;//向量
  float diam,diamMax,alpha,friction;//直径,直径最大值,透明度,摩擦力
  float rtt; //rotation 旋转,旋转量
  color c;
  Particle(float initX,float  initY,float velX,float velY,float _diamMax){ //构造方法
    pos = new PVector(initX,initY);
    if(velX == 0 && velY == 0){ //如果鼠标没有移动随机取方向
      vel = PVector.random2D(); //让速度向量随机取一个任意方向的单位向量,但此时速度一致
      vel.mult(random(0.25,5)); //随机乘一个数值,使速度不同
    }else{  //移动的话跟随鼠标方向
      vel = new PVector(velX,velY); 
      vel.rotate(random(-PI*.1,PI*.1));//让方向偏移一点点
      vel.mult(random(0.05,0.25));
    }
    diamMax = _diamMax;
    c = color(random(255),random(255),random(255));
    //rtt = random(-0.025,0.025)*PI;
    friction = random(0.9,0.99);
    lifeSpan = round(random(60,180)); //存在60-180帧
  }
  
  void update(){
    updateLife();
    updateAppr();
    updatePos();
  }
  
  void updateLife(){ //更新生命
    if(life<lifeSpan) life++; //当生命小于寿命,就让它慢慢增加
    else dead = true;
  }
  void updateAppr(){ //更新透明度
    if(life<lifeSpan * .25){ //生长期
      diam = map(life,0,lifeSpan * .25,0,diamMax);
      alpha = 255;
    }else if(life>=lifeSpan * .25 && life<lifeSpan * .75){ //成熟期
      diam = diamMax;
      alpha = 255;
    }else{ //衰老期
      diam = diamMax;
      alpha = map(life,lifeSpan * .75,lifeSpan,255,0);
    }
    
  }
  void updatePos(){ //更新坐标
    //vel.rotate(rtt);
    vel.mult(friction);//每一帧乘一个摩擦力,速度越来越小
    pos.add(vel);//v += vx;y += vy;
    boundaryTest();
  }
  
  void boundaryTest(){  //碰撞检测
    float leftBound = diam * .5;
    float rightBound = width - diam * .5;
    float topBound = diam * .5;
    float bottomBound = height - diam * .5;
    if(pos.x <= leftBound){
      pos.x = leftBound;
      vel.x *= -1;
    }
    else if(pos.x >= rightBound){
      pos.x = rightBound;
      vel.x *= -1;
    }
    if(pos.y <= topBound){
      pos.y = topBound;
      vel.y *= -1;
    }
    else if(pos.y >= bottomBound){
      pos.y = bottomBound;
      vel.y *= -1;
    }
  }
  
  void display(){
    strokeWeight(diam);
    stroke(c,alpha);
    point(pos.x,pos.y);
  }
}

④课程作业

实现下方效果:

屏幕录制2023-06-0209.55.18

图4-1
图4-1

ArrayList <Firework> fwList;//1.声明

void setup(){
  size(800,800,P3D);
  smooth(8);
  blendMode(ADD);  //颜色叠加效果
  
  fwList = new ArrayList<Firework>();  //2.初始化
}
void draw(){
  //4.调用元素
  for(int i=0;i<fwList.size();i++){
    Firework fw = fwList.get(i);
    if(fw.dieout){
      if(fw.gen<5) fw.explode();  //小于五代时,移除前炸一下
      fwList.remove(fw);
      i--;
    }else{
      fw.update();
    }
  }
  background(0);
  for(int i=0;i<fwList.size();i++){
    Firework fw = fwList.get(i);
    fw.display();
  }
  fill(#00ff00);
  textSize(24);
  text("fwList.size():" + fwList.size(),50,50);
}

void mousePressed(){  
  //3.初始化元素
  Firework fw = new Firework(mouseX,mouseY,random(10,20),0,color(random(255),random(255),random(255)));
  // float x,float y,float _diam,int _gen,color _c
  fwList.add(fw);
}


class Firework{
  int gen;
  boolean dieout;
  PVector pos,tgt;
  float diam,diamT;
  color c,cT;
  int life,lifeSpan;
  
  Firework(float x,float y,float _diam,int _gen,color _c){
    pos = new PVector(x,y);
    tgt = PVector.random2D(); //返回一个模长为1,随机方向的二维向量
    tgt.mult(200); 
    tgt.add(pos); //见图4-1
    
    c = _c;
    cT = color(random(255),random(255),random(255));
    
    diam = _diam;
    diamT = _diam * .75;
    
    lifeSpan = round(random(10,20));
    gen = _gen;
  }
  void explode(){
    for(int i=0;i<round(random(2,3));i++){  //for循环增加数量
      Firework fw_gen = new Firework(pos.x,pos.y,diam,gen+1,c);  //炸的时候传入当前颜色
      fwList.add(fw_gen);
    }
  }
  void update(){
    updateLife();
    diam = lerp(diam,diamT,.0625);  // 慢慢变小
    c = lerpColor(c,cT,.0625); 
    pos.lerp(tgt,0.0625); //pos.x=lerp(pos.x,tgt.x,0.0625);pos.y=lerp(pos.y,tgt.y,0.0625);
  }
  void updateLife(){
    if(life<lifeSpan) life++;
    else dieout = true;
  }
  void display(){
    stroke(c);
    strokeWeight(diam);
    point(pos.x,pos.y);    
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值