Contenido del curso
Tu primer juego
Desarrollando el juego
Conclusión
IA del oponente en Pong con Godot
Resumen
Crear la inteligencia artificial del oponente en Pong con Godot implica diseñar una lógica simple que permita a la paleta automática seguir la pelota y devolverla. Aquí aprenderás a programar ese comportamiento con GDScript, usando posiciones verticales, márgenes de error y la función move_and_slide para darle vida a tu rival.
Qué lógica sigue la inteligencia artificial del oponente
La idea es que la paleta del oponente compare su posición vertical con la de la pelota y se mueva en consecuencia. Si la pelota está más arriba, sube; si está más abajo, baja; y si la diferencia es mínima, se queda quieta.
¿Cómo funciona la IA del oponente en Pong? Compara la posición Y de la pelota con la posición Y de la paleta. Si la diferencia supera un margen definido (por ejemplo 25 píxeles), la paleta se mueve hacia donde está la pelota.
Es una lógica básica, pero suficiente para tener un rival jugable. Y aquí viene lo interesante: ese margen de error es lo que hace posible ganarle, porque sin él devolvería absolutamente todos los tiros.
Por qué duplicar el nodo del player para crear al oponente
El oponente comparte estructura con el player: tiene un nodo de colisión y un nodo de color que forma la barrita. Por eso conviene duplicarlo en el editor de Godot y renombrarlo como oponente [04:08].
Luego ajustas su posición horizontal para ubicarlo del otro lado del escenario. Si tu lienzo mide 1920 píxeles y quieres mantener la misma distancia que el player respecto al borde, escribes 1920 - 50 y Godot calcula automáticamente el valor.
Eso sí, el script duplicado no sirve porque la lógica será distinta. Debes despegar el script del player haciendo clic en el ícono de la crucecita roja y crear uno nuevo llamado oponente [05:30].
Cómo crear el método get_direction en GDScript
Dentro del script del oponente, defines una variable de velocidad un poco mayor que la del player (por ejemplo 450 frente a 400) para compensar que su lógica no será tan precisa como la tuya.
Después creas un método interno con la convención del guion bajo al inicio, que en GDScript indica que solo se usará dentro de esta clase:
gdscript func _get_direction(): if abs(ball.position.y - position.y) > 25: if ball.position.y > position.y: return 1 else: return -1 return 0
Este método devuelve tres valores posibles: 1 si el oponente debe bajar, -1 si debe subir y 0 si debe quedarse quieto [07:20]. Recuerda que en Godot los valores positivos del eje Y van hacia abajo y los negativos hacia arriba.
¿Para qué sirve la función abs en GDScript? Convierte cualquier número negativo en positivo. Así puedes comparar la diferencia entre dos posiciones sin importar si la pelota está arriba o abajo de la paleta.
Cómo acceder a la pelota desde el script del oponente
La variable ball necesita referenciar al nodo de la pelota que vive en el árbol principal de la escena. Para traerla, usas get_parent() que devuelve el nodo del que depende el oponente, en este caso level, y luego find_node("ball") para localizarla por nombre.
La primera versión usa la función _ready() para asignar la referencia cuando todo el entorno ya está cargado:
gdscript var ball
func _ready(): ball = get_parent().find_node("ball")
Después verás un truco mucho más limpio con onready que reduce todo a una sola línea.
Cómo aplicar el movimiento con physics_process y move_and_slide
Con la dirección calculada, falta ejecutarla en cada frame. Para eso usas _physics_process(delta), la misma función que aplicaste al player, porque garantiza que el movimiento se procese en cada actualización física del motor [12:40].
Dentro construyes un Vector2 donde el eje X siempre es 0 (la paleta no se mueve horizontalmente) y el eje Y recibe el resultado de _get_direction():
gdscript func _physics_process(delta): var direction = Vector2(0, _get_direction()) move_and_slide(direction * speed)
Un detalle importante sobre move_and_slide: no necesitas multiplicar por delta porque la función ya lo hace internamente. Si lo multiplicas, el movimiento será demasiado lento.
Qué es onready y por qué simplifica el código
Una vez funcionando, puedes refactorizar la asignación de ball usando la palabra clave onready. Es azúcar sintáctica que ejecuta la asignación cuando el nodo está listo, igual que _ready(), pero en una sola línea:
gdscript onready var ball = get_parent().find_node("ball")
Con esto eliminas la función _ready() y dejas el código más prolijo. Es una práctica común en GDScript cuando solo necesitas asignar referencias al iniciar la escena.
Cómo hacer más difícil al oponente en tu juego de Pong
La lógica que construiste es deliberadamente simple, pero tiene varias variables para subir la dificultad. Estos son los ajustes más directos:
- Aumentar el valor de
speedpara que reaccione más rápido. - Reducir el margen de 25 píxeles para que persiga la pelota con más precisión.
- Combinar ambos para crear niveles progresivos de dificultad.
Estos parámetros te permiten escalar la IA sin reescribir la lógica. Y como reto, piensa qué otra forma se te ocurre para que el oponente sea más inteligente o más divertido de enfrentar y compártela en los comentarios para que tus compañeros vean variantes distintas.