Contenido del curso
Creando un enemigo
- 5

Fluxograma de estados do personagem no GameMaker
10:13 min - 6

Cómo preparar sprites de un enemigo en Game Maker
05:31 min - 7

Diseño de estados para un enemigo en GameMaker
04:57 min - 8

Persecución de enemigos con lengthdir
12:12 min - 9

Alarmas en GameMaker para controlar ataques
05:55 min - 10

Balas enemigas con dirección dinámica en GML
Viendo ahora - 11

Sensor de ataque en GameMaker paso a paso
10:15 min
Persistencia de objetos
Porting
Balas enemigas con dirección dinámica en GML
Resumen
Programar el ataque de un enemigo en Game Maker requiere algo más que una animación: necesitas un proyectil que se mueva, colisione y haga daño al jugador. Aquí aprendes a crear bullets enemigos con dirección dinámica, sensores de colisión y limpieza de memoria, ideal si estás desarrollando tu primer videojuego 2D con GML.
La lógica que vas a construir conecta tres piezas: un sprite animado para la bala, un objeto con físicas tipo sensor, y la instanciación automática desde el evento animation end del enemigo. Todo se sostiene sobre conceptos como lengthdir_x, point_direction y el manejo de scope entre instancias.
Cómo creo el sprite y el objeto de la bala enemiga
Antes de programar el comportamiento, necesitas un recurso visual y un objeto que lo use.
Dentro de la carpeta Enemigo, crea un sprite llamado sprEnemyBullet partiendo de un círculo pequeño. Duplica el frame con Control+C y Control+V, pinta el segundo en rojo con la cubeta y baja la velocidad de animación a 10 para que el parpadeo se vea bien [02:00]. Aplica Image autotrim all frames para recortar el canvas sobrante y centra el origen del sprite.
Luego crea el objeto objEnemyBullet, asígnale el sprite y actívale físicas marcándolo como sensor. Un sensor detecta colisiones sin empujar al jugador, que es justo lo que quieres: solo registrar el impacto.
¿Qué es un sensor en Game Maker? Es un cuerpo físico que detecta colisiones pero no aplica fuerza ni mueve a otros objetos. Sirve para triggers, hitboxes y proyectiles que solo deben "avisar" cuando tocan algo.
Cómo programo el movimiento y la destrucción de la bala
El proyectil necesita dos variables base y dos eventos clave.
En el evento create define spd = 3 y dir = 0 como valores iniciales [03:30]. La velocidad la puedes ecualizar después según el ritmo del juego.
En el evento step mueve la bala con esta lógica:
gml x += lengthdir_x(spd, dir); y += lengthdir_y(spd, dir);
El operador += toma el valor actual de la variable y le suma lo que viene después, equivalente a escribir x = x + lengthdir_x(...). Las funciones lengthdir_x y lengthdir_y calculan cuánto avanzar en cada eje según un ángulo y una distancia.
Para la colisión con el jugador, usa with (other) para aplicar el daño a la instancia tocada y luego destruye solo la bala:
gml with (other) { hp -= 10; } instance_destroy();
Ojo con la posición de instance_destroy: si lo metes dentro de las llaves del with, eliminarías al jugador en vez de a la bala.
Finalmente, agrega el evento Other > Outside Room con instance_destroy() para que las balas que no impacten no se queden flotando en memoria infinitamente.
Cómo hago que el enemigo dispare automáticamente hacia el jugador
La instanciación manual no sirve: necesitas que el enemigo cree la bala al terminar su animación de ataque.
En el evento animation end del enemigo usa instance_create_layer, que devuelve el instance ID del objeto recién creado. Guárdalo en una variable local para poder modificar sus propiedades después:
gml var bullet = instance_create_layer( x + lengthdir_x(10, 0), y, "instances", objEnemyBullet ); bullet.dir = point_direction(x, y, objPlayer.x, objPlayer.y);
La diferencia entre instance_create_layer e instance_create_depth es que la primera coloca el objeto en una capa nombrada del room y la segunda usa profundidad numérica. Para mantener la organización del room conviene la versión por capas.
¿Qué hace point_direction en GML? Calcula el ángulo en grados desde un punto de origen hacia un punto destino. Es ideal para que un proyectil apunte directo al jugador sin importar dónde esté.
Por qué guardar la dirección del enemigo en una variable
Para que la bala salga del dedo y no del pecho, necesitas saber hacia dónde mira el enemigo en ese instante.
En el create del enemigo declara dir_x = 1 y en el step asigna ahí el resultado del sign que ya calculabas antes para el flip del sprite. Después aplica image_xscale = dir_x. De esta forma reutilizas la misma variable en animation end para desplazar el punto de aparición de la bala unos 10 píxeles al frente del enemigo.
Cómo manejo la vida del jugador con escalabilidad
Un detalle importante: si el daño solo se revisaba en la colisión con el hazard, las balas bajaban HP pero nunca disparaban el game over.
La solución es mover la verificación de vida al evento step del jugador. Así, en cada frame el personaje revisa cuánto HP le queda sin importar la fuente del daño: balas, hazards o futuros ataques. Esto conecta directamente con el concepto de escalabilidad: un código que funcionaba bien con una sola fuente de daño deja de servir cuando el sistema crece [14:30].
Errores comunes al leer la consola de Game Maker
Cuando aparece una ventana de error roja, no es el fin del mundo. Es información valiosa.
- Lee el evento donde ocurrió, por ejemplo animation end de
objEnemyNio. - Identifica la función que falló, como
instance_create_layer. - Revisa el mensaje específico, que suele indicar capas mal escritas o variables inexistentes.
Un error típico es escribir mal el nombre de la capa: si en el room se llama instances y en el código pusiste algo distinto, el juego truena. Compara siempre el string exacto con el nombre real en la jerarquía del room.
Con el sistema funcionando, el HP baja de 10 en 10 con cada impacto y el personaje muere cuando llega a cero. ¿Qué cambios harías tú al daño o a la velocidad de las balas para ajustar la dificultad? Cuéntalo en los comentarios.