👑
FichaGame PRO
🪙 100 Fichas 💎 Tienda
← Volver al Blog
Física & Motores 2D

Implementación de Gravedad y Saltos Realistas en JavaScript para Minijuegos Platformer

📅 Publicado el 4 de Octubre, 2026 • Por FichaGame Pro Team

🕹️

El género de plataformas (*platformer*) es, sin lugar a dudas, uno de los pilares fundamentales en la historia de los videojuegos arcade. Desde los clásicos salones recreativos de los años 80 hasta las experiencias web optimizadas actuales que disfrutamos en FichaGame PRO, la sensación de control sobre un personaje que salta, cae, rebota y esquiva obstáculos define por completo la jugabilidad. Cuando un salto se siente pesado, impreciso o carente de inercia, el jugador pierde el interés de inmediato; por el contrario, un motor físico pulido con precisión matemática es capaz de enganchar durante horas.

En esta guía técnica exhaustiva de más de 2000 palabras, analizaremos al detalle cómo construir un sistema físico robusto desde cero utilizando JavaScript puro y el elemento Canvas 2D de HTML5. Abordaremos las fórmulas matemáticas esenciales de aceleración constante, la gestión del tiempo mediante MDN Web Docs, el control de saltos con inercia variable y las técnicas avanzadas de resolución de colisiones ortogonales. Si te apasiona el desarrollo web y quieres comprender cómo optimizamos nuestros minijuegos arcade interactivos, prepárate porque nos adentraremos de lleno en el código fuente.

1. Anatomía de un Motor de Plataformas en JavaScript

Antes de escribir la primera línea de código en JavaScript, is vital comprender la arquitectura que sostiene un juego de plataformas en 2D ejecutándose directamente en un navegador web. A diferencia de los motores comerciales pesados como Unity o Unreal Engine, que compilan en capas de bajo nivel, JavaScript opera dentro del motor V8 (o equivalentes) ejecutándose sobre un hilo principal que comparte recursos con el DOM, los estilos CSS y los eventos de usuario.

Un motor de plataformas ligero pero potente se compone de tres capas principales interconectadas de forma síncrona:

  • Capa de Entrada (Input Handler): Captura los eventos del teclado, ratón o pantallas táctiles virtuales, traduciéndolos en banderas booleanas o vectores de intención de movimiento.
  • Capa de Actualización Física (Physics Update): Aplica las leyes del movimiento rectilíneo uniformemente acelerado (MRUA), gestiona la gravedad, comprueba colisiones espaciales y actualiza las coordenadas de los objetos.
  • Capa de Renderizado (Canvas 2D Context): Limpia el búfer gráfico y dibuja los sprites, fondos y elementos de interfaz en sus nuevas posiciones calculadas.

Mantener estas tres capas desacopladas es el secreto mejor guardado para evitar bugs visuales y lograr tasas estables de 60 fotogramas por segundo. Puedes explorar el resultado final de esta arquitectura probando directamente nuestro catálogo en la sección de juegos arcade destacados.

2. El Bucle de Juego y la Dependencia Crítica del Delta Time

Uno de los errores más comunes al iniciarse en la programación de juegos web es actualizar las posiciones sumando valores fijos por cada iteración del bucle, por ejemplo: player.y += 5;. En los albores de la informática, esto funcionaba porque los ordenadores operaban a una velocidad de reloj estrictamente constante. Sin embargo, en la web moderna, los dispositivos de los usuarios varían enormemente: desde smartphones económicos con pantallas de 60Hz hasta monitores gaming de 144Hz, 240Hz o superiores.

Si confiamos en bucles basados puramente en fotogramas fijos, un usuario con un monitor de alta tasa de refresco experimentará un juego que corre al doble de velocidad, haciendo que el personaje salte el doble de alto y rompiendo por completo las mecánicas del juego. La solución estándar de la industria, respaldada por especificaciones de la W3C, es el uso de la API requestAnimationFrame combinada con el cálculo matemático del Delta Time.

let lastTime = 0;
const GRAVITY = 1800; // Píxeles por segundo al cuadrado

function gameLoop(timestamp) {
    if (!lastTime) lastTime = timestamp;
    const deltaTime = (timestamp - lastTime) / 1000; // Tiempo en segundos
    lastTime = timestamp;

    // Limitar el delta time máximo para evitar saltos gigantescos si la pestaña pierde foco
    const clampedDelta = Math.min(deltaTime, 0.1);

    updatePhysics(clampedDelta);
    renderFrame();

    requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);

Multiplicar las velocidades y aceleraciones por clampedDelta garantiza que el desplazamiento físico se mida en píxeles por segundo reales, logrando un comportamiento idéntico sin importar si el juego se ejecuta en un móvil antiguo o en un ordenador de gama alta. Si te interesa profundizar en técnicas complementarias de renderizado web, te invitamos a leer nuestra guía sobre optimización avanzada de Canvas 2D.

3. Modelado Matemático de la Gravedad y Velocidad Terminal

Para que un personaje caiga de una plataforma de forma natural, debemos simular una fuerza de aceleración constante hacia abajo (eje positivo +y en el sistema de coordenadas de HTML5 Canvas, donde el origen (0,0) se sitúa en la esquina superior izquierda).

