// red_thing (2005. 1. 31.) // by SeungJoon Choi // erucipe@hanmail.net // // http://processing.org Node[] nodes; Node selected = null; float mx, my; void setup() { size(400, 300); ellipseMode(CENTER_RADIUS); background(0); noStroke(); mx = width*0.5; my = height*0.5; int n = 300; nodes = new Node[n]; for(int i = 0; i < n; i++) { nodes[i] = new Node(random(400), random(300), 2+random(4)); } } void mousePressed() { for(int i = 0; i < nodes.length; i++) { Node node = nodes[i]; float dx = mouseX - node.x; float dy = mouseY - node.y; float d = sqrt(dx*dx+dy*dy); if(d < node.radius) { selected = node; } } } void mouseReleased() { selected = null; } void loop() { background(255); if(selected != null) { selected.x = mouseX; selected.y = mouseY; } for(int i = 0; i < nodes.length; i++) { Node node = nodes[i]; node.Update(nodes); node.Draw(); } //blur(g); if(mouseX != 0) mx = mouseX; if(mouseY != 0) my = mouseY; } class Node { Node(float _x, float _y, float _r) { x = _x; y = _y; radius = _r; _radius = _r; vx = 0; vy = 0; dt = 0.05; type = (int)random(2); tempo = 0.0001*(1+random(10)); blood = 127 + (int)random(128); } void Update(Node[] nodes) { for(int i = 0; i < nodes.length; i++) { Node node = nodes[i]; if(this != node) { float dx = x - node.x; float dy = y - node.y; float d = sqrt(dx*dx + dy*dy); if(d > 0) { float ux = dx / d; float uy = dy / d; if(d > radius + node.radius && d < radius * 5) { vx += -ux*dt*(1+random(5)); vy += -uy*dt*(1+random(5)); node.vx += ux*dt; node.vy += uy*dt; } } } } x += vx*dt; y += vy*dt; for(int i = 0; i < nodes.length; i++) { Node node = nodes[i]; if(this != node) { float dx = x - node.x; float dy = y - node.y; float d = sqrt(dx*dx + dy*dy); if(d > 0) { float ux = dx / d; float uy = dy / d; if(d < radius + node.radius) { float k = radius + node.radius - d; x += k*ux*0.5; y += k*uy*0.5; vx += k*ux*8; vy += k*uy*8; node.x += -k*ux*0.5; node.y += -k*uy*0.5; node.vx += -k*ux*8; node.vy += -k*uy*8; } } } } if(x < radius || x > width-radius) vx = -vx * 0.9; if(y < radius || y > height-radius) vy = -vy * 0.9; x = constrain(x, 0+radius, width-radius); y = constrain(y, 0+radius, height-radius); } void Draw() { fill(blood, 128-blood, 0, blood); float r = 0; switch(type) { case 0 : r = abs(_radius*sin(millis()*tempo)); break; case 1 : r = abs(_radius*cos(millis()*tempo)); break; } ellipse(x, y, r, r); radius = r+2; } float x, y, radius, _radius; float dt, vx, vy; int type; float tempo; int blood; } int Red(int c) { return (c & 0xff0000) >> 16; } int Green(int c) { return (c & 0x00ff00) >> 8; } int Blue(int c) { return c & 0x0000ff; } void blur(BGraphics target) { int index,left,right,top,bottom; int sumr, sumg, sumb; for(int j=0;j0) left=-1; else left=width-1; if(j==(width-1)) right=-width+1; else right=1; if(i>0) top=-width; else top=(height-1)*width; if(i==(height-1)) bottom=-(height-1)*width; else bottom=width; // Calculate the sum of n neighbors sumr=Red(target.pixels[left+index]); // left middle sumg=Green(target.pixels[left+index]); sumb=Blue(target.pixels[left+index]); sumr+=Red(target.pixels[right+index]); // right middle sumg+=Green(target.pixels[right+index]); sumb+=Blue(target.pixels[right+index]); sumr+=Red(target.pixels[index]); // middle middle sumg+=Green(target.pixels[index]); sumb+=Blue(target.pixels[index]); sumr+=Red(target.pixels[index+top]); // middle top sumg+=Green(target.pixels[index+top]); sumb+=Blue(target.pixels[index+top]); sumr+=Red(target.pixels[index+bottom]); // middle bottom sumg+=Green(target.pixels[index+bottom]); sumb+=Blue(target.pixels[index+bottom]); sumr=(int)((float)sumr/5.01); sumg=(int)((float)sumg/5.01); sumb=(int)((float)sumb/5.01); target.pixels[index]=(sumr<<16)+(sumg<<8)+sumb; } } }