Service Smart

Como hacer un juego de Ping Pong con Html5 y JavaScript

Ping Pong Mejorado - Alta Velocidad

Juego rápido y fluido con IA adaptativa. ¡Demuestra tus habilidades!

Controles
  • Flecha Arriba: Mover hacia arriba
  • Flecha Abajo: Mover hacia abajo
  • Espacio: Pausar/Reanudar
  • R: Reiniciar juego
Estadísticas

0

Jugador

1

Nivel

0

SMART
SERVICE

Características del Juego

Alta Velocidad

Optimizado para máxima fluidez:

  • Velocidad inicial de pelota: 8px/frame
  • Incremento progresivo por nivel
  • Máxima velocidad: 15px/frame
  • Respuesta instantánea a controles
IA Inteligente

Sistema adaptativo de dificultad:

  • Nivel 1-3: Velocidad media + predicción básica
  • Nivel 4-7: Alta velocidad + predicción media
  • Nivel 8+: Velocidad máxima + predicción avanzada

Código Completo para Copiar

HTML, CSS y JavaScript del Ping Pong Mejorado
<!-- HTML del juego -->
<div class="container">
  <div class="row">
    <div class="col-md-6">
      <div class="card bg-secondary text-white">
        <div class="card-body">
          <h5 class="card-title">Controles</h5>
          <ul class="list-unstyled">
            <li>Flecha Arriba: Mover paleta hacia arriba</li>
            <li>Flecha Abajo: Mover paleta hacia abajo</li>
            <li>Espacio: Pausar/Reanudar</li>
            <li>R: Reiniciar juego</li>
          </ul>
        </div>
      </div>
    </div>
    <div class="col-md-6">
      <div class="card bg-secondary text-white">
        <div class="card-body">
          <h5 class="card-title">Estadísticas</h5>
          <div class="row text-center">
            <div class="col-4">
              <h3 id="player-score" class="text-warning">0</h3>
              <small>Jugador</small>
            </div>
            <div class="col-4">
              <h3 id="level" class="text-info">1</h3>
              <small>Nivel</small>
            </div>
            <div class="col-4">
              <h3 id="pc-score" class="text-danger">0</h3>
              <small>Computadora</small>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  
  <div class="text-center my-4">
    <canvas id="pingpongCanvas" width="800" height="500" class="border border-light rounded shadow"></canvas>
  </div>
  
  <div class="text-center">
    <button id="startBtn" class="btn btn-success btn-lg me-2">Iniciar Juego</button>
    <button id="pauseBtn" class="btn btn-warning btn-lg me-2" disabled>Pausar</button>
    <button id="resetBtn" class="btn btn-danger btn-lg">Reiniciar</button>
  </div>
</div>

<style>
  /* Estilos del juego */
  canvas {
    background: #000;
    display: block;
    margin: 0 auto;
  }
  
  .card {
    margin-bottom: 1rem;
  }
</style>

