processing《代码本色》第4章练习

一、 粒子系统
从20世纪80年代初开始,粒子系统就被用于制作各种电子游戏、动画、数码艺术作品,还被用于模拟各种不规则的自然现象,比如火焰、烟雾、瀑布、草丛和泡沫。
这一章讨论粒子系统的实现策略。我们将探讨一下问题:在实现粒子系统时,如何组织代码;如何存放单个粒子及整个系统的相关信息。在模拟过程中,用最基本的图形代表例子,并且只涉及粒子的最基本行为(比如在重力作用下的行为)。
在粒子系统的研究过程中,我们将会接触两种面向对象编程的关键技术:继承和多态。在前面的例子中,数组中存储的只是同种类型的对象,就像Mover和Oscillator。有了继承和多态之后,我们就可以在数组中存放不同类型的的对象。
首先尝试模拟单个粒子的运动情况,粒子发射出来后受重力逐渐坠落并消亡。
二、 例子一
1、在Particle类中定义所需变量位置、速度、加速度以及生命周期。在particle构造函数中给变量赋值。

class Particle {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float lifespan;
  Particle(PVector l) {
    acceleration = new PVector(0, 0.05);
    velocity = new PVector(random(-1, 1), random(-1, 0));
    position = l.get();
    lifespan = 255.0;
  	}
  }

2、update()函数更新粒子每一帧的速度、当前位置以及生命长度。Display()函数中画出粒子。IsDead()判断粒子的生命是否结束,如果结束、不在绘制此点。

 void update() {
    velocity.add(acceleration);
    position.add(velocity);
    lifespan -= 2.0;
  }
  void display() {
    stroke(0, lifespan);
    strokeWeight(2);
    fill(127, lifespan);
    ellipse(position.x, position.y, 12, 12);
  }
boolean isDead() {
    if (lifespan < 0.0) {
      return true;
    } 
    else {
      return false;
    }
  }

3、 主函数中new一个对象并调用。Draw()函数中,如果isDead()返回值为true,则新发射一个粒子。显示运行结果

Particle p;
void setup() {
  size(500,500);
  p = new Particle(new PVector(width/2,20));
  background(255);
  smooth();
}
void draw() {
  background(255);
  p.run();
  if (p.isDead()) {
    p = new Particle(new PVector(width/2,20));
  }
}

在这里插入图片描述
三、 由系统组成的系统
如果系统中的粒子数量位置,该如何管理粒子列表呢。
我们可以使用数组管理。如果粒子系统的粒子数量是恒定的,数组是非常有效的工具。此外,processing还提供了一些函数用于改变数组长度,比如expend()、contract()、subset()、splice()等。这里,我使用ArrayList类,这是一种更高级的对象列表管理方法。
ArrayList的实现思路与普通数组类似,但语法并不相同。
用数组实现:

int total=10;
Particle[] parray = new Particle[total];
void setup(){
  for(int i=0;i<parray.length;i++){
    parray[i]=new Particle();
  }
}
  void draw(){
    for(int i=0;i<parray.length;i++){
      Particle p=parray[i];
      p.run();
    }
  }
}

用ArrayList实现:

int total=10;
ArrayList<Particle>plist=new ArrayList<Particle>();
void setup(){
  for(int i=0;i<total;i++){
    plist.add(new Particle());
  }
}
  void draw(){
    for(int i=0;i<plist.size();i++){
      Particle p=plist.get[i];
      p.run();
    }
  }

在两种实现路径中,最后一个for循环的实现方式相似,都是通过一个下标遍历数组中的每个元素,我们创建了变量i,让他从0开始每次递增1,诸葛访问ArrayList的元素,知道遍历结束。除此之外,Java还提供一种更简洁的改进型for循环。

ArrayList<Particle>plist=new ArrayList<Particle>();
for(Particle p:particle){
p.run();
}

ArrayList类提供remove()函数,可以通过这个函数移除某个粒子对象(通过对象的下标)。在判断粒子对象的isDead()函数返回值是否为true后,如果是,则调用remove()移除对象。
粒子系统的是由一系列独立对象组成的集合,我们可以让这些粒子系统对象组成一个集合,产生一个由系统组成的系统。
四、 例子二。
1、在Particle类中定义所需变量位置、速度、加速度以及生命长度。在构造函数中给变量赋值。

class Particle {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float lifespan;
  Particle(PVector l) {
    acceleration = new PVector(0,0.05);
    velocity = new PVector(random(-1,1),random(-2,0));
    position = l.get();
    lifespan = 255.0;
  }
}

2、update()函数中更新粒子的速度、加速度以及缩短生命长度。Display()函数中画出初始粒子的位置。

void update() {
    velocity.add(acceleration);
    position.add(velocity);
    lifespan -= 2.0;
  }
  void display() {
    stroke(0,lifespan);
    fill(127,lifespan);
    ellipse(position.x,position.y,12,12);
  }

3、ParticleSystem粒子系统类。创建ArrayList数组particles。在构造函数中给入参数粒子数量num和起始位置v。添加num数量的粒子进入arraylist数组。

class ParticleSystem {
  ArrayList<Particle> particles;
  PVector origin;              
  ParticleSystem(int num, PVector v) {
    particles = new ArrayList<Particle>();
    origin = v.get();
    for (int i = 0; i < num; i++) {
      particles.add(new Particle(origin));
    }
  }
}

4、run()函数中遍历arraylist数组创建粒子,如果isDead()函数返回真值,则remove()清除该粒子。

void run() {
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = particles.get(i);
      p.run();
      if (p.isDead()) {
        particles.remove(i);
      }
    }
  }

5、主函数中new一个系统对象(注意是ArrayList)并调用,利用上边提到的简易for循环不断执行操作。

ArrayList<ParticleSystem> systems;
void setup() {
  size(500,500);
  systems = new ArrayList<ParticleSystem>();
}
void draw() {
  background(255);
  for (ParticleSystem ps: systems) {
    ps.run();
    ps.addParticle(); 
  }
}

6、添加一个鼠标获取起始点的函数,在鼠标点击时,获取mouseX和mouseY传给ParticleSystem。在点击点开始运行整个系统。

void mousePressed() {
  systems.add(new ParticleSystem(1,new PVector(mouseX,mouseY)));
}

在这里插入图片描述
五、 总结
本章中掌握了粒子系统的实现,并且会运用ArrayList数组对单个粒子对象管理,从而实现系统的粒子系统。在随后的实践操作中,可以添加前边学到的各种力的作用,实现受力作用的粒子系统、带排斥对象的粒子系统。以及进行粒子纹理化渲染图像。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值