How to check if a game is paused?

Implementa la Pausa Perfecta en GameMaker

31/10/2014

Valoración: 4.04 (12658 votos)

Una de las características más subestimadas pero esenciales en cualquier videojuego es la capacidad de pausar la acción. No es solo un botón; es una puerta de entrada a una mejor experiencia de usuario, un signo de pulido y profesionalismo que distingue a un proyecto amateur de un juego bien acabado. Afortunadamente para nosotros, desarrolladores, GameMaker Studio nos brinda herramientas increíblemente sencillas y potentes para implementar esta funcionalidad. En este artículo, exploraremos a fondo cómo crear un sistema de pausa robusto y fácil de mantener, centrándonos en el método más elegante y eficiente.

How to check if a game is paused?
To do this, you need to set a global which we’ll call gamePaused to true: Create a pause button object with a pause button sprite set to it’s default sprite. Add the following code to the step event: This checks to see if the game is paused.
Índice de Contenido

¿Por Qué es Tan Importante una Buena Función de Pausa?

Antes de sumergirnos en el código, reflexionemos un momento sobre el impacto de la pausa. Para el jugador, es una necesidad básica. Permite atender una llamada, tomar un respiro en un nivel difícil o simplemente admirar el entorno del juego sin la presión de la acción. Para el desarrollador, es una oportunidad. Un buen menú de pausa puede albergar opciones, mapas, inventarios o información crucial, convirtiéndose en un centro neurálgico del juego. Implementarlo correctamente no solo mejora la jugabilidad, sino que demuestra un cuidado por el detalle que los jugadores aprecian enormemente.

Los Dos Caminos para Pausar en GameMaker

Fundamentalmente, existen dos enfoques populares para detener el tiempo en tu juego. Ambos tienen el mismo objetivo, pero difieren drásticamente en su implementación, mantenimiento y elegancia. Vamos a analizarlos para entender por qué uno de ellos es claramente superior.

Método 1: La Bandera de la Variable Global (El Enfoque Engorroso)

La primera técnica, y quizás la más intuitiva para los principiantes, es usar una variable global que actúe como un interruptor o "bandera". La lógica es simple:

  1. Creas una variable global, por ejemplo, global.juego_pausado = false;.
  2. En el evento Step de todos los objetos que quieres que se detengan (enemigos, jugador, proyectiles, etc.), envuelves todo su código en una condición.
// En el Evento Step de obj_enemigo, obj_jugador, etc. if (!global.juego_pausado) { // Todo el código de movimiento, ataque y lógica va aquí }

Cuando el jugador presiona el botón de pausa, simplemente cambias el valor de global.juego_pausado a true. Esto detendrá la ejecución del código en todos los objetos que tengan esta verificación. Aunque funciona, este método presenta problemas serios a medida que tu proyecto crece:

  • Mantenimiento Difícil: Si olvidas añadir la condición en un nuevo objeto, este seguirá moviéndose cuando el juego esté en pausa, rompiendo la ilusión.
  • Código Repetitivo: Añadir el mismo bloque if() en docenas de objetos es ineficiente y ensucia tu código.
  • Propenso a Errores: Es muy fácil cometer errores y difícil de depurar si algo no se detiene como debería.

Personalmente, considero esta solución poco elegante y la desaconsejo para cualquier proyecto que aspire a ser algo más que un prototipo rápido.

Método 2: Desactivación de Instancias (El Enfoque Profesional)

Aquí es donde GameMaker realmente brilla. El motor incluye funciones nativas diseñadas específicamente para "apagar" y "encender" instancias: instance_deactivate_all() e instance_activate_all(). Este método es limpio, eficiente y centralizado.

La idea es simple: cuando el jugador pausa, le decimos a GameMaker que desactive todas las instancias activas en la habitación, excepto el objeto que controla la pausa. Una instancia desactivada sigue existiendo en memoria, pero no ejecuta ninguno de sus eventos (Step, Draw, etc.) y no procesa colisiones. Es, a todos los efectos, congelada en el tiempo.

Implementación Paso a Paso del Sistema de Pausa Ideal

Vamos a construir este sistema desde cero. Es sorprendentemente fácil y los resultados son excelentes.

Paso 1: Preparar la Variable de Estado y los Recursos

Primero, necesitamos una variable global para saber en todo momento si el juego está en pausa. En el evento Create de un objeto controlador inicial (como un obj_game_manager que exista desde el principio), declara la variable:

global.juego_pausado = false;

También necesitarás dos sprites: uno para el botón de pausa (ej. spr_boton_pausa) y otro para el botón de reanudar o "play" (ej. spr_boton_play).

Paso 2: Crear el Objeto Botón de Pausa

Crea un nuevo objeto, llamémoslo obj_controlador_pausa. Asígnale el sprite spr_boton_pausa por defecto. Es crucial que este objeto sea persistente si quieres que el botón de pausa esté disponible en todas las habitaciones de tu juego. Para ello, simplemente marca la casilla "Persistent" en las propiedades del objeto.

Paso 3: El Código Mágico en el Evento Step

Aquí es donde ocurre toda la lógica. Añade un evento Step al obj_controlador_pausa y pega el siguiente código:

