¿Qué le falta o como terminar mi código de menú de carrusel?

Actualmente estoy trabajando en este código para un menú de carrusel para mi juego, pero no me esta resultando nada bien, quiero aclarar que no soy muy bueno programando, pero hice el código los mas sencillo posible para que lo utilice todo el mundo (Por lo cual busco colaborar con la comunidad y para aquellos que quieren hacer este tipo de menús), también quiero agregar que he buscado la respuesta tanto en YouTube como navegando por internet, y en todos esos casos, colocan códigos demasiado complicados y rebuscados o son para ocasiones muy especificas, aparte que al parecer en la comunidad de español, no hay nadie que hable de esos temas o no tenga la creatividad, o inician los proyectos y nunca los terminan y todo se inclina a la comunidad inglesa (Recordemos que no todos hablan ingles), si alguien me puede ayudar, estaría demasiado agradecido.

extends Node2D
var Current_Time = 0
var Target_Time = 0
var Spd = 500
var Amp = 200
var Posicion = Vector2()
var Element = []

func _ready():
	var Radio = 50
	var Element = get_children()
	for e in range(Element.size()):
		var Espacio = 2*PI/Element.size()
		var Angulo = e * Espacio
		Element[e].set_position(Vector2(cos(Angulo),sin(Angulo))*Radio)

func _process(null):
	var PC = get_node("/root/Menu_Carousel/Punto_Central")
	Posicion = PC.get_position()
	Current_Time = Current_Time + (Target_Time - Current_Time) * 0.1
	position.x = (Posicion.x + sin(Current_Time/Spd)) * Amp
	position.y = (Posicion.y + cos(Current_Time/Spd)) * (Amp * 0.2)
	scale.y = max((position.y - Posicion.y) * 0.05,0.9)
	scale.x = max((position.y - Posicion.x) * 0.05,0.9)
	
	if Input.is_action_pressed("ui_left"):
		Target_Time += 360/PI
	if Input.is_action_pressed("ui_right"):
		Target_Time -= 360/PI

Con este código ocurre un problemas, y es que los hijos se separan, pero no giran por separados, sino todos en conjunto, como a continuación:

The Light vs Dark Knights (DEBUG) 2024-03-18 18-17-17

Cualquier sugerencia es bien recibida.

Vas por buen camino. En vez de cambiar la posicion y escala de todo el carrusel, deberias hacerlo para cada hijo, con un desfasaje apropiado. Algo como…
for i in get_children():
get_child(i).position = blahblahblah + desfasaje_pos * i
get_child(i).scale = blahblahblah + desfasaje_escala * i
Y en vez de ponerlo en el _process, lo meteria en una función que se llame unicamente cuando el jugador apreta derecha o izquierda. :slight_smile:

¿Estás intentando hacer un menú radial o un menú carrusel?
Son cosas diferentes.
Parece que tienes un menú radial.
En un menú radial, todos los elementos del menú son visibles y el usuario pasa el mouse sobre el elemento que desea.
En un menú radial los elementos no giran.
A continuación se muestra un ejemplo de un menú radial.

En un menú carrusel puede ver algunos elementos del menú, pero solo 1 elemento del menú está al frente y al centro y disponible.
El usuario puede alternar los artículos para que otro artículo esté al frente y al centro y disponible.
A continuación se muestra un ejemplo de un menú carrusel.

Tenga en cuenta que no hablo español y estoy usando Google Translate para esto.

1 Like

Estoy haciendo un menú carrusel, como el del ejemplo 2, claro comprendo lo que dices que parece un menú radial, pero es porque no he logrado separar los elementos para que giren al rededor del centro, y como lo dices para que un elemento o articulo quede al frente y al centro.
Voy a intentar con lo que me recomendó la primera persona.

Vaya no lo había pensado así, y se ve un poco complicado, pero lo voy probar esto que me estas diciendo, si hay algún cambio te lo hare saber.

Amigo, probé tu sugerencia y ahora, no se mueve nada y todos los iconos se hicieron uno solo :expressionless:

The Light vs Dark Knights (DEBUG) 2024-03-22 02-54-17

Que valor les diste a desfasaje_pos y a desfasaje_escala?

Puedo ver como quedó el código completo?

extends Node2D
var desfasaje_pos = 0
var desfasaje_escala = 0

func _input(event):
	if event.is_action_pressed("ui_left" or "ui_right"):
		for i in get_children():
			get_children(i).position = Target_Time + desfasaje_pos * i
			get_children(i).scale = Target_Time + desfasaje_escala * i

Te faltan las lineas de codigo que habias escrito tú, eso seria el “blahblahblah” de mi comentario.

Ademas de que estas usando get_children(i) en vez de get_child(i).

Ademas el desfasaje tiene que ser mayor a 0. No estoy seguro de que valor debería tomar, asi que ponle un valor cualquiera y fijate como queda.

El codigo te quedaría:

