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_LOADING = 1; final static int STATE_IMAGE = 2; final static int STATE_ANDROID = 3; int state = STATE_NON; frame = 30; boolean isLooping; int red = 0x74; int green = 0xAC; int blue = 0x23; color c = color(#74AC23); color bg = color(#CCCCCC); Android android; PImage avatar; String id; int bgAlpha = 88; boolean enableTouch = true; void setup() { background(bg); //intial(externals.canvas.title,externals.canvas.width,externals.canvas.height); } void intial(String hash,int w,int h){ enableTouch = false; size(w,h); id = hash; loadAvatar(hash); noStroke(); //c = randColor(); //bg = randColor(); bg = getHashColor(0); fill(c); android = new Android(Android.D_V,0,-h/8,w,h); smooth(); //noLoop(); frameRate(frame); android.draw(); state =STATE_LOADING; } String getAvatarUrl(String hash,int size){ return "http://www.gravatar.com/avatar/"+hash+"?d=404&s="+size; } boolean loadAvatar(String hash){ int size = min(width, height); url = getAvatarUrl(hash,width); avatar = loadImage(url); avatar.sourceImg.onerror=function(){ state = STATE_ANDROID; frameCount = 0; genByHash(); } } void draw(){ switch(state){ case STATE_LOADING: loading(); break; case STATE_IMAGE : image(avatar,0,0); noLoop(); break; case STATE_ANDROID: drawAndrod(); break; } } void loading(){ if(avatar.sourceImg.complete){ if(avatar.width>0){ state = STATE_IMAGE; }else{ if(frameCount>5*frame){ state = STATE_ANDROID; frameCount = 0; genByHash(); } } }else{ //console.log("loading"); } } void drawAndrod(){ background(bg,bgAlpha); float [] v = new float[inc.length]; for(int i =0 ;i=frame){ state = STATE_NON; noLoop(); } android.draw(); } /*void stop(){ noLoop(); frameCount = 0; isLooping = false; } void restart(){ loop(); isLooping=true; }*/ void mouseClicked() { if(enableTouch){ console.log(state); if(android == null){ //size(w,h); noStroke(); bg = 0xFFCCCCCC; fill(c); android = new Android(Android.D_V,0,-height/8,width,height); smooth(); frameRate(frame); android.draw(); state = STATE_NON; }else if(state == STATE_ANDROID){ state = STATE_NON; noLoop(); }else{ state = STATE_ANDROID; genByRand(); frameCount =0; loop(); } } } float []inc; void genByRand(){ float [] target = android.rand(); console.log(target); randColor(); inc = new float[target.length]; float c = 1.0f/frame; for(int i =0 ;i