diff --git a/scenes/objects/XRayMachine.tscn b/scenes/objects/XRayMachine.tscn new file mode 100644 index 0000000..8dfabce --- /dev/null +++ b/scenes/objects/XRayMachine.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=2 format=3 uid="uid://cozypaw_xraymachine"] + +[ext_resource type="Script" path="res://scripts/objects/xray_machine.gd" id="1_xraymachine"] + +[node name="XRayMachine" type="Node2D"] +script = ExtResource("1_xraymachine") + +[node name="MachineBody" type="ColorRect" parent="."] +color = Color(0.68, 0.70, 0.76, 1) +size = Vector2(80, 200) +position = Vector2(-40, -200) + +[node name="MachineArm" type="ColorRect" parent="."] +color = Color(0.62, 0.64, 0.70, 1) +size = Vector2(220, 24) +position = Vector2(-40, -180) + +[node name="ViewerFrame" type="ColorRect" parent="."] +color = Color(0.20, 0.22, 0.26, 1) +size = Vector2(80, 60) +position = Vector2(-40, -195) + +[node name="Viewer" type="ColorRect" parent="."] +color = Color(0.06, 0.08, 0.12, 1) +size = Vector2(66, 46) +position = Vector2(-33, -189) + +[node name="Plate" type="Node2D" parent="."] +position = Vector2(-50, 20) + +[node name="PlateBody" type="ColorRect" parent="Plate"] +color = Color(0.28, 0.32, 0.38, 1) +size = Vector2(200, 14) +position = Vector2(0, -7) diff --git a/scripts/objects/xray_machine.gd b/scripts/objects/xray_machine.gd new file mode 100644 index 0000000..492b380 --- /dev/null +++ b/scripts/objects/xray_machine.gd @@ -0,0 +1,76 @@ +## XRayMachine — X-ray plate slides out when tapped; viewer lights up during exposure. +class_name XRayMachine extends Node2D + +enum State { IDLE, SLIDING_IN, EXPOSING, SLIDING_OUT } + +const SLIDE_DURATION: float = 0.8 +const EXPOSE_DURATION: float = 1.5 +const BUTTON_HALF_WIDTH: float = 50.0 +const BUTTON_HALF_HEIGHT: float = 100.0 +const PLATE_PARKED_X: float = -50.0 +const PLATE_ACTIVE_X: float = 130.0 +const VIEWER_LIT_COLOR: Color = Color(0.75, 0.90, 1.0, 1) +const VIEWER_DARK_COLOR: Color = Color(0.06, 0.08, 0.12, 1) + +var _state: State = State.IDLE + + +func _ready() -> void: + var plate: Node2D = get_node_or_null("Plate") as Node2D + if plate != null: + plate.position.x = PLATE_PARKED_X + + +func _input(event: InputEvent) -> void: + if _state != State.IDLE: + return + var screen_pos: Vector2 + if event is InputEventScreenTouch and event.pressed: + screen_pos = event.position + elif event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: + screen_pos = event.position + else: + return + var canvas_transform: Transform2D = get_viewport().get_canvas_transform() + var world_pos: Vector2 = canvas_transform.affine_inverse() * screen_pos + var local_pos: Vector2 = to_local(world_pos) + if abs(local_pos.x) <= BUTTON_HALF_WIDTH and abs(local_pos.y) <= BUTTON_HALF_HEIGHT: + _start_scan() + + +func _start_scan() -> void: + _state = State.SLIDING_IN + var plate: Node2D = get_node_or_null("Plate") as Node2D + if plate == null: + _state = State.IDLE + return + var tween: Tween = create_tween() + tween.set_ease(Tween.EASE_IN_OUT) + tween.set_trans(Tween.TRANS_QUAD) + tween.tween_property(plate, "position:x", PLATE_ACTIVE_X, SLIDE_DURATION) + tween.finished.connect(_on_plate_in) + + +func _on_plate_in() -> void: + _state = State.EXPOSING + var viewer: ColorRect = get_node_or_null("Viewer") as ColorRect + if viewer != null: + viewer.color = VIEWER_LIT_COLOR + var timer: SceneTreeTimer = get_tree().create_timer(EXPOSE_DURATION) + timer.timeout.connect(_start_slide_out) + + +func _start_slide_out() -> void: + _state = State.SLIDING_OUT + var viewer: ColorRect = get_node_or_null("Viewer") as ColorRect + if viewer != null: + viewer.color = VIEWER_DARK_COLOR + var plate: Node2D = get_node_or_null("Plate") as Node2D + if plate == null: + _state = State.IDLE + return + var tween: Tween = create_tween() + tween.set_ease(Tween.EASE_IN_OUT) + tween.set_trans(Tween.TRANS_QUAD) + tween.tween_property(plate, "position:x", PLATE_PARKED_X, SLIDE_DURATION) + tween.finished.connect(func() -> void: _state = State.IDLE)