Wednesday 26 August 2009

Example program



Here's a small program that shows some bouncing balls interacting with each other, changing colour when they collide with another ball, to become either lighter or darker.

I've re-used an existing example that comes with processing, the BouncyBubbles program (found in the Examples menu under Topics/Motion).


/**
* Bouncy Bubbles.
* Based on code from Keith Peters (www.bit-101.com).
*
* Multiple-object collision.

* Ammended by Richard Brown to add color routines
*/


int numBalls = 20;
float spring = 0.05;
float gravity = 0.03;
float friction = -0.9;
Ball[] balls = new Ball[numBalls];

void setup()
{
size(640, 200);
noStroke();
smooth();
for (int i = 0; i < numBalls; i++) {
balls[i] = new Ball(random(width), random(height), random(20, 40), i, balls);
}
}

void draw()
{
background(128);
for (int i = 0; i < numBalls; i++) {
balls[i].collide();
balls[i].move();
balls[i].display();
}
}

class Ball {
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
int brighten=0;

Ball[] others;
color ourColor;
color colorArray[]={
color(255,0,0),
color(0,255,0),
color(0,0,255),
color(240,150,40)
};

Ball(float xin, float yin, float din, int idin, Ball[] oin) {
x = xin;
y = yin;
if (random(1)>0.5)
brighten = 1;
else
brighten = 0;
diameter = din;
id = idin;
others = oin;
int numberOfColors=colorArray.length;
ourColor=colorArray[int(random(numberOfColors))];
}

void collide() {
for (int i = id + 1; i < numBalls; i++) {
Ball ball=others[i];
float dx = others[i].x - x;
float dy = others[i].y - y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = others[i].diameter/2 + diameter/2;
if (distance < minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX - others[i].x) * spring;
float ay = (targetY - others[i].y) * spring;
vx -= ax;
vy -= ay;
others[i].vx += ax;
others[i].vy += ay;
ourColor=lerpColor(ourColor,others[i].ourColor,0.1);
if (brighten==1)
// brighten the other ball by 10%
ball.ourColor=brightenColor(ball.ourColor,1.1);
else
// darken the ball
ball.ourColor=brightenColor(ball.ourColor,0.9);
}
}
}

void move() {
vy += gravity;
x += vx;
y += vy;
if (x + diameter/2 > width) {
x = width - diameter/2;
vx *= friction;
}
else if (x - diameter/2 < 0) {
x = diameter/2;
vx *= friction;
}
if (y + diameter/2 > height) {
y = height - diameter/2;
vy *= friction;
}
else if (y - diameter/2 < 0) {
y = diameter/2;
vy *= friction;
}
}

void display() {
fill(ourColor);
ellipse(x, y, diameter, diameter);
}
}

int brightenElement(float element,float percentage)
{
element=(element*percentage);
if (element>255)
element=255;
return (int)element;
}

// brightenColor
// brightens a colour by a percentage
// percentage should be a float e.g. 1.10 to
// brighten by 10%, or 0.75 to darken by 25%
// returns the new colour
color brightenColor(color c,float percentage)
{
int r=brightenElement(red(c),percentage);
int g=brightenElement(green(c),percentage);
int b=brightenElement(blue(c),percentage);
return color(r,g,b);
}

Sunday 23 August 2009

Extra colour functions

A range of extra functions are available to provide information about colours.
red(), green() and blue() provide access to the individual components of a colour.

These functions return float values, which makes them quite slow in practice.

This code snippet shows a method of brightening a colour by accessing the components:


// brightenColour
// an example showing basic colour manipulation
// using red(), green() and blue()

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

void draw()
{
int h=100;
int y=0;
color c = color(230,185,80);
for (int i=0; i<4; i++) {
fill(c);
rect(0,y,width,y+h);
c=brightenColor(c,1.10); // brighten the colour by 10%
y+=h;
}
}

int brightenElement(float element,float percentage)
{
element=(element*percentage);
if (element>255)
element=255;
return (int)element;
}

// brightenColor
// brightens a colour by a percentage
// percentage should be a float e.g. 1.10 to
// brighten by 10%, or 0.75 to darken by 25%
// returns the new colour
color brightenColor(color c,float percentage)
{
int r=brightenElement(red(c),percentage);
int g=brightenElement(green(c),percentage);
int b=brightenElement(blue(c),percentage);
return color(r,g,b);
}

Tuesday 18 August 2009

lerpColor

The oddly named lerpColor provides another colour function. Lerp is short for linear interpolation, a simple means of finding values between a start and end position.

Here's a small program snippet which draws a series of decreasing squares, gradually changing from the first colour (in this case red) to the second (orange):


// lerpColor() example program
size(400, 400);
noStroke();
// set the two colours to draw a gradient between
color red = color(255,0,0);
color orange = color(240,150,40);
// choose the number of steps - the more the smoother the gradient
int number_of_steps=50;
float percentage_per_step = 1.0 / number_of_steps;
for (int i=0; i<number_of_steps; i++) {
fill(lerpColor(red,orange,percentage_per_step*i));
int border=i*((height/2)/number_of_steps);
rect(border,border,width-border-border,height-border-border);
}