import { roundedHex } from './tile-shape.js'; import { hexPoints } from './path-math.js'; export function tint(hex,amount){return '#'+hex.slice(1).match(/../g).map(v=>Math.round(amount>=0?parseInt(v,16)+(255-parseInt(v,16))*amount:parseInt(v,16)*(1+amount)).toString(16).padStart(2,'0')).join('');} export function drawStyledToken(p,x,y,r,tile,angle){ const fill=tile.fill,ink='#263A3A'; if(!fill||!tile.artStyle||tile.artStyle==='classic')return false; if(tile.artStyle==='macaron'){ // Macaron: a flat gummy tile with a white sticker rim and one chunky white line arrow (a white mark on candy). const face=roundedHex(x,y,r,.16),white=tile.arrow||'#FFFFFF',w=Math.max(1.5,r*.20); p.polygon(face,fill);p.line([...face,face[0]],'#FFFFFF',Math.max(1,r*.10)); const rot=pts=>pts.map(([u,v])=>({x:x+r*(u*Math.cos(angle)-v*Math.sin(angle)),y:y+r*(u*Math.sin(angle)+v*Math.cos(angle))})); p.line(rot([[-.34,0],[.30,0]]),white,w);p.line(rot([[.02,-.30],[.30,0],[.02,.30]]),white,w); return true; } if(tile.artStyle==='signpost'){ // Signpost: inset face with a soft ink outline and one white wayfinding arrow for every pigment. const s=r/.90,face=roundedHex(x,y,r); p.polygon(face,fill);p.line([...face,face[0]],'#2E425661',Math.max(1.5,s*.05)); const a=r*.66,shape=[[-.62,-.2],[.06,-.2],[.06,-.52],[.64,0],[.06,.52],[.06,.2],[-.62,.2]]; p.polygon(shape.map(([u,v])=>({x:x+a*(u*Math.cos(angle)-v*Math.sin(angle)),y:y+a*(u*Math.sin(angle)+v*Math.cos(angle))})),tile.arrow||'#FFFFFF'); return true; } if(tile.artStyle==='paper'){ const face=hexPoints(x,y,r),unit=r/.88; p.polygon(face,fill);p.line([...face,face[0]],'#FFFFFFCC',unit*.035); const rotate=points=>points.map(([u,v])=>({x:x+unit*(u*Math.cos(angle)-v*Math.sin(angle)),y:y+unit*(u*Math.sin(angle)+v*Math.cos(angle))})); p.line(rotate([[-.3,0],[.3,0]]),tile.arrow,unit*.09); p.line(rotate([[.08,-.17],[.3,0],[.08,.17]]),tile.arrow,unit*.09); return true; } const face=roundedHex(x,y,r*.94),closed=[...face,face[0]]; let arrowY=y,arrowScale=.58; if(tile.artStyle==='vivid'){ p.polygon(roundedHex(x+r*.04,y+r*.07,r*.94),'#30264C');p.polygon(face,fill);p.line(closed,'#30264C',r*.065); p.line([{x:x-r*.45,y:y-r*.49},{x:x-r*.18,y:y-r*.64}],'#FFFFFF',r*.055); }else if(tile.artStyle==='toy'){ p.polygon(roundedHex(x,y+r*.09,r*.94),tint(fill,-.3)); p.polygon(face,tint(fill,-.08));p.polygon(roundedHex(x,y-r*.06,r*.83),fill); const rim=roundedHex(x,y-r*.06,r*.75);p.line(rim.slice(9,18),tint(fill,.5),r*.045); p.circle(x,y-r*.04,r*.50,tint(fill,.11)); }else{ p.polygon(face,'#FFFCED');p.line(closed,'#526F5744',r*.035); const species=tile.color%4,earY=y-r*.40; const oval=(cx,cy,rx,ry)=>Array.from({length:24},(_,i)=>({x:cx+Math.cos(i*Math.PI/12)*rx,y:cy+Math.sin(i*Math.PI/12)*ry})); if(species===0){ p.polygon([{x:x-r*.58,y:y-r*.1},{x:x-r*.53,y:y-r*.73},{x:x-r*.08,y:y-r*.4}],fill); p.polygon([{x:x+r*.58,y:y-r*.1},{x:x+r*.53,y:y-r*.73},{x:x+r*.08,y:y-r*.4}],fill); }else if(species===2){ for(const sign of [-1,1]){p.polygon(oval(x+sign*r*.24,y-r*.48,r*.13,r*.32),fill);p.polygon(oval(x+sign*r*.24,y-r*.53,r*.055,r*.19),tint(fill,.55));} }else if(species===1){ for(const sign of [-1,1]){p.circle(x+sign*r*.40,earY,r*.23,fill);p.circle(x+sign*r*.40,earY,r*.12,tint(fill,.4));} }else{ for(const sign of [-1,1])p.circle(x+sign*r*.26,y-r*.43,r*.19,fill); } p.circle(x,y-r*.04,r*.51,fill); for(const sign of [-1,1]){ const eyeY=species===3?y-r*.42:y-r*.19; if(species===3)p.circle(x+sign*r*.21,eyeY,r*.10,'#FFFFFF'); p.circle(x+sign*r*.21,eyeY,r*.058,ink);p.circle(x+sign*r*.32,y+r*.02,r*.078,'#EF958B'); } p.line([{x:x-r*.085,y:y-r*.035},{x,y:y+r*.025},{x:x+r*.085,y:y-r*.035}],ink,r*.035); p.circle(x,y+r*.43,r*.36,'#FFFFFF');arrowY=y+r*.43;arrowScale=.44; } const a=r*arrowScale; const shape=[[-.72,-.23],[.06,-.23],[.06,-.59],[.83,0],[.06,.59],[.06,.23],[-.72,.23]]; p.polygon(shape.map(([u,v])=>({x:x+a*(u*Math.cos(angle)-v*Math.sin(angle)),y:arrowY+a*(u*Math.sin(angle)+v*Math.cos(angle))})),tile.artStyle==='animals'?ink:tile.arrow); return true; }