extends Sprite2D # answer for the puzzle, by columns @export var current_answer := [0, 0, 0, 0, 0, 0, 0, 0, 0] @export_enum("closed", "opened", "playing", "finished") var mode := "closed" @export var answer := [1, 0, 0, 0, 0, 0, 0, 0, 0] # @export var answer := [1, 4, 3, 1, 3, 6, 4, 3, 2] @onready var points_polygon = $ButtonPositionPoints as Polygon2D @onready var box = $Box as Sprite2D @onready var side_handle = $SideHandle as AnimatedSprite2D @onready var inside_handle = $Handle as TextureButton @onready var audio_player = $MusicPlayer2D as AudioStreamPlayer2D var button_texture = preload("res://asset/art/little_game/八音盒/小猫.png") var button_highlight_texture = preload("res://asset/art/little_game/八音盒/小猫高亮.png") var box_closed_texture = preload("res://asset/art/little_game/八音盒/无按钮.png") var box_opened_texture = preload("res://asset/art/little_game/八音盒/打开盒子.png") var box_finished_texture = preload("res://asset/art/little_game/八音盒/有按钮.png") var sfx_interact = preload("res://asset/audio/sfx/game/八音盒/八音盒互动.mp3") as AudioStream var sfx_drag = preload("res://asset/audio/sfx/game/八音盒/拖动放置.mp3") as AudioStream var sfx_open = preload("res://asset/audio/sfx/game/八音盒/八音盒打开.mp3") as AudioStream var sfx_close = preload("res://asset/audio/sfx/game/八音盒/关盖子.mp3") as AudioStream var sfx_exit = preload("res://asset/audio/sfx/game/八音盒/退出界面.mp3") as AudioStream var audio_manual = preload("res://asset/audio/sfx/game/八音盒/操纵八音盒.mp3") as AudioStream var audio_auto = preload("res://asset/audio/sfx/game/八音盒/自走八音盒.mp3") as AudioStream var dragging = false var current_selected_btn := 0: set(value): if has_node("button_root"): # set previous button to normal var root = get_node("button_root") root.get_node(str(current_selected_btn)).texture = button_texture # set current button to highlight root.get_node(str(value)).texture = button_highlight_texture current_selected_btn = value func _ready() -> void: _chechout_mode() inside_handle.pressed.connect(_on_handle_pressed) func _chechout_mode(play_sfx := false) -> void: $Handle.visible = mode == "opened" $SideHandle.visible = mode == "playing" or mode == "finished" _reset_buttons() match mode: "closed": audio_player.stream = sfx_interact audio_player.play() box.texture = box_closed_texture _reset_buttons() audio_player.stream = sfx_drag "opened": if play_sfx: audio_player.stream = sfx_open audio_player.play() box.texture = box_opened_texture "playing": audio_player.stream = sfx_drag box.texture = box_opened_texture "finished": if play_sfx: audio_player.stream = sfx_close audio_player.play() box.texture = box_finished_texture func _reset_buttons(): if mode != "closed": if has_node("button_root"): get_node("button_root").visible = false return # create buttons if not exists if not has_node("button_root"): var root = Node2D.new() root.name = "button_root" add_child(root) for i in range(9): var button = Sprite2D.new() button.name = str(i) root.add_child(button) # reset buttons' position and texture for i in range(9): var button = get_node("button_root" + "/" + str(i)) if i == current_selected_btn: button.texture = button_highlight_texture else: button.texture = button_texture # load current_answer button.position = _get_position(i, current_answer[i]) # 自动计算的位置会有偏差,使用 polygon 的点进行标记 # row rom bottom to top, 7 rows in total # col from left to right, 9 cols in total func _get_position(col: int, row: int) -> Vector2: # var col_gap = col_gap_down + (col_gap_up - col_gap_down) * row / 6 # return Vector2(origin_position.x + col_gap * col, origin_position.y - row_gap * row) var index = col + row * 9 if points_polygon.polygon and index < points_polygon.polygon.size(): return points_polygon.polygon[index] else: return Vector2(0, 0) # 1 up 2 down func _move_button(delta: int) -> void: if mode != "closed": return var current_row = current_answer[current_selected_btn] var target_row = clampi(current_answer[current_selected_btn] + delta, 0, 6) current_answer[current_selected_btn] = target_row # tween if not in correct position if current_row != target_row: var target_position = _get_position(current_selected_btn, target_row) var node = get_node("button_root/" + str(current_selected_btn)) create_tween().tween_property(node, "position", target_position, .5) # play sfx audio_player.stream = sfx_drag audio_player.play() # check if all buttons are in correct position if current_answer == answer: mode = "opened" _chechout_mode(true) func _unhandled_input(event: InputEvent) -> void: if mode == "closed": # move button if event.is_action_pressed("up"): _move_button(1) elif event.is_action_pressed("down"): _move_button(-1) elif event.is_action_pressed("left"): current_selected_btn = clampi(current_selected_btn - 1, 0, 8) elif event.is_action_pressed("right"): current_selected_btn = clampi(current_selected_btn + 1, 0, 8) func _on_handle_pressed() -> void: if mode == "opened": mode = "playing" _chechout_mode(true)