Introducción al Desarrollo de Videojuegos con GameMaker · Módulo 4: Controles, movimientos y manejo del jugador.
Implementación del salto básico
Clase 19 de 60 · 60 min
También disponible en: EN
Introducción: La física del salto en los videojuegos 2D
En el diseño de videojuegos de plataformas en dos dimensiones, el salto es habitualmente la mecánica central alrededor de la cual gira toda la experiencia del jugador. Un salto que se sienta impreciso, excesivamente lento («flotante») o rígido restará satisfacción a la jugabilidad, sin importar cuán detallado sea el arte gráfico o cuán profunda sea la narrativa. Para que un salto sea percibido como natural y gratificante, no podemos simplemente desplazar al personaje hacia arriba a una velocidad fija y luego devolverlo al suelo mediante una traslación uniforme; debemos emular, de forma simplificada y controlada, las leyes básicas de la cinemática clásica: impulso y aceleración gravitatoria.
A lo largo de las lecciones anteriores de este módulo, configuramos la lectura de pulsaciones del teclado y el movimiento horizontal del personaje a través de su variable personalizada de velocidad horizontal (`hsp`), además de orientar visualmente el sprite según la dirección de avance mediante `image_xscale`. En esta clase daremos el paso lógico siguiente: dotar a nuestro personaje de desplazamiento vertical en el eje Y. Calcularemos paso a paso la velocidad vertical (`vsp`), aplicaremos un impulso instantáneo hacia arriba cuando el jugador presione el botón de salto y someteremos dicho impulso a una desaceleración progresiva provocada por una fuerza de gravedad constante.
El sistema de coordenadas en GameMaker y el eje vertical
Antes de escribir una sola línea de código para el salto, es imperativo entender cómo interpreta GameMaker el espacio bidimensional de una habitación (Room). En la geometría cartesiana tradicional que se enseña en la educación formal, el origen (0, 0) suele ubicarse en el centro o en la esquina inferior izquierda de un plano, donde los valores de Y aumentan a medida que nos desplazamos hacia arriba. En el desarrollo de videojuegos y en la renderización de pantallas digitales, este estándar difiere notablemente.
En GameMaker, el punto de origen (0, 0) de cualquier Room se localiza en la esquina superior izquierda. La orientación de los ejes es la siguiente:
| Eje | Dirección positiva (+) | Dirección negativa (-) | Efecto en el juego |
|---|---|---|---|
| Eje Horizontal (X) | Hacia la derecha | Hacia la izquierda | Avanzar o retroceder lateralmente |
| Eje Vertical (Y) | Hacia abajo | Hacia arriba | Descenso/caída (+) o ascenso/salto (-) |
Esta particularidad del eje Y es el origen más común de errores y confusiones en desarrolladores principiantes. Subir en la pantalla implica restar píxeles al valor de la coordenada `y`, mientras que caer o descender implica sumar píxeles. Por lo tanto, si deseamos que nuestro personaje salte con fuerza hacia arriba, debemos asignarle una velocidad vertical negativa inicial. A medida que la gravedad actúe, sumaremos un valor positivo a esa velocidad en cada ciclo de ejecución, provocando que la velocidad pase de ser muy negativa (ascenso rápido), a cero (vértice superior del salto), y finalmente a valores positivos (caída libre hacia el suelo).
Cinemática del salto: Impulso, gravedad y parábola
El movimiento que describe un cuerpo al saltar en un entorno con gravedad constante es una parábola. Este arco de salto consta de tres fases bien diferenciadas que debemos replicar en nuestro ciclo de procesamiento por fotograma (Step Event):
1. El Impulso Inicial: Al momento exacto en que el usuario presiona la tecla asignada al salto, se transfiere al personaje una velocidad vertical negativa instantánea de magnitud considerable (por ejemplo, `vsp = -9`). En ese instante preciso, el personaje se mueve hacia arriba a su máxima velocidad. 2. La Desaceleración y el Ápice: En cada fotograma sucesivo, la gravedad añade una pequeña cantidad de velocidad positiva (por ejemplo, `vsp += 0.4`). Conforme los fotogramas transcurren, la velocidad vertical se aproxima a cero: -9, -8.6, -8.2, ..., -0.6, -0.2, 0. Cuando `vsp` alcanza exactamente cero, el personaje se encuentra en el ápice o punto culminante de su trayectoria, suspendido en el aire durante una fracción infinitesimal de segundo. 3. La Caída Acelerada: Inmediatamente después del ápice, la gravedad continúa acumulándose. Ahora `vsp` se vuelve positiva (+0.4, +0.8, +1.2...) y el personaje empieza a descender, ganando velocidad hacia abajo hasta colisionar con una superficie firme o alcanzar una velocidad terminal límite preestablecida.

