AppResidencia/seguir-la-linea/game.gd

144 lines
4.7 KiB
GDScript

extends Node2D
@export var line_width: float = 25.0
@export var allowed_distance: float = 60.0
@export var selected_shape: String = "rombo"
@export var shape_scale: float = 1.0
@export var margin_ratio: float = 0.1
var shape_points: PackedVector2Array
var current_progress := 0
var fail_count := 0
var tracking := false
var shape_presets := {}
func _ready():
get_viewport().connect("size_changed", Callable(self, "_on_viewport_resized"))
_create_shape_presets()
_draw_selected_shape()
func _draw_selected_shape():
var screen_size = get_viewport().get_visible_rect().size
var center = screen_size / 2.0
var min_dim = min(screen_size.x, screen_size.y)
var scale = (min_dim * shape_scale * (1.0 - margin_ratio * 2)) / 2
if shape_presets.has(selected_shape):
var original = shape_presets[selected_shape]
var interpolated = _interpolate_shape(original, 100, true)
shape_points = PackedVector2Array()
for point in interpolated:
var scaled_point = center + (point * scale)
shape_points.append(scaled_point)
else:
print("⚠️ Forma no encontrada:", selected_shape)
return
$ShapeLine.points = shape_points
$ShapeLine.width = line_width
$ShapeLine.default_color = Color.GRAY
$ShapeLine.texture = null
$ProgressLine.clear_points()
$ProgressLine.points = []
$ProgressLine.width = line_width
$ProgressLine.default_color = Color.GREEN
$ProgressLine.texture = null
current_progress = 0
fail_count = 0
tracking = false
func _on_viewport_resized():
_draw_selected_shape()
func _unhandled_input(event):
if event is InputEventScreenTouch or event is InputEventMouseButton:
if event.pressed:
tracking = true
current_progress = 0
fail_count = 0
$ProgressLine.clear_points()
else:
tracking = false
elif (event is InputEventScreenDrag or event is InputEventMouseMotion) and tracking:
if current_progress >= shape_points.size():
return
var pos = event.position
var nearest_point = -1
var min_distance = allowed_distance
for i in range(current_progress, shape_points.size()):
var dist = pos.distance_to(shape_points[i])
if dist < min_distance:
min_distance = dist
nearest_point = i
if nearest_point != -1:
current_progress = nearest_point
$ProgressLine.add_point(shape_points[nearest_point])
if current_progress >= shape_points.size() - 1:
tracking = false
print("✅ ¡Forma completada!")
print("❌ Errores:", fail_count)
else:
fail_count += 1
print("❌ Fuera de la línea. Total:", fail_count)
func _create_shape_presets():
shape_presets = {
"cuadrado": [Vector2(-1, -1), Vector2(1, -1), Vector2(1, 1), Vector2(-1, 1)],
"triangulo": [Vector2(0, -1), Vector2(1, 1), Vector2(-1, 1)],
"casa": [Vector2(-1, 1), Vector2(-1, 0), Vector2(0, -1), Vector2(1, 0), Vector2(1, 1)],
"paraguas": [Vector2(-1, 0.5), Vector2(1, 0.5), Vector2(0, -1), Vector2(-1, 0.5), Vector2(0, 1)],
"diamante": [Vector2(0, -1), Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0)],
"linea": [Vector2(-1, 0), Vector2(1, 0)],
"rectangulo": [Vector2(-1, -0.5), Vector2(1, -0.5), Vector2(1, 0.5), Vector2(-1, 0.5)],
"rombo": [Vector2(0, -1), Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0)],
"circulo": generate_circle(Vector2.ZERO, 1),
"estrella": generate_star(Vector2.ZERO, 1),
"corazon": generate_heart(Vector2.ZERO, 1)
}
func _interpolate_shape(points: PackedVector2Array, density: int = 100, closed: bool = true) -> PackedVector2Array:
var interpolated := PackedVector2Array()
var count = points.size()
for i in range(count):
var a = points[i]
var b = points[(i + 1) % count] if closed or i < count - 1 else null
if b != null:
for j in range(density):
var t = float(j) / density
interpolated.append(a.lerp(b, t))
return interpolated
func generate_circle(center: Vector2, radius: float, segments: int = 64) -> PackedVector2Array:
var points := PackedVector2Array()
for i in range(segments + 1):
var angle = 2.0 * PI * float(i) / float(segments)
points.append(center + Vector2(cos(angle), sin(angle)) * radius)
return points
func generate_star(center: Vector2, radius: float, spikes: int = 5) -> PackedVector2Array:
var points := PackedVector2Array()
var inner_radius = radius * 0.5
for i in range(spikes * 2):
var r = radius if i % 2 == 0 else inner_radius
var angle = PI / float(spikes) * i
points.append(center + Vector2(cos(angle), sin(angle)) * r)
points.append(points[0])
return points
func generate_heart(center: Vector2, size: float) -> PackedVector2Array:
var points := PackedVector2Array()
for t in range(0, 360, 10):
var rad = deg_to_rad(t)
var x = size * 16 * pow(sin(rad), 3)
var y = -size * (13 * cos(rad) - 5 * cos(2 * rad) - 2 * cos(3 * rad) - cos(4 * rad))
points.append(center + Vector2(x, y))
points.append(points[0])
return points