"use strict"; function render(){ var canvas=$("gc"),ctx=canvas.getContext("2d"); var cam=S.camera,P=S.player,net=S.net,cfg=S.cfg; ctx.save();ctx.clearRect(0,0,CW,CH); // Sky var sg=ctx.createLinearGradient(0,0,0,CH); if(S.phase===1){sg.addColorStop(0,cfg.skyA);sg.addColorStop(1,cfg.skyB);} else{var u=Math.min(1,S.kidneyDmg/80);sg.addColorStop(0,lerpCol(cfg.skyA,"#5a2020",u));sg.addColorStop(1,lerpCol(cfg.skyB,"#3a1515",u));} ctx.fillStyle=sg;ctx.fillRect(0,0,CW,CH); ctx.translate(-cam.x,-cam.y); // Ground ctx.fillStyle=cfg.ground;ctx.fillRect(0,0,net.mapW,net.mapH); ctx.fillStyle="#00000014"; for(var gi=0;gi<250;gi++)ctx.fillRect((gi*137.5)%net.mapW,(gi*97.3)%net.mapH,2,2); // ── Paths ── ctx.lineCap="round";ctx.lineJoin="round"; ctx.strokeStyle="#1a150f";ctx.lineWidth=PATH_W+8; net.edges.forEach(function(e){var a=net.nodes[e[0]],b=net.nodes[e[1]];ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke()}); ctx.strokeStyle="#8a7a5e";ctx.lineWidth=PATH_W; net.edges.forEach(function(e){var a=net.nodes[e[0]],b=net.nodes[e[1]];ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke()}); ctx.strokeStyle="#a0906840";ctx.lineWidth=PATH_W*0.5; net.edges.forEach(function(e){var a=net.nodes[e[0]],b=net.nodes[e[1]];ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke()}); // ── Bushes ── var bCols=["#2d6b1e","#3a7a2a","#1e5a14"]; S.veg.bushes.forEach(function(b){ ctx.fillStyle=bCols[b.shade%3]; ctx.beginPath();ctx.arc(b.x,b.y,b.sz,0,Math.PI*2);ctx.fill(); ctx.fillStyle="#22551540"; ctx.beginPath();ctx.arc(b.x-b.sz*0.3,b.y-b.sz*0.3,b.sz*0.5,0,Math.PI*2);ctx.fill(); }); // ── Trees ── var tCols=["#1e6b1e","#2a7a25","#22651a","#2b7030"]; S.veg.trees.forEach(function(t){ ctx.fillStyle="#5a3a1a";ctx.fillRect(t.x-3,t.y,6,t.trunk); ctx.fillStyle="#00000020";ctx.beginPath();ctx.ellipse(t.x,t.y+t.trunk+2,t.sz*0.6,t.sz*0.25,0,0,Math.PI*2);ctx.fill(); ctx.fillStyle=tCols[t.shade%4]; ctx.beginPath();ctx.arc(t.x,t.y-t.sz*0.2,t.sz,0,Math.PI*2);ctx.fill(); ctx.fillStyle="#3a9a3018";ctx.beginPath();ctx.arc(t.x-t.sz*0.25,t.y-t.sz*0.5,t.sz*0.45,0,Math.PI*2);ctx.fill(); }); // ── Keims ── for(var ki=0;ki0.35){ ctx.strokeStyle="rgba(255,50,50,"+(k.size*0.6)+")"; ctx.lineWidth=1.5;ctx.beginPath();ctx.arc(k.x,k.y,r2*2,0,Math.PI*2);ctx.stroke(); } } // ── Spray particles ── sprayParticles.forEach(function(p){ var alpha=p.life*1.5; ctx.fillStyle=p.color.replace(")",","+alpha+")").replace("rgb","rgba"); ctx.beginPath();ctx.arc(p.x,p.y,2+p.life*3,0,Math.PI*2);ctx.fill(); }); // ── Buildings ── drawBldg(ctx,net.lab.x,net.lab.y,"\uD83D\uDD2C","Labor","#304050"); drawBldg(ctx,net.apo.x,net.apo.y,"\uD83D\uDC8A","Apotheke","#2a4a2a"); // Peak ctx.fillStyle="#9a9a8a"; ctx.beginPath();ctx.moveTo(net.peak.x-50,net.peak.y+30);ctx.lineTo(net.peak.x-12,net.peak.y-40);ctx.lineTo(net.peak.x+8,net.peak.y-35);ctx.lineTo(net.peak.x+50,net.peak.y+30);ctx.closePath();ctx.fill(); ctx.fillStyle="#e0e0e0";ctx.beginPath();ctx.moveTo(net.peak.x-18,net.peak.y-22);ctx.lineTo(net.peak.x-12,net.peak.y-40);ctx.lineTo(net.peak.x+8,net.peak.y-35);ctx.lineTo(net.peak.x+14,net.peak.y-20);ctx.closePath();ctx.fill(); ctx.fillStyle="#fff8";ctx.font="11px sans-serif";ctx.textAlign="center";ctx.fillText("\u26F0\uFE0F Gipfel",net.peak.x,net.peak.y+48); // ── Hints (phase 1) ── if(S.phase===1){ var hAlpha=S.cfg.hintAlpha; S.hints.forEach(function(h){ var sp=Math.sin(frame*0.06+h.phase)*0.5+0.5; ctx.fillStyle="rgba(255,240,180,"+(sp*hAlpha)+")"; ctx.beginPath();ctx.arc(h.x,h.y,3+sp*3,0,Math.PI*2);ctx.fill(); }); } // ── Stones ── S.stones.forEach(function(st){ if(st.rolling)return; if(st.scanned&&!st.isCystine){ ctx.globalAlpha=0.25;ctx.fillStyle="#555";drawStone(ctx,st.x,st.y,st.shape,st.rollAngle);ctx.globalAlpha=1;return; } ctx.fillStyle=st.color; drawStone(ctx,st.x,st.y,st.shape,st.rollAngle); if(!st.scanned&&S.phase===1){ ctx.fillStyle="#fff7";ctx.font="11px sans-serif";ctx.textAlign="center";ctx.fillText("?",st.x,st.y-18); } }); // Rolling stone if(S.rollingStone){ var rs=S.rollingStone; ctx.fillStyle=rs.color; drawStone(ctx,rs.x,rs.y,rs.shape,rs.rollAngle); if(frame%3===0){ ctx.fillStyle="#a0906840"; ctx.beginPath();ctx.arc(rs.x+rng(-8,8),rs.y+rng(8,14),rng(2,4),0,Math.PI*2);ctx.fill(); } } // Parked stone glow if(S.parkedStone){ var gl=Math.sin(frame*0.08)*0.3+0.5; ctx.strokeStyle="rgba(255,200,50,"+gl+")";ctx.lineWidth=2; ctx.beginPath();ctx.arc(S.parkedStone.x,S.parkedStone.y,STONE_R+8,0,Math.PI*2);ctx.stroke(); ctx.fillStyle=S.parkedStone.color; drawStone(ctx,S.parkedStone.x,S.parkedStone.y,S.parkedStone.shape,S.parkedStone.rollAngle); } // ── Player (Sisyphus) ── var bob=Math.sin(P.frame*2)*1.5; var sprinting=P.sprinting; ctx.fillStyle="#00000028";ctx.beginPath();ctx.ellipse(P.x,P.y+20+bob,10,4,0,0,Math.PI*2);ctx.fill(); ctx.fillStyle="#d4a060";ctx.beginPath();ctx.arc(P.x,P.y-14+bob,9,0,Math.PI*2);ctx.fill(); ctx.fillStyle="#5a3a1a";ctx.beginPath();ctx.arc(P.x,P.y-18+bob,6,Math.PI,Math.PI*2);ctx.fill(); ctx.fillStyle=sprinting?"#7a5535":"#8b6040"; ctx.fillRect(P.x-6,P.y-5+bob,12,15); if(S.rollingStone){ var armDx=Math.cos(P.dir)*10,armDy=Math.sin(P.dir)*10; ctx.strokeStyle="#d4a060";ctx.lineWidth=3; ctx.beginPath();ctx.moveTo(P.x,P.y+2+bob);ctx.lineTo(P.x+armDx,P.y+2+bob+armDy);ctx.stroke(); } ctx.fillStyle="#4a3020";ctx.fillRect(P.x-7,P.y+3+bob,14,3); ctx.fillStyle="#6a4830"; var lOff=Math.sin(P.frame*3)*(sprinting?3:1.5); ctx.fillRect(P.x-5,P.y+10+bob+lOff,4,8); ctx.fillRect(P.x+1,P.y+10+bob-lOff,4,8); if(sprinting&&frame%2===0){ ctx.fillStyle="#a0906830"; ctx.beginPath();ctx.arc(P.x-Math.cos(P.dir)*12,P.y-Math.sin(P.dir)*12+20,rng(2,4),0,Math.PI*2);ctx.fill(); } // ── Prompts ── ctx.font="bold 11px sans-serif";ctx.textAlign="center"; if(S.phase===1){ S.stones.forEach(function(st){ if(!st.scanned&&!st.rolling&&dist(P,st)<55){ ctx.fillStyle="#ffffffcc";ctx.fillText("[Leertaste] Aufheben",st.x,st.y-22); } }); if(S.rollingStone&&dist(P,net.lab)<65){ ctx.fillStyle="#00ff88cc";ctx.font="bold 12px sans-serif"; ctx.fillText("[Leertaste] Scannen!",net.lab.x,net.lab.y-48); } } if(S.phase===2){ if(S.parkedStone&&!S.rollingStone&&dist(P,S.parkedStone)<55){ ctx.fillStyle="#ffcc00cc";ctx.fillText("[Leertaste] Aufheben",S.parkedStone.x,S.parkedStone.y-STONE_R-14); } if(S.rollingStone&&S.rollingStone.isCystine){ ctx.fillStyle="#88aaffcc";ctx.font="10px sans-serif";ctx.fillText("[Leertaste] Parken",S.rollingStone.x,S.rollingStone.y-STONE_R-14); } if(dist(P,net.apo)<65){ ctx.fillStyle="#00ff88cc";ctx.fillText("[Leertaste] Auff\u00FCllen",net.apo.x,net.apo.y-48); } for(var ki=0;ki0){ ctx.fillStyle="#ffcc44cc";ctx.font="10px sans-serif"; ctx.fillText("[Leertaste] Spr\u00FChen",k.x,k.y-k.size*30-12); break; } } } // ── Minimap ── drawMinimap(ctx,cam); ctx.restore(); } function drawStone(ctx,x,y,shape,angle){ ctx.save();ctx.translate(x,y);ctx.rotate(angle||0); ctx.beginPath(); if(shape===0)ctx.ellipse(0,0,STONE_R,STONE_R*0.72,0,0,Math.PI*2); else if(shape===1){ctx.moveTo(-STONE_R,STONE_R*0.6);ctx.lineTo(-STONE_R*0.5,-STONE_R*0.8);ctx.lineTo(STONE_R*0.8,-STONE_R*0.5);ctx.lineTo(STONE_R,STONE_R*0.6);ctx.closePath();} else ctx.arc(0,0,STONE_R,0,Math.PI*2); ctx.fill();ctx.strokeStyle="#00000030";ctx.lineWidth=1;ctx.stroke(); ctx.fillStyle="#00000015";ctx.beginPath();ctx.arc(STONE_R*0.2,-STONE_R*0.2,STONE_R*0.3,0,Math.PI*2);ctx.fill(); ctx.fillStyle="#ffffff10";ctx.beginPath();ctx.arc(-STONE_R*0.3,-STONE_R*0.3,STONE_R*0.25,0,Math.PI*2);ctx.fill(); ctx.restore(); } function drawCrystal(ctx,x,y,r){ ctx.beginPath(); var spikes=7; for(var i=0;i