Introducción al Desarrollo de Videojuegos con GameMaker · Módulo 8: HUD, interfaces, menús y sistema de pausa.
Diseño del HUD (Puntuación, vidas y coleccionables)
Clase 37 de 60 · 60 min
También disponible en: EN
Introducción al diseño del HUD en videojuegos 2D
El HUD (Heads-Up Display) es el canal directo de comunicación entre el estado interno del juego y el jugador. A través de este componente visual, el usuario se informa de manera instantánea e intuitiva sobre variables críticas para su supervivencia y progreso: cuántos puntos de salud le quedan, cuántas vidas conserva, cuántas monedas o gemas ha recolectado y qué puntuación acumulada lleva en la partida. En la lección previa comprendimos el propósito del evento Draw GUI y cómo se diferencia sustancialmente del evento Draw tradicional al operar en un espacio de coordenadas estático e independiente del movimiento de la cámara y de la posición de las habitaciones (rooms). En esta lección nos enfocaremos en la implementación gráfica y programática integral de los componentes que dan vida a un HUD funcional, limpio y estéticamente coherente dentro de nuestro videojuego de plataformas.
Diseñar un HUD no consiste únicamente en ubicar números y rectángulos sobre la pantalla; requiere comprender cómo GameMaker procesa las instrucciones de renderizado en cola, cómo gestionar los estados de dibujo para no alterar otros elementos de la escena y cómo presentar la información de modo que no obstruya la visibilidad de la acción principal del juego. A lo largo de esta clase, construiremos paso a paso un sistema visual completo que incluirá una barra de energía con degradado de color y fondo protector, un marcador numérico de puntuación con alineación tipográfica precisa, un contador de monedas complementado con iconos gráficos y una hilera de corazones para representar las vidas disponibles del personaje.
💡 Recuerda que todas las funciones que comiencen por draw_ deben invocarse dentro de eventos de la familia Draw. Para el HUD utilizaremos de forma exclusiva el evento Draw GUI. Si intentaras colocar estas instrucciones en el evento Step, GameMaker generará un error o simplemente no mostrará nada en pantalla, ya que el motor reserva la renderización gráfica para su ciclo de dibujado especializado.
Arquitectura del sistema: El objeto gestor de interfaz
Uno de los errores más frecuentes al comenzar en el desarrollo de videojuegos es colocar el código de dibujo de la interfaz dentro del objeto del jugador (por ejemplo, obj_player). Aunque al inicio parezca conveniente porque el jugador contiene las variables de salud y vidas, esta práctica rompe el principio de responsabilidad única y genera fallos graves de arquitectura. Si el personaje muere y su instancia se destruye temporalmente mediante instance_destroy(), el HUD desaparecerá instantáneamente de la pantalla, provocando errores en cascada si otros sistemas intentan consultar esos datos o dejando al jugador sin información visual durante las transiciones de reaparición.
La arquitectura profesional estándar consiste en delegar la representación de la interfaz a un objeto controlador dedicado, habitualmente denominado obj_hud, obj_gui o integrado dentro del gestor global obj_game_manager que configuramos en los módulos anteriores. Este objeto gestor será persistente, no tendrá una representación física en el mundo de juego (no requiere máscara de colisión ni sprite asignado como cuerpo físico) y se encargará de consultar los valores de las variables globales o de la instancia del jugador para trasladarlos a la pantalla mediante primitivas geométricas, fuentes tipográficas y sprites auxiliares.
Preparación tipográfica: Creación y configuración de fuentes
Por defecto, si invocamos la función draw_text() sin especificar una fuente personalizada, GameMaker recurre a una tipografía básica del sistema sin suavizado ni estilo retro. Para lograr una estética atractiva en nuestro videojuego de plataformas, crearemos un recurso de fuente propio en el Asset Browser. Haremos clic derecho sobre la carpeta Fonts, seleccionaremos Create -> Font y nombraremos al recurso fnt_hud.
En el editor de fuentes podemos escoger cualquier tipografía instalada en nuestro sistema operativo. Para juegos de estilo píxel art clásico, se recomiendan fuentes de tipo monospace o fuentes bitmap diseñadas específicamente para rejillas de baja resolución (como 'Consolas', 'Courier New' o fuentes pixeladas de dominio público como 'Kenney Pixel'). En la ventana de configuración debemos definir un tamaño adecuado (por ejemplo, 16 o 20 puntos) y asegurarnos de activar o desactivar la opción Anti-aliasing según la fidelidad retro que busquemos: desactivar el suavizado suele brindar bordes definidos y nítidos característicos de las consolas de 8 y 16 bits.

