> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.ilSY-PEYCFx/rev.3161
 * 
 * authors: 
 *   Tiou Lims

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



class Android{
    final static float SCALE = 100f / (78 + 183 + 9 + 100);
    final static float D_P_XF = (16 * SCALE); //0
    final static float D_P_AB = (9 * SCALE);//1
    final static float D_P_HB = (9 * SCALE);//2
    final static float D_F_W = (49 * SCALE);//3
    final static float D_F_H = (78 * SCALE);//4
    final static float D_B_W = (108 * SCALE);//5
    final static float D_B_H = (183 * SCALE);//6
    final static float D_A_W = (48 * SCALE);//7
    final static float D_A_H = (146 * SCALE);//8
    final static float D_H_W = (108 * SCALE);//9
    final static float D_H_H = (100 * SCALE);//10
    final static float D_E_R = (10 * SCALE);//11
    final static float D_T_D = 60 ; //角度 0~PI/2  逆时针 //12
    final static float D_T_W = (18 * SCALE);//13
    final static float D_T_H = (37 * SCALE);//14
    final static float D_H = D_F_H + D_B_H  + D_P_HB + D_H_H;
    final static float D_W = D_B_W + D_P_AB + D_A_W ;
    
final static float[] D_V = {
    D_P_XF,
D_P_AB,
D_P_HB,
D_F_W,
D_F_H,
D_B_W,
D_B_H,
D_A_W,
D_A_H,
D_H_W,
D_H_H,
D_E_R,
D_T_D,
D_T_W,
D_T_H,
D_H  ,
D_W  
    };
    final static int ret = 12;
    float free [] ;
    
    Rect rF, rB, rA,rH ,rE,rT,rS;
    class Rect {
        /**
         * 笛卡尔坐标系
         * 
         * 
         */
        protected float l, t, r, b;
        
        public Rect() {
        }
        
