extends SceneTree # Headless test: run with # godot --headless -s res://tests/test_joystick_recentres.gd # Both sticks float: the base jumps to wherever the finger lands, so a player # does not have to hit an exact spot on a screen they cannot feel. Releasing # used to put only the KNOB back onto the base, leaving the base parked # wherever that touch had been - so an idle stick sat off-centre, in a # different place every time, and read as a control still in use. # # Covers, for the movement stick AND the fire stick: # A. an untouched stick sits in the middle of its own rect # B. pressing off-centre moves the base there - the floating behaviour is # still intact, which is the thing this must not break # C. releasing puts base AND knob back in the middle # D. releasing also clears the reported direction, so nothing keeps acting # on a stick nobody is holding const OFFSET := Vector2(-58.0, 41.0) var main: Node var stage: int = 0 var elapsed: float = 0.0 func _initialize() -> void: main = load("res://Main.tscn").instantiate() root.add_child(main) current_scene = main func _check(stick: Control, label: String) -> bool: var home: Vector2 = stick.home_pos() # --- A. idle means centred ------------------------------------------- if stick.base_pos.distance_to(home) > 0.01 or stick.knob_pos.distance_to(home) > 0.01: return _fail("%s starts at base %s knob %s, expected both at %s" \ % [label, stick.base_pos, stick.knob_pos, home]) # --- B. it still floats to the finger --------------------------------- var press := InputEventScreenTouch.new() press.index = 2 press.pressed = true press.position = stick.global_position + home + OFFSET if not stick.handle_touch(press): return _fail("%s refused a touch inside its own rect" % label) if stick.base_pos.distance_to(home + OFFSET) > 0.01: return _fail("%s did not float its base to the finger: base %s, expected %s" \ % [label, stick.base_pos, home + OFFSET]) var drag := InputEventScreenDrag.new() drag.index = 2 drag.position = press.position + Vector2(stick.max_radius, 0.0) stick.handle_drag(drag) if stick.direction == Vector2.ZERO: return _fail("%s reported no direction while pushed" % label) if stick.knob_pos.distance_to(stick.base_pos) < stick.max_radius * 0.5: return _fail("%s knob barely moved while pushed" % label) # --- C/D. release recentres everything and stops reporting ------------ var release := InputEventScreenTouch.new() release.index = 2 release.pressed = false release.position = drag.position stick.handle_touch(release) if stick.base_pos.distance_to(home) > 0.01: return _fail("%s left its base at %s after release, expected %s" \ % [label, stick.base_pos, home]) if stick.knob_pos.distance_to(home) > 0.01: return _fail("%s left its knob at %s after release, expected %s" \ % [label, stick.knob_pos, home]) if stick.direction != Vector2.ZERO: return _fail("%s still reports %s after release" % [label, stick.direction]) if stick.is_active(): return _fail("%s still claims to be held after release" % label) print("%s: floats to the finger, and returns to centre on release" % label) return true func _process(delta: float) -> bool: elapsed += delta if stage != 0: return false if elapsed < 0.2: return false stage = 1 if not _check(main.get_node("UI/Joystick"), "movement stick"): return true if not _check(main.get_node("UI/FireStick"), "fire stick"): return true print("TEST_JOYSTICK_RECENTRES: PASS") quit(0) return true func _fail(message: String) -> bool: print("TEST_JOYSTICK_RECENTRES: FAIL (%s)" % message) quit(1) return false