No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Desarrollando la IA de tu oponente

12/17
Recursos

Aportes 17

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Hola, comparto mi solución “actual” para el funcionamiento del enemigo :)

Esta permite de cierta forma modificar la dificultad, lo realicé teniendo en cuenta la distancia de reacción que podría llegar a tener el enemigo respecto a la posición de la pelota, además esta solución le otorga al enemigo un poco de movimiento independiente en el eje y, para que parezca que no está todo el tiempo siguiendo la misma dirección de la pelota (al menos cuando no es necesario) y se note un poco más animado.

extends KinematicBody2D

var speed = 600
var direction = Vector2.ZERO
var reaction_dist_x = 0
var reaction_dist_y = 0

onready var ball = get_parent().find_node('Ball')

func _ready():
	randomize()
	
	var window_width = OS.get_window_size().x
	var shape_height = find_node('CollisionShape2D').shape.extents.y
	reaction_dist_x = window_width
	reaction_dist_y = shape_height
	# modify the reaction distance component values in terms of dificulty
	# the difficulty can be graduated through the percentage
	# "more percentage decrease, more difficulty"
	reaction_dist_x -= window_width * 0.35 #easy
	reaction_dist_y -= shape_height * 0.5 #easy
	direction.y = [-1, 1][_random_select()]

func _physics_process(delta):
	var delta_y = ball.position.y - position.y
	
	if ball.position.x > reaction_dist_x && ball.direction.x > 0 && abs(delta_y) > reaction_dist_y:
		direction = Vector2(0, delta_y).normalized()
		move_and_slide(direction * speed)
	else:
		var collide = move_and_collide(direction * speed * delta)
		if collide:
			direction.y *= -1

func _random_select():
	return int(randf() > 0.5)

Si se encuentran con algunas líneas confusas o ambiguas, etc… lo siento 😓, nunca antes había visto este lenguaje de programación, así que por el momento, solo me comprometo a mejorar >:)

Versión del script del oponente para godot 4

extends CharacterBody2D

const SPEED = 600.0
@onready var ball = get_parent().find_child("Ball")

func _physics_process(delta):
	
	velocity.y = _get_oponent_direction() * SPEED
	#velocity.x = 0
	
	move_and_collide(velocity * delta)
	
func _get_oponent_direction():
	
	if abs(ball.position.y - position.y) > 25:
		if ball.position.y > position.y:
			return 1
		else:
			return -1
	else:
		return 0
		

Es importante resaltar que cambié el move_and_slide por move_and_collide porque si la pelota golpea en cierto ángulo al oponente entonces éste hace un slide y se va junto con la pelota.

Yo agregué una línea de código para que el oponente solo se mueva cuando la pelota este en la mitad del tablero. Esto lo hice para que el oponente no se mueva en todo momento, y solo cuando la pelota este cerca de él

extends KinematicBody2D

var speed = 600
onready var ball = get_parent().find_node("Ball")

func _physics_process(delta):
	if ball.position.x > 960: #esta es la linea que agregué
		var direction = Vector2(0, _get_direction())
		move_and_slide(direction * speed)
	
func _get_direction():
	if abs(ball.position.y - position.y) > 20:
		if ball.position.y > position.y:
			return 1
		else:
			return -1
	else:
		return 0

Sobre la pregunta de como hacer mas complicado el juego

Con las condiciones:

  • Player 400
  • Ball y Rival 600
  • Paleta 160 px
  • Diferencia de altura 25 para que se mueva la paleta Rival

El resultado es que la paleta rival empieza a moverse cuando la pelota esta 25 por arriba/debajo del centro(posicion) del Nodo

No es dificil responder, pero tampoco es tan facil “hacerle puntos”

Se podria disminuir el margen de 25 y/o aumentar la velocidad de la pelota y lapaleta Rival. Aumentar las velocidades conforme pasa el tiempo.

Otra opcion que vi, aunque no estoy seguro

Me parecio notar que la escena Player tiene el centro del Nodo en la esquina superior izquierda de los objetos (ColorRect y CollisionShape) y no en el centro de estos.

Esto provoca una demora en el arranque de la paleta rival cuando la pelota se mueve hacia arriba, ya que espera a que la paleta este 25 px por encima para empezar a moverse.
De esta manera es mas facil hacer puntos si buscas que la pelota rebote hacia arriba.
Teniendo esto como referencia, podriamos usar 2 margenes distintos y que de manera aleatoria la paleta se mueva mas rapido hacia arriba que hacia abajo o al reves. Para confundir al jugador.

Como yo odio los strings mágicos (en este caso “Ball”) porque acopla el código a la escena recomiendo usar:

@export var ball:CharacterBody2D = null

en lugar de:

onready var ball = get_parent().find_node("Ball")

Eso sí, tienes que asignarlo de forma “visual” en el editor así:

En este proyecto no hace falta, pero es una buena práctica, así tus nodos serán más reutilizables.

