Wednesday 22 September 2010

day 22 - Hacking Hakim

Today, I happened upon this, one of the excellent HTML5 experiments by Hakim el Hattab. Just for fun I thought I'd try to simulate this in Processing without looking at Hakim's code. And it turned out pretty well I think.

I based a lot of it on Lee's bouncing points from earlier posts, but the mouse-proximity detection and ball-expanding is new. UPDATED with colour change built into the ball-expanding, and updated trails from ellipses to lines: they were a stream of trailing ellipses (size 1) but that meant the trails broke up at faster speeds, now replaced with lines.








Ball[] myBall = new Ball[50];

void setup() {
 size(400,400);
 for (int i= 0; i < myBall.length; i++) {
    int randCol = int(random(3));
    myBall [i] = new Ball(randCol, 0, 0, random(0.5, 5), random(0.5, 5));
 }
}


void draw() {
  background(240);
  for (int i= 0; i < myBall.length; i++) {
    myBall[i].bounce();
    myBall[i].display();
  }
}


class Ball {

  int c;
  float xpos;
  float ypos;
  float xspeed;
  float yspeed;
  int i;
  color col;
  float [] holdX = new float[30];
  float [] holdY = new float[30];
  float big = 10;

Ball(int tempC, float tempXpos, float tempYpos, float tempXspeed, float tempYspeed) {

    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
    xspeed = tempXspeed;
    yspeed = tempYspeed;
  
  }
 
 void display() {
  if (c == 0) {
      col = color(1,1,1);
    } else if (c == 1) {
      col = color(255,0,0);    
    } else if (c == 2) {
      col = color(255,255,0);    
    }

    fill(col);  
    noStroke();
    smooth();
  
    int r = (col >> 16) & 0xFF;  // Faster way of getting red(col)
    int g = (col >> 8) & 0xFF;   // Faster way of getting green(col)
    int b = col & 0xFF;          // Faster way of getting blue(col)
  
   float rad = 100;
   float kx = mouseX - xpos;
   float ky = mouseY - ypos;
   float mx = sqrt(pow(kx, 2) + pow(ky, 2));
   if (mx <= rad) {
   big = 10 + (100 - mx);
   r = constrain(r + int(255 - 2.55*mx),0,255);
   g = constrain(g + int(255 - 2.55*mx),0,255);  
   b = constrain(b + int(255 - 2.55*mx),0,255);
   }  
    for (int i=0; i<29; i++) {
      stroke(r,g,b);
       line(holdX[i],holdY[i], holdX[i+1],holdY[i+1]);
    }
   fill(r,g,b);  
   ellipse(xpos,ypos, big, big);  


  for (int i=29; i>=1; i--) {
   holdX[i] = holdX[i - 1];  
   holdY[i] = holdY[i - 1];
  }
 holdX[0] = xpos;
 holdY[0] = ypos;      
 }

  void bounce() {
    xpos = xpos + xspeed;
    if (xpos > width) {
      xspeed = xspeed * -1;
    }

    if (xpos < 0) {
      xspeed = xspeed * -1;
    }

    ypos = ypos - yspeed;
    if (ypos > height) {
      yspeed = yspeed * -1;
    }

    if (ypos < 0) {
      yspeed = yspeed * -1;
    }
  }
}

void mousePressed() {
 saveFrame("pic-####.jpg");
}

Monday 20 September 2010

day 20 - not much, application of sin() to blending

Not much done today, had a lot of 'work' to do. But I did finally get by head around the sin() function asa way of smoothly traversing something up and down. I really never 'got' this before, feels like a big achievement to me at least :)

In this example sin() is moving through the 0-255 range of the RGB colours art different rates.  made this pretty picture...



float angle = 0.0;

void setup() {
   size(400,400);
  smooth();
}


void draw() {
   translate(mouseX,mouseY);
  rotate(angle);
  float circ = ((1+sin(angle))*(255/2));  //sin(angle) = -1 to +1, so add one to get range 1 to 2, then multiply by colour range 255 divided by 2
  float circ1 = ((1+sin(angle/3))*(255/2));
  float circ2 = ((1+sin(angle/7))*(255/2));
  fill(circ, circ1, circ2);
 rect(-15,-15,60,10);
  angle += .1;
}

void mouseClicked() {
 saveFrame("pic-####.jpg");
}

Saturday 18 September 2010

day 18 - joined my worm to Lee's movers

Been following Lee's wonderful swarm work over the past few days and added my worms into his swarm. Also added in a jitter factor as my worms were clumping too much, though this seems to have messed with the original patch and added some odd behaviour where the worms all clump to the bottom right of the screen once they're released from following the mouse (as opposed to travelling in straight lines as before...)

