// ========== RENDERING ========== // Extends Game.prototype — must be loaded after game.js Object.assign(Game.prototype, { _draw(){ const c=this.cx; c.fillStyle=CO.bg;c.fillRect(0,0,CW,CH); c.fillStyle=CO.hud;c.fillRect(0,0,CW,HUD_TOP);c.fillRect(0,CH-HUD_BOT,CW,HUD_BOT); if(this.state==='start'){this._hud(c);return} this._maze(c);this._dDots(c);this._dMed(c);this._dPatient(c);this._dPain(c);this._dPl(c);this._dFx(c); if(this.challActive){ const pct=this.challTimer/(FPS*CHALL_DURATION),bw=CW-16,bx=8,by=HUD_TOP-5; c.fillStyle='rgba(0,0,0,0.5)';c.fillRect(bx,by,bw,4); c.fillStyle=pct>0.5?'#22c55e':pct>0.25?'#f59e0b':'#ef4444'; c.fillRect(bx,by,bw*pct,4); } this._hud(c); }, _maze(c){ for(let r=0;r{const rr=r+dr,cc=col+dc;if(rr<0||rr>=ROWS||cc<0||cc>=COLS)return true;const v=MAP[rr][cc];return v===1||v===3}; if(!w(-1,0)){c.beginPath();c.moveTo(x,y+1.5);c.lineTo(x+TILE,y+1.5);c.stroke()} if(!w(1,0)){c.beginPath();c.moveTo(x,y+TILE-1.5);c.lineTo(x+TILE,y+TILE-1.5);c.stroke()} if(!w(0,-1)){c.beginPath();c.moveTo(x+1.5,y);c.lineTo(x+1.5,y+TILE);c.stroke()} if(!w(0,1)){c.beginPath();c.moveTo(x+TILE-1.5,y);c.lineTo(x+TILE-1.5,y+TILE);c.stroke()} } else if(t===3){c.fillStyle=CO.gW;c.fillRect(x,y,TILE,TILE)} else if(t===4){c.fillStyle=CO.gD;c.fillRect(x,y+TILE*.35,TILE,TILE*.3)} } }, _dPatient(c){ if(!this.patient)return; const x=this.patient.c*TILE+TILE/2,y=this.patient.r*TILE+HUD_TOP+TILE/2; c.save();c.translate(x,y); // pulsing glow c.globalAlpha=0.25+0.2*Math.abs(Math.sin(this.fr*0.08)); c.fillStyle='#EC4899';c.beginPath();c.arc(0,0,10,0,Math.PI*2);c.fill(); c.globalAlpha=1; const sc=0.9+0.08*Math.sin(this.fr*0.1);c.scale(sc,sc); // pain aura c.strokeStyle='#EF4444';c.lineWidth=0.8; for(let i=0;i<6;i++){const a=i*Math.PI/3;c.beginPath();c.moveTo(Math.cos(a)*5,Math.sin(a)*5);c.lineTo(Math.cos(a)*9,Math.sin(a)*9);c.stroke()} // head c.fillStyle='#FCD9B6';c.beginPath();c.arc(0,-4,3,0,Math.PI*2);c.fill(); // torso c.fillStyle='#93C5FD';c.fillRect(-2,-1,5,6); // legs c.fillStyle='#FCD9B6';c.fillRect(-3,5,2,4);c.fillRect(1,5,2,4); // arms raised c.strokeStyle='#FCD9B6';c.lineWidth=1.5; c.beginPath();c.moveTo(-2,1);c.lineTo(-8,-3);c.stroke(); c.beginPath();c.moveTo(3,1);c.lineTo(9,-3);c.stroke(); // sad eyebrows c.strokeStyle='#555';c.lineWidth=0.8; c.beginPath();c.moveTo(-2,-6);c.lineTo(-1,-5);c.stroke(); c.beginPath();c.moveTo(2,-6);c.lineTo(1,-5);c.stroke(); // eyes c.fillStyle='#333';c.fillRect(-2,-5,1,1);c.fillRect(1,-5,1,1); // frown c.strokeStyle='#8B0000';c.lineWidth=0.8; c.beginPath();c.arc(0,-2,1.5,0,Math.PI,true);c.stroke(); c.restore(); }, _dMed(c){ for(const m of this.meds){ if(m.eaten)continue; const x=m.c*TILE+TILE/2,y=m.r*TILE+HUD_TOP+TILE/2; const sc=1+0.06*Math.sin(m.pulse); c.save();c.translate(x,y);c.scale(sc,sc); const pw=14,ph=7,r=ph/2; // left (red) half c.fillStyle='#EF4444'; c.beginPath();c.arc(-pw/2+r,0,r,Math.PI/2,Math.PI*3/2);c.lineTo(0,-r);c.lineTo(0,r);c.closePath();c.fill(); // right (white) half c.fillStyle='#FFF'; c.beginPath();c.arc(pw/2-r,0,r,-Math.PI/2,Math.PI/2);c.lineTo(0,r);c.lineTo(0,-r);c.closePath();c.fill(); // outline c.strokeStyle='rgba(0,0,0,0.4)';c.lineWidth=0.5; c.beginPath();c.arc(-pw/2+r,0,r,Math.PI/2,Math.PI*3/2);c.arc(pw/2-r,0,r,-Math.PI/2,Math.PI/2);c.closePath();c.stroke(); c.restore(); } }, _dDots(c){c.fillStyle=CO.dot;for(const d of this.dots)if(!d.e)c.fillRect(d.c*TILE+TILE/2-2,d.r*TILE+HUD_TOP+TILE/2-2,4,4)}, _dPain(c){ for(const p of this.pains){if(p.eaten)continue;const x=p.x+TILE/2,y=p.y+TILE/2,pu=1+.06*Math.sin(p.pulse),r=TILE*.44*pu; c.save();c.translate(x,y);c.fillStyle=p.scared?CO.pSc:CO.pB;c.beginPath();c.arc(0,2,r,Math.PI,0,false);c.lineTo(r,4);c.lineTo(-r,4);c.closePath();c.fill(); if(!p.scared){c.strokeStyle=CO.pBo;c.lineWidth=1.5;[-r*.5,0,r*.5].forEach(bx=>{c.beginPath();c.moveTo(bx,-r*.15);c.lineTo(bx-2,-r*.55);c.lineTo(bx+1,-r*.45);c.lineTo(bx-1,-r*.9);c.stroke()})} else{c.fillStyle='#FFF';c.fillRect(-3,-4,2,2);c.fillRect(2,-4,2,2);c.strokeStyle='#FFF';c.lineWidth=1;c.beginPath();for(let i=0;i<5;i++){const qx=-4+i*2;i===0?c.moveTo(qx,1):c.lineTo(qx,i%2===0?1:3)}c.stroke()} c.restore()} }, _dPl(c){ const p=this.pl,x=p.x+TILE/2,y=p.y+TILE/2,r=TILE*.44; c.save();c.translate(x,y);const dir=p.moving?p.dir:p.lastFace; c.rotate({right:0,down:Math.PI/2,left:Math.PI,up:-Math.PI/2}[dir]||0); const mo=p.mouth*.45;c.fillStyle=CO.kid;c.beginPath();c.arc(0,0,r,mo,Math.PI*2-mo,false);c.lineTo(0,0);c.closePath();c.fill(); const ey=dir==='left'?r*.4:-r*.4; c.fillStyle=CO.kE;c.beginPath();c.arc(-r*.1,ey,r*.18,0,Math.PI*2);c.fill(); c.fillStyle='#000';c.beginPath();c.arc(-r*.05,ey,r*.08,0,Math.PI*2);c.fill(); c.restore(); if(this.hasMed){ c.save();c.translate(x,y-r-6); const pw=7,ph=4,pr=ph/2; c.fillStyle='#EF4444';c.beginPath();c.arc(-pw/2+pr,0,pr,Math.PI/2,Math.PI*3/2);c.lineTo(0,-pr);c.lineTo(0,pr);c.closePath();c.fill(); c.fillStyle='#FFF';c.beginPath();c.arc(pw/2-pr,0,pr,-Math.PI/2,Math.PI/2);c.lineTo(0,pr);c.lineTo(0,-pr);c.closePath();c.fill(); c.restore(); } }, _dFx(c){ for(const f of this.fx){const pg=1-f.t/f.mx,al=1-pg;const hr=parseInt(f.co.slice(1,3),16),hg=parseInt(f.co.slice(3,5),16),hb=parseInt(f.co.slice(5,7),16); if(f.tp==='glow'){c.fillStyle=`rgba(${hr},${hg},${hb},${al*.4})`;c.beginPath();c.arc(f.x,f.y,12+pg*25,0,Math.PI*2);c.fill()} else if(f.tp==='exp'){for(let i=0;i<8;i++){const a=i/8*Math.PI*2,d=pg*28;c.fillStyle=`rgba(255,${0|120+135*(1-pg)},0,${al})`;c.fillRect(f.x+Math.cos(a)*d-2,f.y+Math.sin(a)*d-2,4,4)}} else if(f.tp==='burst'){c.strokeStyle=`rgba(${hr},${hg},${hb},${al})`;c.lineWidth=2;c.beginPath();c.arc(f.x,f.y,pg*18,0,Math.PI*2);c.stroke()}} }, _hud(c){ c.font='10px "Press Start 2P",monospace';c.textBaseline='middle';const ty=HUD_TOP/2; c.fillStyle=CO.hudT;c.textAlign='left';c.fillText('PUNKTE: '+(this.lsc+this.sc),8,ty); c.textAlign='center';c.fillText('LEVEL '+this.lv,CW/2,ty); const sec=0|this.lt/FPS;c.fillStyle=CO.hudT;c.textAlign='right';c.fillText('ZEIT: '+(0|sec/60)+':'+String(sec%60).padStart(2,'0'),CW-8,ty); const by=CH-HUD_BOT/2; for(let i=0;i