Espero en un futuro poner una mejor IA, pues solo tengo mis ideas aunque no se como poner el código pero se trata de engañar al jugador player entonces que se mueva en sentido opuesto a la pelota y posteriormente cuando este le de el golpe se mueva en sentido a la pelota para que le tiempo de poder pegarlo o a su ves calcular los golpes de pelota por ángulos y este esperando la pelota jajajajaja NIEVEL MASTER de la IA.

Saludos! 😄
No me funciono la IA, asi que use el código del compañero Santiago Palacio Vasquez.
Lo dejaré como mejora a futuro. (Quizás por niveles)

Postee el de la pelota jaja, este es el de la maquina, version Godot 4. `extends CharacterBody2D` `var speed = 600` `var ball` `var direction = 0` `func _ready() -> void:` ` ``ball = get_parent().find_child("Ball")` `func _physics_process(delta: float):` ` ``if ball.position.x > get_viewport_rect().size.x / 2 :` ` `` ``direction = Vector2(0, _get_direction())` ` `` ``velocity = direction * speed` ` `` ``move_and_slide()` `func _get_direction():` ` ``if abs(ball.position.y - position.y) > 25:` ` `` ``if ball.position.y > position.y:` ` `` `` ``return 1` ` `` ``else: ` ` `` `` ``return -1` ` ``else: ` ` `` ``return 0`

Lista la IA comparto mi codigo 😃

Me gustaría agregar un metodo mío pero me falta aprender más para programar.

Mi solución para el _get_direction

func _get_direction():
	var direction = Vector2.ZERO
	
	var y_diff = ball.position.y - position.y
	
	if abs(y_diff) > ai_reaction:
		direction.y = y_diff
		
	return direction.normalized()
Estuve renegando un poquitin tratando de deducir como adaptar esto al codigo de Godot 4. Resulta que find\_node fue removido, ahora se usa find\_child jaja. En fin. Aca esta mi codigo, le agregue un multiplicador de velocidad porque sino la partida no termina nunca. Y tambien hice una reformulacion de algo que hizo un compañero para que la maquina solo se mueva si la pelota esta en su mitad del campo. extends CharacterBody2D var speed = 500 var is\_moving = false func \_ready(): randomize() velocity.x =\[-1,1]\[randi() % 2 ] \* speed velocity.y =\[-0.8,0.8]\[randi() % 2 ] \* speed is\_moving = true func \_physics\_process(delta): if is\_moving: var collide = move\_and\_collide(velocity \* delta) if collide: velocity.x = velocity.x \* 1.05 velocity.y = velocity.y \* 1.02 velocity = velocity.bounce(collide.get\_normal())
Solución para Godot 4.2.2: ```js extends CharacterBody2D var SPEED = 600.0 @onready var ball = get_parent().find_child("Ball") func _physics_process(delta): var direction = Vector2(0, _get_direction()) move_and_collide(SPEED * direction * delta) func _get_direction(): if abs(ball.position.y - position.y) > 25: if ball.position.y > position.y: return 1 else: return -1 else: return 0 ```
Para Godot 4.2.1, se hace esto: * En la parte donde el profe dice lo de "onready", se debe escribir eso mismo pero con una arroba al inicio -> @onready * Esto es algo que hice yo porque no entendí bien como usar "move\_and\_slide()" en esta versión de Godot, así que yo usé "move\_and\_collide()" con tanto el Player como con el Oponente. Si lo haces, no olvides que hay que ponerle como argumento "direction \* speed \* delta". Si no pones ese delta, las barras se moverán a la velocidad de la luz. Espero que esto ayude <3

Para los que esten en Godot 4 y no puedan usar el move_and_slide(direction * speed) aqui les dejo mi codigo como referencia para que el oponente se mueva, tambien le agregue que el oponente se pueva solo cuando la pelota este a mitad del tablero y que no se mueva si la pelota le pasa.

extends CharacterBody2D

var speed = 620
var ball

func _ready():
	ball = get_parent().find_child("Ball")


func _physics_process(delta):
	if ball.position.x < 960 and ball.position.x > position.x:
		var direction = Vector2(0, _get_direction())
		velocity = direction * speed
		
		move_and_slide()


func _get_direction():
	if abs(ball.position.y - position.y) > 5:
		if ball.position.y > position.y:
			return 1
			
		else:
			return -1
		
	else:
		return 0

Por cierto en mi juego quise poner el oponente a la izquierda y el jugador a la derecha, en caso de tenerlo como en la clase solo deberian modificar la linea que dice “if ball.position.x < 960 and ball.position.x > position.x”

Para los que estén usando godot 4, en vez de poner “onready” directamente antes de la variable, ahora se pone “@onready” por lo que la línea de código quedaría de la siguiente forma:

@onready var ball = get_parent().get_node("Ball")

Siguiendo la idea de la compañera Andrea Stephania Garcia Castillo lo que hice fue agregar su condicional y juntarle el valor que tenemos cuando la pelota se dirije al enemigo, quedaría algo así…

func _physics_process(delta):
	if ball.direction.x > 0 and ball.position.x > 960: 
		var direction = Vector2(0, _get_direction())
		move_and_slide(direction * speed)