| <!doctype html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <title>Canvas Platformer</title> |
| <style>html,body{margin:0;height:100%;overflow:hidden;background:#162033;font-family:system-ui,sans-serif}canvas{display:block;width:100vw;height:100vh}#hud{position:fixed;left:12px;top:12px;color:white;background:#0008;padding:10px 12px;border-radius:12px}</style> |
| </head> |
| <body> |
| <canvas id="game"></canvas><div id="hud"></div> |
| <script> |
| const canvas=document.getElementById("game"),ctx=canvas.getContext("2d"),hud=document.getElementById("hud"),keys={}; |
| const T=32,map=[ |
| "1111111111111111111111111", |
| "1000000000000000000000001", |
| "1000000000000000000000G01", |
| "1000111000001110000011111", |
| "100000000C000000000000001", |
| "1000001111110000011100001", |
| "100C000000000000000000001", |
| "111100000000C000111100001", |
| "1000000001111110000000001", |
| "100000H00000000000000C001", |
| "1001111111000000111110001", |
| "1000000000000000000000001", |
| "1111111111111111111111111"]; |
| const player={x:48,y:300,w:24,h:28,vx:0,vy:0,onGround:false,coins:0,win:false,dead:false}; |
| function resize(){const d=Math.max(1,devicePixelRatio||1);canvas.width=innerWidth*d;canvas.height=innerHeight*d;ctx.setTransform(d,0,0,d,0,0)}addEventListener("resize",resize);resize(); |
| addEventListener("keydown",e=>{keys[e.code]=1;if(e.code==="Space"&&(player.dead||player.win))location.reload()});addEventListener("keyup",e=>keys[e.code]=0); |
| function tile(x,y){return map[Math.floor(y/T)]?.[Math.floor(x/T)]||"1"}function solid(x,y){return tile(x,y)==="1"}function setTile(px,py,ch){const r=Math.floor(py/T),c=Math.floor(px/T);map[r]=map[r].slice(0,c)+ch+map[r].slice(c+1)} |
| function moveAxis(axis,amount){player[axis]+=amount;const pts=[[player.x,player.y],[player.x+player.w,player.y],[player.x,player.y+player.h],[player.x+player.w,player.y+player.h]];if(pts.some(p=>solid(p[0],p[1]))){if(axis==="x"){player.x-=amount;player.vx=0}else{if(amount>0)player.onGround=true;player.y-=amount;player.vy=0}}} |
| function update(dt){if(player.dead||player.win)return;player.vx=((keys.ArrowRight||keys.KeyD?1:0)-(keys.ArrowLeft||keys.KeyA?1:0))*210;if((keys.ArrowUp||keys.KeyW)&&player.onGround){player.vy=-520;player.onGround=false}player.vy=Math.min(900,player.vy+1400*dt);moveAxis("x",player.vx*dt);player.onGround=false;moveAxis("y",player.vy*dt);const cx=player.x+player.w/2,cy=player.y+player.h/2,t=tile(cx,cy);if(t==="C"){player.coins++;setTile(cx,cy,"0")}if(t==="H")player.dead=true;if(t==="G"&&player.coins>=4)player.win=true} |
| function render(){const w=innerWidth,h=innerHeight;ctx.clearRect(0,0,w,h);ctx.save();ctx.translate(Math.min(0,w/2-player.x),Math.min(0,h/2-player.y));for(let r=0;r<map.length;r++)for(let c=0;c<map[r].length;c++){const ch=map[r][c],x=c*T,y=r*T;if(ch==="1"){ctx.fillStyle="#334155";ctx.fillRect(x,y,T,T)}if(ch==="C"){ctx.fillStyle="#fde047";ctx.beginPath();ctx.arc(x+16,y+16,9,0,7);ctx.fill()}if(ch==="H"){ctx.fillStyle="#ef4444";ctx.fillRect(x+4,y+20,24,12)}if(ch==="G"){ctx.fillStyle="#22c55e";ctx.fillRect(x+8,y+4,16,28)}}ctx.fillStyle=player.dead?"#64748b":"#38bdf8";ctx.fillRect(player.x,player.y,player.w,player.h);ctx.restore();hud.textContent=player.win?"You win! Space to retry.":player.dead?"Ouch. Space to retry.":`Coins ${player.coins}/4 | Arrows/WASD, jump with Up/W`;} |
| let last=performance.now();function loop(now){const dt=Math.min((now-last)/1000,.05);last=now;update(dt);render();requestAnimationFrame(loop)}requestAnimationFrame(loop); |
| </script> |
| </body> |
| </html> |
|
|