float angleTowards(float current, float desired, float stepsize) { float diff = desired - current; while(diff < 0) diff+=TWO_PI; while(diff >= TWO_PI) diff-=TWO_PI; if(diff < stepsize || diff > TWO_PI - stepsize) return desired; if(diff < PI) return current + stepsize; else return current - stepsize; } 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(); } class BoostWave extends Particle { BoostWave(PVector p) { super(p, new PVector(0,0), 60); } void draw() { strokeWeight(2); stroke(255, 255*life/maxlife); noFill(); ellipse(pos.x, pos.y, (maxlife-life)*3, (maxlife-life)*3); } } class DashEcho extends Particle { DashEcho(PVector p) { super(p, new PVector(0,0), 30); } void draw() { strokeWeight(2); stroke(DRAGONDOT_STROKE, 255*life/maxlife); fill(DRAGONDOT_FILL, 255*life/maxlife); ellipse(pos.x, pos.y, DRAGONDOT_RADIUS, DRAGONDOT_RADIUS); } } class SmokePoof extends Particle { SmokePoof(PVector p, int bigness) { super(p, randomVector(random(1.0/6)), new PVector(0, -0.05/36), bigness*6); } void draw() { fill(230, 230, 220); noStroke(); ellipse(pos.x, pos.y, life/6, life/6); } } class Ember extends Particle { Ember(PVector p) { super(p, randomVector(random(0.3)), 120); } void draw() { fill(blendColors(color(255, 255, 0), color(255, 0, 0), 1-life/(float)maxlife)); noStroke(); ellipse(pos.x, pos.y, life/8, life/8); } } void poof(float radius, PVector pos) { for(int i = 0; i < 5; i++) { particles.add(new SmokePoof(pos, (int)radius + 5)); } if(!muted) poofSound.trigger(); } class TextBlip extends Particle { String myText; color myColor; TextBlip(PVector p, int life, String label) { super(p, PVector.add(randomVector(0.5), new PVector(0, -1)), new PVector(0, 2.0/life), life); myText = label; myColor = color(255); } TextBlip(PVector p, int life, String label, color c) { super(p, PVector.add(randomVector(0.5), new PVector(0, -1)), new PVector(0, 2.0/life), life); myText = label; myColor = c; } void draw() { textAlign(CENTER, BOTTOM); textFont(font, 8); if(myColor == color(255)) { fill(0); text(myText, pos.x+1, pos.y+1); } fill(myColor); text(myText, pos.x, pos.y); } } void callAttack(PVector pos, String name) { particles.add(new TextBlip(new PVector(pos.x, pos.y - 20), 90, name, ATTACK_TEXT)); } void showDamage(PVector pos, int amt) { particles.add(new TextBlip(new PVector(pos.x, pos.y), 90, ""+amt)); } 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); } color blendColors(color a, color b, float blent) { return color(red(a)*(1-blent)+red(b)*(blent), green(a)*(1-blent)+green(b)*(blent), blue(a)*(1-blent)+blue(b)*(blent)); } void mosaic(int blocksize) { if(blocksize < 1) blocksize = 1; loadPixels(); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { pixels[x + y*width] = pixels[x/blocksize*blocksize + y/blocksize*blocksize*width]; } updatePixels(); } void iris(int cx, int cy, int radius) { loadPixels(); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { if((x-cx)*(x-cx)+(y-cy)*(y-cy)>radius*radius) pixels[x + y*width] = color(0); } updatePixels(); } void diamonds(float amount) { // background(255); loadPixels(); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { if(( (abs(x-width/2)%32+abs(y-height/2)%32)+abs(x-width/2)/32*3+(abs(y-height/2)/32*3) ) > amount) pixels[x + y*width] = color(0);//color(0); } updatePixels(); } void drawCharge(float x, float y, float ratio, float radius, float circleSize, int numCircles) { float angle = (ratio * TWO_PI); for(int i = 0; i