> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.kTZ6VanaHPl/rev.2963
 * 
 * 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(arm_angle){
                l = this.l;
                t = this.t;
                r = this.r;
                b = this.b;
                pushMatrix(); 
                float w = r-l;
                float h = b-t;
                if(arm_angle){
                    translate(l+w,b-h/2);
                    rotate(arm_angle);
                }else{
                    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+1,-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-1, b, w+1, 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,alpha);
                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(color,alpha);
                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(color,alpha/5);
                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,int ax,int ay,int a_w,int a_h){
        init();
        regen(v);
        resize(ax,ay,a_w,a_h);
    }
    
    void init() {
        rF = new Foot();
        rB = new Body();
        rH = new Head();
        rA = new Arm();
        rE = new Eye();
        rT = new Antenna();
        rS = new Shadow();
    }
    var color=#74AC23;
    int alpha=0xFF;
    void setColor(a_c,al){
        color=a_c;
        alpha=al;
    }
    float scaleNum;
    int anchor_x,anchor_y,a_width,a_height;
    void resize(int ax,int ay,int w,int h){
        anchor_x = ax ;
        anchor_y = ay ;
        a_width = w;
        a_height = h;
        sw =   (float) (w/( D_W *2 *1.5)); 
        sh =  (float) (h/ (D_H  * 1.8));
        if(sw < sh){
            scaleNum = sw;
        }else{
            scaleNum  = sh;
        }
    }
    var larm;
    var rarm;
    void draw(){
       pushMatrix();
       pushStyle();
       fill(color,alpha);
       translate(anchor_x,anchor_y);
       translate(a_width/2,a_height);
       rotate(PI);
       scale(scaleNum  ,scaleNum );
       drawOnce(rarm);
       scale(-1 ,1); 
       drawOnce(larm);
       popStyle();
       popMatrix();
    }
    void drawOnce(arm_angle){
        rT.draw();
        rS.draw();
        rF.draw();
        rB.draw();
        rH.draw();
        rA.draw(arm_angle);
        rE.draw();
    }

    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 fromHex(v,min,max,hash){
        int dif = (int)((max-min)*100);
        int i =parseInt(hash,16);
        float f = min + (i%dif)/100.0f;
        //console.log("fromHex:"+{f,min,max,i,hash});
        return v*f;
     }

      static int randHex(min,max,hash){
        int dif = (max -min);
        int i = parseInt(hash,16);
        int rs = (int) (min + (i%dif));
        //console.log("randHex:"+{rs,min,max,i,hash});
        return rs;
     }
     
     static float[] fromHash(hash){
        float min = 0.5f;
        float max = 1.5f;
        int idx =0;
        String sh = hash.substring(idx,idx+2);idx =idx+2;
        float tall = fromHex(D_H,min,max,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        int n1= randHex(1,7,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        int n2 = randHex(1,9-n1,sh); 
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float lf_h = tall * n1 /10;
        float lb_h = tall * n2 /10;
        float lh_h = tall -lf_h-lb_h;
        
        float lb_w = fromHex(D_B_W,min,max,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float lh_w = fromHex(D_H_W,0.2f,1.5f,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        n1= randHex(1,7,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        n2 = randHex(1,10-n1,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float lp_xf = lb_w * n1 /10;
        float lf_w = lb_w * n2 /10;
        
        float la_w = fromHex(D_A_W,0.2f,1.5f,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float la_h = fromHex(lf_h+lb_h,0.2f,1.0f,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float lp_ab = D_P_AB;
        float  lp_hb = D_P_HB;
        
        float le_r = D_E_R;
        
        float lt_x = randHex(20,80,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float lt_w = fromHex(D_T_W,0.5f,1.5f,sh);
        sh = hash.substring(idx,idx+2);idx =idx+2;
        float lt_h = fromHex(D_T_H,0.5f,1.5f,sh);
        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[] 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); 
    }

}
/******************            MAIN               **********************/
final static int STATE_NON = 0;
final static int STATE_IN = 1;
final static int STATE_OUT = 2;

int state = STATE_NON;

frame = 30;
myframeCount =0;
boolean isLooping;
int red = 0x74;
int green = 0xAC;
int blue = 0x23;
color c = color(#74AC23);
color bg = color(#FFFFFF);
Android android;
Android android2;
PImage avatar;
int bgAlpha = 0xFF;
int bfm_color=0xFFFF70D6;
void setup() {
    background(bg);
    intial();
}
float[] DS={
10.052319,
2.4324324,
2.4324324,
10.052319,
13.899584,
25.130796,
20.849375,
8.525072,
14.561987,
43.612053,
34.748962,
2.7027025,
25.0,
6.0413947,
12.755632
};
void intial(){
    size(700 ,200);
    noStroke();
    fill(c);
    android = new Android(Android.D_V,width/8,0,width/4,width/4);
    android.larm = PI/6;
    float[] AA_V ={Android.D_P_XF,Android.D_P_AB,Android.D_P_HB,Android.D_F_W*0.5,Android.D_F_H,Android.D_B_W*0.9,Android.D_B_H,Android.D_A_W*0.5,Android.D_A_H,Android.D_H_W,Android.D_H_H*0.8,Android.D_E_R,Android.D_T_D,Android.D_T_W,Android.D_T_H,Android.D_H,Android.D_W};
    android2 = new Android(AA_V,width/4,0,width/4,width/4);
    android2.rarm = PI/6;
    //console.log(Android.fromHash(hash));
    smooth();
    noLoop();
    frameRate(frame);
    background(bg); 
    android.draw();
    android2.setColor(#FF70D6,0xFF);
    android2.draw();
    myframeCount = 0;
}
void draw(){
    switch(state){
        case STATE_IN:
            drawIn();
            break;
        case STATE_OUT:
            drawOut();
            break;
        default:
            myframeCount=0;
    }
}
void drawOut(){
     bgred  =0xFF - myframeCount*5;
    bggreen  =0xFF - myframeCount*5;
    bgblue =0xFF - myframeCount*5;
    bgc= color(0xff000000 | (int)bgred <<16 |(int)bggreen <<8 |(int)bgblue);
    console.log(toColorHex(bgc)); 
    background(bgc);
    if(myframeCount==0){
        android.larm = PI/6;
        android2.rarm = PI/6;
        noLoop();
    }else{
        myframeCount--;
        } 
    float [] v = new float[inc.length];
    for(int i =0 ;i<inc.length;i++){
        v[i] =  android.free[i] + inc[i];
    }
    red  =red + rc;
    green  =green + gc;
    blue =blue + bc;
    c= color(0xff000000 | (int)red <<16 |(int)green <<8 |(int)blue);
    android.setColor(c,0xff);   
    android.regen(v);
    android.draw();
    
    tmpx = android2.anchor_x;
    tmpa = android2.alpha;
    android2.anchor_x =  android2.anchor_x +myframeCount*10;
    android2.setColor(bfm_color,android2.alpha-myframeCount*12);
    android2.draw();
    android2.alpha = tmpa ;
    android2.anchor_x = tmpx;
    
    }
void drawIn(){
     bgred  =0xFF - myframeCount*2;
    bggreen  =0xFF - myframeCount*2;
    bgblue =0xFF - myframeCount*2;
    bgc= color(0xff000000 | (int)bgred <<16 |(int)bggreen <<8 |(int)bgblue);
    console.log(toColorHex(bgc)); 
    background(bgc);
    float [] v = new float[inc.length];
    for(int i =0 ;i<inc.length;i++){
        v[i] =  android.free[i] + inc[i];
    }
    red  =red  + rc;
    green  =green  + gc;
    blue =blue + bc;
    c= color(0xff000000 | (int)red <<16 |(int)green <<8 |(int)blue);
    android.setColor(c,0xff);   
    android.regen(v);
    android.draw();
    
    tmpx = android2.anchor_x;
    tmpa = android2.alpha;
    android2.anchor_x =  android2.anchor_x +myframeCount*10;
    android2.setColor(bfm_color,android2.alpha-myframeCount*12);
    android2.draw();
    android2.alpha = tmpa ;
    android2.anchor_x = tmpx;
    if(myframeCount>=frame){
        PFont fontA = loadFont("Courier New");
        textFont(fontA, width/30);
        text('女朋友什么的屌丝就不用想了',width/3,height/2);
        noLoop();
    }else{
        myframeCount++;
        }
}


float []inc;

void mouseOver() {
    state=STATE_IN;
    int rr = 0x33;
    int rg = 0x33;
    int rb= 0x33;
    rc = (rr -red ) /frame;
    gc = (rg -green) /frame;
    bc = (rb -blue) /frame;
    genInc(DS);
    android.larm = undefined;
    android2.rarm = undefined;
    loop();
}
void mouseOut(){
     state=STATE_OUT;
    int rr = 0x74;
    int rg = 0xAC;
    int rb= 0x23;
    rc = (rr -red ) /frame;
    gc = (rg -green) /frame;
    bc = (rb -blue) /frame;
     genInc(Android.D_V);
     loop();
    }
void genInc(target){
    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;
    }
}
void reRand(){
    float [] target = android.fromHash(id);
    hashColor(7);
     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;
void randColor(){
            int rr = (int)random(0xff);
            int rg = (int)random(0xff);
            int rb= (int)random(0xff);
            rc = (rr -red ) /frame;
            gc = (rg -green) /frame;
            bc = (rb -blue) /frame;
}
 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;
      }
/*返回颜色的HEX码,见*/
String toColorHex(number){
    if (number < 0)
    {
        number = 0xFFFFFFFF + number + 1;
    }

    return number.toString(16).toUpperCase();
}