Renderizado de texto: Puntuación y contador de coleccionables
El renderizado de cadenas de texto en GameMaker opera mediante una máquina de estados de dibujo. Esto significa que cuando modificamos el color con draw_set_color() o la alineación con draw_set_halign(), dicho cambio afectará a absolutamente todas las llamadas de dibujo posteriores en el proyecto hasta que se restablezca explícitamente otro valor. Comprender este principio es fundamental para evitar efectos secundarios imprevistos, como textos que cambian de color repentinamente o sprites que se tintan con tonalidades erróneas.
Para mostrar la puntuación y las monedas recolectadas emplearemos las funciones draw_set_font(), draw_set_color(), draw_set_halign(), draw_set_valign() y draw_text(). La función draw_text(x, y, string) recibe las coordenadas de pantalla donde se anclará el texto y la cadena de caracteres a imprimir. Dado que nuestras variables de puntuación (global.puntos) y monedas (global.monedas) son de tipo numérico entero (Real), debemos concatenarlas convirtiéndolas a texto mediante la función string() o usando la sintaxis de concatenación con el operador suma (+).
// Evento Draw GUI en obj_hud
// 1. Configuración de estados de dibujo
draw_set_font(fnt_hud);
draw_set_color(c_white);
draw_set_halign(fa_left);
draw_set_valign(fa_top);
// 2. Coordenadas base para la esquina superior izquierda
var _base_x = 32;
var _base_y = 64;
// 3. Dibujado de texto con sombra paralela para garantizar legibilidad
var _texto_puntos = "SCORE: " + string(global.puntos);
// Sombra negra desplazada 2 píxeles hacia abajo y a la derecha
draw_set_color(c_black);
draw_text(_base_x + 2, _base_y + 2, _texto_puntos);
// Texto principal en blanco
draw_set_color(c_white);
draw_text(_base_x, _base_y, _texto_puntos);
// 4. Restablecimiento preventivo de los estados de dibujo
draw_set_color(c_white);
draw_set_halign(fa_left);
draw_set_valign(fa_top);Observa el patrón de renderizado de sombra implementado en el fragmento anterior: dibujamos exactamente el mismo texto primero con color c_black en una posición ligeramente desplazada (por ejemplo, x + 2, y + 2) y de inmediato dibujamos el texto frontal con el color principal deseado. Este recurso técnico, denominado habitualmente 'drop shadow', es vital en videojuegos donde el fondo del escenario cambia constantemente entre zonas claras y oscuras, evitando que la tipografía pierda contraste o resulte ilegible sobre determinadas texturas.
Barras indicadoras dinámicas: Salud y energía
La representación de la salud del personaje puede abordarse mediante dos técnicas principales: el uso de la función incorporada draw_healthbar() provista por GameMaker, o el diseño de barras personalizadas compuestas por rectángulos primitivos o sprites segmentados. Analizaremos en primer lugar la solución nativa por su facilidad de configuración y posteriormente crearemos una solución gráfica personalizada de mayor calidad visual.
Uso de la función draw_healthbar()
La función draw_healthbar() calcula y renderiza de forma automática un rectángulo que se vacía progresivamente. Su firma recibe once argumentos que permiten controlar las dimensiones de la caja delimitadora, el porcentaje actual de llenado, los colores de fondo y transición, la dirección del vaciado y la presencia de bordes decorativos:
draw_healthbar(x1, y1, x2, y2, amount, backcol, mincol, maxcol, direction, showback, showborder);Un aspecto crítico que suele confundir a los principiantes es el argumento 'amount'. Este parámetro no representa los puntos de salud absolutos (como 3 de 5 de salud), sino un porcentaje normalizado que debe situarse estrictamente en el rango entre 0 y 100. Si pasas un valor directo de salud actual sin normalizar, la barra representará visualmente un porcentaje incorrecto. Por ello, es imperativo calcular la proporción matemática: (salud_actual / salud_maxima) * 100.
// Evento Draw GUI en obj_hud
// Comprobamos la existencia del jugador para evitar errores de lectura
if (instance_exists(obj_player)) {
var _salud_actual = obj_player.hp;
var _salud_maxima = obj_player.hp_max;
// Cálculo del porcentaje normalizado entre 0 y 100
var _porcentaje = (_salud_actual / _salud_maxima) * 100;
// Coordenadas del rectángulo de la barra
var _bx1 = 32;
var _by1 = 24;
var _bx2 = 232;
var _by2 = 44;
// Dibujamos la barra con degradado dinámico de rojo (min) a verde (max)
draw_healthbar(
_bx1, _by1, _bx2, _by2,
_porcentaje,
c_dkgray, // Color de fondo cuando la barra está vacía
c_red, // Color cuando la salud es crítica (cerca del 0%)
c_lime, // Color cuando la salud está llena (cerca del 100%)
0, // Dirección: 0 = vaciado de derecha a izquierda
true, // Mostrar fondo protector
true // Dibujar borde negro perimetral
);
}Construcción de barras de salud personalizadas mediante primitivas
Aunque draw_healthbar() es sumamente útil para prototipar rápidamente, sus opciones estéticas son limitadas: los bordes son de un solo píxel negro y no permite biseles, brillos ni sombras internas personalizadas. Para dotar a nuestro juego de un acabado profesional, podemos construir nuestra propia barra modular utilizando la función draw_rectangle_color() o draw_rectangle(). El sistema se compone de tres capas superpuestas dibujadas en orden secuencial:
| Capa | Función técnica | Color sugerido |
|---|---|---|
| 1. Marco exterior (Borde) | Delimita el tamaño total del contenedor y resalta contra el fondo del nivel. | Negro o gris muy oscuro (c_black / make_color_rgb(20,20,20)) |
| 2. Fondo interior (Vaciado) | Representa el espacio de vida perdida o capacidad máxima no disponible. | Gris oscuro o carmesí apagado (make_color_rgb(60,20,20)) |
| 3. Relleno dinámico (Vida) | Rectángulo con ancho variable calculado por el porcentaje actual de salud. | Verde esmeralda, azul brillante o rojo vibrante |
// Evento Draw GUI en obj_hud - Barra personalizada por capas
if (instance_exists(obj_player)) {
var _hp = obj_player.hp;
var _hp_max = obj_player.hp_max;
var _fraccion = clamp(_hp / _hp_max, 0, 1);
var _x = 32;
var _y = 20;
var _ancho_total = 200;
var _alto_total = 18;
var _grosor_borde = 2;
// Capa 1: Borde exterior oscuro
draw_set_color(c_black);
draw_rectangle(_x - _grosor_borde, _y - _grosor_borde, _x + _ancho_total + _grosor_borde, _y + _alto_total + _grosor_borde, false);
// Capa 2: Fondo de barra vacía
draw_set_color(make_color_rgb(50, 50, 50));
draw_rectangle(_x, _y, _x + _ancho_total, _y + _alto_total, false);
// Capa 3: Relleno de salud con interpolación de color según el estado
var _color_salud = c_lime;
if (_fraccion < 0.25) {
_color_salud = c_red;
} else if (_fraccion < 0.5) {
_color_salud = c_yellow;
}
draw_set_color(_color_salud);
var _ancho_actual = _ancho_total * _fraccion;
if (_ancho_actual > 0) {
draw_rectangle(_x, _y, _x + _ancho_actual, _y + _alto_total, false);
}
// Restablecer color base
draw_set_color(c_white);
}En el código anterior empleamos la función clamp() para garantizar matemáticamente que la fracción de salud nunca sea inferior a 0 ni superior a 1, protegiendo al motor de anomalías visuales en caso de recibir daño negativo o sobrecuraciones. Asimismo, condicionamos el color del relleno dinámico con una estructura condicional (if / else if), alertando dramáticamente al jugador con tonos amarillos y rojos cuando su nivel de vitalidad disminuye peligrosamente.
Indicadores icónicos: Vidas y coleccionables mediante sprites
No toda la información del HUD debe resolverse con texto o barras continuas. Elementos discretos como las vidas restantes del jugador o los coleccionables especiales se representan de manera óptima mediante pequeños iconos o sprites repetidos. Por ejemplo, en lugar de imprimir 'VIDAS: 3', un estándar visual clásico consiste en dibujar tres pequeños corazones o cabezas del personaje alineados horizontalmente.
Para implementar este patrón de diseño, aprovecharemos la estructura de control repetitiva for que aprendimos en el Módulo 3 combinada con la función draw_sprite() o draw_sprite_ext(). La función draw_sprite_ext() resulta especialmente potente porque permite definir escala horizontal, escala vertical, rotación, color de tintado y canal alfa (transparencia) para cada icono individual.
// Evento Draw GUI en obj_hud - Dibujado de iconos de vidas y monedas
// ---------------------------------------------------------
// SECCIÓN 1: DIBUJADO DE VIDAS (HILERA DE CORAZONES)
// ---------------------------------------------------------
var _vidas_totales = global.vidas;
var _corazon_x_inicio = 32;
var _corazon_y = 52;
var _espaciado = 28; // Distancia en píxeles entre cada icono
for (var i = 0; i < _vidas_totales; i++) {
// Calculamos el desplazamiento horizontal para cada corazón sucesivo
var _pos_x = _corazon_x_inicio + (i * _espaciado);
// Dibujamos el sprite spr_hud_heart (subimagen 0, x, y)
draw_sprite(spr_hud_heart, 0, _pos_x, _corazon_y);
}
// ---------------------------------------------------------
// SECCIÓN 2: DIBUJADO DEL CONTADOR DE MONEDAS
// ---------------------------------------------------------
var _moneda_x = 32;
var _moneda_y = 88;
// Dibujamos el icono representativo de la moneda
draw_sprite(spr_coin_ui, 0, _moneda_x, _moneda_y);
// Configuramos tipografía y alineación para el número adyacente
draw_set_font(fnt_hud);
draw_set_halign(fa_left);
draw_set_valign(fa_middle);
// Texto con cantidad de monedas precedido de una 'x'
var _texto_monedas = "x " + string(global.monedas);
// Sombra
draw_set_color(c_black);
draw_text(_moneda_x + 30 + 1, _moneda_y + 12 + 1, _texto_monedas);
// Frente en amarillo brillante
draw_set_color(c_yellow);
draw_text(_moneda_x + 30, _moneda_y + 12, _texto_monedas);
// Limpieza final de estados
draw_set_color(c_white);
draw_set_valign(fa_top);Analicemos la lógica matemática del bucle for para los corazones: en la primera iteración (i = 0), la posición horizontal resultante es 32 + (0 * 28) = 32. En la segunda iteración (i = 1), la posición es 32 + (1 * 28) = 60. En la tercera iteración (i = 2), la posición es 32 + 56 = 88. Este cálculo produce una hilera simétrica perfecta y adaptable: si el jugador recolecta un contenedor de vida adicional incrementando global.vidas a 4, el bucle dibujará automáticamente el cuarto icono sin requerir ninguna modificación en el código fuente.
Integración consolidada: El objeto obj_hud
Para garantizar la máxima limpieza en nuestro proyecto de plataformas, reuniremos todos estos componentes en un único objeto centralizado denominado obj_hud. A continuación, presentamos la estructura completa de variables iniciales en el evento Create y la ejecución orquestada en el evento Draw GUI.
// =========================================================
// OBJETO: obj_hud
// EVENTO: Create
// =========================================================
// Fijar tamaño explícito para la capa GUI (resolución nativa de la UI)
display_set_gui_size(960, 540);
// Variables de amortiguación para animaciones suaves (opcional visual)
barra_hp_visual = 100;
// Asegurar que las variables globales existan si no fueron creadas antes
if (!variable_global_exists("puntos")) {
global.puntos = 0;
}
if (!variable_global_exists("monedas")) {
global.monedas = 0;
}
if (!variable_global_exists("vidas")) {
global.vidas = 3;
}El uso de display_set_gui_size(960, 540) en el evento Create es una de las mejores prácticas técnicas en GameMaker. Por omisión, el lienzo de la GUI adopta la resolución nativa de la ventana del juego o de la pantalla del dispositivo. Al fijar una resolución virtual fija para la GUI, garantizamos que las coordenadas absolutas (como x = 32 o y = 20) conserven la misma proporción relativa sin importar si el usuario ejecuta el juego en un monitor de 720p, 1080p o 4K.
// =========================================================
// OBJETO: obj_hud
// EVENTO: Draw GUI
// =========================================================
// Comprobar si existe la instancia del jugador para extraer sus métricas
var _hp_actual = 0;
var _hp_maxima = 100;
if (instance_exists(obj_player)) {
_hp_actual = obj_player.hp;
_hp_maxima = obj_player.hp_max;
}
// 1. DIBUJAR BARRA DE SALUD (Superior izquierda)
var _ancho_barra = 180;
var _alto_barra = 16;
var _pos_x = 24;
var _pos_y = 20;
var _porcentaje_vida = clamp(_hp_actual / _hp_maxima, 0, 1);
// Borde exterior
draw_set_color(c_black);
draw_rectangle(_pos_x - 2, _pos_y - 2, _pos_x + _ancho_barra + 2, _pos_y + _alto_barra + 2, false);
// Fondo barra vacía
draw_set_color(make_color_rgb(40, 40, 40));
draw_rectangle(_pos_x, _pos_y, _pos_x + _ancho_barra, _pos_y + _alto_barra, false);
// Relleno barra activa
if (_porcentaje_vida > 0) {
var _color_barra = (_porcentaje_vida > 0.3) ? make_color_rgb(70, 210, 70) : make_color_rgb(220, 50, 50);
draw_set_color(_color_barra);
draw_rectangle(_pos_x, _pos_y, _pos_x + (_ancho_barra * _porcentaje_vida), _pos_y + _alto_barra, false);
}
// 2. DIBUJAR VIDAS (Iconos debajo de la barra de salud)
var _vidas_espacio = 26;
for (var i = 0; i < global.vidas; i++) {
draw_sprite(spr_hud_heart, 0, _pos_x + (i * _vidas_espacio), _pos_y + 24);
}
// 3. DIBUJAR MONEDAS (Debajo de los corazones)
draw_sprite(spr_coin_ui, 0, _pos_x, _pos_y + 56);
draw_set_font(fnt_hud);
draw_set_halign(fa_left);
draw_set_valign(fa_middle);
var _str_monedas = "x " + string(global.monedas);
draw_set_color(c_black);
draw_text(_pos_x + 25, _pos_y + 67, _str_monedas);
draw_set_color(make_color_rgb(255, 215, 0)); // Color dorado
draw_text(_pos_x + 24, _pos_y + 66, _str_monedas);
// 4. DIBUJAR PUNTUACIÓN (Esquina superior derecha)
var _gui_ancho = display_get_gui_width();
draw_set_halign(fa_right);
draw_set_valign(fa_top);
var _str_score = "PUNTOS: " + string(global.puntos);
// Sombra de puntuación
draw_set_color(c_black);
draw_text(_gui_ancho - 22, 22, _str_score);
// Texto frontal
draw_set_color(c_white);
draw_text(_gui_ancho - 24, 20, _str_score);
// 5. RESTABLECER ESTADOS DE DIBUJO GLOBALES
draw_set_color(c_white);
draw_set_halign(fa_left);
draw_set_valign(fa_top);| Función GML | Propósito principal | Recomendación de uso |
|---|---|---|
| draw_text(x, y, string) | Dibuja texto tipográfico en pantalla. | Siempre emparejar con draw_set_font() previo. |
| draw_set_halign(halign) | Alineación horizontal del texto (fa_left, fa_center, fa_right). | Usar fa_right para elementos fijados al margen derecho. |
| draw_set_valign(valign) | Alineación vertical del texto (fa_top, fa_middle, fa_bottom). | Usar fa_middle para centrar texto verticalmente con iconos. |
| draw_healthbar(...) | Renderizado rápido de barras porcentuales. | Requiere que el valor de entrada esté normalizado entre 0 y 100. |
| draw_rectangle(x1, y1, x2, y2, outline) | Dibuja cuadriláteros rellenos o de contorno. | Esencial para construir barras de estado y marcos multicapa. |
| display_set_gui_size(w, h) | Establece una resolución virtual para la capa Draw GUI. | Invocarse preferentemente en el evento Create del objeto HUD. |
| display_get_gui_width() | Retorna el ancho actual en píxeles del lienzo GUI. | Imprescindible para calcular márgenes dinámicos en la derecha. |
Técnicas avanzadas: Formateo numérico y amortiguación visual
En los videojuegos clásicos de corte arcade, los marcadores numéricos de puntuación raramente se imprimen como un simple '45'; en su lugar, se presentan formateados con ceros a la izquierda ocupando un ancho fijo de caracteres (por ejemplo, '000045'). Esta técnica mantiene intacta la estabilidad visual del HUD, evitando que el bloque de texto altere su longitud o se desplace a saltos cada vez que el valor numérico cambia de orden de magnitud (de decenas a centenas o a millares).
GameMaker ofrece la función nativa string_format(val, total, dec), donde 'total' indica el número mínimo de columnas que ocupará la cifra y 'dec' los decimales deseados. Sin embargo, string_format rellena los espacios vacíos con espacios en blanco en lugar de ceros. Para obtener ceros a la izquierda, podemos utilizar una función auxiliar sencilla o encadenar la función string_replace_all():
// Función técnica para rellenar ceros a la izquierda
// Transforma un número entero en una cadena de longitud fija con ceros
var _puntos_crudos = global.puntos;
var _puntos_formateados = string_replace_all(string_format(_puntos_crudos, 6, 0), " ", "0");
// Si global.puntos es 350, _puntos_formateados devolverá "000350"
draw_text(_gui_ancho - 24, 20, "SCORE: " + _puntos_formateados);Otro refinamiento estético de gran impacto es la amortiguación visual en la barra de salud (animación lerp). Cuando el personaje recibe un golpe brusco, en lugar de que la barra caiga instantáneamente al nuevo valor en un solo fotograma, podemos almacenar una variable visual que persiga suavemente al valor real mediante la función de interpolación lineal lerp(). En el evento Step de obj_hud escribiríamos: barra_hp_visual = lerp(barra_hp_visual, obj_player.hp, 0.1); y en el evento Draw GUI usaríamos barra_hp_visual para dibujar el ancho del rectángulo. Esto genera una sensación de pulido ('game juice') sumamente profesional.
Buenas prácticas y resolución de errores frecuentes
Al trabajar con interfaces gráficas en GameMaker suelen manifestarse ciertos errores comunes entre los desarrolladores principiantes. El primero es la 'fuga de estados de dibujo': si cambias draw_set_color(c_red) dentro de un objeto para pintar un texto y no lo devuelves a c_white al terminar, cualquier otro objeto en la escena que dibuje un sprite sin color explícito heredará ese tinte rojo. Como regla de oro, todo evento Draw GUI debe concluir restableciendo el color a c_white y las alineaciones a fa_left y fa_top.
El segundo problema habitual surge al intentar posicionar elementos a la derecha o al pie de la pantalla empleando valores numéricos fijos (hardcoded), como x = 900. Si el usuario maximiza la ventana o cambia la relación de aspecto, el elemento quedará desalineado o flotando en medio de la pantalla. La solución consiste en referenciar siempre los extremos calculados mediante display_get_gui_width() y display_get_gui_height(). De este modo, una coordenada como display_get_gui_width() - 32 se mantendrá exactamente a 32 píxeles de distancia del margen derecho en cualquier pantalla.
Ejercicios prácticos
A continuación, se presentan tres actividades estructuradas para consolidar los conocimientos adquiridos en esta clase:
1. Contador de monedas con ceros fijos: Modifica el renderizado de la cantidad de monedas en el evento Draw GUI de obj_hud para que siempre se visualice con exactamente tres dígitos (por ejemplo: 'x 005', 'x 023', 'x 100'). Criterio de comprobación: Incrementa las monedas recogidas en el juego y confirma visualmente que los ceros a la izquierda se reducen proporcionalmente sin desalinear la tipografía respecto al icono.
2. Barra de salud con amortiguación suave (Lerp): Declara una variable hp_visual en el evento Create de obj_hud. En el evento Step, haz que hp_visual se aproxime suavemente al hp del jugador usando lerp(hp_visual, obj_player.hp, 0.15). En el evento Draw GUI, renderiza la barra usando esta variable. Criterio de comprobación: Haz que un enemigo golpee al jugador; comprueba que la barra de salud disminuye mediante una transición fluida y amortiguada en lugar de un salto inmediato en pantalla.
3. Indicador de corazones vacíos (Contenedores): Modifica el bucle for que dibuja las vidas para que siempre dibuje un total fijo de 3 iconos de corazón (representando la capacidad máxima de vidas), utilizando la subimagen 0 (corazón lleno) si el índice es menor que global.vidas, y la subimagen 1 (silueta o corazón gris/vacío) si el índice es mayor o igual. Criterio de comprobación: Reduce global.vidas a 1 durante la partida y verifica que en pantalla se observa 1 corazón rojo lleno y 2 corazones vacíos o apagados en la hilera.
Resumen
- El HUD debe implementarse preferentemente en un objeto controlador independiente (obj_hud) y renderizarse siempre dentro del evento Draw GUI.
- El lienzo de la GUI utiliza un sistema de coordenadas de pantalla desacoplado de la cámara del juego. La función display_set_gui_size() permite estandarizar una resolución virtual estable.
- GameMaker gestiona el renderizado de texto mediante una máquina de estados: tras modificar draw_set_font, draw_set_color o las alineaciones, siempre deben restaurarse los valores por defecto.
- Las sombras paralelas ('drop shadows') dibujadas con un ligero desplazamiento en color negro garantizan el contraste del texto sobre cualquier entorno visual del nivel.
- Las barras de salud pueden crearse con draw_healthbar() (normalizando el valor de 0 a 100) o mediante capas superpuestas de rectángulos para lograr un acabado visual superior.
- Los bucles for permiten dibujar hileras modulares y simétricas de iconos repetidos (corazones, medallas o gemas) calculando desplazamientos matemáticos por iteración.
Practica lo aprendido
Ejercicio 1 · 1 punto
¿Por qué se recomienda crear un objeto controlador dedicado (como obj_hud) para gestionar la interfaz, en lugar de colocar el código de dibujo dentro de obj_player?
Ejercicio 2 · 1 punto
Ordena los pasos necesarios para implementar la técnica de sombra paralela ('drop shadow') al renderizar el texto de puntuación en el evento Draw GUI, según el patrón visto en la lección:
- 1Cambiar el color a negro (c_black) y dibujar el texto desplazado ligeramente de las coordenadas base.
- 2Definir las coordenadas base y almacenar la cadena de texto convertida con la función string().
- 3Cambiar el color al tono frontal (c_white) y dibujar el texto en las coordenadas base originales.
- 4Restablecer preventivamente los estados de dibujo a sus valores predeterminados.
- 5Configurar los estados iniciales de dibujo (fuente, color y alineaciones horizontal y vertical).
Ejercicio 3 · 1 punto
El parámetro 'amount' de la función draw_healthbar() exige un porcentaje normalizado entre 0 y 100 calculado con la fórmula: (salud_actual / salud_maxima) * 100. Si el personaje tiene actualmente 15 puntos de salud y su salud máxima es de 60, ¿qué valor numérico debe recibir dicho parámetro? (Ingresa solo el número).
Ingresa para guardar tu progreso — Ingresar