PAU
can you make an exact copy of the old super mario bros
BUDDY
I can't make an exact copy of Super Mario Bros. since that's Nintendo's copyrighted game, but I can build you a super fun Mario-STYLE platformer with a little jumping hero, coins, enemies, and platforms — inspired by that classic feel! Let's call it "Pau's Platformer!" 🎮
PAU
nothings happening
BUDDY
Let me fix that! The game should now load and respond to your keyboard right away. Press the arrow keys to move and Space or ↑ to jump! 🎮
CODE
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Pau's Platformer</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #5c94fc; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; font-family: 'Courier New', monospace; overflow: hidden; } #hud { color: white; font-size: 20px; font-weight: bold; text-shadow: 2px 2px #000; margin-bottom: 8px; display: flex; gap: 40px; } canvas { border: 4px solid #000; display: block; } #message { color: white; font-size: 18px; font-weight: bold; text-shadow: 2px 2px #000; margin-top: 8px; min-height: 28px; } </style> </head> <body> <div id="hud"> <span>⭐ SCORE: <span id="scoreDisplay">0</span></span> <span>🪙 COINS: <span id="coinsDisplay">0</span></span> <span>❤️ LIVES: <span id="livesDisplay">3</span></span> </div> <canvas id="gameCanvas" width="800" height="400"></canvas> <div id="message">← → to move | SPACE or ↑ to jump | Stomp enemies from above!</div> <script> const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); // ── State ────────────────────────────────────────────────────────────────── let score = 0, coins = 0, lives = 3; let gameOver = false, win = false; let cameraX = 0; // ── Input ────────────────────────────────────────────────────────────────── const keys = {}; window.addEventListener('keydown', e => { keys[e.code] = true; e.preventDefault(); }); window.addEventListener('keyup', e => { keys[e.code] = false; }); // ── Level Layout ─────────────────────────────────────────────────────────── const GROUND_Y = 340; const platforms = [ // ground chunks (gaps between them!) {x:0, y:GROUND_Y, w:450, h:60, color:'#8B4513'}, {x:500, y:GROUND_Y, w:250, h:60, color:'#8B4513'}, {x:800, y:GROUND_Y, w:300, h:60, color:'#8B4513'}, {x:1150, y:GROUND_Y, w:250, h:60, color:'#8B4513'}, {x:1450, y:GROUND_Y, w:400, h:60, color:'#8B4513'}, {x:1900, y:GROUND_Y, w:500, h:60, color:'#8B4513'}, // floating platforms {x:150, y:250, w:100, h:18, color:'#228B22'}, {x:320, y:200, w:80, h:18, color:'#228B22'}, {x:530, y:230, w:120, h:18, color:'#228B22'}, {x:760, y:195, w:100, h:18, color:'#228B22'}, {x:920, y:250, w:80, h:18, color:'#228B22'}, {x:1100, y:210, w:120, h:18, color:'#228B22'}, {x:1290, y:175, w:80, h:18, color:'#228B22'}, {x:1460, y:240, w:100, h:18, color:'#228B22'}, {x:1620, y:195, w:80, h:18, color:'#228B22'}, {x:1760, y:225, w:100, h:18, color:'#228B22'}, {x:1920, y:175, w:120, h:18, color:'#228B22'}, ]; let coinItems = [ {x:170,y:220},{x:340,y:170},{x:550,y:200},{x:780,y:165}, {x:940,y:220},{x:1120,y:180},{x:1310,y:145},{x:1480,y:210}, {x:1640,y:165},{x:1780,y:195},{x:1940,y:145}, {x:210,y:310},{x:610,y:310},{x:850,y:310},{x:1200,y:310}, {x:1550,y:310},{x:1960,y:310},{x:2100,y:310}, ].map(c => ({...c, collected:false})); let enemies = [ {x:300, y:GROUND_Y-32, w:32, h:32, vx:1.2, alive:true, patrol:[50,440]}, {x:560, y:GROUND_Y-32, w:32, h:32, vx:-1.2, alive:true, patrol:[502,740]}, {x:850, y:GROUND_Y-32, w:32, h:32, vx:1.2, alive:true, patrol:[802,1090]}, {x:1200, y:GROUND_Y-32, w:32, h:32, vx:-1.2, alive:true, patrol:[1152,1390]}, {x:1550, y:GROUND_Y-32, w:32, h:32, vx:1.2, alive:true, patrol:[1452,1840]}, {x:1950, y:GROUND_Y-32, w:32, h:32, vx:-1.2, alive:true, patrol:[1902,2380]}, {x:2080, y:GROUND_Y-32, w:32, h:32, vx:1.2, alive:true, patrol:[1902,2380]}, ]; const FLAG_X = 2400; // ── Player ───────────────────────────────────────────────────────────────── let player = { x:60, y:280, w:32, h:40, vx:0, vy:0, onGround:false, facing:1, invincible:0, }; function resetPlayer() { player.x = 60; player.y = 280; player.vx = 0; player.vy = 0; player.onGround = false; player.invincible = 120; cameraX = 0; } // ── Collision ────────────────────────────────────────────────────────────── function rectOverlap(a, b) { return a.x < b.x+b.w && a.x+a.w > b.x && a.y < b.y+b.h && a.y+a.h > b.y; } function resolvePlatforms() { player.onGround = false; for (const pl of platforms) { if (!rectOverlap(player, pl)) continue; const overlapL = (player.x + player.w) - pl.x; const overlapR = (pl.x + pl.w) - player.x; const overlapT = (player.y + player.h) - pl.y; const overlapB = (pl.y + pl.h) - player.y; const minO = Math.min(overlapL, overlapR, overlapT, overlapB); if (minO === overlapT && player.vy >= 0) { player.y = pl.y - player.h; player.vy = 0; player.onGround = true; } else if (minO === overlapB && player.vy < 0) { player.y = pl.y + pl.h; player.vy = 0; } else if (minO === overlapL) { player.x = pl.x - player.w; player.vx = 0; } else if (minO === overlapR) { player.x = pl.x + pl.w; player.vx = 0; } } } // ── Update ───────────────────────────────────────────────────────────────── function update() { if (gameOver || win) return; // Movement const spd = 3.8; if (keys['ArrowLeft'] || keys['KeyA']) { player.vx = -spd; player.facing = -1; } else if (keys['ArrowRight'] || keys['KeyD']) { player.vx = spd; player.facing = 1; } else { player.vx *= 0.65; } // Jump if ((keys['Space'] || keys['ArrowUp'] || keys['KeyW']) && player.onGround) { player.vy = -13; player.onGround = false; } // Gravity player.vy += 0.6; if (player.vy > 15) player.vy = 15; player.x += player.vx; player.y += player.vy; resolvePlatforms(); if (player.x < 0) player.x = 0; // Fell off if (player.y > canvas.height + 60) { lives--; updateHUD(); if (lives <= 0) { gameOver = true; return; } resetPlayer(); } // Camera const target = player.x - canvas.width / 3; cameraX += (target - cameraX) * 0.14; if (cameraX < 0) cameraX = 0; // Coins for (const c of coinItems) { if (c.collected) continue; if (rectOverlap(player, {x:c.x, y:c.y, w:20, h:20})) { c.collected = true; coins++; score += 100; updateHUD(); } } // Enemies for (const e of enemies) { if (!e.alive) continue; e.x += e.vx; if (e.x <= e.patrol[0] || e.x + e.w >= e.patrol[1]) e.vx *= -1; if (player.invincible <= 0 && rectOverlap(player, e)) { // Stomp check if (player.vy > 0 && player.y + player.h < e.y + e.h * 0.55) { e.alive = false; player.vy = -9; score += 200; updateHUD(); } else { lives--; updateHUD(); if (lives <= 0) { gameOver = true; return; } resetPlayer(); } } } // Win if (player.x + player.w >= FLAG_X) { win = true; score += 1000; updateHUD(); } if (player.invincible > 0) player.invincible--; } function updateHUD() { document.getElementById('scoreDisplay').textContent = score; document.getElementById('coinsDisplay').textContent = coins; document.getElementById('livesDisplay').textContent = lives; } // ── Draw ─────────────────────────────────────────────────────────────────── function drawBG() { ctx.fillStyle = '#5c94fc'; ctx.fillRect(0, 0, canvas.width, canvas.height); // simple clouds ctx.fillStyle = 'rgba(255,255,255,0.9)'; const cloudDefs = [{x:80,y:55},{x:300,y:35},{x:520,y:65},{x:700,y:40}]; for (const cd of cloudDefs) { const cx = ((cd.x - cameraX * 0.25) % (canvas.width + 200) + canvas.width + 200) % (canvas.width + 200) - 100; ctx.beginPath(); ctx.arc(cx+30, cd.y+20, 22, 0, Math.PI*2); ctx.arc(cx+58, cd.y+10, 28, 0, Math.PI*2); ctx.arc(cx+86, cd.y+20, 22, 0, Math.PI*2); ctx.fill(); } } function drawPlatforms() { for (const pl of platforms) { const sx = pl.x - cameraX; if (sx + pl.w < 0 || sx > canvas.width) continue; ctx.fillStyle = '#8B4513'; ctx.fillRect(sx, pl.y + 10, pl.w, pl.h - 10); ctx.fillStyle = '#228B22'; ctx.fillRect(sx, pl.y, pl.w, 12); ctx.fillStyle = '#2ECC40'; for (let gx = sx + 5; gx < sx + pl.w - 4; gx += 14) { ctx.fillRect(gx, pl.y - 4, 6, 6); } } } function drawCoins() { for (const c of coinItems) { if (c.collected) continue; const sx = c.x - cameraX; if (sx < -30 || sx > canvas.width + 30) continue; ctx.fillStyle = '#FFD700'; ctx.strokeStyle = '#FFA500'; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(sx + 10, c.y + 10, 10, 0, Math.PI*2); ctx.fill(); ctx.stroke(); ctx.fillStyle = '#A0522D'; ctx.font = 'bold 12px Courier New'; ctx.fillText('$', sx + 6, c.y + 15); } } function drawEnemies() { for (const e of enemies) { if (!e.alive) continue; const sx = e.x - cameraX; if (sx < -50 || sx > canvas.width + 50) continue; // body ctx.fillStyle = '#CC2200'; ctx.fillRect(sx, e.y, e.w, e.h); // eyes ctx.fillStyle = 'white'; ctx.fillRect(sx+4, e.y+5, 9, 9); ctx.fillRect(sx+19, e.y+5, 9, 9); ctx.fillStyle = '#000'; const ex = e.vx > 0 ? 3 : 1; ctx.fillRect(sx+4+ex, e.y+7, 5, 5); ctx.fillRect(sx+19+ex, e.y+7, 5, 5); // feet ctx.fillStyle = '#880000'; ctx.fillRect(sx+2, e.y+e.h-9, 11, 9); ctx.fillRect(sx+19, e.y+e.h-9, 11, 9); } } function drawPlayer() { if (player.invincible > 0 && Math.floor(player.invincible / 6) % 2 === 0) return; const sx = player.x - cameraX; const f = player.facing; // hat top ctx.fillStyle = '#CC0000'; ctx.fillRect(sx+5, player.y, player.w-10, 10); ctx.fillRect(sx, player.y+7, player.w, 8); // face ctx.fillStyle = '#FFDAB9'; ctx.fillRect(sx+4, player.y+14, player.w-8, 13); // eye ctx.fillStyle = '#000'; ctx.fillRect(sx + (f===1 ? 18 : 6), player.y+17, 5, 5); // mustache ctx.fillStyle = '#5c3317'; ctx.fillRect(sx+5, player.y+22, player.w-10, 4); // shirt/overalls ctx.fillStyle = '#0033CC'; ctx.fillRect(sx+3, player.y+27, player.w-6, 13); // buckles ctx.fillStyle = '#CC0000'; ctx.fillRect(sx+7, player.y+27, 7, 8); ctx.fillRect(sx+player.w-14, player.y+27, 7, 8); // legs ctx.fillStyle = '#5c3317'; ctx.fillRect(sx+3, player.y+40, 11, player.h-40); ctx.fillRect(sx+player.w-14, player.y+40, 11, player.h-40); } function drawFlag() { const sx = FLAG_X - cameraX; if (sx < -20 || sx > canvas.width + 20) return; ctx.fillStyle = '#999'; ctx.fillRect(sx - 3, GROUND_Y - 200, 6, 200); ctx.fillStyle = '#00CC00'; ctx.beginPath(); ctx.moveTo(sx+3, GROUND_Y-200); ctx.lineTo(sx+50, GROUND_Y-175); ctx.lineTo(sx+3, GROUND_Y-150); ctx.closePath(); ctx.fill(); } function drawOverlay() { if (gameOver) { ctx.fillStyle = 'rgba(0,0,0,0.65)'; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.fillStyle = '#FF4444'; ctx.font = 'bold 52px Courier New'; ctx.textAlign = 'center'; ctx.fillText('GAME OVER', canvas.width/2, canvas.height/2 - 20); ctx.fillStyle = 'white'; ctx.font = '26px Courier New'; ctx.fillText('Press R to restart', canvas.width/2, canvas.height/2 + 30); ctx.textAlign = 'left'; } if (win) { ctx.fillStyle = 'rgba(0,0,0,0.55)'; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.fillStyle = '#FFD700'; ctx.font = 'bold 52px Courier New'; ctx.textAlign = 'center'; ctx.fillText('YOU WIN! 🎉', canvas.width/2, canvas.height/2 - 30); ctx.fillStyle = 'white'; ctx.font = '26px Courier New'; ctx.fillText('Score: ' + score, canvas.width/2, canvas.height/2 + 20); ctx.fillText('Press R to play again', canvas.width/2, canvas.height/2 + 58); ctx.textAlign = 'left'; } } // ── Restart ──────────────────────────────────────────────────────────────── window.addEventListener('keydown', e => { if (e.code === 'KeyR' && (gameOver || win)) { score = 0; coins = 0; lives = 3; gameOver = false; win = false; coinItems.forEach(c => c.collected = false); enemies.forEach(e => e.alive = true); updateHUD(); resetPlayer(); } }); // ── Game Loop ────────────────────────────────────────────────────────────── function gameLoop() { update(); ctx.clearRect(0, 0, canvas.width, canvas.height); drawBG(); drawFlag(); drawPlatforms(); drawCoins(); drawEnemies(); drawPlayer(); drawOverlay(); requestAnimationFrame(gameLoop); } gameLoop(); </script> </body> </html>
PREVIEW
PICTURES0/50
No pictures yet. Add one, then ask your buddy to put it in your app!