xxxxxxxxxx
final int N = 192; // number of mass
float T = 0.5; // tense
float rho = 0.1; // density of string
float d = 0.7; // distance of mass
int i=1;
boolean change=false,rainbow=false,changebow=false,Default=false;
float[][] p = new float[(int)(N*1.8)][N];
float[][] np = new float[(int)(N*1.8)][N]; // temporary value of p
float[][] dp = new float[(int)(N*1.8)][N]; // variation of p
Creature[] c;
float dt = 1.0/frameRate;
void setup() {
//fullScreen();
size(800,600);
smooth();
noCursor();
colorMode(HSB,360);
background(240,360,150);
for(int i=0;i<(int)(N*1.8);i++){
for(int j=0;j<N;j++){
p[i][j] = 0.0;
dp[i][j] = 0.0;
}
}
// /*
for(int i=0;i<200;i++){
float x=random(width);
float y=random(height);
if(x>=20 && x<= 4*(int)(N*1.8) + 20 && y>=20 && y<= 4*N + 20){
int n = round((x-20)/4);
int m = round((y-20)/4);
dp[n][m] = -1.0f;
}
}
// */
c = new Creature[0];
for (int a=0; a<15; a++) {
new Creature(new PVector(int(random(width)),int(random(height))), 10, 10, 11, 60, 12, 2 );
//start pos, x-dist between each tentacle start, y-dist between each tentacle start, num tentacles ,num segmentes per tentacle, tentacle start radius, compactness
}
}
void draw() {
calc();
float col = 0f;
for(int i=0;i<(int)(N*1.8);i++){
for(int j=0;j<N;j++){
col = p[i][j]*50+240;
fill(240,360,360-col);
rect(i*4,j*4,4,4);
}
}
for (int a=0; a<c.length; a++) {
c[a].update();
c[a].draw();
}
}
void mouseClicked(){
if((mouseButton == RIGHT)){
if(i>3){
i=0;
}
if(i==0){
if(changebow==true)changebow=(!changebow);
Default=(!Default);
}
if(i==1){
if(Default==true)Default=(!Default);
rainbow=(!rainbow);
}
if(i==2){
if(rainbow==true)rainbow=(!rainbow);
change=(!change);
}
if(i==3){
if(change==true)change=(!change);
changebow=(!changebow);
}
i++;
}
}
// From Robert Penner's easing equations
static class Penner {
// time, beginning position, change in position, and duration
static float easeInOutExpo(float t, float b, float c, float d) {
if (t==0) return b;
if (t==d) return b+c;
if ((t/=d/2) < 1) return c/2 * pow(2, 10 * (t - 1)) + b;
return c/2 * (-pow(2, -10 * --t) + 2) + b;
}
};
class TentaclePart {
PVector position;
float width;
float height;
color clr;
};
class Tentacle {
PVector position;
float orientation;
float angularVelocity;
int nbParts;
float compactness;
ArrayList<TentaclePart> parts;
Tentacle(PVector pos, int nb, float w, float h, float o, float c) {
position = pos;
nbParts = nb;
float headWidth = w;
float headHeight = h;
compactness = c;
orientation = o;
angularVelocity = 0;
parts = new ArrayList<TentaclePart>();
float coul = 360.0/(nbParts);
for (int i = 0; i < nbParts; i++) {
TentaclePart part = new TentaclePart();
part.width = (nbParts-i) * headWidth / (float)nbParts;
part.height = (nbParts-i) * headHeight / (float)nbParts;
part.position = position.get();
part.position.x += compactness * i * cos(orientation);
part.position.y += compactness * i * sin(orientation);
parts.add(part);
}
}
void update() {
PVector pos0 = parts.get(0).position;
PVector pos1 = parts.get(1).position;
pos0.set(position.get());
pos1.x = pos0.x + ( compactness * cos(orientation));
pos1.y = pos0.y + ( compactness * sin(orientation));
float coul=360.0/(nbParts);
for (int i = 2; i < nbParts; i++) {
PVector currentPos = parts.get(i).position.get();
PVector dist = PVector.sub( currentPos, parts.get(i-2).position.get() );
float distmag = dist.mag();
PVector pos = parts.get(i - 1).position.get();
PVector move = PVector.mult(dist, compactness);
move.div(distmag);
pos.add(move);
parts.get(i).position.set(pos);
if(rainbow==true || change==true || changebow==true){
if(rainbow==true){
parts.get(i).clr = color(coul*i,360,250); // rainbow ones
}
if(change==true){
parts.get(i).clr = color(frameCount%360,360,250); // ones that change color over time
}
if(changebow==true){
parts.get(i).clr = color(((frameCount+(coul*i))%360),360,250); // rainbow ones that change color over time
}
}
else parts.get(i).clr = color(0,0,200); // original white
}
for(int i=0;i<2;i++){
if(rainbow==true || change==true || changebow==true){
if(rainbow==true){
parts.get(i).clr = color(coul*i,360,250); // rainbow ones
}
if(change==true){
parts.get(i).clr = color(frameCount%360,360,250); // ones that change color over time
}
if(changebow==true){
parts.get(i).clr = color(((frameCount+(coul*i))%360),360,250); // rainbow ones that change color over time
}
}
else parts.get(i).clr = color(0,0,200); // original white
}
}
void draw() {
for (int i = nbParts - 1; i >= 0; i--) {
TentaclePart part = parts.get(i);
noStroke();
fill(part.clr,75);
ellipse(part.position.x, part.position.y, part.width, part.height);
}
}
};
class Creature {
PVector position;
float radX, radY;
float orientation;
ArrayList<Tentacle> tentacles;
int nbTentacles;
int tentaclesLength;
int moveTime;
int moveDuration;
PVector dest;
PVector lastPos;
float moveDistance;
boolean reachedDest;
Creature(PVector pos, float rx, float ry, int nb, int l, float ts, float td) {
position = pos;
radX = rx;
radY = ry;
orientation = 0;
nbTentacles = nb;
tentaclesLength = l;
tentacles = new ArrayList<Tentacle>();
dest = new PVector(random(-1, 1), random(-1, 1));
dest.mult(moveDistance);
lastPos = position.get();
moveDuration = int(random(90, 130));
moveDistance = random(400, 500);
reachedDest = true;
moveTime = 0;
for (int i = 0; i < nbTentacles; i++) {
float tx = position.x + (cos(i * TWO_PI / nbTentacles) * radX/2);
float ty = position.y + (sin(i * TWO_PI / nbTentacles) * radY/2);
float tr = atan2(ty - position.y, tx - position.x);
Tentacle tentacle = new Tentacle(new PVector(tx, ty), tentaclesLength, ts, ts, tr, td);
tentacles.add(tentacle);
}
c = (Creature[]) append(c, this);
}
void update() {
for (int i = 0; i < nbTentacles; i++) {
Tentacle t = tentacles.get(i);
t.position.x = position.x + (cos((i * TWO_PI / nbTentacles) + orientation) * radX/2);
t.position.y = position.y + (sin((i * TWO_PI / nbTentacles) + orientation) * radY/2);
t.orientation = atan2((t.position.y - position.y), (t.position.x - position.x));
t.update();
}
if (reachedDest) {
lastPos = position.get();
dest = new PVector(random(-1, 1), random(-1, 1));
dest.normalize();
dest.mult(moveDistance);
PVector nextPos = PVector.add(position, dest);
if (nextPos.x > width)
dest.x = -abs(dest.x);
else if (nextPos.x < 0)
dest.x = abs(dest.x);
if (nextPos.y > height)
dest.y = -abs(dest.y);
else if (nextPos.y < 0)
dest.y = abs(dest.y);
reachedDest = false;
moveTime = 0;
if(position.x>=20 && position.x<= 4*(int)(N*1.8) + 20 && position.y>=20 && position.y<= 4*N + 20){
int n = round((position.x-20)/4);
int m = round((position.y-20)/4);
dp[n][m] = -1.0f;
}
} else {
position.x = Penner.easeInOutExpo(moveTime, lastPos.x, dest.x, moveDuration);
position.y = Penner.easeInOutExpo(moveTime, lastPos.y, dest.y, moveDuration);
moveTime++;
if (moveTime >= moveDuration)
reachedDest = true;
}
orientation += random(-3, 3) * radians(.1);
}
void draw() {
for (int i = 0; i < nbTentacles; i++)
tentacles.get(i).draw();
}
};
void calc(){
float _dm = 1.0/(rho*d*d);
for(int i=1;i<(int)(N*1.8)-1;i++){
for(int j=1;j<N-1;j++){
// wave equation
dp[i][j] = dp[i][j] + (T/(d*d)*(p[i+1][j] + p[i][j+1] -4*p[i][j] + p[i-1][j] + p[i][j-1]))*_dm*dt*dt;
np[i][j] = p[i][j] + dp[i][j];
// boundary condition
p[0][j] = 0.0;
p[(int)(N*1.8)-1][j] = 0.0;
p[i][0] = 0.0;
p[i][N-1] = 0.0;
}
}
for(int i=0;i<(int)(N*1.8);i++){
for(int j=0;j<N;j++){
p[i][j] = np[i][j];
}
}
}