La ecuación física fundamental que aplicamos en cada ciclo de actualización para la velocidad vertical es:

velocity.y += gravity * deltaTime;

Sin embargo, en el mundo real y en los videojuegos arcade equilibrados, los cuerpos caen hasta alcanzar una velocidad límite provocada por la resistencia del aire, conocida como velocidad terminal. Sin este límite, si un personaje cayera desde un abismo muy alto, su velocidad crecería indefinidamente hasta provocar desbordamientos numéricos o atravesar las colisiones del suelo por tunelamiento.

class Player {
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.vx = 0;
        this.vy = 0;
        this.width = 32;
        this.height = 48;
        this.isGrounded = false;
    }

    applyPhysics(deltaTime) {
        // Aplicar gravedad si no está apoyado en el suelo
        if (!this.isGrounded) {
            this.vy += 1200 * deltaTime; // Aceleración de gravedad
            // Establecer velocidad terminal de caída
            if (this.vy > 800) {
                this.vy = 800;
            }
        }

        // Actualizar posición basada en la velocidad y el tiempo transcurrido
        this.x += this.vx * deltaTime;
        this.y += this.vy * deltaTime;
    }
}

Como señalan manuales de ingeniería de software e instituciones de referencia como Wikipedia, el control preciso de los límites numéricos previene anomalías físicas imprevistas. Puedes poner a prueba estas fórmulas interactivas disfrutando de nuestro catálogo en la sección de juegos arcade destacados.

4. Arquitectura de un Salto Realista: Impulso Inicial y Control Aéreo

El salto es el núcleo absoluto de cualquier juego de plataformas. Un salto plano y robótico arruina la experiencia del usuario. Para conseguir un salto orgánico, no debemos modificar directamente la posición y del jugador, sino aplicarle un impulso negativo instantáneo a su vector de velocidad vertical (this.vy = -jumpForce;).

Además, los mejores juegos implementan dos características avanzadas que distinguen un título amateur de uno profesional:

  • Salto Variable (Variable Jump Height): Permite al jugador controlar la altura del salto según el tiempo que mantenga presionada la tecla o el botón táctil. Si el usuario suelta el botón antes de alcanzar el punto máximo del salto, cortamos bruscamente la velocidad ascendente multiplicándola por un factor de amortiguación (por ejemplo, this.vy *= 0.4;), logrando saltos cortos y precisos.
  • Inercia Aérea Limitada (Air Control): En el aire, la fricción es menor que en el suelo. Modificar la aceleración lateral horizontal con menor autoridad que en tierra otorga una sensación de peso muy característica de los plataformas clásicos.
function handleInput(player, inputState, deltaTime) {
    // Control de movimiento lateral con inercia
    const acceleration = player.isGrounded ? 1500 : 800;
    const friction = player.isGrounded ? 1200 : 300;

    if (inputState.left) {
        player.vx -= acceleration * deltaTime;
    } else if (inputState.right) {
        player.vx += acceleration * deltaTime;
    } else {
        // Aplicar fricción para detener el movimiento gradualmente
        if (player.vx > 0) {
            player.vx = Math.max(0, player.vx - friction * deltaTime);
        } else if (player.vx < 0) {
            player.vx = Math.min(0, player.vx + friction * deltaTime);
        }
    }

    // Limitar velocidad horizontal máxima
    const maxSpeed = 300;
    player.vx = Math.max(-maxSpeed, Math.min(maxSpeed, player.vx));

    // Ejecutar salto
    if (inputState.jump && player.isGrounded) {
        player.vy = -550; // Impulso inicial hacia arriba
        player.isGrounded = false;
    }
}

Este nivel de ajuste fino es lo que transforma un código sencillo en una experiencia altamente adictiva. Si quieres aprender más sobre la estructuración de mecánicas y software web, te invitamos a explorar nuestro blog técnico especializado.

5. Detección y Resolución de Colisiones Axis-Aligned (AABB) con Plataformas

De nada sirve calcular una gravedad perfecta si nuestro personaje atraviesa las plataformas y cae al vacío infinito. La detección y resolución de colisiones es el proceso más delicado en el desarrollo de motores 2D. Para rectángulos alineados con los ejes (como bloques, suelos y paredes), el algoritmo estándar es el AABB (Axis-Aligned Bounding Box).

Sin embargo, detectar que dos cajas se solapan es solo la mitad del trabajo; el verdadero desafío radica en la resolución de la colisión: decidir exactamente dónde recolocar al jugador para que no se quede incrustado dentro del suelo o una pared lateral. Para evitar errores de precisión, los programadores experimentados separamos siempre la comprobación de colisiones en dos ejes independientes: primero el eje horizontal X y luego el eje vertical Y.

