Meta Description" name="description" />

Share this result

Previews are deleted daily. Get a permanent share link sent to your inbox:
Script
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>Kirby Scroll Vertical</title> <style> body { margin: 0; overflow: hidden; background: #87CEEB; font-family: sans-serif; touch-action: none; } canvas { display: block; } .ui { position: fixed; bottom: 40px; left: 0; right: 0; display: flex; justify-content: space-between; padding: 0 30px; pointer-events: none; z-index: 100; } .btn { width: 80px; height: 80px; background: rgba(255, 255, 255, 0.5); border: 5px solid #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 30px; color: #333; pointer-events: auto; user-select: none; -webkit-tap-highlight-color: transparent; } #jumpBtn { background: rgba(255, 105, 180, 0.8); color: white; width: 100px; height: 100px; } .btn:active { transform: scale(1.1); background: white; } </style> </head> <body> <canvas id="gameCanvas"></canvas> <div class="ui"> <div style="display:flex; gap: 20px;"> <div class="btn" id="lBtn">◀</div> <div class="btn" id="rBtn">▶</div> </div> <div class="btn" id="jumpBtn">↑</div> </div> <script> const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resize); resize(); // --- ESTADO DEL JUEGO --- const player = { x: canvas.width / 2, y: canvas.height - 150, radius: 25, vx: 0, vy: 0, isJumping: false, color: "#ffb6c1" }; // Generamos muchas plataformas hacia arriba const platforms = []; for(let i = 0; i < 20; i++) { platforms.push({ x: Math.random() * (canvas.width - 150), y: (canvas.height - 100) - (i * 180), w: 120 + Math.random() * 50, h: 35 }); } const input = { left: false, right: false, jump: false }; let cameraY = 0; // Posición de la cámara // --- CONTROLES --- function bind(id, key) { const el = document.getElementById(id); const start = (e) => { e.preventDefault(); input[key] = true; }; const end = (e) => { e.preventDefault(); input[key] = false; }; el.addEventListener('touchstart', start); el.addEventListener('touchend', end); } bind('lBtn', 'left'); bind('rBtn', 'right'); bind('jumpBtn', 'jump'); function update() { // Movimiento if (input.left) player.vx = -7; else if (input.right) player.vx = 7; else player.vx *= 0.85; if (input.jump && !player.isJumping) { player.vy = -18; player.isJumping = true; } player.vy += 0.8; player.x += player.vx; player.y += player.vy; // Colisiones platforms.forEach(p => { if (player.vy > 0 && player.x + 15 > p.x && player.x - 15 < p.x + p.w && player.y + 25 > p.y && player.y + 25 < p.y + p.h) { player.isJumping = false; player.vy = 0; player.y = p.y - 25; } }); // --- LÓGICA DE LA CÁMARA --- // La cámara sigue a Kirby para que siempre esté en el centro de la pantalla let targetCameraY = player.y - canvas.height / 2; // Suavizado de cámara (Interpolación lineal) cameraY += (targetCameraY - cameraY) * 0.1; // Límites de pantalla laterales if (player.x < 25) player.x = 25; if (player.x > canvas.width - 25) player.x = canvas.width - 25; // Reset si cae mucho más abajo de la cámara if (player.y > cameraY + canvas.height + 100) { player.y = canvas.height - 150; player.x = canvas.width / 2; player.vy = 0; cameraY = player.y - canvas.height / 2; } draw(); requestAnimationFrame(update); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); // Guardamos el estado, movemos la cámara y dibujamos ctx.save(); ctx.translate(0, -cameraY); // <--- AQUÍ OCURRE EL MOVIMIENTO DE CÁMARA // Fondo Dinámico (Nubes que se repiten) ctx.fillStyle = "white"; for(let i = 0; i < 10; i++) { ctx.beginPath(); ctx.arc(100, i * -400, 40, 0, Math.PI*2); ctx.arc(canvas.width - 100, i * -400 - 200, 50, 0, Math.PI*2); ctx.fill(); } // Dibujar Plataformas platforms.forEach(p => { ctx.fillStyle = "#7cfc00"; ctx.fillRect(p.x, p.y, p.w, p.h); ctx.fillStyle = "#228b22"; ctx.fillRect(p.x, p.y + p.h - 10, p.w, 10); }); // Dibujar Kirby const px = player.x; const py = player.y; ctx.fillStyle = player.color; ctx.beginPath(); ctx.arc(px, py, player.radius, 0, Math.PI * 2); ctx.fill(); ctx.strokeStyle = "#ff69b4"; ctx.lineWidth = 3; ctx.stroke(); // Ojos y detalles ctx.fillStyle = "black"; ctx.beginPath(); ctx.ellipse(px - 7, py - 5, 3, 6, 0, 0, Math.PI*2); ctx.ellipse(px + 7, py - 5, 3, 6, 0, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#ffc0cb"; ctx.beginPath(); ctx.arc(px - 15, py + 5, 5, 0, Math.PI*2); ctx.arc(px + 15, py + 5, 5, 0, Math.PI*2); ctx.fill(); ctx.restore(); // Restauramos para que la UI no se mueva } update(); </script> </body> </html>
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

1

Requests

1

Domains

6KB

Transfer Size

6KB

Content Size

190.0ms

Dom Content Loaded

204.0ms

First Paint

190.0ms

Load Time
Domain Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...
Timings (ms)
Loading...
Total Time
Loading...
Content Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...