Variables necesarias en el Evento Create
Para implementar este comportamiento de manera modular y escalable, no debemos utilizar valores numéricos directos («números mágicos») dispersos en la lógica de control. Por el contrario, declararemos variables descriptivas en el evento Create de nuestro objeto principal del jugador (`obj_player`). Reutilizaremos las variables creadas en clases anteriores (`hsp` y `walk_speed`) y añadiremos aquellas dedicadas en exclusiva al movimiento vertical.
/// Evento Create de obj_player
// --- Variables de movimiento horizontal (repaso lecciones previas) ---
hsp = 0;
walk_speed = 4;
// --- Variables de movimiento vertical y salto ---
vsp = 0; // Velocidad vertical actual del jugador (píxeles por paso)
grav = 0.4; // Aceleración constante de la gravedad
jump_speed = 9; // Fuerza o magnitud del impulso de salto (píxeles hacia arriba)
vsp_max = 12; // Velocidad terminal máxima de caída (evita caídas excesivamente rápidas)
// --- Variable temporal de soporte de suelo ---
// Nota: En el Módulo 5 construiremos el sistema formal de colisiones con bloques.
// Por ahora, utilizaremos una coordenada base en Y como suelo provisional de pruebas.
ground_y = 500;Analicemos con detalle el propósito de cada variable vertical recién declarada:
• `vsp`: Representa el desplazamiento vertical que el objeto experimentará en el fotograma actual. Al inicializarse en 0, el personaje comienza en reposo vertical. • `grav`: Es el incremento que sumaremos a `vsp` en cada paso del juego. Un valor entre 0.3 y 0.6 suele ofrecer una sensación clásica de plataformas retro sin volverse abrupto ni provocar un efecto submarino. • `jump_speed`: Determina la potencia del salto. Nótese que se define como un número positivo (9); luego, al aplicarlo como impulso hacia arriba, lo multiplicaremos por -1 o lo asignaremos directamente como negativo (`-jump_speed`). • `vsp_max`: Es la velocidad terminal. En un entorno de física simulada sin límite superior, un personaje que cae desde una gran altura acumularía tanta velocidad positiva que podría atravesar plataformas por un error de muestreo discreto (túnel cuántico computacional) o volverse incontrolable para el ojo humano. Limitar `vsp` garantiza estabilidad. • `ground_y`: Se define temporalmente una altura en la Room (500 píxeles desde el borde superior) para que nuestro personaje tenga una superficie de apoyo donde posarse mientras llegamos a la lección de colisiones complejas con instancias sólidas.
Diferenciación de entradas: keyboard_check frente a keyboard_check_pressed
En la primera lección de este módulo vimos que GameMaker dispone de diversas funciones para interactuar con los dispositivos de entrada. Para el salto, la distinción entre `keyboard_check` y `keyboard_check_pressed` es de trascendental importancia técnica:
• `keyboard_check(key)` retorna `true` de manera ininterrumpida durante todos y cada uno de los fotogramas en los que la tecla se mantenga físicamente apretada hacia abajo. Es la función idónea para correr o caminar lateralmente, pues deseamos que la velocidad horizontal persista mientras se mantenga la pulsación. • `keyboard_check_pressed(key)` retorna `true` únicamente en el primer fotograma exacto en el que el teclado registra el contacto físico de la tecla. Si el jugador sigue sosteniendo la tecla presionada durante diez segundos, la función continuará retornando `false` hasta que la suelte y la presione otra vez.
💡 Regla de oro: Para detonar un salto siempre debe emplearse keyboard_check_pressed. Si se usase keyboard_check para iniciar el impulso, el código renovaría la fuerza de salto en cada fotograma sucesivo mientras la barra espaciadora estuviera oprimida, haciendo que el personaje se eleve como un cohete sin ser afectado por la gravedad hasta que el jugador soltara la tecla.
Estructuración de la física en el Evento Step
El Evento Step se ejecuta recurrentemente a la velocidad de fotogramas del juego (habitualmente 60 veces por segundo). La estructuración del código en este evento debe seguir un orden lógico riguroso de captura, procesamiento y aplicación:
1. Captura de entradas (Inputs): Leer el estado del teclado o mando y almacenarlo en variables locales booleanas. 2. Procesamiento horizontal: Calcular `hsp` en función de las teclas laterales. 3. Detección de suelo: Comprobar si el personaje está actualmente posado en una superficie firme. 4. Procesamiento vertical del salto: Aplicar el impulso negativo solo si el jugador presiona el botón y cumple con la condición de estar en el suelo. 5. Aplicación de la gravedad: Incrementar `vsp` con el valor de `grav`, limitando el resultado con `vsp_max`. 6. Actualización de coordenadas espaciales: Modificar las coordenadas nativas `x` e `y` del objeto sumándoles `hsp` y `vsp`.
A continuación, se expone la implementación completa y comentada dentro del evento Step de `obj_player`:
/// Evento Step de obj_player
// --------------------------------------------------------
// 1. CAPTURA DE ENTRADAS DEL JUGADOR
// --------------------------------------------------------
var _key_right = keyboard_check(vk_right) || keyboard_check(ord("D"));
var _key_left = keyboard_check(vk_left) || keyboard_check(ord("A"));
var _key_jump = keyboard_check_pressed(vk_space) || keyboard_check_pressed(ord("W"));
// --------------------------------------------------------
// 2. MOVIMIENTO HORIZONTAL
// --------------------------------------------------------
var _move_dir = _key_right - _key_left;
hsp = _move_dir * walk_speed;
// Inversión visual del sprite según la dirección
if (_move_dir != 0) {
image_xscale = _move_dir;
}
// --------------------------------------------------------
// 3. ESTADO DE SUELO PROVISIONAL Y SALTO
// --------------------------------------------------------
// Verificamos si el personaje se encuentra sobre la línea de suelo provisional.
var _is_on_ground = (y >= ground_y);
if (_is_on_ground) {
// Si estamos tocando el suelo, fijamos la posición vertical y cancelamos vsp residual.
y = ground_y;
vsp = 0;
// Si el jugador presiona el botón de salto mientras está en el suelo:
if (_key_jump) {
vsp = -jump_speed; // Asignamos el impulso vertical negativo hacia arriba
}
} else {
// Si no estamos en el suelo, el personaje está en el aire: aplicamos gravedad.
vsp += grav;
// Limitamos la velocidad de caída a la velocidad terminal permitida.
if (vsp > vsp_max) {
vsp = vsp_max;
}
}
// --------------------------------------------------------
// 4. ACTUALIZACIÓN FINAL DE POSICIONES
// --------------------------------------------------------
x += hsp;
y += vsp;Revisemos con precisión lo que ocurre en cada bloque lógico. La condición `var _is_on_ground = (y >= ground_y);` evalúa si el personaje ha alcanzado o sobrepasado la altura fijada para el suelo. Si esto es verdadero, anulamos cualquier velocidad de descenso residual (`vsp = 0`) e impedimos que el personaje se hunda forzando `y = ground_y`.
Dentro de ese mismo bloque condicional de suelo se verifica `if (_key_jump)`. Al evaluar el salto exclusivamente cuando `_is_on_ground` es verdadero, resolvemos de raíz el problema clásico del «salto infinito»: el usuario no puede volver a saltar mientras se encuentre suspendido en el aire. Cuando el impulso se ejecuta (`vsp = -jump_speed`), en el siguiente fotograma `y` se modificará mediante `y += vsp`, provocando que `y` sea menor a `ground_y`. Automáticamente, `_is_on_ground` pasará a ser falso, entrando en la rama alternativa `else` donde la gravedad incrementa la velocidad hasta consumar el descenso parabólico.
La relación matemática entre la altura del salto y la gravedad
Frecuentemente, los principiantes intentan ajustar la sensación del salto cambiando valores al azar hasta que «parece funcionar». Sin embargo, comprender la base matemática detrás del cálculo de la velocidad vertical permite calibrar con exactitud milimétrica la altura máxima alcanzable y la duración temporal del salto.
En la física newtoniana simplificada que emplean los videojuegos de plataformas discretos, podemos aproximar la altura máxima ($h$) en píxeles que alcanzará un salto con la siguiente fórmula cinemática:
$$h = \frac{v_{salto}^2}{2 \cdot g}$$
Del mismo modo, el tiempo estimado ($t$) en fotogramas que le toma al personaje alcanzar la cúspide del salto viene dado por:
$$t = \frac{v_{salto}}{g}$$
Si en nuestro juego configuramos `jump_speed = 9` y `grav = 0.4`, el tiempo transcurrido hasta llegar al ápice será de $9 / 0.4 = 22.5$ pasos (aproximadamente un tercio de segundo a 60 FPS). La altura máxima alcanzada sobre la posición de partida será de $9^2 / (2 \cdot 0.4) = 81 / 0.8 \approx 101.25$ píxeles.
Esta relación matemática es de inestimable valor al momento de diseñar niveles: si el artista o diseñador de niveles dibuja una plataforma a 120 píxeles de altura respecto al suelo, sabrás matemáticamente que con los valores actuales el jugador jamás logrará alcanzarla, independientemente de la pericia con el teclado. Deberás aumentar `jump_speed` o reducir `grav` si deseas que dicha distancia sea franqueable.
| Estilo de juego deseado | jump_speed sugerido | grav sugerida | Sensación jugable |
|---|---|---|---|
| Plataformas clásico / retro (Mario, Megaman) | 8.5 a 10.5 | 0.40 a 0.55 | Ágil, reactivo, arco claro y altura controlada. |
| Plataformas cinemático / pesado | 6.0 a 7.5 | 0.45 a 0.60 | Salto bajo, sensación de peso corporal notable. |
| Baja gravedad / espacial / flotante | 5.0 a 7.0 | 0.12 a 0.20 | Descenso muy suave, gran tiempo de suspensión en el aire. |
| Arcade frenético / alta precisión (Celeste) | 11.0 a 13.0 | 0.70 a 0.90 | Curva muy rápida, respuesta inmediata, máxima exigencia de reflejos. |
Ejemplo práctico 1: Implementación de un salto con amortiguación de caída
Veamos un ejemplo de código en el que aplicamos la función nativa `clamp` de GameMaker para mantener la velocidad vertical dentro de un rango seguro en una sola línea de cómputo, simplificando la condición de la velocidad terminal y evitando anidamientos innecesarios.
Ejemplo práctico 2: Visualización de datos de depuración (Debug Overlay)
Al calibrar el salto, resulta sumamente útil poder observar en tiempo real los valores numéricos de las variables físicas directamente en la pantalla mientras el personaje se mueve y salta. Para ello, recurrimos al Evento Draw GUI.
Pruebas de ensayo y resolución de problemas habituales
Durante la implementación inicial de esta mecánica, es habitual toparse con comportamientos anómalos. A continuación, se detallan las incidencias más recurrentes y su resolución:
1. El personaje salta infinitas veces en el aire: Ocurre si la condición `_is_on_ground` no se valida estrictamente antes de otorgar el impulso de salto, o si la posición `y` del personaje se reasigna a la altura de suelo en cada fotograma sin validar su relación previa. Asegúrate de que `vsp = -jump_speed;` esté subordinado a la verificación de suelo. 2. El personaje tiembla o vibra en el suelo: Esto sucede si en cada ciclo el personaje cae unos pocos decimales de píxel por la gravedad, penetra la línea de suelo, el código lo reposiciona hacia arriba en `y = ground_y`, y el ciclo se repite. La solución es poner `vsp = 0` y cancelar la aplicación de la gravedad tan pronto se confirma que el objeto está en el suelo. 3. El salto se siente como si el personaje flotara en la luna: El valor de `grav` es excesivamente bajo en proporción a `jump_speed`. Eleva la gravedad a un rango entre 0.4 y 0.55 y ajusta `jump_speed` de forma correspondiente para conseguir un arco más enérgico y dinámico.
Ejercicios prácticos
A continuación, se presentan tres actividades progresivas para consolidar y poner a prueba los conocimientos adquiridos en esta clase:
Ejercicio 1: Calibración intencional de la física Modifica los valores de `grav` y `jump_speed` en el evento Create de `obj_player` para simular dos perfiles de juego completamente opuestos. Primero, configura un salto estilo «Luna o Subacuático» que alcance 150 píxeles de elevación pero tarde al menos 40 fotogramas en llegar al ápice. Posteriormente, ajusta los valores para un salto estilo «Retro Snappy» muy rápido, que ascienda un máximo de 75 píxeles en solo 14 fotogramas. Documenta en comentarios de código los cálculos matemáticos empleados para alcanzar ambos objetivos. Criterio de comprobación: Utiliza el monitor en pantalla desarrollado en el Ejemplo Práctico 2 para comprobar la coordenada máxima alcanzada por `y` antes de que `vsp` pase a ser positiva.
Ejercicio 2: Implementación de salto doble con contador discreto Utilizando una variable entera declarada en el evento Create (por ejemplo, `jumps_remaining = 2;`), modifica la lógica del evento Step para que el personaje pueda ejecutar un segundo impulso en el aire incluso después de haber abandonado el suelo. Cuando el personaje toque nuevamente el suelo (`y >= ground_y`), la variable debe restablecerse a su capacidad máxima (`jumps_remaining = 2`). Criterio de comprobación: El personaje debe ser capaz de saltar desde el suelo y realizar exactamente un impulso adicional mientras está cayendo o subiendo. Pulsar la tecla una tercera vez en el aire no debe provocar ningún efecto hasta haber hecho contacto de nuevo con el suelo.
Ejercicio 3: Detección combinada de controles (Teclado y Gamepad) Extiende la variable local de captura `_key_jump` para que acepte tanto la barra espaciadora (`vk_space`) y la letra W (`ord("W")`) en el teclado, como el botón inferior de acción de un mando o gamepad estándar conectado en la ranura 0 (utilizando la función nativa de GameMaker `gamepad_button_check_pressed(0, gp_face1)`). Criterio de comprobación: Conecta un mando compatible y verifica que presionar el botón A (en mando tipo Xbox) o Cruz (en mando tipo PlayStation) dispara la mecánica de salto con la misma respuesta instantánea y parabólica que la barra espaciadora del teclado.
Resumen
- En GameMaker, el eje Y se encuentra invertido respecto al plano cartesiano tradicional: los valores negativos corresponden a desplazamientos hacia arriba y los positivos hacia abajo.
- El salto básico se compone cinemáticamente de dos fuerzas simuladas: un impulso instantáneo hacia arriba (velocidad vertical negativa) y una desaceleración constante hacia abajo producida por la gravedad (adición continua de velocidad positiva).
- Es imprescindible utilizar keyboard_check_pressed para activar el salto, garantizando que el impulso solo se aplique una única vez por pulsación física y no de forma continua.
- La cúspide o ápice del salto ocurre en el instante exacto en que la velocidad vertical vsp alcanza el valor 0, tras lo cual la velocidad positiva hace que el personaje inicie la caída.
- El uso de variables como vsp_max o la función clamp previene que el jugador alcance velocidades de caída anómalas que puedan desestabilizar la lógica de colisiones.
- Comprender la relación matemática h = (v^2) / (2 * g) permite a los diseñadores calcular de forma analítica y precisa la altura que alcanzará el personaje antes de trazar las plataformas del nivel.
Practica lo aprendido
Ejercicio 1 · 1 punto
¿Por qué es necesario asignar un valor negativo a la velocidad vertical (`vsp`) para que el personaje salte hacia arriba en GameMaker?
Ejercicio 2 · 1 punto
Ordena lógicamente los procesos que deben ejecutarse en el Evento Step para gestionar el salto y la física vertical del personaje:
- 1Captura de entradas (Inputs)
- 2Detección de suelo
- 3Actualización de coordenadas espaciales
- 4Procesamiento vertical del salto
- 5Aplicación de la gravedad
Ejercicio 3 · 1 punto
Para detonar un salto siempre debe emplearse la función , ya que retorna true únicamente en el primer fotograma exacto en el que se registra el contacto. Si se usase , el impulso se renovaría continuamente mientras la tecla permanezca apretada, haciendo que el personaje se eleve sin control.
Ingresa para guardar tu progreso — Ingresar