If you run the code, pressing any key releases the worms from following the mouse, 'w' sends them straight to the mouse, 'q' is inbetween.

Code below.


Mover[] mover = new Mover[20];


void setup() {

  size(640, 480);

  smooth();

  background(0);

  for (int i = 0; i < mover.length; i++) {

    mover[i] = new Mover();

  }

}

void draw() {

  background(180, 100, 180);

  for (int i = 0; i < mover.length; i++) {

    mover[i].update();

    mover[i].checkEdges();

    mover[i].display();

  }

}

class Mover {

  PVector location;

  PVector velocity;

  PVector acceleration;
  
  PVector jitter;

  float topspeed;
  
  float [] holdX = new float[20];
  float [] holdY = new float[20];
  color col = color(random(255),random(255),100,255);

  Mover() {

    location = new PVector(random(width), random(height));

    velocity = new PVector(0, 0);
    
    // adds a random jitter factor to each worm to stop them clumping
    float l = random(1)/2; 
    float m = random(1)/2;
    jitter = new PVector(l,m);

    topspeed = 7;

  }

  void update() {

    PVector mouse = new PVector(mouseX, mouseY);

    PVector dir = PVector.sub(mouse, location);

    dir.normalize();

    // any key pressed will stop them following mouse, q,w,e have specific effects
    if (keyPressed) {
      if (key == 'q') {

      dir.mult(0.2);

    } else if (key == 'e') {

      dir.mult(1);

    } else if (key == 'w') {

      dir.mult(5);

    } else {

      dir.mult(0.000001);

    }
    }


    acceleration = dir;

    acceleration.add(jitter);
    
    velocity.add(acceleration);

    velocity.limit(topspeed);

    location.add(velocity);

  }

  void display() {

    stroke(location.x, location.y, location.y);

    fill(col);

    ellipse(holdX[0], holdY[0] , 20, 20);
  
  // generates the tail drawing
   for (int i=0; i<20; i++) {
    fill(col - i*(col/20));
    ellipse(holdX[i],holdY[i], 20-i,20-i); 
   } 
    
   // stores the current location and shifts previous locations down the tail
   for (int i=19; i>=1; i--) {
     holdX[i] = holdX[i - 1];   
     holdY[i] = holdY[i - 1];
   }
   holdX[0] = location.x;
   holdY[0] = location.y;

  }

  void checkEdges() {

    if ((location.x > width) || (location.x < 0)) {

      velocity.x = velocity.x * -1;

    } 

    if ((location.y > height) || (location.y < 0)) {

      velocity.y = velocity.y * -1;

    }

  }

}

day 17 - mouse-following psychedelic worm in Processing

Great work today! I managed to half figure-out how to do a proper echo effect in video using Processing. I had been cheating by having a rectangle with very low alpha value as the bottom layer, so when "void draw" runs there's always a shadow of the previous image left behind, essentially an echo effect. But this technique is very limiting. So I flexed my array muscles and got this together, creating an array that tracks the current position as [0] and continually shunts the previous 20 positions down the array, creating a tail. In this version I've also made the previous positions shrink and change colour, getting this pleasing psychedelic effect.

I say half figured-out because this works fine in grayscale but the colour implementation isn't quite a successful in making the transparency work. This is mainly because I'm being lazy and using "color" rather than just sending the RGBA values through as separate variables. I'd like to figure out how to manipulate the alpha in "color" separately.

So this version is a worm rather than an echo. Code below.



float x;
float y;
float easing = 0.05;

void setup() {
 size(400,400);
smooth();

}

float [] holdX = new float[20];
float [] holdY = new float[20];
color col = color(200,0,100,255);

void draw() {
  background(0);
  noStroke();
  fill(255);
  float targetX = mouseX;
  x += (targetX - x) * easing;
    float targetY = mouseY;
  y += (targetY - y) * easing;
 ellipse(x,y, 20, 20);
 for (int i=0; i<20; i++) {
   //fill((255-i*(255/20)), (255-i*(255/20)));
   fill(col - i*(col/20));
   ellipse(holdX[i],holdY[i], 20-i,20-i);
 }

 for (int i=19; i>=1; i--) {
   holdX[i] = holdX[i - 1];
   holdY[i] = holdY[i - 1];
 }
 holdX[0] = x;
 holdY[0] = y;
}

void mouseClicked() {
 for (int i=1; i<19; i++) {
   println(holdX[i]);
 }
}

Friday 17 September 2010

days 16

Today I went back to the books to do what I originally intended with my creativepact, to learn Processing properly. So I managed to plough through the first 71 pages of Getting started with Processing and filled in some serious knowledge gaps, as well as picking up some neat tricks in general coding, stuff that had stumped me before such as 'easing' to make response to mouse input less jerky. also got to understand 'for loops' a bit better.

