demo-game/scripts/calibration_overlay.gd
simon bc25226a31 Initial commit: Godot Pong game with WebSocket accelerometer control.
Includes platform steering via calibrated accel axes, ball physics,
calibration overlay with axis detection, and runtime tuning sliders.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 21:52:35 +02:00

150 lines
3.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Control
signal calibration_finished(calibration: AccelCalibration)
enum Phase { WAITING, RIGHT, LEFT, DONE }
const TRAVEL_PX := 140.0
const PHASE_DURATION := 4.5
const CIRCLE_RADIUS := 44.0
const NEEDLE_LEN := 58.0
var _phase := Phase.WAITING
var _phase_time := 0.0
var _guide_offset := Vector2.ZERO
var _instruction := ""
var _calibration := AccelCalibration.new()
var _connection_notified := false
@onready var _hint_label: Label = $HintLabel
@onready var _start_button: Button = $StartButton
func _ready() -> void:
set_anchors_preset(Control.PRESET_FULL_RECT)
mouse_filter = Control.MOUSE_FILTER_PASS
_start_button.pressed.connect(_on_start_pressed)
_show_waiting()
func start() -> void:
_calibration.reset()
_connection_notified = false
_phase = Phase.WAITING
_phase_time = 0.0
_guide_offset = Vector2.ZERO
visible = true
_start_button.visible = true
_show_waiting()
queue_redraw()
func is_active() -> bool:
return _phase != Phase.DONE
func feed_accel(accel: Vector3i) -> void:
match _phase:
Phase.RIGHT:
_calibration.record_right(accel)
Phase.LEFT:
_calibration.record_left(accel)
func notify_connected() -> void:
if _phase != Phase.WAITING or _connection_notified:
return
_hint_label.text = "Verbunden tippe „Kalibrierung starten“ oder warte…"
# Automatisch starten sobald verbunden
begin_calibration()
func begin_calibration() -> void:
if _phase == Phase.RIGHT or _phase == Phase.LEFT:
return
_connection_notified = true
_start_button.visible = false
_begin_phase(Phase.RIGHT)
func _on_start_pressed() -> void:
begin_calibration()
func _process(delta: float) -> void:
if _phase == Phase.WAITING or _phase == Phase.DONE:
return
_phase_time += delta
var t := clampf(_phase_time / PHASE_DURATION, 0.0, 1.0)
var ease := t * t * (3.0 - 2.0 * t)
match _phase:
Phase.RIGHT:
_guide_offset.x = TRAVEL_PX * ease
_instruction = "Neige das Gerät nach rechts folge dem Kreis →"
if _phase_time >= PHASE_DURATION:
_begin_phase(Phase.LEFT)
Phase.LEFT:
_guide_offset.x = -TRAVEL_PX * ease
_instruction = "Neige das Gerät nach links folge dem Kreis ←"
if _phase_time >= PHASE_DURATION:
_finish()
_hint_label.text = _instruction
queue_redraw()
func _begin_phase(phase: Phase) -> void:
_phase = phase
_phase_time = 0.0
_guide_offset = Vector2.ZERO
match phase:
Phase.RIGHT:
_instruction = "Neige das Gerät nach rechts folge dem Kreis →"
Phase.LEFT:
_instruction = "Neige das Gerät nach links folge dem Kreis ←"
_hint_label.text = _instruction
queue_redraw()
func _finish() -> void:
_phase = Phase.DONE
visible = false
if _calibration.analyze():
calibration_finished.emit(_calibration)
else:
_hint_label.text = "Kalibrierung fehlgeschlagen zu wenig Daten"
visible = true
_start_button.visible = true
_show_waiting()
func _show_waiting() -> void:
_instruction = "Warte auf Verbindung zu localhost:9090…"
_hint_label.text = _instruction + "\n(Oder „Kalibrierung starten“ ohne Verbindung)"
func _screen_center() -> Vector2:
return get_viewport_rect().size * 0.5
func _draw() -> void:
if _phase == Phase.DONE:
return
var pos := _screen_center() + _guide_offset
draw_circle(pos, CIRCLE_RADIUS, Color(0.25, 0.72, 0.95, 0.2))
draw_arc(pos, CIRCLE_RADIUS, 0.0, TAU, 64, Color(0.35, 0.82, 1.0), 2.5)
var needle_tip := pos + Vector2(0.0, -NEEDLE_LEN)
draw_line(pos, needle_tip, Color(1.0, 1.0, 1.0, 0.95), 3.0)
draw_circle(needle_tip, 5.0, Color(1.0, 1.0, 1.0))
var center := _screen_center()
if _phase == Phase.RIGHT:
draw_line(center, center + Vector2(TRAVEL_PX, 0.0), Color(1.0, 1.0, 1.0, 0.12), 1.0)
elif _phase == Phase.LEFT:
draw_line(center, center + Vector2(-TRAVEL_PX, 0.0), Color(1.0, 1.0, 1.0, 0.12), 1.0)