        public void reBound(float x, float y, float w, float h) {
            
            this.l = x;
            this.t = (y + h);
            this.r = x + w;
            this.b = y;
            
        }
        void draw(){
            rect(l,t,r-l,b-t);
        }        
    }
    class Arm extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                pushMatrix(); 
                float w = r-l;
                float h = b-t;
                translate(l+w/2,b-h/2);
                rrect(w,-h,{w/2,w/2,w/2,w/2},ret);
                popMatrix(); 
            }
     }
     class Foot extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                pushMatrix(); 
                float w = r-l;
                float h = b-t;
                translate(l+w/2,b-h/2);
                rrect(w,-h,{w/2,w/2,0,0},ret);
                popMatrix(); 
            }
     }
     class Body extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                float w = r-l;
                float h = b-t;
                float dr = r -rF.r;
                float ra = dr>w/8?w/8:dr<0?0:dr;
                
                pushMatrix(); 
                translate(l+w/2,b-h/2);
                rrect(w,-h,{0,ra,0,0},ret);
                popMatrix(); 
                /*pushStyle();
                noFill();
                stroke(#000000);
                strokeWeight(1);
                rect(l,t,r-l,b-t);
                popStyle();*/
            }
     }
     class Head extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                float w = (r-l)*2;
                float h = -(b-t)*2;
                //rect(l,b,w,h);
                arc(l, b, w, h, 0, HALF_PI);
            }
     }
     class Eye extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                float w = (r-l);
                float h = (t-b);
                ellipse(l+w/2, t-h/2, w+2, h+2);
                pushStyle();
                fill(#FFFFFF);
                ellipse(l+w/2, t-h/2, w, h);
                popStyle();
                
            }
     }
    class Antenna extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                pushStyle();
                stroke(c);
                strokeWeight(2);
                line(l,b,r,t);
                popStyle();
                
            }
     }
     class Shadow extends Rect{
            void draw(){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                float w = (r-l);
                float h = (b-t);
                pushStyle();
                fill(c,51);
                arc(l, t+h/2, w*2, h, PI+HALF_PI,TWO_PI+HALF_PI);
                popStyle();
                
            }
     }
    void regen(float []v){
       
regen_d(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]);
        
    }
    Android(float []v){
        init();
        regen(v);
    }
    float s ;
    void init() {
        if(width < height){
            s =   (float) (width /( D_W *2 *1.5)); 
        }else{
            s = (float) (height / (D_H  * 1.8));
        }
        rF = new Foot();
        rB = new Body();
        rH = new Head();
        rA = new Arm();
        rE = new Eye();
        rT = new Antenna();
        rS = new Shadow();
    }
    private void regen_d(float l_p_xf, float l_p_ab, float l_p_hb,
            float l_f_w,float l_f_h,
            float l_b_w, float l_b_h,
            float l_a_w, float l_a_h,
            float l_h_w, float l_h_h, 
            float l_e_r,
            float l_t_d,float l_t_w,float l_t_h ) {
        
        float p_xf = l_p_xf;
        float p_ab = l_p_ab;
        float p_hb = l_p_hb;
        float f_x = p_xf;
        float f_y = 0;
        float f_w = l_f_w;
        float f_h = l_f_h;
        rF.reBound(f_x, f_y, f_w, f_h);
        float b_x = 0;
        float b_y = rF.t;
        float b_w = l_b_w;
        float b_h = l_b_h;
        rB.reBound(b_x, b_y, b_w, b_h);
        float a_x = rB.r + p_ab;
        float a_w = l_a_w;
        float a_h = l_a_h;
        float a_y = rB.t - a_h;
        rA.reBound(a_x, a_y, a_w, a_h);
        float h_x = 0;
        float h_y = rB.t + p_hb;
        float h_w = l_h_w;
        float h_h = l_h_h;
        rH.reBound(h_x, h_y, h_w, h_h);
        
        float e_r = l_e_r;
        float e_x = h_x + h_w/3;
        float e_y = h_y + h_h/2;
        float e_h = l_e_r*2;
        float e_w = l_e_r*2;
        rE.reBound(e_x, e_y, e_w, e_h);
    
        float t_x = h_x+(float) (h_w* Math.cos(l_t_d*Math.PI/180));
        float t_y = h_y+(float) (h_h* Math.sin(l_t_d*Math.PI/180));
        float t_w = l_t_w;
        float t_h = l_t_h;
        rT.reBound(t_x, t_y, t_w, t_h);
        float s_x = 0;
        
        float s_w = b_w + a_w;
        float s_h = s_w/3;
        float s_y = f_y - s_h/2; 
        rS.reBound(s_x, s_y, s_w, s_h);
        
        free =new float[] {p_xf, p_ab, p_hb, f_w, f_h, b_w, b_h, a_w, a_h, h_w, h_h, e_r, t_x, t_w,t_h};
        
    }
    static float[] rand(){
        float min = 0.5f;
        float max = 1.5f;
        
        float tall = roll(D_H,min,max);
        int n1= random(1,7);
        int n2 = random(1,9-n1); 
        float lf_h = tall * n1 /10;
        float lb_h = tall * n2 /10;
        float lh_h = tall -lf_h-lb_h;
        
        float lb_w = roll(D_B_W,min,max);
        float lh_w = roll(D_H_W,0.2f,1.5f);
        n1= random(1,7);
        n2 = random(1,10-n1);
        float lp_xf = lb_w * n1 /10;
        float lf_w = lb_w * n2 /10;
        
        float la_w = roll(D_A_W,0.2f,1.5f);
        float la_h = roll(lf_h+lb_h,0.2f,1.0f);
        float lp_ab = D_P_AB;
        float  lp_hb = D_P_HB;
        
        float le_r = D_E_R;
        
        float lt_x = random(20,80);
        float lt_w = roll(D_T_W,0.5f,1.5f);
        float lt_h = roll(D_T_H,0.5f,1.5f);
        float []rand = new float[]{lp_xf, lp_ab, lp_hb, lf_w, lf_h, lb_w, lb_h, la_w, la_h, lh_w, lh_h,le_r,lt_x,lt_w,lt_h};
        return rand;    
    }
    static float roll(float v, float min,float max){
        return v * random(min,max); 
    }
