Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Processing:Примеры/Дым при помощи системы частиц (Дэниэл Шиффман)

Материал из Онлайн справочника
Перейти к: навигация, поиск


Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Ambox content.png Черновик


Описание[1]

Простой эффект дыма при помощи системы частиц. Каждая частица рендерится как изображение с наложенной на нее альфа-маской.

Пример

  1. ParticleSystem ps;
  2.  
  3. void setup() {
  4.   size(640, 360);
  5.   PImage img = loadImage("texture.png");
  6.   ps = new ParticleSystem(0, new PVector(width/2, height-60), img);
  7. }
  8.  
  9. void draw() {
  10.   background(0);
  11.  
  12.   // рассчитываем силу «ветра» на основе
  13.   // движения курсора мыши по оси X:
  14.   float dx = map(mouseX, 0, width, -0.2, 0.2);
  15.   PVector wind = new PVector(dx, 0);
  16.   ps.applyForce(wind);
  17.   ps.run();
  18.   for (int i = 0; i < 2; i++) {
  19.     ps.addParticle();
  20.   }
  21.  
  22.   // рисуем стрелку, демонстрирующую силу «ветра»:
  23.   drawVector(wind, new PVector(width/2, 50, 0), 500);
  24. }
  25.  
  26. // рисуем векторный объект «v» как стрелку на позиции «loc»:
  27. void drawVector(PVector v, PVector loc, float scayl) {
  28.   pushMatrix();
  29.   float arrowsize = 4;
  30.   // перемещаем стрелку на позицию, где ее нужно отрисовать:
  31.   translate(loc.x, loc.y);
  32.   stroke(255);
  33.   // вызываем метод heading(),
  34.   // чтобы извлечь угол вращения вектора («0» - это верх):
  35.   rotate(v.heading());
  36.   // считываем длину вектора и, если необходимо,
  37.   // масштабируем его к какому-либо диапазону (scayl):
  38.   float len = v.mag()*scayl;
  39.   // рисуем три линии, чтобы создать стрелку
  40.   // (она будет смотреть вверх,
  41.   // но мы повернем ее в нужном направлении):
  42.   line(0, 0, len, 0);
  43.   line(len, 0, len-arrowsize, +arrowsize/2);
  44.   line(len, 0, len-arrowsize, -arrowsize/2);
  45.   popMatrix();
  46. }
  47.  
  48.  
  49. // класс для управления группой объектов Particle;
  50. // для хранения объектов Particle будет использован ArrayList
  51.  
  52. class ParticleSystem {
  53.  
  54.   ArrayList<Particle> particles;    // объект ArrayList
  55.                                     // для хранения всех частиц
  56.   PVector origin;                   // точка, из которой
  57.                                     // будут извергаться частицы
  58.   PImage img;
  59.  
  60.   ParticleSystem(int num, PVector v, PImage img_) {
  61.     particles = new ArrayList<Particle>();           // инициализируем
  62.                                                      // ArrayList  
  63.     origin = v.copy();                          // сохраняем точку,
  64.                                                 // из которой будут
  65.                                                 // извергаться частицы
  66.     img = img_;
  67.     for (int i = 0; i < num; i++) {
  68.       particles.add(new Particle(origin, img));  // добавляем в
  69.                                                  // ArrayList
  70.                                                  // количество частиц,
  71.                                                  // заданное в «num»
  72.     }
  73.   }
  74.  
  75.   void run() {
  76.     for (int i = particles.size()-1; i >= 0; i--) {
  77.       Particle p = particles.get(i);
  78.       p.run();
  79.       if (p.isDead()) {
  80.         particles.remove(i);
  81.       }
  82.     }
  83.   }
  84.  
  85.   // метод для применения вектора силы
  86.   // на все частицы, в данный момент находящиеся в системе:
  87.   void applyForce(PVector dir) {
  88.     // продвинутая версия цикла for() !!!
  89.     for (Particle p : particles) {
  90.       p.applyForce(dir);
  91.     }
  92.   }  
  93.  
  94.   void addParticle() {
  95.     particles.add(new Particle(origin, img));
  96.   }
  97. }
  98.  
  99.  
  100.  
  101. // простой класс Particle, рендерит частицу в виде изображения
  102.  
  103. class Particle {
  104.   PVector loc;
  105.   PVector vel;
  106.   PVector acc;
  107.   float lifespan;
  108.   PImage img;
  109.  
  110.   Particle(PVector l, PImage img_) {
  111.     acc = new PVector(0, 0);
  112.     float vx = randomGaussian()*0.3;
  113.     float vy = randomGaussian()*0.3 - 1.0;
  114.     vel = new PVector(vx, vy);
  115.     loc = l.copy();
  116.     lifespan = 100.0;
  117.     img = img_;
  118.   }
  119.  
  120.   void run() {
  121.     update();
  122.     render();
  123.   }
  124.  
  125.   // метод для применения вектора силы к объекту Particle;
  126.   // обратите внимание, что мы здесь игнорируем «массу»:
  127.   void applyForce(PVector f) {
  128.     acc.add(f);
  129.   }  
  130.  
  131.   // метод для обновления позиции:
  132.   void update() {
  133.     vel.add(acc);
  134.     loc.add(vel);
  135.     lifespan -= 2.5;
  136.     acc.mult(0); // стираем данные об ускорении
  137.   }
  138.  
  139.   // метод для отрисовки:
  140.   void render() {
  141.     imageMode(CENTER);
  142.     tint(255, lifespan);
  143.     image(img, loc.x, loc.y);
  144.     // вместо изображения можно воспользоваться эллипсом:
  145.     // fill(255,lifespan);
  146.     // noStroke();
  147.     // ellipse(loc.x,loc.y,img.width,img.height);
  148.   }
  149.  
  150.   // частица еще видна?
  151.   boolean isDead() {
  152.     if (lifespan <= 0.0) {
  153.       return true;
  154.     } else {
  155.       return false;
  156.     }
  157.   }
  158. }

См.также

Внешние ссылки

  1. processing.org - Smoke Particle System by Daniel Shiffman.