2025-03-18 15:47:09 +08:00
|
|
|
|
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]
|
|
|
|
|
|
2025-03-20 02:03:37 +08:00
|
|
|
|
@export var score_num_label : Label
|
2025-03-18 15:47:09 +08:00
|
|
|
|
|
|
|
|
|
signal dragging_card
|
2025-03-20 00:56:38 +08:00
|
|
|
|
signal release_dragging_card
|
2025-03-20 02:03:37 +08:00
|
|
|
|
signal place_card
|
|
|
|
|
signal kill_cards
|
|
|
|
|
|
|
|
|
|
var score = 0
|
|
|
|
|
|
|
|
|
|
var waitting_cards_num = 4
|
2025-03-18 15:47:09 +08:00
|
|
|
|
|
|
|
|
|
var has_mouse: bool = false
|
|
|
|
|
var dragged_card : Card
|
|
|
|
|
|
2025-03-20 00:56:38 +08:00
|
|
|
|
var hovered_cell_control : ColorRect
|
|
|
|
|
|
2025-03-18 15:47:09 +08:00
|
|
|
|
var hovered_cell : Vector2 = Global.invalid_cell_index
|
|
|
|
|
var board_info : Array = []
|
|
|
|
|
|
2025-03-20 00:56:38 +08:00
|
|
|
|
const GLOBAL_LEFT_TOP = "global-left-top"
|
|
|
|
|
const GLOBAL_CENTER = "global-center"
|
|
|
|
|
const INDEX = "index"
|
|
|
|
|
const AREA = "area"
|
|
|
|
|
const HOLD_CARD = "hold-card"
|
|
|
|
|
|
|
|
|
|
const hovered_color = "015aafb8"
|
|
|
|
|
|
2025-03-18 15:47:09 +08:00
|
|
|
|
func _ready() -> void:
|
|
|
|
|
init_game()
|
|
|
|
|
dragging_card.connect(_on_dragging_card)
|
2025-03-20 00:56:38 +08:00
|
|
|
|
release_dragging_card.connect(_on_release_dragging_card)
|
2025-03-20 02:03:37 +08:00
|
|
|
|
place_card.connect(_on_place_card)
|
|
|
|
|
kill_cards.connect(_on_kill_cards)
|
2025-03-18 15:47:09 +08:00
|
|
|
|
|
|
|
|
|
func init_game() -> void:
|
|
|
|
|
board_info = create_cells()
|
2025-03-20 02:03:37 +08:00
|
|
|
|
score = 0
|
|
|
|
|
waitting_cards_num = init_card_anchos.size()
|
2025-03-18 15:47:09 +08:00
|
|
|
|
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)
|
2025-03-20 00:56:38 +08:00
|
|
|
|
var cell = setup_cell_rect(left_top_pos, cell_size)
|
|
|
|
|
$BoardCells.add_child(cell)
|
2025-03-18 15:47:09 +08:00
|
|
|
|
var dict = {
|
2025-03-20 00:56:38 +08:00
|
|
|
|
GLOBAL_LEFT_TOP : left_top_pos,
|
|
|
|
|
GLOBAL_CENTER : center_pos,
|
|
|
|
|
INDEX: Vector2i(i, j),
|
|
|
|
|
AREA : cell,
|
|
|
|
|
HOLD_CARD : null
|
2025-03-18 15:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
row.append(dict)
|
|
|
|
|
cells_matrix.append(row)
|
|
|
|
|
return cells_matrix
|
|
|
|
|
|
2025-03-20 00:56:38 +08:00
|
|
|
|
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
|
2025-03-18 15:47:09 +08:00
|
|
|
|
return cell
|
|
|
|
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
2025-03-20 00:56:38 +08:00
|
|
|
|
var cell = clamp_cell()
|
|
|
|
|
if hovered_cell_control != null:
|
|
|
|
|
hovered_cell_control.visible = false
|
|
|
|
|
if cell != null:
|
|
|
|
|
hovered_cell_control = cell
|
|
|
|
|
cell.visible = true
|
2025-03-18 15:47:09 +08:00
|
|
|
|
|
|
|
|
|
func _on_dragging_card(card: Card) -> void:
|
|
|
|
|
dragged_card = card
|
|
|
|
|
|
2025-03-20 00:56:38 +08:00
|
|
|
|
func _on_release_dragging_card(card: Card, index: Vector2i) -> void:
|
|
|
|
|
dragged_card = null
|
2025-03-20 02:03:37 +08:00
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
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("-------------------")
|
2025-03-20 00:56:38 +08:00
|
|
|
|
|
2025-03-18 15:47:09 +08:00
|
|
|
|
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:
|
2025-03-20 00:56:38 +08:00
|
|
|
|
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
|
2025-03-18 15:47:09 +08:00
|
|
|
|
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
|
|
|
|
|
|
2025-03-20 00:56:38 +08:00
|
|
|
|
func clamp_cell() -> ColorRect:
|
2025-03-18 15:47:09 +08:00
|
|
|
|
var index = get_hover_cell_index()
|
|
|
|
|
if index != Global.invalid_cell_index:
|
|
|
|
|
var cell_info = board_info[index.x][index.y]
|
2025-03-20 00:56:38 +08:00
|
|
|
|
var cell = cell_info[AREA]
|
|
|
|
|
if cell != null:
|
|
|
|
|
var control = cell as ColorRect
|
|
|
|
|
return control
|
|
|
|
|
return null
|
2025-03-18 15:47:09 +08:00
|
|
|
|
|
|
|
|
|
func send_cards() -> void:
|
|
|
|
|
var card_prefab = load("res://Scenes/Card.tscn")
|
2025-03-20 02:03:37 +08:00
|
|
|
|
for i in range(waitting_cards_num):
|
2025-03-18 15:47:09 +08:00
|
|
|
|
var pos = init_card_anchos[i].global_position
|
2025-03-20 02:03:37 +08:00
|
|
|
|
var card_instance = card_prefab.instantiate() as Card
|
2025-03-18 15:47:09 +08:00
|
|
|
|
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)
|
2025-03-20 02:03:37 +08:00
|
|
|
|
var val = randi() % 9 + 1
|
2025-03-18 15:47:09 +08:00
|
|
|
|
var cate_num = randi() % 4
|
|
|
|
|
card_instance.setup_card(cate_num, val)
|
|
|
|
|
$Cards.add_child(card_instance)
|
2025-03-20 00:56:38 +08:00
|
|
|
|
|
|
|
|
|
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)
|
2025-03-20 02:03:37 +08:00
|
|
|
|
emit_signal("place_card", card, index)
|