int WIDTH = 400; int HEIGHT = 400; int c1, c2, s1, s2; float RANGE = 4; int STILLRUNNING = 0; int[] DONE = new int[WIDTH*HEIGHT]; float dist(float x1, float y1, float x2, float y2) { return sqrt(sq(x1-x2) + sq(y1-y2)); } float[] sintable = new float[(int)(TWO_PI*1001)]; float[] costable = new float[(int)(TWO_PI*1001)]; int blend(int org, int col, int alpha) { // org is original colour // col is colour to add // alpha is a value between 0 and 255, // where 0 makes 'col' completely opaque int r1=(org&0x0000ff); int g1=(org&0x00ff00); int b1=(org&0xff0000); int r2=(col&0x0000ff); int g2=(col&0x00ff00); int b2=(col&0xff0000); int r3=(((alpha*(r1-r2)) >>8 )+r2)&0x000000ff; int g3=(((alpha*(g1-g2)) >>8 )+g2)&0x0000ff00; int b3=(((alpha*(b1-b2)) >>8 )+b2)&0x00ff0000; return (r3)|(g3)|(b3); } void aapixel(float ax, float ay, int col) { int x = 0, y = 0; float fx = 0, fy = 0; x = (int)ax; y = (int)ay; fx = ax - x; fy = ay - y; pixels[x+y*WIDTH] = blend(col, pixels[x+y*width], (int)((1-fx)*(1-fy)*255)); pixels[x+y*WIDTH+1] = blend(col, pixels[x+y*width+1], (int)((fx)*(1-fy)*255)); pixels[x+y*WIDTH+width] = blend(col, pixels[x+y*width+width], (int)((1-fx)*(fy)*255)); pixels[x+y*WIDTH+width+1] = blend(col, pixels[x+y*width+width+1], (int)((fx)*(fy)*255)); } class Edge { Edge e1; Edge e2; float startx, starty, endx, endy; float x, y, dir, dirvel; int[] xhist = new int[400]; int[] yhist = new int[400]; int running = 0; int exists = 0; int spawned = 0; int oldpos; int age; int col; int steps; Edge(float xIn, float yIn, float dirIn, float dirvelIn, int ageIn, int colIn) { running = 1; startx = xIn; starty = yIn; x = xIn; y = yIn; dir = dirIn; dirvel = dirvelIn; exists = 1; spawned = 0; steps = 0; age = ageIn+1; col = colIn; } void posupdate() { int next; dir += dirvel; dir = dir % TWO_PI; if(dir < 0) dir+=TWO_PI; steps++; x += sintable[(int)(dir*1000)]; y += costable[(int)(dir*1000)]; if(steps%3 == 1 && steps < 1200) { xhist[steps/3] = (int)x; yhist[steps/3] = (int)y; } else if(steps > 1500) { println("exceeded"); } next = (int)x + (int)y*WIDTH; if(x >= WIDTH || x <= 0 || y <= 0 || y >= HEIGHT || next <= 0 || next >= WIDTH*HEIGHT || DONE[next] != 0 && oldpos != next && steps > 1) { borked(); } else if(next < WIDTH*HEIGHT-WIDTH-1 && next > WIDTH) { DONE[next] = 1; aapixel(x, y, col); STILLRUNNING = 1; } else { borked(); } oldpos = next; } void borked() { running = 0; endx = x; endy = y; stroke(col); //line(startx, starty, endx, endy); //ellipse((int)endx, (int)endy, 3, 3); //if(dist(startx, starty, endx, endy) > RANGE) { if(steps > RANGE) { spawn(); } } void spawn() { int dir1; spawned = 1; int brightness; brightness = (age < 32) ? 191 + age*2:255; int pos1, x1, y1; int pos2, x2, y2; pos1 = (int)random(steps/3); pos2 = (int)random(steps/3); if(pos1 > 399) pos1 = 399; if(pos2 > 399) pos2 = 399; x1 = xhist[pos1]; y1 = yhist[pos1]; x2 = xhist[pos2]; y2 = yhist[pos2]; e1 = new Edge(x1, y1, dir+PI/4+random(PI/2), random(-0.01, 0.01), age, color(c1, s1, brightness)); e2 = new Edge(x2, y2, dir-PI/4-random(PI/2), random(-0.01, 0.01), age, color(c2, s2, brightness)); xhist = null; yhist = null; } void update() { if(running == 1) posupdate(); if(spawned == 1) { e1.update(); e2.update(); } } } Edge e1; void setup() { size(400,400); colorMode(HSB); background(#ffffff); noBackground(); startup(); ellipseMode(CENTER_DIAMETER); fill(#fdfdfd); for(int i = 0; i < TWO_PI*1000; i++) { // the int rounding error below is intentional (believe it or not) sintable[i] = sin(i/1000); costable[i] = cos(i/1000); } } void startup() { c1 = (int)random(255); c2 = (int)random(255); s1 = (int)random(80,210); s2 = (int)random(80,210); for(int i = 0; i < WIDTH*HEIGHT; i++) { pixels[i] = 0xffffffff; DONE[i] = 0; } e1 = new Edge((int)random(WIDTH), (int)random(HEIGHT), random(TWO_PI), random(-0.01, 0.01), 0, color((int)random(255), 255, 196)); } void loop() { STILLRUNNING = 0; e1.update(); if(STILLRUNNING == 0) { delay(5000); startup(); } }