// Comprobar si se debe pausar el juego if (global.juego_pausado == false and mouse_check_button_pressed(mb_left) and position_meeting(mouse_x, mouse_y, id)) { // Desactivar todas las instancias EXCEPTO la actual (este botón) instance_deactivate_all(true); // Actualizar el estado del juego global.juego_pausado = true; // Cambiar el sprite del botón para indicar que se puede reanudar sprite_index = spr_boton_play; } // Comprobar si se debe reanudar el juego else if (global.juego_pausado == true and mouse_check_button_pressed(mb_left) and position_meeting(mouse_x, mouse_y, id)) { // Reactivar todas las instancias previamente desactivadas instance_activate_all(); // Actualizar el estado del juego global.juego_pausado = false; // Volver al sprite original del botón de pausa sprite_index = spr_boton_pausa; }

Analicemos este código. La función clave aquí es instance_deactivate_all(true). El parámetro true le dice a GameMaker: "Desactiva todo, pero no te desactives a ti mismo". Esto es fundamental, ya que si el propio botón se desactivara, no podría detectar la entrada del jugador para reanudar el juego. El resto del código simplemente gestiona el estado de la variable global y cambia el sprite del botón para dar una retroalimentación visual clara al jugador.

Tabla Comparativa de Métodos

Para que quede aún más clara la superioridad del segundo método, aquí tienes una tabla comparativa:

CaracterísticaMétodo Variable GlobalMétodo Desactivación de Instancias
MantenibilidadMuy baja. Requiere modificar cada objeto nuevo.Muy alta. La lógica está centralizada en un solo objeto.
Eficiencia (Rendimiento)Menor. La CPU sigue evaluando el if en cada Step de cada instancia.Mayor. Las instancias desactivadas no consumen casi recursos.
Riesgo de ErroresAlto. Es fácil olvidar la condición en un objeto.Bajo. El sistema es robusto y funciona de forma global.
Limpieza del CódigoCódigo repetitivo y desordenado.Lógica limpia, aislada y centralizada.

Llevándolo al Siguiente Nivel: Un Menú de Pausa

Nuestro sistema ya es funcional, pero podemos mejorarlo fácilmente añadiendo un menú de pausa. Cuando el juego se pausa, en lugar de solo cambiar un icono, podemos crear todo un menú con opciones.

Modifica el primer bloque del código de nuestro obj_controlador_pausa:

if (global.juego_pausado == false and mouse_check_button_pressed(mb_left) and position_meeting(mouse_x, mouse_y, id)) { instance_deactivate_all(true); global.juego_pausado = true; sprite_index = spr_boton_play; // ¡Aquí creamos nuestro menú! instance_create_layer(x, y, "Instances_UI", obj_menu_pausa); }

Y en el bloque para reanudar, nos aseguramos de destruir el menú:

else if (global.juego_pausado == true and ...) { instance_activate_all(); global.juego_pausado = false; sprite_index = spr_boton_pausa; // Destruimos el menú al reanudar with (obj_menu_pausa) { instance_destroy(); } }

El objeto obj_menu_pausa se crea después de que todo lo demás ha sido desactivado, por lo que estará activo y funcional. Dentro de este objeto, puedes dibujar un fondo, texto y crear otros botones (como "Opciones" o "Salir al Menú Principal") que funcionarán perfectamente en el estado de pausa.

Preguntas Frecuentes (FAQ)

¿Qué pasa con el sonido y la música cuando pauso el juego?
Por defecto, el audio seguirá sonando. Las funciones de desactivación de instancias no afectan al sistema de audio. Para pausar también el sonido, debes usar las funciones audio_pause_all() cuando pausas y audio_resume_all() cuando reanudas el juego. Intégralas en los bloques de código correspondientes.
Mi botón de pausa desaparece o deja de funcionar, ¿qué hago?
Este es el error más común. Asegúrate de que estás usando instance_deactivate_all(true). El true es vital para que el objeto que ejecuta el código no se desactive a sí mismo.
¿Puedo tener animaciones en mi menú de pausa?
¡Sí! Como el objeto obj_menu_pausa y cualquier otro objeto que crees mientras el juego está en pausa estarán activos, sus eventos Step y Draw se ejecutarán normalmente. Puedes tener botones animados, transiciones y cualquier otro efecto visual que desees.
¿Funciona este método para pausar las físicas del juego?
Sí. Al desactivar una instancia, todo su comportamiento, incluido el motor de físicas asociado a ella, se congela por completo hasta que la instancia es reactivada.

Implementar un sistema de pausa robusto es un paso fundamental para elevar la calidad de tu juego. El método de desactivación de instancias que hemos explorado no solo es la forma más limpia y eficiente de hacerlo en GameMaker, sino que también te proporciona una base sólida sobre la cual puedes construir menús y funcionalidades complejas. No te conformes con soluciones a medias; dedica un poco de tiempo a implementar este sistema y tus jugadores te lo agradecerán.

Si quieres conocer otros artículos parecidos a Implementa la Pausa Perfecta en GameMaker puedes visitar la categoría Juegos.

Subir