function resolveCollisions(player, platforms) {
    player.isGrounded = false;

    // 1. Resolver movimiento y colisión en el eje X
    player.x += player.vx * deltaTime;
    for (const plat of platforms) {
        if (checkAABB(player, plat)) {
            if (player.vx > 0) { // Chocaendo por la derecha
                player.x = plat.x - player.width;
            } else if (player.vx < 0) { // Chocando por la izquierda
                player.x = plat.x + plat.width;
            }
            player.vx = 0;
        }
    }

    // 2. Resolver movimiento y colisión en el eje Y
    player.y += player.vy * deltaTime;
    for (const plat of platforms) {
        if (checkAABB(player, plat)) {
            if (player.vy > 0) { // Cayendo sobre la plataforma
                player.y = plat.y - player.height;
                player.vy = 0;
                player.isGrounded = true;
            } else if (player.vy < 0) { // Golpeando el techo con la cabeza
                player.y = plat.y + plat.height;
                player.vy = 0;
            }
        }
    }
}

function checkAABB(rect1, rect2) {
    return rect1.x < rect2.x + rect2.width &&
           rect1.x + rect1.width > rect2.x &&
           rect1.y < rect2.y + rect2.height &&
           rect1.y + rect1.height > rect2.y;
}

Tal y como discuten referentes de la industria en portales como Game Developer, separar los ejes de colisión elimina por completo los molestos bugs de traspaso en esquinas. Puedes probar estos algoritmos en acción disfrutando de nuestro catálogo en la sección de juegos arcade destacados.

6. Fricción, Rozamiento y Control de Movimiento Lateral en Suelos

La sensación de deslizamiento al detenerse es otro factor crucial en la física de plataformas. Si un personaje se detiene de forma instantánea al soltar el mando, el movimiento se percibe robótico y poco natural. Introducir un coeficiente de fricción realista permite simular superficies variadas (como hielo resbaladizo, asfalto adherente o plataformas móviles).

Al multiplicar la velocidad horizontal por un coeficiente de fricción menor a 1 (por ejemplo, 0.85 por fotograma o aplicado mediante el Delta Time), logramos una frenada suave y gradual conocida como *damping*. Este nivel de pulido técnico es el que aplicamos en todos los minijuegos desarrollados en FichaGame PRO.

7. Optimización de Memoria y Rendimiento en Navegadores Móviles

Los juegos web actuales deben ejecutarse con la misma fluidez en un ordenador de sobremesa con refrigeración líquida que en un smartphone de gama media mientras el usuario recibe notificaciones en segundo plano. El mayor enemigo del rendimiento en JavaScript no son los cálculos matemáticos puros, sino la **recolección de basura (Garbage Collection)** provocada por la creación excesiva de objetos temporales en cada fotograma.

Para garantizar una tasa constante de 60 FPS sin tirones (*jank*), implementamos rigurosas prácticas de optimización:

  • Object Pooling (Búfer de Objetos): En lugar de instanciar nuevos objetos vectoriales o partículas en cada salto o impacto, reutilizamos instancias estáticas previamente reservadas en memoria.
  • Estructuras de Datos Planas: Sustituimos objetos complejos anidados por arrays tipados (`Float32Array`) cuando gestionamos grandes cantidades de entidades físicas simultáneas.
  • Renderizado Selectivo: Evitamos redibujar elementos estáticos del fondo recalculándolos en un lienzo secundario independiente (layering de Canvas).

Estas medidas garantizan tiempos de carga instantáneos sin necesidad de descargas pesadas. Si quieres profundizar en técnicas de desarrollo web eficiente, te recomendamos leer nuestro artículo sobre creación de minijuegos en JavaScript puro.

8. Casos Prácticos y Arquitectura en FichaGame PRO

El desarrollo de experiencias arcade basadas en estándares web abiertos demuestra el enorme poder de HTML5 frente a tecnologías propietarias obsoletas. Al eliminar barreras de entrada y plugins externos, los usuarios pueden acceder de forma instantánea a contenidos interactivos de alta calidad, participar en competiciones de la comunidad y canjear recompensas en la tienda oficial de mejoras y fichas.

Cada título alojado en nuestra plataforma se somete a estrictas pruebas de rendimiento multiplataforma, asegurando una experiencia fluida, segura y altamente optimizada tanto para jugadores ocasionales de PC como para entusiastas móviles.

9. Preguntas Frecuentes (FAQ)

¿Es necesario utilizar motores externos como Matter.js para un juego de plataformas web?

Para la inmensa mayoría de minijuegos arcade de plataformas 2D, escribir un sistema de físicas AABB nativo en JavaScript puro ofrece un control absoluto del rendimiento, un código más ligero y cero dependencias externas innecesarias.

¿Cómo afecta el Delta Time a la velocidad de salto en diferentes pantallas?

El Delta Time mide el tiempo exacto entre fotogramas, multiplicando las fuerzas físicas por este factor. Esto garantiza que el personaje salte exactamente a la misma altura y velocidad en monitores de 60Hz, 144Hz o dispositivos móviles.

¿Dónde puedo probar minijuegos creados con estas técnicas físicas avanzadas?

Puedes explorar todo nuestro catálogo interactivo actualizado y disfrutar de los títulos arcade directamente en la plataforma de FichaGame PRO de forma totalmente gratuita.

Disfruta de una experiencia totalmente fluida probando nuestros títulos arcade directamente en la plataforma o descubriendo más publicaciones técnicas en nuestra sección de artículos y novedades.