final int NUM_EXPLOSIONS = 20; Explosion[] fireworks = new Explosion[NUM_EXPLOSIONS]; void setup() { size(800,600,P3D); background(0); noStroke(); for ( int i=0; i < NUM_EXPLOSIONS; i++ ) fireworks[i] = new Explosion(); } void draw() { background(0); for ( int i=0; i < NUM_EXPLOSIONS; i++ ) { Explosion ex = fireworks[i]; ex.Draw(); ex.Grow(); } } class Coord { private final float MAX_Z = 100; public float x,y,z; public Coord() { x = random(0,width); y = random(0,height); z = random(0,MAX_Z); } public Coord(float _x, float _y, float _z) { x = _x; y = _y; z = _z; } } class Vertex extends Coord { private Vector myVector; public Vertex() { super(); InitVector(); } public Vertex(float _x, float _y, float _z) { super(_x,_y,_z); InitVector(); } private void InitVector() { myVector = new Vector(true); } public void Move() { x += myVector.x; y += myVector.y; z += myVector.z; x %= width; y %= height; z %= super.MAX_Z; } } class Vector extends Coord { private final float MAX_RANDOM_OFFSET = 3f; public Vector() { super(); } public Vector(float _x, float _y, float _z) { super(_x,_y,_z); } public Vector(boolean random) { super(); if ( random ) { x = random(-MAX_RANDOM_OFFSET, MAX_RANDOM_OFFSET); y = random(-MAX_RANDOM_OFFSET, MAX_RANDOM_OFFSET); z = random(-MAX_RANDOM_OFFSET*0.005, MAX_RANDOM_OFFSET*0.005); } } } class Colour { public int r,g,b,a; public Colour() { r = (int)random(32,255); g = (int)random(32,255); b = (int)random(32,255); a = 255; } public Colour(int _r, int _g, int _b, int _a) { r = _r; g = _g; b = _b; a = _a; } public Colour GetDarkened(int amount) { int newR,newG,newB,newA; newR = max(0,r - amount); newG = max(0,g - amount); newB = max(0,b - amount); newA = max(0,a - amount); return new Colour(newR, newG, newB, newA); } } class FCircle { private float numRings = 50f; private final float RING_INCREASE_AMOUT = 0.1f; private Vertex myPoint; private Colour myColor; private final int MAX_RADIUS = 20; private PGraphics myFrame = null; public FCircle() { myPoint = new Vertex(); myColor = new Colour(); } public FCircle(Vertex _point, Colour _color) { myColor = _color; myPoint = _point; } public FCircle(Vertex _point, Colour _color, PGraphics _frame) { myColor = _color; myPoint = _point; myFrame = _frame; } public void Draw() { if ( myFrame == null ) Render(); //translate(myPoint.x, myPoint.y, myPoint.z); float drawSize = MAX_RADIUS / myPoint.z; blend(myFrame, 0, 0, width, height, (int)myPoint.x-MAX_RADIUS/2, (int)myPoint.y-MAX_RADIUS/2, (int)drawSize, (int)drawSize, SCREEN); //image(myFrame,0,0); //translate(-myPoint.x, -myPoint.y, -myPoint.z); } private void Render() { PGraphics pg = createGraphics(MAX_RADIUS*4, MAX_RADIUS*4, P3D); pg.beginDraw(); pg.background(0,0,0,0); pg.noStroke(); int step = GetStep(); for ( int ring=(int)numRings; ring > 0; ring-- ) { int _radius = int( (ring*step * MAX_RADIUS) / numRings ); Colour _color = myColor.GetDarkened( ring*step ); pg.fill(_color.r, _color.g, _color.b, _color.a); pg.ellipse(MAX_RADIUS*2, MAX_RADIUS*2, _radius, _radius); } pg.endDraw(); myFrame = pg; } public PGraphics GetFrame() { return myFrame; } public void Move() { myPoint.Move(); } public Vertex GetVertex() { return myPoint; } public Colour GetColor() { return myColor; } private int GetStep() { /* if ( numRings < 256 ) numRings += RING_INCREASE_AMOUT; */ return (int)(256 / numRings); } } class Explosion { private ArrayList myCircles = new ArrayList(); private final float MAX_OFFSET = 5f; private final int MAX_PARTICLES = 100; private boolean growing=true; public Explosion() { myCircles.add(new FCircle()); } public void Draw() { for ( int i=0; i < myCircles.size(); i++ ) { FCircle thisCircle = myCircles.get(i); thisCircle.Draw(); if ( i != 0 ) thisCircle.Move(); } } public void Grow() { if ( !growing ) Shrink(); else { FCircle lastCircle = myCircles.get(myCircles.size()-1); Vertex v = lastCircle.GetVertex(); Vertex newVertex = new Vertex( v.x + random(-MAX_OFFSET, MAX_OFFSET), v.y + random(-MAX_OFFSET, MAX_OFFSET), v.z + random(-MAX_OFFSET, MAX_OFFSET) ); myCircles.add(new FCircle(newVertex, lastCircle.GetColor(), lastCircle.GetFrame() ) ); } if ( myCircles.size() > MAX_PARTICLES ) myCircles.remove(1); //growing=false; } private void Shrink() { myCircles.remove(1); if ( myCircles.size() < 2 ) growing=true; } }