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"> <title>Futbol Pro 2D - Edición Cordobesa</title> <style> @import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Roboto:wght@400;700&display=swap'); body { margin: 0; overflow: hidden; background: #1a1a1a; font-family: 'Roboto', sans-serif; color: white; user-select: none; } #game-container { position: relative; width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; background: radial-gradient(circle, #333, #000); } canvas { box-shadow: 0 0 50px rgba(0,0,0,0.8); cursor: none; /* Ocultar mouse en juego */ } /* UI y Menus */ .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; display: flex; flex-direction: column; justify-content: center; align-items: center; } .menu-screen { background: rgba(16, 20, 30, 0.95); width: 100%; height: 100%; position: absolute; display: flex; flex-direction: column; justify-content: center; align-items: center; pointer-events: auto; z-index: 10; backdrop-filter: blur(5px); } .hidden { display: none !important; } h1 { font-family: 'Bebas Neue', sans-serif; font-size: 80px; margin: 0; color: #ffce00; letter-spacing: 5px; text-shadow: 4px 4px 0 #000; transform: skew(-5deg); } h2 { font-family: 'Bebas Neue', sans-serif; font-size: 40px; margin: 10px; color: #fff; text-shadow: 2px 2px 0 #000; } p { color: #aaa; font-size: 14px; margin-bottom: 30px; } .btn-group { display: flex; flex-wrap: wrap; justify-content: center; gap: 15px; max-width: 800px; } .btn { background: linear-gradient(180deg, #e91e63, #c2185b); color: white; border: none; padding: 15px 40px; font-size: 22px; font-family: 'Bebas Neue', sans-serif; cursor: pointer; border-radius: 4px; box-shadow: 0 4px 0 #880e4f; transition: 0.1s; min-width: 200px; text-align: center; letter-spacing: 1px; } .btn:active { transform: translateY(4px); box-shadow: 0 0 0 #880e4f; } .btn:hover { filter: brightness(1.2); } .btn-sec { background: linear-gradient(180deg, #3f51b5, #303f9f); box-shadow: 0 4px 0 #1a237e; } .btn-back { background: #555; box-shadow: 0 4px 0 #222; margin-top: 20px;} /* HUD */ #hud { position: absolute; top: 20px; width: 95%; display: flex; justify-content: space-between; align-items: flex-start; pointer-events: none; } .scoreboard { background: rgba(0,0,0,0.6); padding: 10px 30px; border-radius: 8px; border: 2px solid rgba(255,255,255,0.1); display: flex; align-items: center; gap: 20px; } .team-badge { width: 40px; height: 40px; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: bold; border: 2px solid white; box-shadow: 0 0 10px rgba(0,0,0,0.5); } .score-txt { font-family: 'Bebas Neue', sans-serif; font-size: 50px; line-height: 40px; } .time-box { background: rgba(0,0,0,0.8); color: #00ff00; font-family: 'Courier New', monospace; font-weight: bold; font-size: 30px; padding: 10px 20px; border: 2px solid #555; border-radius: 5px; } #controls-hint { position: absolute; bottom: 10px; right: 20px; font-size: 12px; color: rgba(255,255,255,0.5); text-align: right; } .notification { position: absolute; top: 20%; left: 50%; transform: translateX(-50%); font-family: 'Bebas Neue', sans-serif; font-size: 100px; color: #fff; -webkit-text-stroke: 2px black; text-shadow: 5px 5px 0 red; opacity: 0; transition: opacity 0.5s; pointer-events: none; z-index: 20; text-align: center; } .visible { opacity: 1 !important; } .list-container { max-height: 50vh; overflow-y: auto; width: 600px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 10px; } .list-item { background: #2c3e50; padding: 15px; cursor: pointer; border-radius: 4px; text-align: center; font-weight: bold; border: 1px solid #34495e; } .list-item:hover { background: #34495e; border-color: #e91e63; } .list-item.selected { background: #e91e63; color: white; border-color: white; } /* Scrollbar */ ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { background: #111; } ::-webkit-scrollbar-thumb { background: #555; border-radius: 5px; } </style> </head> <body> <div id="game-container"> <canvas id="gameCanvas"></canvas> <div id="ui-layer" class="overlay hidden"> <div id="hud"> <div class="scoreboard"> <div class="team-badge" id="hud-badge1">L</div> <div class="score-txt"><span id="score1">0</span> - <span id="score2">0</span></div> <div class="team-badge" id="hud-badge2">V</div> </div> <div class="time-box" id="timer">00:00</div> </div> <div id="notification" class="notification">¡GOLAZO!</div> <div id="controls-hint"> WASD: Mover | ESPACIO: Pase/Chute | F: Cambiar Jugador | X: Quitar/Falta </div> </div> <div id="main-menu" class="menu-screen"> <h1>FÚTBOL TOTAL 2D</h1> <p>Edición Hno Cordobés</p> <div class="btn-group"> <button class="btn" onclick="startFlow('friendly')">AMISTOSO</button> <button class="btn btn-sec" onclick="startFlow('cup')">COPAS</button> </div> </div> <div id="league-select" class="menu-screen hidden"> <h2 id="league-title">Elegí Liga (Tu Equipo)</h2> <div id="league-list" class="list-container"></div> <button class="btn btn-back" onclick="backToMain()">Volver</button> </div> <div id="team-select" class="menu-screen hidden"> <h2 id="team-title">Elegí Tu Equipo</h2> <div id="team-list" class="list-container"></div> <button class="btn btn-back" onclick="backToLeagues()">Volver</button> </div> <div id="game-over" class="menu-screen hidden"> <h1 id="go-title">FIN DEL PARTIDO</h1> <h2 id="go-score"></h2> <button class="btn" onclick="backToMain()">Menú Principal</button> </div> </div> <script> /** --- BASE DE DATOS DE EQUIPOS --- **/ const DATABASE = { "ARG": { name: "Liga Argentina", teams: ["Boca Jrs", "River Plate", "Talleres", "Belgrano", "Racing", "Independiente", "San Lorenzo", "Estudiantes", "Newells", "Rosario Central", "Velez", "Lanus", "Argentinos", "Instituto"] }, "ENG": { name: "Premier League", teams: ["Man City", "Arsenal", "Liverpool", "Aston Villa", "Tottenham", "Man Utd", "Newcastle", "Chelsea", "West Ham", "Brighton", "Leeds Utd", "Everton"] }, "ESP": { name: "La Liga", teams: ["Real Madrid", "Barcelona", "Girona", "Atletico Madrid", "Athletic Bilbao", "Real Sociedad", "Betis", "Valencia", "Sevilla", "Villarreal"] }, "ITA": { name: "Serie A", teams: ["Inter", "Juventus", "Milan", "Roma", "Bologna", "Atalanta", "Napoli", "Fiorentina", "Lazio", "Torino"] }, "GER": { name: "Bundesliga", teams: ["Leverkusen", "Bayern Munich", "Stuttgart", "Dortmund", "RB Leipzig", "Frankfurt", "Hoffenheim", "Werder Bremen"] }, "BRA": { name: "Brasileirao", teams: ["Palmeiras", "Flamengo", "Botafogo", "Atletico Mineiro", "Gremio", "Fluminense", "Sao Paulo", "Internacional", "Corinthians", "Cruzeiro"] }, "SUD": { name: "Resto de America", teams: ["Colo Colo", "U de Chile", "U Catolica", "Peñarol", "Nacional", "Olimpia", "Cerro Porteño", "Libertad", "Bolivar", "The Strongest", "LDU Quito", "Barcelona SC", "Universitario", "Alianza Lima"] }, "FRA": { name: "Ligue 1", teams: ["PSG", "Monaco", "Brest", "Lille", "Nice", "Lens", "Marseille", "Lyon"] } }; const TEAM_COLORS = { "Boca Jrs": ["#00388d", "#fcb900"], "River Plate": ["#ffffff", "#db0030"], "Talleres": ["#002664", "#ffffff"], "Belgrano": ["#68a3e5", "#000000"], "Man City": ["#6cabdd", "#ffffff"], "Man Utd": ["#da291c", "#ffffff"], "Real Madrid": ["#ffffff", "#000000"], "Barcelona": ["#a50044", "#004d98"], "Brasil": ["#ffee00", "#009c3b"], "Argentina": ["#75aadb", "#ffffff"] }; // Generador de colores si no está en la lista function getColors(name) { if (TEAM_COLORS[name]) return TEAM_COLORS[name]; let hash = 0; for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash); let c = (hash & 0x00FFFFFF).toString(16).toUpperCase(); return ["#" + "00000".substring(0, 6 - c.length) + c, "#ffffff"]; } /** --- MOTOR DEL JUEGO --- **/ const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); let W, H; const TILE_SIZE = 100; // Para el pasto function resize() { W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; } window.addEventListener('resize', resize); resize(); // Constantes Físicas const PLAYER_R = 14; const BALL_R = 6; const GOAL_W = 140; const FRICTION = 0.94; const KICK_POWER = 12; const DRIBBLE_DIST = 18; // Estado Global let state = { mode: 'MENU', // MENU, PLAY, PAUSE, GOAL, FOUL, END time: 300, score: [0, 0], teams: { home: "Equipo 1", away: "Equipo 2" }, colors: { home: ["#f00","#fff"], away: ["#00f","#fff"] }, ball: { x: 0, y: 0, vx: 0, vy: 0, owner: null }, // Owner is the player object players: [], controlledPlayer: 4, // Index in home team camera: { x: 0, y: 0 }, selectionStep: 0, // 0: League Home, 1: Team Home, 2: League Away, 3: Team Away tempSelection: {} }; // Input const keys = {}; window.addEventListener('keydown', e => { keys[e.code] = true; if (state.mode === 'PLAY') { if (e.code === 'KeyF') switchPlayer(); if (e.code === 'KeyX') tryTackle(); } }); window.addEventListener('keyup', e => { keys[e.code] = false; if (e.code === 'Space' && state.mode === 'PLAY') releaseKick(); }); let spacePressedTime = 0; /** --- LOGICA DEL JUEGO --- **/ function initMatch(homeTeam, awayTeam) { state.teams.home = homeTeam; state.teams.away = awayTeam; state.colors.home = getColors(homeTeam); state.colors.away = getColors(awayTeam); state.score = [0, 0]; state.time = 300; // 5 mins // Configurar HUD document.getElementById('hud-badge1').style.background = state.colors.home[0]; document.getElementById('hud-badge1').style.color = state.colors.home[1]; document.getElementById('hud-badge1').innerText = homeTeam.substring(0,1); document.getElementById('hud-badge2').style.background = state.colors.away[0]; document.getElementById('hud-badge2').style.color = state.colors.away[1]; document.getElementById('hud-badge2').innerText = awayTeam.substring(0,1); document.getElementById('score1').innerText = "0"; document.getElementById('score2').innerText = "0"; setupFormation(); resetPositions('kickoff'); document.getElementById('ui-layer').classList.remove('hidden'); document.getElementById('main-menu').classList.add('hidden'); document.getElementById('game-over').classList.add('hidden'); state.mode = 'PLAY'; lastTime = Date.now(); gameLoop(); } function setupFormation() { state.players = []; // Formacion 1-2-1-1 (5 jugadores) // Team 0 (Left/Home) const t0 = 0; const c0 = state.colors.home; state.players.push(createPlayer(t0, 'GK', 50, H/2, c0)); state.players.push(createPlayer(t0, 'DEF', 250, H/2 - 100, c0)); state.players.push(createPlayer(t0, 'DEF', 250, H/2 + 100, c0)); state.players.push(createPlayer(t0, 'MID', 450, H/2, c0)); state.players.push(createPlayer(t0, 'FWD', 600, H/2, c0)); // Team 1 (Right/Away) const t1 = 1; const c1 = state.colors.away; state.players.push(createPlayer(t1, 'GK', W-50, H/2, c1)); state.players.push(createPlayer(t1, 'DEF', W-250, H/2 - 100, c1)); state.players.push(createPlayer(t1, 'DEF', W-250, H/2 + 100, c1)); state.players.push(createPlayer(t1, 'MID', W-450, H/2, c1)); state.players.push(createPlayer(t1, 'FWD', W-600, H/2, c1)); state.controlledPlayer = 4; // FWD starts controlled } function createPlayer(team, role, x, y, colors) { return { team, role, x, y, startX: x, startY: y, vx: 0, vy: 0, color: colors[0], sColor: colors[1], cooldown: 0 }; } function resetPositions(type) { state.ball.vx = 0; state.ball.vy = 0; state.ball.owner = null; state.ball.x = W/2; state.ball.y = H/2; state.players.forEach(p => { p.vx = 0; p.vy = 0; if(type === 'goal') { // Reset to formation side p.x = p.startX; p.y = p.startY; } else { p.x = p.startX; p.y = p.startY; } }); } function switchPlayer() { // Find next nearest player to ball in my team let bestDist = Infinity; let bestIdx = -1; state.players.forEach((p, i) => { if(p.team === 0 && i !== state.controlledPlayer) { let d = Math.hypot(p.x - state.ball.x, p.y - state.ball.y); // Prioritize players slightly closer to ball but not Gk unless necessary if (d < bestDist) { bestDist = d; bestIdx = i; } } }); if (bestIdx !== -1) state.controlledPlayer = bestIdx; } function tryTackle() { const me = state.players[state.controlledPlayer]; // Check collision with ball or opponent let tackled = false; // Check against opponents state.players.forEach(p => { if (p.team === 1) { let d = Math.hypot(me.x - p.x, me.y - p.y); if (d < PLAYER_R * 2.5) { // If opponent has ball, steal it if (state.ball.owner === p) { state.ball.owner = null; // Ball impulse let angle = Math.atan2(p.y - me.y, p.x - me.x); state.ball.vx = Math.cos(angle) * 8; state.ball.vy = Math.sin(angle) * 8; tackled = true; // Clean tackle } else { // Check if ball is close enough to be "legal" tackle let dBall = Math.hypot(state.ball.x - me.x, state.ball.y - me.y); if (dBall > 40) { // FOUL! callFoul(me.x, me.y); tackled = true; } } } } }); // Slide animation (visual fake) if(!tackled) { me.vx *= 3; me.vy *= 3; // Lunge } } function callFoul(x, y) { state.mode = 'FOUL'; showNotification("¡FALTA!", "#ffff00"); setTimeout(() => { state.mode = 'PLAY'; // Give ball to opponent nearby state.ball.x = x; state.ball.y = y; state.ball.vx = 0; state.ball.vy = 0; state.ball.owner = null; // Move players away slightly state.players.forEach(p => { let d = Math.hypot(p.x - x, p.y - y); if(d < 60) p.x += (p.x > x ? 60 : -60); }); }, 1500); } function releaseKick() { const p = state.players[state.controlledPlayer]; const now = Date.now(); let power = Math.min((now - spacePressedTime) / 1000, 1.0); // 0 to 1 if (state.ball.owner === p) { state.ball.owner = null; let kickSpeed = 5 + (power * KICK_POWER); // 5 to 17 // Direction based on movement or facing goal if still let angle = 0; if (Math.abs(p.vx) > 0.1 || Math.abs(p.vy) > 0.1) { angle = Math.atan2(p.vy, p.vx); } else { angle = Math.atan2((H/2) - p.y, W - p.x); // Aim to goal } state.ball.vx = Math.cos(angle) * kickSpeed; state.ball.vy = Math.sin(angle) * kickSpeed; } else { // Pass request logic if ball is far (not implemented in simple mode) } spacePressedTime = 0; } function updatePhysics() { if (keys['Space'] && !spacePressedTime) spacePressedTime = Date.now(); // 1. Players Movement state.players.forEach((p, idx) => { let ax = 0, ay = 0; let speed = 2.5; // Human Control if (p.team === 0 && idx === state.controlledPlayer) { if(keys['KeyW'] || keys['ArrowUp']) ay = -1; if(keys['KeyS'] || keys['ArrowDown']) ay = 1; if(keys['KeyA'] || keys['ArrowLeft']) ax = -1; if(keys['KeyD'] || keys['ArrowRight']) ax = 1; // Sprint? Maybe later } // CPU AI (And Human Teammates) else { let targetX = p.startX, targetY = p.startY; // Logic for Team 1 (CPU) if (p.team === 1) { // If own ball, Attack if (state.ball.owner && state.ball.owner.team === 1) { // Attack logic if (state.ball.owner === p) { // I have the ball. Run to goal targetX = 50; targetY = H/2; // Random Shoot let distGoal = Math.hypot(p.x - 0, p.y - H/2); if (distGoal < 250 && Math.random() < 0.02) { state.ball.owner = null; let angle = Math.atan2(H/2 - p.y, 0 - p.x) + (Math.random()-0.5)*0.2; state.ball.vx = Math.cos(angle) * 15; state.ball.vy = Math.sin(angle) * 15; } } else { // Support targetX = state.ball.x + (p.startX - W/2); // Relative formation targetY = state.ball.y; } } else { // Defense logic // Only closest chases ball let isClosest = true; let myDist = Math.hypot(p.x - state.ball.x, p.y - state.ball.y); for(let k=5; k<10; k++) { // CPU indices let otherDist = Math.hypot(state.players[k].x - state.ball.x, state.players[k].y - state.ball.y); if (otherDist < myDist) isClosest = false; } if (isClosest) { targetX = state.ball.x; targetY = state.ball.y; speed = 2.6; // Sprint to mark } else { // Zone defense targetX = p.startX * 0.5 + state.ball.x * 0.4; // Shift towards ball but keep shape targetY = p.startY; } } } // Logic for Human AI Teammates else { // Simple stay in formation targetX = p.startX + (state.ball.x - W/2)*0.5; targetY = p.startY; } // Move towards target let dx = targetX - p.x; let dy = targetY - p.y; let dist = Math.hypot(dx, dy); if (dist > 5) { let angle = Math.atan2(dy, dx); ax = Math.cos(angle); ay = Math.sin(angle); } } // Apply velocity p.vx += ax * 0.2; p.vy += ay * 0.2; p.vx *= 0.9; p.vy *= 0.9; // Friction // Cap speed let vel = Math.hypot(p.vx, p.vy); if (vel > speed) { p.vx = (p.vx/vel) * speed; p.vy = (p.vy/vel) * speed; } p.x += p.vx; p.y += p.vy; // Bounds if(p.x < PLAYER_R) p.x = PLAYER_R; if(p.x > W-PLAYER_R) p.x = W-PLAYER_R; if(p.y < PLAYER_R) p.y = PLAYER_R; if(p.y > H-PLAYER_R) p.y = H-PLAYER_R; // Player vs Player collision (simple push) state.players.forEach((p2, idx2) => { if (idx !== idx2) { let pdx = p.x - p2.x; let pdy = p.y - p2.y; let pdist = Math.hypot(pdx, pdy); if (pdist < PLAYER_R * 2) { let angle = Math.atan2(pdy, pdx); let push = 1; p.vx += Math.cos(angle) * push; p.vy += Math.sin(angle) * push; } } }); }); // 2. Ball Logic if (state.ball.owner) { // Ball is stuck to player let p = state.ball.owner; let angle = Math.atan2(p.vy, p.vx); if (Math.hypot(p.vx, p.vy) < 0.1) angle = Math.atan2(state.ball.y - p.y, state.ball.x - p.x); // Keep previous angle if stopped state.ball.x = p.x + Math.cos(angle) * DRIBBLE_DIST; state.ball.y = p.y + Math.sin(angle) * DRIBBLE_DIST; state.ball.vx = p.vx; state.ball.vy = p.vy; } else { // Free ball physics state.ball.x += state.ball.vx; state.ball.y += state.ball.vy; state.ball.vx *= 0.98; // Ball rolls longer state.ball.vy *= 0.98; // Bounce Walls if (state.ball.y < 0 || state.ball.y > H) state.ball.vy *= -1; if (state.ball.x < 0) { if (Math.abs(state.ball.y - H/2) < GOAL_W/2) scoreGoal(1); // Goal for Team 1 else state.ball.vx *= -1; } if (state.ball.x > W) { if (Math.abs(state.ball.y - H/2) < GOAL_W/2) scoreGoal(0); // Goal for Team 0 else state.ball.vx *= -1; } // Check for possession state.players.forEach(p => { let d = Math.hypot(p.x - state.ball.x, p.y - state.ball.y); if (d < PLAYER_R + BALL_R + 2) { state.ball.owner = p; } }); } } function scoreGoal(teamIndex) { state.mode = 'GOAL'; state.score[teamIndex]++; document.getElementById('score1').innerText = state.score[0]; document.getElementById('score2').innerText = state.score[1]; showNotification("¡GOL!", teamIndex === 0 ? state.colors.home[0] : state.colors.away[0]); setTimeout(() => { if(state.score[0] >= 5 || state.score[1] >= 5) { endGame(); } else { resetPositions('goal'); state.mode = 'PLAY'; } }, 2500); } function endGame() { state.mode = 'END'; document.getElementById('ui-layer').classList.add('hidden'); document.getElementById('game-over').classList.remove('hidden'); document.getElementById('go-score').innerText = `${state.teams.home} ${state.score[0]} - ${state.score[1]} ${state.teams.away}`; } function showNotification(text, color) { const el = document.getElementById('notification'); el.innerText = text; el.style.color = color || "#fff"; el.classList.add('visible'); setTimeout(() => el.classList.remove('visible'), 2000); } /** --- RENDER --- **/ function draw() { // 1. Campo (Pasto) for (let x = 0; x < W; x+=TILE_SIZE) { for (let y = 0; y < H; y+=TILE_SIZE) { ctx.fillStyle = ((x+y)%200 === 0) ? "#2e7d32" : "#388e3c"; // Cuadros ctx.fillRect(x,y,TILE_SIZE,TILE_SIZE); } } // Lineas ctx.lineWidth = 4; ctx.strokeStyle = "rgba(255,255,255,0.8)"; // Mitad ctx.beginPath(); ctx.moveTo(W/2, 0); ctx.lineTo(W/2, H); ctx.stroke(); ctx.beginPath(); ctx.arc(W/2, H/2, 70, 0, Math.PI*2); ctx.stroke(); // Areas const areaH = 250; const areaW = 120; ctx.strokeRect(0, H/2 - areaH/2, areaW, areaH); // Izq ctx.strokeRect(W-areaW, H/2 - areaH/2, areaW, areaH); // Der // Arcos (red) ctx.fillStyle = "rgba(255,255,255,0.2)"; ctx.fillRect(0, H/2 - GOAL_W/2, 20, GOAL_W); ctx.fillRect(W-20, H/2 - GOAL_W/2, 20, GOAL_W); // Postes ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(20, H/2 - GOAL_W/2, 4, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(20, H/2 + GOAL_W/2, 4, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(W-20, H/2 - GOAL_W/2, 4, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(W-20, H/2 + GOAL_W/2, 4, 0, Math.PI*2); ctx.fill(); // 2. Sombras Jugadores ctx.fillStyle = "rgba(0,0,0,0.4)"; state.players.forEach(p => { ctx.beginPath(); ctx.arc(p.x + 3, p.y + 3, PLAYER_R, 0, Math.PI*2); ctx.fill(); }); // 3. Jugadores state.players.forEach((p, i) => { // Cuerpo ctx.beginPath(); ctx.arc(p.x, p.y, PLAYER_R, 0, Math.PI*2); ctx.fillStyle = p.color; ctx.fill(); // Borde ctx.strokeStyle = (p.team === 0 && i === state.controlledPlayer) ? "#ffff00" : "#000"; ctx.lineWidth = (p.team === 0 && i === state.controlledPlayer) ? 3 : 1; ctx.stroke(); // Numero/Detalle ctx.fillStyle = p.sColor; ctx.font = "bold 12px Arial"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(p.role === 'GK' ? "1" : (i+2), p.x, p.y); // Marcador jugador controlado if (p.team === 0 && i === state.controlledPlayer) { ctx.beginPath(); ctx.moveTo(p.x - 5, p.y - 25); ctx.lineTo(p.x + 5, p.y - 25); ctx.lineTo(p.x, p.y - 18); ctx.fillStyle = "#ffff00"; ctx.fill(); } }); // 4. Balon // Sombra balon ctx.fillStyle = "rgba(0,0,0,0.3)"; ctx.beginPath(); ctx.arc(state.ball.x + 2, state.ball.y + 2, BALL_R, 0, Math.PI*2); ctx.fill(); // Bola ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(state.ball.x, state.ball.y, BALL_R, 0, Math.PI*2); ctx.fill(); // Parches negros (estilo clasico) ctx.fillStyle = "black"; ctx.beginPath(); ctx.arc(state.ball.x + 2, state.ball.y - 2, 2, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(state.ball.x - 3, state.ball.y + 1, 2, 0, Math.PI*2); ctx.fill(); // 5. HUD Barra de Potencia if (keys['Space']) { const p = state.players[state.controlledPlayer]; const power = Math.min((Date.now() - spacePressedTime) / 1000, 1.0); ctx.fillStyle = "red"; ctx.fillRect(p.x - 15, p.y + 20, 30 * power, 4); ctx.strokeStyle = "white"; ctx.strokeRect(p.x - 15, p.y + 20, 30, 4); } } let lastTime = 0; function gameLoop() { if (state.mode === 'PLAY') { let now = Date.now(); let dt = (now - lastTime) / 1000; lastTime = now; state.time -= dt; let mins = Math.floor(state.time / 60); let secs = Math.floor(state.time % 60); document.getElementById('timer').innerText = `${mins}:${secs < 10 ? '0'+secs : secs}`; if (state.time <= 0) endGame(); updatePhysics(); } draw(); requestAnimationFrame(gameLoop); } /** --- MENU LOGICA --- **/ function startFlow(type) { document.getElementById('main-menu').classList.add('hidden'); document.getElementById('league-select').classList.remove('hidden'); state.selectionStep = 0; // Elegir Liga PROPIA document.getElementById('league-title').innerText = "1. Elegí la Liga de TU Equipo"; renderLeagues(); } function renderLeagues() { const list = document.getElementById('league-list'); list.innerHTML = ""; Object.keys(DATABASE).forEach(key => { let div = document.createElement('div'); div.className = 'list-item'; div.innerText = DATABASE[key].name; div.onclick = () => selectLeague(key); list.appendChild(div); }); } function selectLeague(key) { const teams = DATABASE[key].teams; if (state.selectionStep === 0) { // Eligiendo mi liga state.tempSelection.myLeague = teams; state.selectionStep = 1; document.getElementById('league-select').classList.add('hidden'); document.getElementById('team-select').classList.remove('hidden'); document.getElementById('team-title').innerText = "2. Elegí TU Equipo"; renderTeams(teams); } else if (state.selectionStep === 2) { // Eligiendo liga rival state.tempSelection.rivalLeague = teams; state.selectionStep = 3; document.getElementById('league-select').classList.add('hidden'); document.getElementById('team-select').classList.remove('hidden'); document.getElementById('team-title').innerText = "4. Elegí Equipo RIVAL"; renderTeams(teams); } } function renderTeams(teamList) { const list = document.getElementById('team-list'); list.innerHTML = ""; teamList.forEach(t => { let div = document.createElement('div'); div.className = 'list-item'; div.innerText = t; div.style.borderLeft = `5px solid ${getColors(t)[0]}`; div.onclick = () => selectTeam(t); list.appendChild(div); }); } function selectTeam(t) { if (state.selectionStep === 1) { // Elegí mi equipo state.tempSelection.myTeam = t; // Ahora elegir rival state.selectionStep = 2; document.getElementById('team-select').classList.add('hidden'); document.getElementById('league-select').classList.remove('hidden'); document.getElementById('league-title').innerText = "3. Elegí Liga del RIVAL"; renderLeagues(); } else if (state.selectionStep === 3) { // Elegí rival state.tempSelection.rivalTeam = t; // Iniciar Juego initMatch(state.tempSelection.myTeam, state.tempSelection.rivalTeam); } } function backToMain() { location.reload(); } function backToLeagues() { state.selectionStep--; if (state.selectionStep < 0) state.selectionStep = 0; document.getElementById('team-select').classList.add('hidden'); document.getElementById('league-select').classList.remove('hidden'); renderLeagues(); } </script> </body> </html>
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

4

Requests

3

Domains

85KB

Transfer Size

95KB

Content Size

172.0ms

Dom Content Loaded

100.0ms

First Paint

242.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...