AmazingDigitalPetDentures / knowledge /examples /canvas-platformer.html
VirusDumb's picture
Sync from GitHub via hub-sync
ba3faf3 verified
Raw
History Blame Contribute Delete
3.43 kB
<!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>