<script>
  // JavaScript del juego Ping Pong Mejorado
  const canvas = document.getElementById('pingpongCanvas');
  const ctx = canvas.getContext('2d');
  
  // Elementos del juego
  const playerScoreElem = document.getElementById('player-score');
  const pcScoreElem = document.getElementById('pc-score');
  const levelElem = document.getElementById('level');
  const startBtn = document.getElementById('startBtn');
  const pauseBtn = document.getElementById('pauseBtn');
  const resetBtn = document.getElementById('resetBtn');
  const gameMessage = document.getElementById('gameMessage');
  
  // Variables del juego
  let gameRunning = false;
  let gamePaused = false;
  let animationId;
  let keys = {};
  
  // Configuración del juego - VELOCIDAD MEJORADA
  const config = {
    paddleWidth: 12,
    paddleHeight: 90,
    ballSize: 10,
    initialBallSpeed: 8,  // Aumentada para mayor velocidad
    maxBallSpeed: 15,     // Velocidad máxima más alta
    paddleSpeed: 12,      // Velocidad de paleta aumentada
    winningScore: 7       // Puntuación para ganar reducida para juegos más rápidos
  };
  
  // Objetos del juego
  const player = {
    x: 20,
    y: canvas.height / 2 - config.paddleHeight / 2,
    width: config.paddleWidth,
    height: config.paddleHeight,
    speed: config.paddleSpeed,
    score: 0
  };
  
  const pc = {
    x: canvas.width - 20 - config.paddleWidth,
    y: canvas.height / 2 - config.paddleHeight / 2,
    width: config.paddleWidth,
    height: config.paddleHeight,
    speed: config.paddleSpeed,
    score: 0
  };
  
  const ball = {
    x: canvas.width / 2,
    y: canvas.height / 2,
    size: config.ballSize,
    speed: config.initialBallSpeed,
    velocityX: 0,
    velocityY: 0
  };
  
  // Sistema de niveles
  let level = 1;
  let rallyCount = 0;
  
  // Inicializar el juego
  function initGame() {
    resetBall();
    player.score = 0;
    pc.score = 0;
    level = 1;
    rallyCount = 0;
    updateScore();
    updateLevel();
  }
  
  // Reiniciar la pelota con dirección aleatoria
  function resetBall() {
    ball.x = canvas.width / 2;
    ball.y = canvas.height / 2;
    
    // Dirección aleatoria con mayor velocidad base
    const direction = Math.random() > 0.5 ? 1 : -1;
    const speed = config.initialBallSpeed + (level * 0.4); // Incremento más agresivo
    
    ball.velocityX = direction * Math.min(speed, config.maxBallSpeed);
    ball.velocityY = (Math.random() * 4 - 2) * (config.initialBallSpeed / 3);
    
    rallyCount = 0;
  }
  
  // Dibujar elementos
  function draw() {
    // Limpiar canvas
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    // Dibujar línea central punteada
    ctx.setLineDash([5, 10]);
    ctx.beginPath();
    ctx.moveTo(canvas.width / 2, 0);
    ctx.lineTo(canvas.width / 2, canvas.height);
    ctx.strokeStyle = '#444';
    ctx.lineWidth = 2;
    ctx.stroke();
    ctx.setLineDash([]);
    
    // Dibujar paletas con efecto de gradiente
    const playerGradient = ctx.createLinearGradient(player.x, 0, player.x + player.width, 0);
    playerGradient.addColorStop(0, '#4da6ff');
    playerGradient.addColorStop(1, '#80c1ff');
    ctx.fillStyle = playerGradient;
    ctx.fillRect(player.x, player.y, player.width, player.height);
    
    const pcGradient = ctx.createLinearGradient(pc.x, 0, pc.x + pc.width, 0);
    pcGradient.addColorStop(0, '#ff4d4d');
    pcGradient.addColorStop(1, '#ff8080');
    ctx.fillStyle = pcGradient;
    ctx.fillRect(pc.x, pc.y, pc.width, pc.height);
    
    // Dibujar pelota con efecto de brillo
    ctx.fillStyle = '#fff';
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.size, 0, Math.PI * 2);
    ctx.fill();
    
    // Efecto de brillo en la pelota
    ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
    ctx.beginPath();
    ctx.arc(ball.x - ball.size/3, ball.y - ball.size/3, ball.size/3, 0, Math.PI * 2);
    ctx.fill();
  }
  
  // Actualizar posición de elementos
  function update() {
    if (gamePaused) return;
    
    // Mover pelota con velocidad mejorada
    ball.x += ball.velocityX;
    ball.y += ball.velocityY;
    
    // Rebote en paredes superior e inferior
    if (ball.y + ball.size > canvas.height || ball.y - ball.size < 0) {
      ball.velocityY = -ball.velocityY;
    }
    
    // Detectar colisión con paletas - FÍSICA MEJORADA
    // Jugador
    if (
      ball.x - ball.size < player.x + player.width &&
      ball.y + ball.size > player.y &&
      ball.y - ball.size < player.y + player.height &&
      ball.velocityX < 0
    ) {
      // Ajustar ángulo y velocidad basado en dónde golpea la paleta
      const hitPosition = (ball.y - player.y) / player.height;
      const angle = hitPosition * Math.PI / 2 - Math.PI / 4;
      
      // Incrementar velocidad con cada golpe
      const speedIncrease = 0.1;
      const currentSpeed = Math.sqrt(ball.velocityX * ball.velocityX + ball.velocityY * ball.velocityY);
      const newSpeed = Math.min(currentSpeed * (1 + speedIncrease), config.maxBallSpeed);
      
      ball.velocityX = Math.cos(angle) * newSpeed;
      ball.velocityY = Math.sin(angle) * newSpeed;
      
      rallyCount++;
      checkLevelUp();
    }
    
    // Computadora
    if (
      ball.x + ball.size > pc.x &&
      ball.y + ball.size > pc.y &&
      ball.y - ball.size < pc.y + pc.height &&
      ball.velocityX > 0
    ) {
      // Ajustar ángulo y velocidad basado en dónde golpea la paleta
      const hitPosition = (ball.y - pc.y) / pc.height;
      const angle = hitPosition * Math.PI / 2 - Math.PI / 4;
      
      // Incrementar velocidad con cada golpe
      const speedIncrease = 0.1;
      const currentSpeed = Math.sqrt(ball.velocityX * ball.velocityX + ball.velocityY * ball.velocityY);
      const newSpeed = Math.min(currentSpeed * (1 + speedIncrease), config.maxBallSpeed);
      
      ball.velocityX = -Math.cos(angle) * newSpeed;
      ball.velocityY = Math.sin(angle) * newSpeed;
      
      rallyCount++;
      checkLevelUp();
    }
    
    // IA de la computadora MEJORADA
    moveComputerPaddle();
    
    // Mover jugador con teclado
    movePlayerPaddle();
    
    // Puntuación
    if (ball.x < 0) {
      pc.score++;
      updateScore();
      resetBall();
      checkLevelDown();
    } else if (ball.x > canvas.width) {
      player.score++;
      updateScore();
      resetBall();
      checkLevelUp();
    }
    
    // Verificar ganador
    if (player.score >= config.winningScore || pc.score >= config.winningScore) {
      endGame();
    }
  }
  
  // Mover paleta del jugador
  function movePlayerPaddle() {
    if (keys['ArrowUp']) {
      player.y = Math.max(0, player.y - player.speed);
    }
    if (keys['ArrowDown']) {
      player.y = Math.min(canvas.height - player.height, player.y + player.speed);
    }
  }
  
  // Mover paleta de la computadora con IA MEJORADA
  function moveComputerPaddle() {
    // Calcular posición objetivo con predicción
    const predictY = ball.y + (ball.velocityY * (pc.x - ball.x) / ball.velocityX);
    const targetY = predictY - pc.height / 2;
    
    // Ajustar la dificultad según el nivel
    let reactionSpeed;
    let errorMargin;
    
    if (level <= 3) {
      // Nivel fácil: reacción media, margen de error alto
      reactionSpeed = 0.08;
      errorMargin = 50;
    } else if (level <= 7) {
      // Nivel medio: reacción rápida, margen de error medio
      reactionSpeed = 0.12;
      errorMargin = 30;
    } else {
      // Nivel difícil: reacción muy rápida, margen de error bajo
      reactionSpeed = 0.18;
      errorMargin = 15;
    }
    
    // Añadir error de predicción para hacerlo más humano
    const error = (Math.random() - 0.5) * errorMargin;
    const finalTarget = targetY + error;
    
    // Mover suavemente hacia la posición objetivo
    const diff = finalTarget - pc.y;
    pc.y += diff * reactionSpeed;
    
    // Mantener dentro de los límites
    if (pc.y < 0) pc.y = 0;
    if (pc.y + pc.height > canvas.height) pc.y = canvas.height - pc.height;
  }
  
  // Verificar si subir de nivel
  function checkLevelUp() {
    // Subir nivel si el jugador tiene ventaja de 3 puntos
    if (player.score - pc.score >= 3 && level < 10) {
      level++;
      updateLevel();
      showMessage(`¡Nivel ${level}!`, 'success');
    }
    // Subir nivel si hay un rally muy largo
    else if (rallyCount >= 8 && level < 10) {
      level++;
      updateLevel();
      showMessage(`¡Rally épico! Nivel ${level}`, 'success');
      rallyCount = 0;
    }
  }
  
  // Verificar si bajar de nivel
  function checkLevelDown() {
    // Bajar nivel si la computadora tiene ventaja de 3 puntos
    if (pc.score - player.score >= 3 && level > 1) {
      level--;
      updateLevel();
      showMessage(`Nivel ${level}`, 'warning');
    }
  }
  
  // Actualizar marcador
  function updateScore() {
    playerScoreElem.textContent = player.score;
    pcScoreElem.textContent = pc.score;
  }
  
  // Actualizar nivel
  function updateLevel() {
    levelElem.textContent = level;
  }
  
  // Mostrar mensaje temporal
  function showMessage(text, type) {
    gameMessage.textContent = text;
    gameMessage.className = `position-absolute top-50 start-50 translate-middle display-4 fw-bold text-${type}`;
    gameMessage.style.display = 'block';
    
    setTimeout(() => {
      gameMessage.style.display = 'none';
    }, 1200);
  }
  
  // Terminar juego
  function endGame() {
    gameRunning = false;
    cancelAnimationFrame(animationId);
    
    const winner = player.score > pc.score ? 'Jugador' : 'Computadora';
    showMessage(`¡${winner} gana!`, player.score > pc.score ? 'success' : 'danger');
    
    startBtn.disabled = false;
    pauseBtn.disabled = true;
  }
  
  // Bucle del juego optimizado
  function gameLoop() {
    draw();
    update();
    
    if (gameRunning) {
      animationId = requestAnimationFrame(gameLoop);
    }
  }
  
  // Controles del teclado MEJORADOS
  document.addEventListener('keydown', (e) => {
    keys[e.key] = true;
    
    if (e.key === ' ' && gameRunning) {
      togglePause();
      e.preventDefault();
    }
    
    if ((e.key === 'r' || e.key === 'R') && gameRunning) {
      resetGame();
    }
  });
  
  document.addEventListener('keyup', (e) => {
    keys[e.key] = false;
  });
  
  // Funciones de control del juego
  function startGame() {
    if (!gameRunning) {
      gameRunning = true;
      gamePaused = false;
      startBtn.disabled = true;
      pauseBtn.disabled = false;
      gameLoop();
    }
  }
  
  function togglePause() {
    gamePaused = !gamePaused;
    pauseBtn.textContent = gamePaused ? 'Reanudar' : 'Pausar';
    pauseBtn.innerHTML = gamePaused ? 
      ' Reanudar' : 
      ' Pausar';
    
    if (!gamePaused && gameRunning) {
      gameLoop();
    }
  }
  
  function resetGame() {
    gameRunning = false;
    gamePaused = false;
    cancelAnimationFrame(animationId);
    initGame();
    draw();
    
    startBtn.disabled = false;
    pauseBtn.disabled = true;
    pauseBtn.textContent = 'Pausar';
    pauseBtn.innerHTML = ' Pausar';
    
    gameMessage.style.display = 'none';
  }
  
  // Event listeners
  startBtn.addEventListener('click', startGame);
  pauseBtn.addEventListener('click', togglePause);
  resetBtn.addEventListener('click', resetGame);
  
  // Inicializar
  initGame();
  draw();
</script>

¿Listo para dar el siguiente paso?

Contáctanos hoy mismo y un especialista te atenderá a la brevedad.