Mod: Coding Challenge #27: Fireworks!(2D+3D)
Processingの花火のシミュレータは夏に作ったけど、こちらのほうが爆発時や爆発後の処理が洗練されている。動画視聴しながら2D版を作って、3Dに移植している。
コード(3D)
PVector gravity = new PVector(0, 0.1); ArrayList<ParticleSystem> particleSystem; // setup関数 : 初回1度だけ実行される void setup() { size(960, 540, P3D); // ウィンドウサイズを960px,540pxに colorMode(HSB, 360, 100, 100, 100); // HSBでの色指定にする smooth(); // 描画を滑らかに particleSystem = new ArrayList<ParticleSystem>(); } // draw関数 : setup関数実行後繰り返し実行される void draw() { translate(width/2, height/2, map(sin(frameCount*0.01), -1, 1, 0, -1000)); rotateX(-PI/4); rotateY(frameCount*0.01); background(220, 80, 20); fill(0, 0, 100, 20); noStroke(); beginShape(); vertex(-width/2, height, -500); vertex(-width/2, height, 500); vertex(width/2, height, 500); vertex(width/2, height, -500); endShape(CLOSE); if (random(1) < 0.05) { particleSystem.add(new ParticleSystem()); } for (int i = particleSystem.size()-1; i >= 0; i--) { ParticleSystem ps = particleSystem.get(i); ps.run(); if (ps.done()) { particleSystem.remove(ps); } } } class Particle { PVector pos; PVector vel; PVector acc; float life = 100; float lifeSpan = random(life/50, life/30); boolean seed = false; color c; Particle() { pos = new PVector(random(-width/2, width/2), height, random(-500, 500)); vel = new PVector(0, random(-12, -6)); acc = new PVector(0, 0.1); c = color(random(360), 80, 100); } Particle(float x, float y, float hue) { pos = new PVector(x, y, random(-500, 500)); vel = new PVector(0, random(-12, -6)); acc = new PVector(0, 0.1); c = color(hue, 80, 100); seed = true; } Particle(PVector _pos, float hue) { pos = new PVector(_pos.x, _pos.y, _pos.z); vel = PVector.random3D(); vel.mult(random(4, 6)); acc = new PVector(0, 0.1); c = color(hue, 80, 100); } void update() { pos.add(vel); vel.add(acc); if (!seed) { life -= lifeSpan; vel.mult(0.98); } acc.mult(0); if (pos.y > height) { pos= new PVector(random(-width/2, width/2), height, random(-500, 500)); vel = new PVector(0, random(-12, -8)); } } void draw() { stroke(c, life); strokeWeight(4); pushMatrix(); translate(pos.x, pos.y, pos.z); point(0, 0); popMatrix(); } void applyForce(PVector force) { acc.add(force); } void run() { update(); draw(); } boolean isDead() { if (life < 0) { return true; } return false; } boolean explode() { if (seed && vel.y > 0) { lifeSpan = 0; return true; } return false; } } class ParticleSystem { ArrayList<Particle> particles; Particle p; float hue; ParticleSystem() { hue = random(360); p = new Particle(random(-width/2, width/2), height, hue); particles = new ArrayList<Particle>(); } boolean done() { if (p == null && particles.isEmpty()) { return true; } else { return false; } } void run() { if (p != null) { p.applyForce(gravity); p.update(); p.draw(); if (p.explode()) { for (int i = 0; i < 100; i++) { particles.add(new Particle(p.pos, hue)); } p = null; } } for (int i = particles.size()-1; i >= 0; i--) { Particle child = particles.get(i); child.applyForce(gravity); child.run(); if (child.isDead()) { particles.remove(child); } } } }
コード(2D)
PVector gravity = new PVector(0, 0.1); ArrayList<ParticleSystem> particleSystem; // setup関数 : 初回1度だけ実行される void setup() { size(960, 540); // ウィンドウサイズを960px,540pxに colorMode(HSB, 360, 100, 100, 100); // HSBでの色指定にする smooth(); // 描画を滑らかに particleSystem = new ArrayList<ParticleSystem>(); } // draw関数 : setup関数実行後繰り返し実行される void draw() { background(220, 80, 20); if (random(1) < 0.05) { particleSystem.add(new ParticleSystem()); } for (int i = particleSystem.size()-1; i >= 0; i--) { ParticleSystem ps = particleSystem.get(i); ps.run(); if (ps.done()) { particleSystem.remove(ps); } } } class Particle { PVector pos; PVector vel; PVector acc; float life = 100; float lifeSpan = random(life/50, life/30); boolean seed = false; color c; Particle() { pos = new PVector(random(width), height); vel = new PVector(0, random(-12, -6)); acc = new PVector(0, 0.1); c = color(random(360), 80, 100); } Particle(float x, float y, float hue) { pos = new PVector(x, y); vel = new PVector(0, random(-12, -6)); acc = new PVector(0, 0.1); c = color(hue, 80, 100); seed = true; } Particle(PVector _pos, float hue) { pos = new PVector(_pos.x, _pos.y); vel = PVector.random2D(); vel.mult(random(4, 6)); acc = new PVector(0, 0.1); c = color(hue, 80, 100); } void update() { pos.add(vel); vel.add(acc); if (!seed) { life -= lifeSpan; vel.mult(0.98); } acc.mult(0); if (pos.y > height) { pos= new PVector(random(width), height); vel = new PVector(0, random(-12, -8)); } } void draw() { stroke(c, life); strokeWeight(10); point(pos.x, pos.y); } void applyForce(PVector force) { acc.add(force); } void run() { update(); draw(); } boolean isDead() { if (life < 0) { return true; } return false; } boolean explode() { if (seed && vel.y > 0) { lifeSpan = 0; return true; } return false; } } class ParticleSystem { ArrayList<Particle> particles; Particle p; float hue; ParticleSystem() { hue = random(360); p = new Particle(random(width), height, hue); particles = new ArrayList<Particle>(); } boolean done() { if (p == null && particles.isEmpty()) { return true; } else { return false; } } void run() { if (p != null) { p.applyForce(gravity); p.update(); p.draw(); if (p.explode()) { for (int i = 0; i < 100; i++) { particles.add(new Particle(p.pos, hue)); } p = null; } } for (int i = particles.size()-1; i >= 0; i--) { Particle child = particles.get(i); child.applyForce(gravity); child.run(); if (child.isDead()) { particles.remove(child); } } } }