class ParticleList extends ArrayList { void tick() { Iterator i = iterator(); while(i.hasNext()) { Particle p = (Particle) i.next(); p.tick(); if(p.life <= 0) i.remove(); } } void draw() { Iterator i = iterator(); while(i.hasNext()) { Particle p = (Particle) i.next(); p.draw(); } } } boolean inRadius(PVector a, PVector b, float rad) { return rad*rad > (a.x - b.x)*(a.x - b.x) + (a.y - b.y) * (a.y - b.y);// + (a.z - b.z) * (a.z - b.z); } abstract class Particle { PVector pos; PVector vel; PVector accel; int life; int maxlife; Particle(PVector p, PVector v, int lifetime) { this(p, v, new PVector(0, 0), lifetime); } Particle(PVector p, PVector v, PVector a, int lifetime) { accel = new PVector(a.x, a.y); pos = new PVector(p.x, p.y); vel = new PVector(v.x, v.y); life = maxlife = lifetime; } void tick() { vel.add(accel); pos.add(vel); life--; } abstract void draw(); } PVector proj(PVector src, PVector dest) { return PVector.mult(dest, src.dot(dest)/dest.dot(dest)); } void regPoly(float x, float y, float r, int sides, float rot) { beginShape(); for(int i = 0; i < sides; i++) { float segAngle = TWO_PI/sides; vertex(cos(i*segAngle + rot) * r + x, sin(i*segAngle + rot) * r + y); } endShape(CLOSE); } PVector randomVector(float magn) { float angle = random(TWO_PI); return new PVector(cos(angle)*magn, sin(angle)*magn); } boolean intersects(PVector a1, PVector a2, PVector b1, PVector b2) { float f1 = intersectionFloat(a1, a2, b1, b2); float f2 = intersectionFloat(b1, b2, a1, a2); return (f1 >= 0 && f1 <= 1 && f2 >= 0 && f2 <= 1); } color colorAdd(color a, color b) { return color(red(a)+red(b), green(a)+green(b), blue(a)+blue(b)); } color colorScale(color a, float s) { return color(red(a)*s, green(a)*s, blue(a)*s); } float intersectionFloat(PVector segstart, PVector segend, PVector from, PVector to) { //got my formula backwards (I think?), lazy fix is to swap variaible definitions. 10 hours left for this game; fix it later. PVector seg = PVector.sub(segend, segstart); PVector ray = PVector.sub(to, from); PVector segnorm = new PVector( -seg.y, seg.x ); //if(PVector.dot(ray, segnorm) == 0) return Float.NaN; else return PVector.dot(PVector.sub(segstart, from), segnorm ) / PVector.dot(ray, segnorm); } PVector intersectionPoint(PVector segstart, PVector segend, PVector from, PVector to) { // if(PVector.sub(from, segstart).cross(PVector.sub(segend, segstart)).z * PVector.sub(to, segstart).cross(PVector.sub(segend, segstart)).z >0) // return null; // from and to are on the same side of the segment - no intersection // else { println("intersectionFloat: "+intersectionFloat(segstart, segend, from, to)); return PVector.add(from, PVector.mult(PVector.sub(to, from), intersectionFloat(segstart, segend, from, to))); } } PVector reboundVel(PVector segstart, PVector segend, PVector from, PVector to) { PVector seg = PVector.sub(segend, segstart); PVector ray = PVector.sub(to, from); PVector segnorm = new PVector( -seg.y, seg.x ); return PVector.add(ray, PVector.mult(proj(ray, segnorm), -2)); } PVector reboundPoint(PVector segstart, PVector segend, PVector from, PVector to) { PVector intersect = intersectionPoint(segstart, segend, from, to); //if(!intersects(segstart, segend, from, to)) return new PVector(to.x, to.y); PVector toIntersect = PVector.sub(intersect, from); PVector seg = PVector.sub(segend, segstart); PVector ray = PVector.sub(to, from); PVector segnorm = new PVector( -seg.y, seg.x ); float gone_past_ratio = 1 - PVector.sub(intersect, from).mag() / ray.mag(); println("Gone Past: "+gone_past_ratio); PVector rebound = reboundVel(segstart, segend, from, to); rebound.mult(gone_past_ratio); return PVector.add(intersect, rebound); }