extends Control const TELEMETRY_PORT := 4242 const COMMAND_ADDR := "127.0.0.1" const COMMAND_PORT := 4243 const ADC_MAX := 1023.0 const SMOOTH_SPEED := 12.0 # higher = snappier, lower = floatier @onready var led_button: Button = $Panel/LedButton @onready var pad: Panel = $Panel/Pad @onready var dot: ColorRect = $Panel/Pad/Dot var _udp_in := PacketPeerUDP.new() var _udp_out := PacketPeerUDP.new() var _target_x := 512.0 # rest near center so the dot starts in the middle var _target_y := 512.0 var _smoothed_x := 512.0 var _smoothed_y := 512.0 var _btn_pressed := false var _led_on := false const COLOR_DOT_IDLE := Color(0.3, 0.7, 1.0) # cyan const COLOR_DOT_PRESSED := Color(0.2, 1.0, 0.4) # green func _ready() -> void: _udp_in.bind(TELEMETRY_PORT, "127.0.0.1") # set_dest_address is the reliable way to *send* with PacketPeerUDP in Godot 4; # connect_to_host is aimed at receiving and can silently drop outbound packets. _udp_out.set_dest_address(COMMAND_ADDR, COMMAND_PORT) led_button.pressed.connect(_on_led_pressed) func _process(delta: float) -> void: # Drain the queue; the newest packet wins. Format: "x,y,btn" e.g. "512,498,0" while _udp_in.get_available_packet_count() > 0: var parts := _udp_in.get_packet().get_string_from_utf8().split(",") if parts.size() >= 3 and parts[0].is_valid_int() and parts[1].is_valid_int(): _target_x = float(parts[0]) _target_y = float(parts[1]) _btn_pressed = parts[2].strip_edges() == "1" # Frame-rate-independent smoothing so the dot glides instead of twitching. var t := 1.0 - exp(-SMOOTH_SPEED * delta) _smoothed_x = lerpf(_smoothed_x, _target_x, t) _smoothed_y = lerpf(_smoothed_y, _target_y, t) # Normalize raw ADC (0..1023) to 0..1. var nx := clampf(_smoothed_x / ADC_MAX, 0.0, 1.0) var ny := clampf(_smoothed_y / ADC_MAX, 0.0, 1.0) # Move the dot within the pad. Invert Y so pushing the stick UP moves the dot UP. # (If it feels backwards, change "1.0 - ny" to "ny", or swap for X below.) var travel := pad.size - dot.size dot.position = Vector2(nx * travel.x, (1.0 - ny) * travel.y) # Reflect the stick's push-button by recoloring the dot. dot.color = COLOR_DOT_PRESSED if _btn_pressed else COLOR_DOT_IDLE func _on_led_pressed() -> void: _led_on = not _led_on _udp_out.put_packet(("L1" if _led_on else "L0").to_utf8_buffer()) led_button.text = "LED: ON" if _led_on else "LED: OFF"