xiandie/scene/ground/script/c03/s04_closeup麻将出千游戏.gd

312 lines
9.9 KiB
GDScript3
Raw Normal View History

2025-07-09 16:07:36 +00:00
extends CanvasLayer
signal exit(arg)
@onready var bg = $BG as TextureRect
2025-07-10 09:13:31 +00:00
@onready var front_lay = $MahjongsFrontLay as CanvasItem
2025-07-10 16:29:46 +00:00
@onready var hand = $Hand as CanvasItem
@onready var stand_root = $Stand as CanvasItem
2025-07-10 09:13:31 +00:00
@onready var grid = $Stand/MahjongGrid as GridContainer
var mahjongs = {
2025-07-10 16:29:46 +00:00
# [type][number]
"风南": preload("uid://6hdekasuabnm"),
"万2": preload("uid://c6xcefh4x2t5h"),
"万3": preload("uid://dc6sj2holh1gn"),
"万5": preload("uid://bd12rrssmrdbs"),
"条1": preload("uid://batbu02i8svf6"),
"条2": preload("uid://cbn74yc8j72v6"),
"条3": preload("uid://b66kqhy1mmhc5"),
"筒1": preload("uid://ccpexjd64s5nn"),
"筒2": preload("uid://djefka3gyhxsv"),
"筒4": preload("uid://da50cog64b0tb"),
"筒7": preload("uid://c7tea8ostqbiu"),
"筒8": preload("uid://cr6404ghilc7u"),
"筒9": preload("uid://iovhne3h5dqe"),
2025-07-10 09:13:31 +00:00
}
2025-07-10 16:29:46 +00:00
@onready var standing_mahjongs_btn: Array[TextureButton] = [%"0", %"1", %"2", %"3", %"4", %"5", %"6", %"7", %"8", %"9", %"10", %"11", %"12", %"13"]
# 替换后会从数组中移除
@onready var holding_mahjongs_btn_dict: Dictionary[int, TextureButton] = {14: %"14", 15: %"15", 16: %"16"}
2025-07-10 09:13:31 +00:00
2025-07-10 16:29:46 +00:00
var current_round := 0
# 回合1-4摸牌3万、2万、1条、2筒胜利
var dispatched_card_per_round: Array[String] = ["万3", "万2", "条1", "筒2"]
# 回合1-3自动打出的牌+3个密码共六张2万、3万、1条、南风、4筒、1筒
var useless_cards: Array[String] = ["万2", "万3", "条1", "风南", "筒4", "筒1"]
# 玩家初始牌型13张78筒x1 南风x1 12条x1 4筒x1 5万x2 2筒x2 9筒x2 1筒
# 胜利牌型2筒x3、9筒x2、5万x3、123条x1、789筒x1
var standing_cards: Array[String] = ["筒7", "筒8", "风南", "条1", "条2", "筒4", "万5", "万5", "筒2", "筒2", "筒9", "筒9", "筒1", ""]
# 赖子手在左下角桌子下手中为三个麻将5万、3条、9筒
var holding_cards_dict: Dictionary[int, String] = {14: "万5", 15: "条3", 16: "筒9"}
2025-07-10 09:13:31 +00:00
2025-07-10 16:29:46 +00:00
var freezing = true:
set(val):
if freezing != val:
freezing = val
if freezing and selected_btn:
_toggle_selected(selected_btn, false)
2025-07-10 09:13:31 +00:00
var success = false
var selected_btn: TextureButton
2025-07-09 16:07:36 +00:00
2025-07-10 16:29:46 +00:00
var c03_dialog = preload("uid://b66v5hsf3tdox")
2025-07-09 16:07:36 +00:00
func _ready() -> void:
layer = GlobalConfig.CANVAS_LAYER_LITTLE_GAME
2025-07-10 16:29:46 +00:00
stand_root.hide()
hand.hide()
2025-07-10 09:13:31 +00:00
_toggle_hightlight_for_all(false)
2025-07-10 16:29:46 +00:00
for b in standing_mahjongs_btn:
2025-07-10 09:13:31 +00:00
b.mouse_entered.connect(_toggel_hover.bind(b, true))
b.mouse_exited.connect(_toggel_hover.bind(b, false))
b.pressed.connect(_on_btn_pressed.bind(b))
2025-07-10 16:29:46 +00:00
for b in holding_mahjongs_btn_dict.values():
2025-07-10 09:13:31 +00:00
b.mouse_entered.connect(_toggel_hover.bind(b, true))
b.mouse_exited.connect(_toggel_hover.bind(b, false))
b.pressed.connect(_on_btn_pressed.bind(b))
2025-07-10 16:29:46 +00:00
# 检查是否从整理麻将游戏中跳转过来
var transition_time = ArchiveManager.runtime_get("c03_mahjong_game_black_transition_time", 0.0)
if transition_time > 0:
await Util.wait(transition_time)
_play_dialogue_with_update_stage(0)
await _await_dialog(0)
_start_game()
2025-07-10 09:13:31 +00:00
func _toggel_hover(btn: TextureButton, hovering: bool) -> void:
if freezing:
return
2025-07-10 16:29:46 +00:00
if btn.disabled:
hovering = false
2025-07-10 09:13:31 +00:00
_toggle_hightlight(btn, hovering)
2025-07-10 16:29:46 +00:00
2025-07-10 09:13:31 +00:00
func _on_btn_pressed(btn: TextureButton) -> void:
if freezing:
return
if btn != selected_btn:
if selected_btn:
_toggle_selected(selected_btn, false)
2025-07-10 16:29:46 +00:00
_exchange_texture_and_card(btn, selected_btn)
2025-07-10 09:13:31 +00:00
selected_btn = null
else:
$SfxSelect.play()
_toggle_selected(btn, true)
selected_btn = btn
else:
$SfxSelect.play()
_toggle_selected(btn, false)
selected_btn = null
func _toggle_selected(btn:TextureButton, selected: bool) -> void:
2025-07-10 16:29:46 +00:00
# 0-13 push up. 14-16 in hand, push down.
var front := int(btn.name) <= 13
2025-07-10 09:13:31 +00:00
if (front and selected) or (not front and not selected):
btn.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
else:
btn.size_flags_vertical = Control.SIZE_SHRINK_END
2025-07-10 16:29:46 +00:00
func _align_card_textures() -> void:
# holding_mahjongs_btn 长度会变
for k in holding_mahjongs_btn_dict:
holding_mahjongs_btn_dict[k].texture_normal = mahjongs[holding_cards_dict[k]]
# standing_mahjongs_btn 长度不变
for i in 14:
if standing_cards[i]:
standing_mahjongs_btn[i].texture_normal = mahjongs[standing_cards[i]]
standing_mahjongs_btn[i].modulate = Color.WHITE
standing_mahjongs_btn[i].show()
else:
standing_mahjongs_btn[i].hide()
# 发牌
func _start_game() -> void:
# show_hand 结束时会自动 hand_swing
$AnimationPlayer.play("show_hand")
_play_dialogue_with_update_stage(1)
$SfxStart.play()
stand_root.show()
hand.show()
front_lay.hide()
# dispatch and shuffle
standing_cards[13] = dispatched_card_per_round[current_round]
standing_cards.shuffle()
_align_card_textures()
# shuffle all cards
for b in standing_mahjongs_btn:
_toggle_selected(b, true)
var tween = create_tween()
tween.tween_interval(1.0)
var sfx = $SfxPlace
for b in standing_mahjongs_btn:
tween.tween_interval(0.15)
tween.tween_callback(sfx.play.bind(0.15))
tween.tween_callback(_toggle_selected.bind(b, false))
tween.tween_interval(1.5)
tween.tween_callback(standing_cards.sort)
tween.tween_callback(_align_card_textures)
tween.tween_callback($SfxShuffle.play)
await _await_dialog(1)
if tween and tween.is_running():
await tween.finished
freezing = false
_play_dialogue_with_update_stage(2)
func _play_dialogue_with_update_stage(stage: int):
DialogueManager.show_dialogue_balloon(c03_dialog, "c03_s04_打麻将游戏" + str(stage))
if DialogueManager.dialogue_ended.is_connected(_update_last_dialog):
DialogueManager.dialogue_ended.disconnect(_update_last_dialog)
DialogueManager.dialogue_ended.connect(_update_last_dialog.bind(stage), CONNECT_ONE_SHOT)
var _last_dialog_stage := -1
signal _last_dialog_updated
func _update_last_dialog(_res, id: int) -> void:
if id > _last_dialog_stage:
_last_dialog_stage = id
_last_dialog_updated.emit()
func _await_dialog(id: int) -> void:
if _last_dialog_stage >= id:
return
await _last_dialog_updated
await _await_dialog(id)
func _exchange_texture_and_card(btn1: TextureButton, btn2: TextureButton) -> void:
2025-07-10 09:13:31 +00:00
if btn1 and btn2:
$SfxSwitch.play()
2025-07-10 16:29:46 +00:00
# exchange texture
2025-07-10 09:13:31 +00:00
var texture = btn1.texture_normal
btn1.texture_normal = btn2.texture_normal
btn2.texture_normal = texture
2025-07-10 16:29:46 +00:00
# exchange card name
var id1 := int(btn1.name)
var id2 := int(btn2.name)
var card_name1 = standing_cards[id1] if id1 <= 13 else holding_cards_dict[id1]
var card_name2 = standing_cards[id2] if id2 <= 13 else holding_cards_dict[id2]
if id1 <= 13:
standing_cards[id1] = card_name2
else:
holding_cards_dict[id1] = card_name2
if id2 <= 13:
standing_cards[id2] = card_name1
else:
holding_cards_dict[id2] = card_name1
# 判断回合是否成功
# 要求: 1、standing 区域有 auto_deal_card 2、holding 区域有 should_be_replaced_card
# 查找手牌 id 与区域 id
# 优先先从手里着,再从桌面找不重复的
var require_replacing_card = intersect(useless_cards, holding_cards_dict)
var require_dealing_card = intersect(useless_cards, standing_cards, require_replacing_card)
if require_replacing_card and require_dealing_card:
useless_cards.erase(require_replacing_card)
useless_cards.erase(require_dealing_card)
_toggle_hightlight_for_all(false)
# 开始执行替换
freezing = true
await Util.wait(2.0)
# 重新排序
standing_cards.sort()
$SfxShuffle.play()
_align_card_textures()
var standing_id = standing_cards.find(require_dealing_card)
standing_cards.remove_at(standing_id)
standing_cards.append("")
# 替换到手牌后消失
var holding_id = holding_cards_dict.find_key(require_replacing_card)
var holding_btn = holding_mahjongs_btn_dict[holding_id]
holding_mahjongs_btn_dict.erase(holding_id)
holding_cards_dict.erase(holding_id)
var tween = create_tween()
# 渐隐,表示打出
tween.tween_property(standing_mahjongs_btn[standing_id], "modulate:a", 0.0, 3.0)
# tween.parallel().tween_property(holding_btn, "modulate:a", 0.0, 3.0)
# tween.tween_callback(holding_btn.queue_free)
tween.tween_callback(func(): holding_btn.disabled = true)
tween.tween_callback(_align_card_textures)
tween.tween_callback($SfxShuffle.play)
# 下一回合 unfreeze
tween.tween_interval(2.0)
tween.tween_callback(_next_round)
func intersect(arr:Array, b, except := ""):
var first_intersection = ""
if b is Dictionary:
for item in b.values():
if except and item == except:
continue
if arr.has(item):
first_intersection = item
break
elif b is Array:
for item in arr:
if except and item == except:
continue
if b.has(item):
first_intersection = item
break
return first_intersection
func _next_round() -> void:
freezing = true
current_round += 1
if current_round == 1:
# 第一回合结束
await _await_dialog(2)
_play_dialogue_with_update_stage(3)
# 对话结束后,开始第二回合
await _await_dialog(3)
_play_dialogue_with_update_stage(4)
elif current_round == 2:
# 第二回合结束
await _await_dialog(4)
_play_dialogue_with_update_stage(5)
# 对话结束后,开始第三回合
await _await_dialog(5)
_play_dialogue_with_update_stage(6)
elif current_round == 3:
# 第三回合结束
await _await_dialog(6)
_play_dialogue_with_update_stage(7)
await _await_dialog(7)
# 开始第四回合,自摸后成功
_play_dialogue_with_update_stage(8)
standing_cards[13] = dispatched_card_per_round[current_round]
$SfxPlace.play()
_align_card_textures()
await Util.wait(1.0)
standing_cards.sort()
$SfxShuffle.play()
_align_card_textures()
# 第四回合胜利
if current_round == 3:
await Util.wait(1.0)
$SfxSuccess.play()
print("success")
await _await_dialog(8)
exit.emit(true)
else:
freezing = false
2025-07-10 09:13:31 +00:00
func _toggle_hightlight(btn: TextureButton, hightlight: bool) -> void:
if null == btn:
return
btn.get_node("光束").enabled = hightlight
func _toggle_hightlight_for_all(hightlighted: bool) -> void:
2025-07-10 16:29:46 +00:00
for b in standing_mahjongs_btn:
2025-07-10 09:13:31 +00:00
_toggle_hightlight(b, hightlighted)
2025-07-10 16:29:46 +00:00
for b in holding_mahjongs_btn_dict.values():
2025-07-10 09:13:31 +00:00
_toggle_hightlight(b, hightlighted)