fullscreen
Food.pdeLeg.pdeRipple.pdeoctopus5TextWithRipple_3d.pde
class Food {
PVector pos,vel;
float quantity,a,b,c,angle,BoWa,speed;
String textFood;
char[] letters;
boolean consumed=false;
int g,co;
float d0=10;
float d1=sqrt(sq(d0)+sq(3.3));
float d2=sqrt(sq(2*d0)+sq(3.3));
float d3=sqrt(sq(3*d0)+sq(2));
float an1=atan2(3.3,d1);
float an2=atan2(3.3,d2);
float an3=atan2(2,d3);
Food(String _text, float _x,float _y,float _z) {
pos = new PVector(_x,_y,_z);
textFood = _text;
quantity =(float)textFood.length()/2;
letters = textFood.toCharArray();
pos = new PVector(random(width),random(height),random(-500,500));
vel = new PVector();
vel.normalize();
co = int(random(20,70));
a = random(0,1);
b = random(1,10);
}
void display() {
if (!consumed) {
move();
ff.pushMatrix();
ff.noStroke();
ff.fill(255,100);
ff.translate(pos.x,pos.y,pos.z);
rotateY(atan2(-vel.z,vel.x));
rotateZ(acos(vel.y/vel.mag()));
ff.textFont(font);
ff.textAlign(CENTER);
//ff.textMode(SCREEN);
ff.textSize(10);
drawBody();
//ff.hint(ENABLE_ACCURATE_TEXTURES);
//ff.text(textFood,0,-6);
//ff.box(quantity);
ff.popMatrix();
}
}
void move() {
// movement
a += .005;
b += .035;
if (random(10)>9.5) {
speed = 5*noise(b)/random(0.1,5);
//if (random(10)>7)
} else {
speed = noise(b)*5;
}
vel.add(random(-0.05,0.05),random(-0.05,0.05),random(-0.05,0.05));
vel.normalize();
vel.mult(speed);
pos.add(vel);
//boundary
if (pos.x>width+50) pos.x=-50;
if (pos.x<-50) pos.x= width+50;
if (pos.y>height+50) pos.y =-50;
if (pos.y<-50) pos.y =height+50;
if (pos.z>500) pos.z =-500;
if (pos.z<-500) pos.z =500;
//Fish wave the body according to its speed
c += 0.1*speed;
BoWa=sin(c)*PI/15;
}
void drawBody() {
for (g=0;g<letters.length; g++) {
ff.translate(6,0);
//ff.translate(textWidth(letters[g]),0);
ff.rotate(BoWa/8);
ff.textSize(8);
ff.text(letters[g],0,0);
}
}
}
//every leg is a strand of three lines
class Leg {
int jointsNum = 10;
int counter,life;
PVector[][] joints = new PVector[jointsNum][3];
PVector initia,driver,target,ankle;
float driverAngle,randomness,rotation,angle,O,Oangle;
float speed =100;
float[] armLength= new float[3];
Leg(float xin, float yin, float zin, float _rotation, float _randomness, int _partNum, int _counter) {
for (int i=0; i<jointsNum; i++) {
for (int g= 0; g<3;g++) {
joints[i][g] = new PVector(0,0,0);
}
}
for (int g= 0; g<3;g++) {
armLength[g] = random(9,12);
}
counter= _counter;
angle = counter*TWO_PI/_partNum;
initia = new PVector(xin,yin,zin);
driver = new PVector(xin,yin,zin);
target = new PVector(xin,yin,zin);
rotation = _rotation;
randomness = _randomness;
}
void drawLeg(PVector _target, float _speed) {
//pushMatrix();
//rotate(rotation);
//driver.add(noise(-0.5,0.5),noise(-0.5,0.5),noise(-0.5,0.5));
target= _target;
speed = _speed;
//Oangle+=0.1;
//O=6*cos(Oangle)*cos(Oangle);
/*
initia.x += (target.x-initia.x)/100;
initia.y += (target.y-initia.y)/100;
initia.z += (target.z-initia.z)/100;
*/
//if (random(10)>9.8) target.set(random(width),random(height),random(800));
driver.x += (target.x-driver.x)/speed;
driver.y += (target.y-driver.y)/speed;
driver.z += (target.z-driver.z)/speed;
//float heading = PVector.angleBetween(driver,initia);
initia=driver.get();
//O--;
//if (O<2) O=10;
if (PVector.dist(driver,target)>30) {
Oangle+=0.1;
O=0.8*cos(Oangle)+0.2;
driver.add(O*cos(angle),O*sin(angle),0);
}
//driverAngle += noise(randomness);
//driver.add(5*cos(driverAngle),5*sin(driverAngle),0);
for (int g= 0; g<3;g++) {
joints[0][g]=driver.get();
}
for (int g= 0; g<3;g++) {
ff.noFill();
//stroke(255, 102, 180);
//strokeWeight(1);
/*
line(initia.x, initia.y, initia.z,
joints[0][g].x,joints[0][g].y,joints[0][g].z);
line(joints[0][g].x,joints[0][g].y,joints[0][g].z,
joints[0][g].x,joints[0][g].y+20,joints[0][g].z);
*/
//stroke(0, 0, 0);
ff.pushMatrix();
ff.stroke(255,10);
ff.point(initia.x, initia.y, initia.z);
//point(joints[0][g].x,joints[0][g].y,joints[0][g].z);
ff.stroke(255,40);
ff.line(initia.x, initia.y, initia.z, joints[0][g].x,joints[0][g].y,joints[0][g].z);
/*
translate(initia.x, initia.y, initia.z);
rotateZ(angle);
bezier(0, 0, 30,
-10, -30, 30,
O*cos(angle)+10,O*sin(angle)+30,0,
O*cos(angle),O*sin(angle),0);
*/
/*
bezier(initia.x, initia.y, initia.z,
initia.x+100, initia.y+100, initia.z,
joints[0][g].x-100,joints[0][g].y-30,joints[0][g].z,
joints[0][g].x,joints[0][g].y,joints[0][g].z);
*/
ff.popMatrix();
ff.beginShape();
ff.noFill();
ff.stroke(255,10);
ff.strokeWeight(2);
//point(joints[0].x,joints[0].y,joints[0].z);
ff.curveVertex(joints[0][g].x,joints[0][g].y,joints[0][g].z);
//vertex(joints[0].x,joints[0].y,joints[0].z);
for (int i=1; i<jointsNum; i++) {
float angleZ = atan2(joints[i][g].y-joints[i-1][g].y,joints[i][g].x-joints[i-1][g].x);
float angleY = atan2(joints[i][g].z-joints[i-1][g].z,joints[i][g].x-joints[i-1][g].x);
float angleX = atan2(joints[i][g].y-joints[i-1][g].y,joints[i][g].z-joints[i-1][g].z);
joints[i][g].x = joints[i-1][g].x + armLength[g]*cos(angleZ);
joints[i][g].y = joints[i-1][g].y + armLength[g]*sin(angleZ);
joints[i][g].z = joints[i-1][g].z + armLength[g]*cos(angleX);
//line(joints[i].x,joints[i].y,joints[i].z,joints[i-1].x,joints[i-1].y,joints[i-1].z);
//point(joints[i].x+random(-i*0.3,i*0.3),joints[i].y+random(-i*0.3,i*0.3),joints[i].z);
//if (random(1)>0.2)
ff.curveVertex(joints[i][g].x+random(-i*0.3,i*0.3),joints[i][g].y+random(-i*0.3,i*0.3),joints[i][g].z);
}
ff.endShape();
}
}
}
class Ripple {
int i, a, b;
int oldind, newind, mapind;
short ripplemap[]; // the height map
int col[]; // the actual pixels
int riprad;
int rwidth, rheight;
int ttexture[];
int ssize;
Ripple() {
// constructor
riprad = 3;
rwidth = width >> 1;
rheight = height >> 1;
ssize = width * (height + 2) * 2;
ripplemap = new short[ssize];
col = new int[width * height];
ttexture = new int[width * height];
oldind = width;
newind = width * (height + 3);
}
void newframe() {
// update the height map and the image
i = oldind;
oldind = newind;
newind = i;
i = 0;
mapind = oldind;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
short data = (short)((ripplemap[mapind - width] + ripplemap[mapind + width] +
ripplemap[mapind - 1] + ripplemap[mapind + 1]) >> 1);
data -= ripplemap[newind + i];
data -= data >> 5;
if (x == 0 || y == 0) // avoid the wraparound effect
ripplemap[newind + i] = 0;
else
ripplemap[newind + i] = data;
// where data = 0 then still, where data > 0 then wave
data = (short)(1024 - data);
// offsets
a = ((x - rwidth) * data / 1024) + rwidth;
b = ((y - rheight) * data / 1024) + rheight;
//bounds check
if (a >= width)
a = width - 1;
if (a < 0)
a = 0;
if (b >= height)
b = height-1;
if (b < 0)
b=0;
col[i] = ff.pixels[a + (b * width)];
mapind++;
i++;
}
}
}
}
void mouseDragged() {
hit(mouseX,mouseY);
foodNum++;
food[foodNum-1] =new Food("New food!!!", mouseX, mouseY,random(-500,500));
}
void hit(float _foodX, float _foodY) {
int foodX =(int)_foodX;
int foodY = (int)_foodY;
for (int j = foodY - ripple.riprad; j < foodY + ripple.riprad; j++) {
for (int k = foodX - ripple.riprad; k < foodX + ripple.riprad; k++) {
if (j >= 0 && j < height && k>= 0 && k < width) {
ripple.ripplemap[ripple.oldind + (j * width) + k] += 512;
}
}
}
}
//import processing.opengl.*;
int legNum=6;
int partNum=18;
Leg[][] leg = new Leg[legNum][partNum];
PVector[] Target = new PVector[legNum];
float[] speed = new float[legNum];
PFont font;
Food[] food = new Food[1000];
int foodNum = 90;
int foodCounter;
PGraphics ff;
Ripple ripple;
void setup() {
size(800,600,P3D);
ff= createGraphics(width,height,P3D);
ff.smooth();
ff.fill(255, 100);
font = createFont("arial",100,true);
ff.textFont(font);
ff.textAlign(CENTER);
//initiate food
for (int i=0; i<foodNum; i++) {
food[i] = new Food("This is food",random(width),random(height),random(-500,500));
}
//initiate the creature
for (int i=0; i<legNum; i++) {
float x = random(width);
float y = random(height);
for (int g=0; g<partNum;g++){
float angle = g*TWO_PI/partNum;
leg[i][g]= new Leg(x,y,300,i*TWO_PI/legNum,0.1+i*0.5, partNum, g);
//leg[i][g]= new Leg(x+30*cos(angle),y+30*sin(angle),300,i*TWO_PI/legNum,0.1+i*0.5, partNum, g);
Target[i] = new PVector();
speed[i] = 100;
}
}
ripple = new Ripple();
frameRate(30);
}
void draw() {
ff.beginDraw();
ff.background(0);
//background(0);
//display food
foodCounter=0;
for (int i=0;i<food.length; i++) {
if (food[i]!= null && !food[i].consumed) {
food[i].display();
foodCounter++;
}
}
println("There is "+foodCounter+" pieces of food left.");
//display creature
for (int i=0; i<legNum; i++) {
float randomNumber =random(10);
if (randomNumber>9.8 && randomNumber <=9.9) Target[i].set(random(width),random(height),random(-800,800));
if (randomNumber>9.9) {
int iWantFood = (int)random(foodNum);
if (food[i]!= null && !food[i].consumed)
Target[i].set(food[iWantFood].pos.x,food[iWantFood].pos.y,food[iWantFood].pos.z);
}
speed[i] +=0.05;
for (int g=0; g<partNum;g++){
leg[i][g].drawLeg(Target[i],speed[i]);
}
//eat!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
for (int j =0; j<foodNum; j++) {
float d = PVector.dist(food[j].pos,leg[i][0].initia);
if (d<50) {
food[j].consumed =true;
leg[i][0].life++;
hit(food[j].pos.x,food[j].pos.y);
if(speed[i]>21) speed[i] -=10;
}
}
}
ff.endDraw();
loadPixels();
ff.loadPixels();
for (int loc = 0; loc < width * height; loc++) {
pixels[loc] = ripple.col[loc];
}
updatePixels();
ripple.newframe();
}
void cameraLight() {
//camera(width/2,height/2,850, 450,0,-30, 0,0,-0.5);
/*
// Orange point light on the right
pointLight(255, 255, 255, // Color
200, -150, 0); // Position
// Blue directional light from the left
directionalLight(0, 102, 255, // Color
1, 0, 0); // The x-, y-, z-axis direction
// Yellow spotlight from the front
spotLight(255, 255, 109, // Color
0, 40, 200, // Position
0, -0.5, -0.5, // Direction
PI / 2, 2); // Angle, concentration
*/
}