so here's a few gifs of things I messed around with: hopefully these animate correctly, if not try downloading them... They don't seem to animate, oh well, you get the idea.

This is a grid (code) made from for-loop with randomised trace lines in the background and colour changes across the grid using the loop variables.





This is an inkpen-style mouse drawing (code) with timed colour changes, speed-linked width and time-linked colour changes.


Wednesday 15 September 2010

Day 15 - back to processing

I seem to be doing my best work hacking other people's code lately, so here's my minor alterations to Lee Freeman's bouncing balls. I've added some small changes to the balls' appearance over time.



I really wanted to make the balls path curve but that didn't turn out to be so easy, but I did make something kind mental instead, today I might try to work out why it's so bonkers. That code is below, after the normal code.


Variation on Lee's balls


Point[] myPoint = new Point[100];

void setup() {

 size(400, 400);

 for (int i= 0; i < myPoint.length; i++) {

myPoint[i] = new Point(0, 100, random(0.1, 2), random(0.1, 2));

 }

}

void draw() {

  background(mouseY, mouseY, mouseX);

  for (int i= 0; i < myPoint.length; i++) {

  myPoint[i].bounce();

  myPoint[i].display();

  }

}

class Point {

  color c;

  float xpos;

  float ypos;

  float xspeed;

  float yspeed;

  int[] bigs = {0, 5, 10, 15, 20, 15, 10, 5};

  int i;
  int t;

  Point(float tempXpos, float tempYpos, float tempXspeed, float tempYspeed) {

    xpos = tempXpos;

    ypos = tempYpos;

    xspeed = tempXspeed;

    yspeed = tempYspeed;

  }

  void display() {

    int k = (t*10) % 255;
    int l = abs(255-t*10);
    stroke(k, l);

    fill((10 + t*7)%255, (10 + t*11)%255, abs(255 - t*5), abs(255-t*10));

    smooth();

    ellipse(xpos, ypos, 10 + bigs[i], 10 + bigs[i]);

  }

  void bounce() {

    xpos = xpos + xspeed;

    if (xpos > width) {

      xspeed = xspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (xpos < 0) {

      xspeed = xspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }
    }

    ypos = ypos - yspeed;

    if (ypos > height) {

      yspeed = yspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (ypos < 0) {

      yspeed = yspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }
    
    }

  }

}


******************************************************

Bonkers but nice 


Point[] myPoint = new Point[100];

void setup() {

 size(400, 400);
 frameRate(20);

 for (int i= 0; i < myPoint.length; i++) {

myPoint[i] = new Point(0, 100, random(0.1, 2), random(0.1, 2));

 }

}

void draw() {

  background(mouseY, mouseY, mouseX);

  for (int i= 0; i < myPoint.length; i++) {

  myPoint[i].bounce();

  myPoint[i].display();

  }

}

class Point {

  color c;

  float xpos;

  float ypos;

  float xspeed;

  float yspeed;
  
  int[] bigs = {0, 5, 10, 15, 20, 15, 10, 5};
  
  int i;
  int t;
  
  Point(float tempXpos, float tempYpos, float tempXspeed, float tempYspeed) {

    xpos = tempXpos;

    ypos = tempYpos;

    xspeed = tempXspeed;

    yspeed = tempYspeed;

  }

  void display() {

    int k = (t*10) % 255;
    int l = abs(255-t*10);
    stroke(k, l);

    fill((10 + t*7)%255, (10 + t*11)%255, abs(255 - t*5), abs(255-t*10));

    smooth();

    ellipse(xpos, ypos, 10 + bigs[i], 10 + bigs[i]);

  }

  void bounce() {

    xpos = abs(10*(tan(xpos))) + xspeed;

    if (xpos > width) {

      xspeed = xspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (xpos < 0) {

      xspeed = xspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }
    }

    ypos = ypos - yspeed;

    if (ypos > height) {

      yspeed = yspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (ypos < 0) {

      yspeed = yspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }
      
    }

  }

}

Tuesday 14 September 2010

day 14 - a dip into HTML5

Being doing a lot of maxmsp lately for a contract, and not been putting it up here much for various reasons, but also completely fallen off the horse as regards my original Processing intentions.

But thanks to Sam Freeman's creativePact looking at HTML5 audio, I've solved a problem that stumped me six months ago when I was first looking at HTML5 audio (and I haven't been back there since).

I took Sam's sine wave generator and extended the envelopes so that Test is a reverse envelope, and Test1 is an A(D)SR envelope: fades in across 1/3 of the sample, sustains for 1/3, and fades out for 1/3.

test and test1