extends Node @export var cols : int @export var cell_size : Vector2i @export var left_top_of_board : Marker2D @export var init_card_anchos : Array[Marker2D] @export var score_num_label : Label signal dragging_card signal release_dragging_card signal place_card signal kill_cards var score = 0 var waitting_cards_num = 4 var has_mouse: bool = false var dragged_card : Card var hovered_cell_control : ColorRect var hovered_cell : Vector2 = Global.invalid_cell_index var board_info : Array = [] const GLOBAL_LEFT_TOP = "global-left-top" const GLOBAL_CENTER = "global-center" const INDEX = "index" const AREA = "area" const HOLD_CARD = "hold-card" const HOLD_CARD_VALUE = "hold-card-value" const HOLD_CARD_CATEGORY = "hold-card-category" const hovered_color = "015aafb8" func _ready() -> void: init_game() dragging_card.connect(_on_dragging_card) release_dragging_card.connect(_on_release_dragging_card) place_card.connect(_on_place_card) kill_cards.connect(_on_kill_cards) func init_game() -> void: board_info = create_cells() score = 0 waitting_cards_num = init_card_anchos.size() send_cards() func create_cells() -> Array: var cells_matrix = [] var init_pos = Vector2(left_top_of_board.global_position.x, left_top_of_board.global_position.y) for i in range(0, cols): var row = [] for j in range(0, cols): var left_top_pos = Vector2(init_pos.x + i * cell_size.x, init_pos.y + j * cell_size.y) var center_pos = Vector2(left_top_pos.x + cell_size.x / 2, left_top_pos.y + cell_size.y / 2) var cell = setup_cell_rect(left_top_pos, cell_size) $BoardCells.add_child(cell) var dict = { GLOBAL_LEFT_TOP : left_top_pos, GLOBAL_CENTER : center_pos, INDEX: Vector2i(i, j), AREA : cell, HOLD_CARD : null } row.append(dict) cells_matrix.append(row) return cells_matrix func setup_cell_rect(left_top: Vector2, size: Vector2i) -> ColorRect: var cell = ColorRect.new() cell.color = Color(hovered_color) cell.size = cell_size cell.global_position = left_top cell.visible = false return cell func _process(_delta: float) -> void: var cell = clamp_cell() if hovered_cell_control != null: hovered_cell_control.visible = false if cell != null: hovered_cell_control = cell cell.visible = true func _on_dragging_card(card: Card) -> void: dragged_card = card func _on_release_dragging_card(card: Card, index: Vector2i) -> void: dragged_card = null waitting_cards_num -= 1 if waitting_cards_num == 0: waitting_cards_num = init_card_anchos.size() send_cards() func _on_place_card(card: Card, index: Vector2i) -> void: var cell_info = board_info[index.x][index.y] var lt = cell_info[GLOBAL_LEFT_TOP] card.global_position = lt card.settled = true cell_info[HOLD_CARD] = card cell_info[HOLD_CARD_VALUE] = card.value cell_info[HOLD_CARD_CATEGORY] = card.category card.index = index try_kill_card(index) func try_kill_card(index: Vector2i) -> void: var detected_cards = detect_cards(index) if detected_cards.size() > 1: emit_signal("kill_cards", detected_cards) func detect_cards(index: Vector2i) -> Array[Vector2i]: var cell_info = board_info[index.x][index.y] var card = cell_info[HOLD_CARD] if card == null: return [] return _detect_cards(index, index, []) func _detect_cards(index: Vector2i, origin_index: Vector2i, visited) -> Array[Vector2i]: # 检查是否越界或已经访问 if index.x < 0 or index.y < 0 or index.x >= cols or index.y >= cols: return [] if index in visited: return [] # 标记当前格子为已访问 visited.append(index) var cell_info = board_info[index.x][index.y] var origin_cell_info = board_info[origin_index.x][origin_index.y] # 如果当前格子为空(值为0),则返回空列表 if cell_info[HOLD_CARD] == null: return [] # 当前格子含有棋子,将其加入结果 if cell_info[HOLD_CARD].category == origin_cell_info[HOLD_CARD].category and cell_info[HOLD_CARD].value == origin_cell_info[HOLD_CARD].value: var result : Array[Vector2i] = [index] # 检查上下左右相邻格子 var directions = [ Vector2i(0, 1), # 上 Vector2i(0, -1), # 下 Vector2i(1, 0), # 右 Vector2i(-1, 0) # 左 ] for dir in directions: result += _detect_cards(index + dir, index, visited) return result return [] func _on_kill_cards(index_array: Array[Vector2i]) -> void: print("------*****--------") for i in index_array: var cell_info = board_info[i.x][i.y] var card = cell_info[HOLD_CARD] as Card cell_info[HOLD_CARD] = null cell_info[HOLD_CARD_CATEGORY] = 0 cell_info[HOLD_CARD_VALUE] = -999 card.index = Global.invalid_cell_index card.queue_free() print("kill-" + str(i) + "-" + str(cell_info)) score += 1 score_num_label.text = str(score) print("-------------------") func get_hover_cell_index() -> Vector2i: var mouse_global_position = $MouseAnchor.get_global_mouse_position() return get_cell_on_pos(mouse_global_position) func get_cell_on_pos(pos: Vector2) -> Vector2i: if pos.x < left_top_of_board.global_position.x or pos.y < left_top_of_board.global_position.y: return Global.invalid_cell_index var relative_pos = Vector2(pos.x - left_top_of_board.global_position.x, pos.y - left_top_of_board.global_position.y) var index = Vector2i(int(relative_pos.x) / cell_size.x, int(relative_pos.y) / cell_size.y) if index.x < 0 or index.x >= cols or index.y < 0 or index.y >= cols: index = Global.invalid_cell_index return index func clamp_cell() -> ColorRect: var index = get_hover_cell_index() if index != Global.invalid_cell_index: var cell_info = board_info[index.x][index.y] var cell = cell_info[AREA] if cell != null: var control = cell as ColorRect return control return null func send_cards() -> void: var card_prefab = load("res://Scenes/Card.tscn") for i in range(waitting_cards_num): var pos = init_card_anchos[i].global_position var card_instance = card_prefab.instantiate() as Card var card_size = (card_instance as Card).texture_normal.get_size() card_instance.global_position = Vector2(pos.x - card_size.x / 2, pos.y - card_size.y / 2) var val = randi() % 9 + 1 var cate_num = randi() % 4 card_instance.setup_card(cate_num, val) $Cards.add_child(card_instance) func _on_board_area_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void: if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT: if not event.pressed: try_place_card(dragged_card) func try_place_card(card: Card) -> void: var index = get_hover_cell_index() if dragged_card == null or index == Global.invalid_cell_index: return var cell_info = board_info[index.x][index.y] if cell_info[HOLD_CARD] == null: emit_signal("release_dragging_card", card, index) emit_signal("place_card", card, index)