void draw(){
        
        rT.draw();
        rS.draw();
        rF.draw();
        rB.draw();
        rH.draw();
        rA.draw();
        rE.draw();
       
        
    }
}
/******************            MAIN               **********************/
frame = 30;
boolean isLooping;
int r = 0x74;
int g = 0xAC;
int b = 0x23;
color c = color(#74AC23);
color bg = color(#CCCCCC);
Android android;
void setup() {
    background(bg);
    intial(externals.canvas.width,externals.canvas.height);
}

void intial(String hash,int w,int h){ 
    size(300,480);
    loadAvatar(hash);
    noStroke();
    //c = randColor();
    //bg = randColor();
    fill(c);
    android = new Android(Android.D_V);
    //android = new Android(Android.rand());
    smooth();
    noLoop();
    isLooping = false;
    frameRate(frame);
}
String getAvatarUrl(String hash,int size){
    return "http://www.gravatar.com/avatar/"+hash+"?d=404&s="+size;
}
PImage avatar;
boolean loadAvatar(String hash){
    int size = min(width, height);  
    url = getAvatarUrl(hash,width);
    console.log(url);
    avatar = loadImage(url);
    //avatar.sourceImg.crossOrigin = "";  
}
void drawAndrod(){
    if(isLooping){
    float [] v = new float[inc.length];
    for(int i =0 ;i<inc.length;i++){
        v[i] =  android.free[i] + inc[i];
    }
    
    r +=rc;
    g +=gc;
    b +=bc;
    c= color(0xff000000 | (int)r<<16 |(int)g<<8 |(int)b);
    fill(c);   
    android.regen(v);
    }

    if(frameCount>=frame){
    stop();    
    }
   background(bg);
   pushMatrix();
   translate(width+Android.D_H *0.6,height-Android.D_H/9);
   rotate(PI-PI/4);
   scale(android.s ,android.s);
   android.draw();
   scale(-1 ,1); 
   android.draw();
   popMatrix();

    }
void draw() {
    drawAndrod();
}
void stop(){
      noLoop();
      frameCount = 0;
      isLooping = false;
    }
void restart(){
    loop();
    isLooping=true;
    
    }
void mouseClicked() {
    
     if(isLooping){
         stop();
    }else{
         reRand();
         restart();
     }
 }
float []inc;
void reRand(){
    float [] target = Android.rand();
    randColor();
    inc = new float[target.length];
    
    float c = 1.0f/frame;
    for(int i =0 ;i<inc.length;i++){
         inc[i] = (target[i] - android.free[i])*c;
    }
    
}
int rc,gc,bc;
color randColor(){
    int rr = (int)random(0xff);
    int rg = (int)random(0xff);
    int rb= (int)random(0xff);
    rc = (rr -r) /frame;
    gc = (rg -g) /frame;
    bc = (rb -b) /frame;
    return color(0xff000000 | (int)rr<<16 |(int)rg<<8 |(int)rb);
}
PVector[] rrect(float w, float h, float[] r, int res) {
        PVector[] ret = new PVector[res*4];
        int[] cor = new int[]{-1, -1, 1, -1, 1, 1, -1, 1};
        float[] ang = new float[]{PI, PI+HALF_PI, 0, HALF_PI};
        float inc = HALF_PI/res;
        
        beginShape();
        for(int a=0; a<4; a++) {
          int crx = cor[a*2];
          int cry = cor[a*2+1];
              for(int b=0; b<res; b++) {
                float cag = ang[a]+inc*b;
                float posx = w*.5*crx + r[a]*crx*-1;
                float posy = h*.5*cry + r[a]*cry*-1;
                float x = posx + cos(cag)*r[a];
                float y = posy + sin(cag)*r[a];
                vertex(x, y);
                ret[b+res*a] = new PVector(x, y);
              }
        }
        endShape(CLOSE);
        return ret;
      }