xxxxxxxxxx
ArrayList<Chain> chains;
float R, r;
Boolean pressed = false;
PVector[] palette;
final PVector[][] tints = {
{
new PVector(0, 80), new PVector(30, 205), new PVector(75, 224)//blue
}
,
{
new PVector(150, 250), new PVector(12, 190), new PVector(120, 208)//pink
}
,
{
new PVector(15, 41), new PVector(30, 95), new PVector(20, 72)//green
}
,
{
new PVector(255, 255), new PVector(0, 193), new PVector(0, 0)//red-orange
}
,
{
new PVector(0, 255), new PVector(0, 255), new PVector(0, 255)//b&w
}
};
void setup() {
size(450, 350);
initialize();
}
void initialize() {
chains = new ArrayList<Chain>();
R = random(15, 120);
r = sqrt(3) * R / 2;
palette = tints[(int)random(tints.length - 1)];
}
void draw() {
background(255);
if (pressed) {
int rx = round(mouseX / r);
int ry = round(mouseY / R);
Boolean bx = rx % 2 == 0;
Boolean by = ry % 2 == 0;
float x = rx * r;
float y = (ry - (bx ? 0 : .5)) * R;
chains.add(new Chain(x, y, bx != by));
}
ArrayList<Chain> chainsToRemove = new ArrayList<Chain>();
for (Chain c : chains) {
if (c.display())
chainsToRemove.add(c);
}
for (Chain c : chainsToRemove) {
chains.remove(c);
}
}
void mousePressed() {
pressed = true;
}
void mouseReleased() {
pressed = false;
}
void keyPressed() {
initialize();
}
class Chain {
ArrayList<Triangl> triangls;
float beta;
int age, ageMax = (int)random(500, 2000), col;
PVector o;
Chain(float x, float y, Boolean rot) {
float cc = random(1);
col = color(map(cc, 0, 1, palette[0].x, palette[0].y), map(cc, 0, 1, palette[1].x, palette[1].y), map(cc, 0, 1, palette[2].x, palette[2].y));
o = new PVector(x, y);
triangls = new ArrayList<Triangl>();
triangls.add(new Triangl(null, null, null, x, y, random(6, 14), (int)random(180, 400)));
if (rot)
beta = TWO_PI / 3;
else
beta = 0;
}
Boolean display() {
age++;
pushMatrix();
translate(o.x, o.y);
rotate(beta);
translate(-o.x, -o.y);
Triangl toAdd = null, toRemove = null;
for (Triangl t : triangls) {
Triangl[] toManage = t.display(col);
if (toManage[0] != null)
toAdd = toManage[0];
if (toManage[1] != null)
toRemove = toManage[1];
}
if (toAdd != null) {
toAdd.last = age >= ageMax;//check if triangl is the last one for this chain
triangls.add(toAdd);
}
if (toRemove != null) {
triangls.remove(toRemove);
}
popMatrix();
return triangls.size() == 0;
}
}
class Triangl {
Boolean isMoving = true, last = false;
PVector A, B, C, D, M, w;
float theta = 0, speed;
int life = 0, maxLife;
Triangl(PVector pA, PVector pB, PVector pC, float x, float y, float s, int l) {
speed = s;
maxLife = l;
if (pA == null) {//first triangl
A = new PVector(x+2*r/3, y);
B = new PVector(x+2*r*cos(TWO_PI/3)/3, y+2*r*sin(TWO_PI/3)/3);
C = new PVector(x+2*r*cos(-TWO_PI/3)/3, y+2*r*sin(-TWO_PI/3)/3);
} else {
A = pA;
B = pB;
C = pC;
}
D = A.get();
M = new PVector((B.x+C.x)/2, (B.y+C.y)/2);//middle of [BC]
w = A.get();
w.sub(M);//vector MA
}
Triangl[] display(color c) {
Triangl[] toDealWith = new Triangl[2];//
if (constrain(life ++, 0, maxLife) < maxLife) {
float op = map(life, 0, maxLife, 255, 0);
beginShape(TRIANGLES);
fill(c, op);
stroke(20, op);
vertex(A.x, A.y, 0);
vertex(B.x, B.y, 0);
vertex(C.x, C.y, 0);
if (!last && theta < PI) {
theta += (PI - theta) / speed;
D.x = cos(theta) * w.x;
D.y = cos(theta) * w.y;
D.z = r * sin(theta);
D.add(M);
vertex(B.x, B.y, 0);
vertex(C.x, C.y, 0);
vertex(D.x, D.y, D.z);
if (theta >= .99 * PI) {
theta = 45;
float rand = random(1);
if (rand > .5)
toDealWith[0] = new Triangl(B, C, D, 0, 0, speed, maxLife);//triangl to add
else
toDealWith[0] = new Triangl(B, D, C, 0, 0, speed, maxLife);//triangl to add
}
}
endShape();
} else {
toDealWith[1] = this;//remove the current triangl
}
return toDealWith;
}
}