258 lines
8.7 KiB
GDScript
258 lines
8.7 KiB
GDScript
extends Node2D
|
|
|
|
@export var shapes: Array = []
|
|
@export var radius: float = 300
|
|
@export var width: float = 5
|
|
@export var circle_color: Color = Color(1, 1, 1, 1)
|
|
|
|
var num_points = 100
|
|
var points = []
|
|
var segment_colors = []
|
|
|
|
# === ESTADÍSTICAS ===
|
|
var start_time : int
|
|
var end_time : int
|
|
var fallos : int = 0
|
|
var segmentos_visitados = []
|
|
var resultados_formas = {} # Diccionario para guardar los resultados de cada forma
|
|
|
|
var juego_finalizado = false
|
|
var forma_actual_index = 0 # Índice de la forma actual en el array 'shapes'
|
|
var forma_actual_nombre : String # Nombre de la forma actual
|
|
|
|
func _ready():
|
|
iniciar_forma()
|
|
|
|
func iniciar_forma():
|
|
if forma_actual_index < shapes.size():
|
|
forma_actual_nombre = shapes[forma_actual_index]
|
|
print("Empezando forma:", forma_actual_nombre)
|
|
start_time = Time.get_unix_time_from_system()
|
|
fallos = 0
|
|
segmentos_visitados.clear()
|
|
points = get_shape_points()
|
|
segment_colors.resize(points.size() - 1)
|
|
segmentos_visitados.resize(points.size() - 1)
|
|
for i in range(segment_colors.size()):
|
|
segment_colors[i] = circle_color
|
|
segmentos_visitados[i] = false
|
|
juego_finalizado = false
|
|
queue_redraw()
|
|
else:
|
|
finalizar_juego()
|
|
|
|
func _process(delta):
|
|
update_center()
|
|
|
|
func update_center():
|
|
var screen_size = get_viewport_rect().size
|
|
position = screen_size / 2
|
|
|
|
func _draw():
|
|
points = get_shape_points()
|
|
for i in range(points.size() - 1):
|
|
draw_line(points[i], points[i + 1], segment_colors[i], width)
|
|
for point in points:
|
|
draw_circle(point, width / 2, circle_color)
|
|
|
|
|
|
func _input(event):
|
|
if juego_finalizado:
|
|
return
|
|
|
|
if event is InputEventScreenDrag:
|
|
var local_pos = to_local(event.position)
|
|
var closest_index = get_closest_point_index(local_pos)
|
|
if closest_index != -1:
|
|
segment_colors[closest_index] = Color(0, 1, 0, 1)
|
|
segmentos_visitados[closest_index] = true
|
|
if is_completed():
|
|
finalizar_nivel()
|
|
else:
|
|
fallos += 1
|
|
queue_redraw()
|
|
|
|
func get_closest_point_index(pos: Vector2) -> int:
|
|
var min_dist = 20
|
|
var closest_index = -1
|
|
for i in range(points.size() - 1):
|
|
var mid_point = (points[i] + points[i + 1]) / 2
|
|
var dist = pos.distance_to(mid_point)
|
|
if dist < min_dist:
|
|
min_dist = dist
|
|
closest_index = i
|
|
return closest_index
|
|
|
|
# === DETECCIÓN DE FINALIZACIÓN ===
|
|
|
|
func is_completed() -> bool:
|
|
for visited in segmentos_visitados:
|
|
if not visited:
|
|
return false
|
|
return true
|
|
|
|
func finalizar_nivel():
|
|
end_time = Time.get_unix_time_from_system()
|
|
juego_finalizado = true
|
|
guardar_resultado_forma()
|
|
forma_actual_index += 1
|
|
iniciar_forma()
|
|
|
|
func guardar_resultado_forma():
|
|
var duracion = end_time - start_time
|
|
resultados_formas[forma_actual_nombre] = {
|
|
"tiempo": duracion,
|
|
"fallos": fallos
|
|
}
|
|
print("Resultados de", forma_actual_nombre, ":", resultados_formas[forma_actual_nombre])
|
|
|
|
func finalizar_juego():
|
|
var mensaje_final = "🎉 ¡Juego Completado!\n\nResultados por forma:\n"
|
|
for forma in resultados_formas:
|
|
var resultado = resultados_formas[forma]
|
|
mensaje_final += "%s: Tiempo: %s seg, Fallos: %s\n" % [forma, resultado.tiempo, resultado.fallos]
|
|
|
|
var popup = Label.new()
|
|
popup.text = mensaje_final
|
|
popup.position = Vector2(50, 50)
|
|
popup.add_theme_color_override("font_color", Color(1,1,1))
|
|
popup.add_theme_font_size_override("font_size", 20)
|
|
add_child(popup)
|
|
|
|
# === Formas ===
|
|
|
|
func get_shape_points():
|
|
match forma_actual_nombre : # Usamos la forma actual para dibujar
|
|
"CircleButton": return get_circle_points()
|
|
"StarButton": return get_star_points()
|
|
"heart": return get_heart_points()
|
|
"TriangleButton": return get_polygon_points(3)
|
|
"SquareButton": return get_square_points()
|
|
"diamond": return get_polygon_points(4, true)
|
|
"cross": return get_cross_points()
|
|
"arrow": return get_arrow_points()
|
|
"HouseButton": return get_house_points()
|
|
"UmbrellaButton": return get_umbrella_points()
|
|
_: return []
|
|
|
|
func get_circle_points():
|
|
var result = []
|
|
for i in range(num_points + 1):
|
|
var angle = i * (2 * PI / num_points)
|
|
result.append(Vector2(cos(angle), sin(angle)) * radius)
|
|
return result
|
|
|
|
func get_square_points():
|
|
var result = []
|
|
# Definimos la mitad del tamaño del lado del cuadrado basado en el radio del círculo para que sea similar en tamaño
|
|
var half_side = radius * 0.5
|
|
|
|
# Definimos las cuatro esquinas del cuadrado
|
|
result.append(Vector2(-half_side, -half_side)) # Esquina superior izquierda
|
|
result.append(Vector2(half_side, -half_side)) # Esquina superior derecha
|
|
result.append(Vector2(half_side, half_side)) # Esquina inferior derecha
|
|
result.append(Vector2(-half_side, half_side)) # Esquina inferior izquierda
|
|
result.append(Vector2(-half_side, -half_side)) # Volvemos a la primera esquina para cerrar el cuadrado
|
|
|
|
# Ahora, vamos a añadir puntos intermedios entre las esquinas para que se puedan colorear los segmentos
|
|
var num_segments = 10 # Podemos ajustar cuántos puntos hay en cada lado
|
|
|
|
var points_per_segment = num_points / 4 # Repartimos los puntos entre los 4 lados
|
|
|
|
result.clear() # Empezamos de nuevo con los puntos para los segmentos
|
|
|
|
for i in range(points_per_segment + 1):
|
|
var t = float(i) / points_per_segment
|
|
result.append(lerp(Vector2(-half_side, -half_side), Vector2(half_side, -half_side), t)) # Lado superior
|
|
for i in range(points_per_segment + 1):
|
|
var t = float(i) / points_per_segment
|
|
result.append(lerp(Vector2(half_side, -half_side), Vector2(half_side, half_side), t)) # Lado derecho
|
|
for i in range(points_per_segment + 1):
|
|
var t = float(i) / points_per_segment
|
|
result.append(lerp(Vector2(half_side, half_side), Vector2(-half_side, half_side), t)) # Lado inferior
|
|
for i in range(points_per_segment + 1):
|
|
var t = float(i) / points_per_segment
|
|
result.append(lerp(Vector2(-half_side, half_side), Vector2(-half_side, -half_side), t)) # Lado izquierdo
|
|
result.append(Vector2(-half_side, -half_side)) # Cerramos la figura
|
|
|
|
return result
|
|
|
|
func get_star_points():
|
|
var result = []
|
|
var spikes = 5
|
|
var outer_radius = radius * 0.8 # Un poco más pequeño que el radio del círculo
|
|
var inner_radius = radius * 0.4
|
|
var step = PI / spikes
|
|
for i in range(spikes * 2):
|
|
var angle = i * step - PI/2 # Empezar desde arriba
|
|
var r = outer_radius if i % 2 == 0 else inner_radius
|
|
result.append(Vector2(cos(angle), sin(angle)) * r)
|
|
result.append(result[0]) # Cerrar la forma
|
|
return result
|
|
|
|
func get_heart_points():
|
|
var result = []
|
|
for i in range(num_points + 1):
|
|
var t = i * (2 * PI / num_points)
|
|
var x = 16 * pow(sin(t), 3)
|
|
var y = -(13 * cos(t) - 5 * cos(2*t) - 2 * cos(3*t) - cos(4*t)) # Invertir para que mire hacia arriba
|
|
result.append(Vector2(x, y) * (radius / 15.0)) # Escalar para que quepa
|
|
return result
|
|
|
|
func get_polygon_points(sides: int, rotated := false):
|
|
var result = []
|
|
var angle_offset = PI / sides if rotated else 0
|
|
for i in range(sides + 1):
|
|
var angle = angle_offset + i * (2 * PI / sides)
|
|
result.append(Vector2(cos(angle), sin(angle)) * radius * 0.8) # Un poco más pequeño
|
|
return result
|
|
|
|
func get_cross_points():
|
|
var thickness = radius * 0.2
|
|
var length = radius * 0.6
|
|
return [
|
|
Vector2(-thickness/2, -length/2), Vector2(thickness/2, -length/2),
|
|
Vector2(thickness/2, -thickness/2), Vector2(length/2, -thickness/2),
|
|
Vector2(length/2, thickness/2), Vector2(thickness/2, thickness/2),
|
|
Vector2(thickness/2, length/2), Vector2(-thickness/2, length/2),
|
|
Vector2(-thickness/2, thickness/2), Vector2(-length/2, thickness/2),
|
|
Vector2(-length/2, -thickness/2), Vector2(-thickness/2, -thickness/2),
|
|
Vector2(-thickness/2, -length/2)
|
|
]
|
|
|
|
func get_arrow_points():
|
|
var head_width = radius * 0.4
|
|
var head_height = radius * 0.5
|
|
var tail_width = radius * 0.2
|
|
var tail_height = radius * 0.6
|
|
return [
|
|
Vector2(-tail_width/2, tail_height/2), Vector2(tail_width/2, tail_height/2),
|
|
Vector2(tail_width/2, 0), Vector2(head_width/2, 0),
|
|
Vector2(0, -head_height/2), Vector2(-head_width/2, 0),
|
|
Vector2(-tail_width/2, 0), Vector2(-tail_width/2, tail_height/2)
|
|
]
|
|
|
|
func get_house_points():
|
|
var base_width = radius * 0.8
|
|
var base_height = radius * 0.6
|
|
var roof_height = radius * 0.5
|
|
return [
|
|
Vector2(-base_width/2, base_height/2), Vector2(base_width/2, base_height/2),
|
|
Vector2(base_width/2, -base_height/2), Vector2(0, -(base_height/2 + roof_height)),
|
|
Vector2(-base_width/2, -base_height/2), Vector2(-base_width/2, base_height/2)
|
|
]
|
|
|
|
func get_umbrella_points():
|
|
var result = []
|
|
var steps = num_points / 2
|
|
var umbrella_radius = radius * 0.7
|
|
for i in range(steps + 1):
|
|
var angle = PI * i / steps
|
|
result.append(Vector2(cos(angle), sin(angle)) * umbrella_radius)
|
|
result.append(Vector2(0, umbrella_radius))
|
|
result.append(Vector2(0, umbrella_radius * 1.3)) # Mango más largo
|
|
return result
|
|
|
|
func get_diamond_points(): # Recuerda que en tu match "diamond" llama a get_polygon_points con rotated = true
|
|
return get_polygon_points(4, true) # Ya debería estar bien con los ajustes de get_polygon_points
|