for i in get_child_count():
get_child(i).position.x = (Posicion.x + sin(Current_Time/Spd)) * Amp + desfasaje_pos * i
get_child(i).position.y = (Posicion.y + cos(Current_Time/Spd)) * (Amp * 0.2) + desfasaje_pos * i
get_child(i).scale.y = max((get_child(i).position.y - Posicion.y) * 0.05,0.9) + desfasaje_escala * i
get_child(i).scale.x = max((get_child(i).position.y - Posicion.x) * 0.05,0.9) + desfasaje_escala * i

No esperes que funcione a la primera, revisa bien lo que escribi y me respondes con el resultado. :slight_smile:

En lo que vi tu mensaje lo probé, y lo que pasa es que cuando presiono el botón asignado al func _input(event), se sale de la prueba.

Ponlo en el process como estaba antes

Hace lo mismo :cry:

Cual seria el error?

No da error, nada mas al presionar el botón asignado al input y presionarlo, sale automáticamente de la prueba, pero, si es el código realmente no sabría decirte donde esta el error :no_mouth:

Puedes mostrar como te queda el codigo completo ahora?

extends Node2D
var Current_Time = 0
var Posicion = Vector2()
var Spd = 500
var Amp = 200
var desfasaje_pos = 2
var desfasaje_escala = 2

func _process(delta):
	for i in get_child_count():
		get_child(i).position.x = (Posicion.x + sin(Current_Time/Spd)) * Amp + desfasaje_pos * i
		get_child(i).position.y = (Posicion.y + cos(Current_Time/Spd)) * (Amp * 0.2) + desfasaje_pos * i
		get_child(i).scale.y = max((get_child(i).position.y - Posicion.y) * 0.05,0.9) + desfasaje_escala * i
		get_child(i).scale.x = max((get_child(i).position.y - Posicion.x) * 0.05,0.9) + desfasaje_escala * i

Agregale las lineas de codigo que calculan la Posicion del punto central y las de Target Time. Que quede lo mas parecido posible a tu version original donde todo funcionaba, pero agregandole lo que yo te dije.

Incluso haciendo lo que dices, no funciona

extends Node2D
var Current_Time = 0
var Target_Time = 0
var Spd = 500
var Amp = 200
var Posicion = Vector2()
var Elementos = []
var desfasaje_pos = 2
var desfasaje_escala = 2

func _process(null):
	for i in get_child_count():
		var PC = get_node("/root/Menu_Carousel/Punto_Central")
		Posicion = PC.get_position()
		get_child(i).position.x = (Posicion.x + sin(Current_Time/Spd)) * Amp + desfasaje_pos * i
		get_child(i).position.y = (Posicion.y + cos(Current_Time/Spd)) * (Amp * 0.2) + desfasaje_pos * i
		get_child(i).scale.y = max((get_child(i).position.y - Posicion.y) * 0.05,0.9) + desfasaje_escala * i
		get_child(i).scale.x = max((get_child(i).position.y - Posicion.x) * 0.05,0.9) + desfasaje_escala * i
		Current_Time = Current_Time + (Target_Time - Current_Time) * 0.1
		if Input.is_action_pressed("ui_left"):
			Target_Time += 360/PI
		if Input.is_action_pressed("ui_right"):
			Target_Time -= 360/PI
1 Like

No estábamos yendo a ningún lado así que me senté a resolverlo y lo logré.

Para que funcione, tienes que darle este script a un Nodo2D, que actuará como el centro, y cuyos hijos sean las opciones del menú (no importan sus escalas o posiciones iniciales)

Si tienes dudas o quieres cambiar algo me dices. :slight_smile:

(Probablemente tengas que usar un valor distinto para Amp)

Si te sirvió y puedes compartir un gif del resultado para los demás, mejor.
Saludos :slight_smile:

extends Node2D

var current_angle: float = 0.0
@onready var Spd: float = 360.0 / get_child_count() # Grados recorridos por pulsacion
var Amp = 50  


func _ready():
	calculate_position_and_scale(0.0)


func calculate_position_and_scale(angulo):
	var tween = create_tween()
	tween.set_parallel(true)
	
	for e in get_child_count():
		var Espacio = 2*PI / get_child_count()
		var angulo_new = e * Espacio + angulo
		
		
		tween.tween_property(get_child(e), "global_position:x", global_position.x + sin(angulo_new) * Amp, 0.25)
		tween.tween_property(get_child(e), "global_position:y", global_position.y + cos(angulo_new) * Amp * 0.5, 0.25)
		tween.tween_property(get_child(e), "scale", Vector2(1, 1) * ((cos(angulo_new) + 3) / 4), 0.25)


func _process(_delta):
	if Input.is_action_just_pressed("ui_left") or Input.is_action_just_pressed("ui_right"):
		if Input.is_action_just_pressed("ui_left"):
			current_angle -= 2*PI/360 * Spd
		if Input.is_action_just_pressed("ui_right"):
			current_angle += 2*PI/360 * Spd
	
		calculate_position_and_scale(current_angle)

Ok? Gracias por tu intensión y por tu colaboración, pero debo decirte que el código que acabas de colocar lo probé en el godot, y marca errores, y no hace ni la prueba, directamente marca error tanto en el onready y en tween = create_tween