xiandie/scene/little_game/弹珠游戏/弹珠游戏.gd

307 lines
8.0 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends CanvasLayer
signal exit(success)
@onready var animation_player = $AnimationPlayer as AnimationPlayer
@onready var pivot = $Pivot as Node2D
@onready var hand_pivot = $Pivot/HandPivot as Node2D
@onready var label = %RichTextLabel as RichTextLabel
@onready var audio_player = %AudioStreamPlayer as AudioStreamPlayer
@onready var sfx_hit = $SfxHit as Sfx
@onready var sfx_shoot = $SfxShoot as Sfx
var dialogue_c02 = preload("res://asset/dialogue/c02.dialogue")
var balls_scene_dict = {
0: preload("uid://d0tuv2dtlosfe"),
1: preload("uid://cv12saxinfoi7"),
2: preload("uid://dr0rwr0xjgnjw"),
}
func _ready() -> void:
layer = GlobalConfig.CANVAS_LAYER_LITTLE_GAME
hand_pivot.modulate.a = 0
# 0:默认 1:寻找弹珠(老虎钳可以换弹珠) 2:给出弹珠 3:游戏结束
if ArchiveManager.get_global_value("c02_ball_game_stage", 0) == 2:
# checkout_round(2)
checkout_round(0)
else:
intro()
label.hide()
func intro():
round_id = -1
# 关闭所有碰撞
for i in range(3):
var balls_name = "Balls" + str(i)
get_node(balls_name).visible = false
get_tree().call_group(balls_name, "hide_away")
pivot.get_child(0).modulate.a = 0
DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏0")
await dialogue_ended
func intro_finished():
SceneManager.disable_prop_item("prop_弹珠")
# 0:默认 1:寻找弹珠(老虎钳可以换弹珠) 2:给出弹珠 3:游戏结束
# 放入弹珠,开始游戏
ArchiveManager.set_global_entry("c02_ball_game_stage", 2)
var ball = pivot.get_child(0) as RigidBody2D
ball.angular_velocity = 20
animation_player.play("give_ball")
await animation_player.animation_finished
# 开始弹珠游戏
checkout_round(0)
var round_ready = false
var round_id := 0 #-1:intro; 0, 1, 2
var hit_count = 0
var shooting = false
func checkout_round(r: int):
round_id = r
# 关闭所有碰撞
for i in range(3):
var balls_name = "Balls" + str(i)
get_node(balls_name).visible = false
get_tree().call_group(balls_name, "hide_away")
reload_round()
# 重置当前回合 introduce是否播放回合 dialogue
func reload_round():
# 重置参数
round_ready = false
hit_count = 0
hand_pivot.modulate.a = 0
# 重新加载 balls
var balls_name = "Balls" + str(round_id)
var old_balls = get_node(balls_name)
remove_child(old_balls)
old_balls.queue_free()
var new_balls = balls_scene_dict[round_id].instantiate()
new_balls.name = balls_name
add_child(new_balls)
new_balls.z_index = 2
get_tree().call_group(balls_name, "hide_away")
# 分散 balls
animation_player.play("dispatch_balls")
await animation_player.animation_finished
# 加载手中的球
reload_hand_ball()
wave_hand()
round_ready = true
func do_dispatch_balls():
var balls_name = "Balls" + str(round_id)
get_tree().call_group(balls_name, "dispatch", Vector2(296.0, 102.0))
func reload_hand_ball() -> void:
shooting = false
# 重新加载
var ball_scene = preload("res://scene/little_game/弹珠游戏/ball.tscn")
var ball = ball_scene.instantiate()
ball.is_shooter = true
var old_ball = pivot.get_node_or_null("Ball")
if old_ball:
pivot.remove_child(old_ball)
old_ball.queue_free()
pivot.add_child(ball)
pivot.move_child(ball, 0)
ball.name = "Ball"
# ball.rand_id()
ball.hit_ball.connect(_on_hit_ball)
ball.hit_ball_callback.connect(_on_hit_ball_callback)
ball.hit_boundary.connect(_on_hit_boundary)
var wave_tween: Tween
func wave_hand() -> void:
hand_pivot.visible = true
if hand_pivot.modulate.a < 1:
create_tween().tween_property(hand_pivot, "modulate:a", 1.0, 0.5)
# var hand_ball = pivot.get_child(0)
# if hand_ball.modulate.a < 1:
# create_tween().tween_property(hand_ball, "modulate:a", 1.0, 0.5)
# 转动 pivot
if wave_tween:
if not wave_tween.is_running():
wave_tween.play()
return
wave_tween = create_tween()
var timeout = 2.0
(
wave_tween
. tween_property(hand_pivot, "rotation", 1.0, timeout)
. set_ease(Tween.EASE_OUT)
. set_trans(Tween.TRANS_SINE)
)
(
wave_tween
. tween_property(hand_pivot, "rotation", 0.0, timeout)
. set_ease(Tween.EASE_IN)
. set_trans(Tween.TRANS_SINE)
)
(
wave_tween
. tween_property(hand_pivot, "rotation", -1.0, timeout)
. set_ease(Tween.EASE_OUT)
. set_trans(Tween.TRANS_SINE)
)
(
wave_tween
. tween_property(hand_pivot, "rotation", 0.0, timeout)
. set_ease(Tween.EASE_IN)
. set_trans(Tween.TRANS_SINE)
)
wave_tween.set_loops(9999999)
# interactE 与 spacebar 都可以 shoot
func shoot() -> void:
if not round_ready or shooting or round_id < 0:
return
shooting = true
sfx_shoot.play()
# 触发射击事件
if wave_tween and wave_tween.is_running():
wave_tween.pause()
var ball = pivot.get_child(0) as RigidBody2D
var direction = Vector2(0, -1).rotated(hand_pivot.rotation)
ball.linear_velocity = direction * 200
ball.angular_velocity = 20.0
create_tween().tween_property(hand_pivot, "modulate:a", 0.0, 0.5)
func _on_hit_ball():
sfx_hit.play()
sfx_shoot.stop()
func _on_hit_ball_callback():
reload_hand_ball()
hit_count += 1
if round_id == 0:
round_ready = false
_success_dialogue()
await dialogue_ended
checkout_round(1)
elif round_id == 1 and hit_count >= 3:
round_ready = false
_success_dialogue()
await dialogue_ended
checkout_round(2)
elif round_id == 2 and hit_count >= 5:
round_ready = false
game_win()
else:
wave_hand()
shooting = false
func _success_dialogue():
match round_id:
0:
DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏1")
1:
DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏2")
2:
DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏3")
func _on_hit_boundary():
sfx_shoot.stop()
if round_id > 0:
# 后面的回合必须每次都击中球
get_tree().call_group("Balls" + str(round_id), "ease_out")
DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏fail")
await dialogue_ended
reload_round()
else:
reload_hand_ball()
wave_hand()
shooting = false
func game_win() -> void:
print("game_win 弹珠游戏胜利")
# 0:默认 1:寻找弹珠(老虎钳可以换弹珠) 2:给出弹珠 3:游戏结束
ArchiveManager.set_global_entry("c02_ball_game_stage", 3)
# 弹珠雨
$BallsFalling.emitting = true
pivot.visible = false
DialogueManager.show_dialogue_balloon_scene(self, dialogue_c02, "c02_弹珠游戏4")
await dialogue_ended
await get_tree().create_timer(3.0).timeout
exit.emit(true)
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("interact"):
if round_id == -1:
# intro 阶段,给出弹珠
var hud = SceneManager.get_prop_hud() as PropHud
if SceneManager.get_current_prop(false) != "prop_弹珠":
hud.on_toggle_invalid_prop()
else:
intro_finished()
else:
shoot()
get_viewport().set_input_as_handled()
elif event.is_action_pressed("space"):
if round_id >= 0:
shoot()
get_viewport().set_input_as_handled()
signal dialogue_ended
## The current line
var dialogue_line: DialogueLine:
set(value):
if value:
dialogue_line = value
apply_dialogue_line()
get:
return dialogue_line
func start(
dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []
) -> void:
var temporary_game_states = [self] + extra_game_states
self.dialogue_line = await dialogue_resource.get_next_dialogue_line(
title, temporary_game_states
)
## Apply any changes to the balloon given a new [DialogueLine].
func apply_dialogue_line() -> void:
var translation_key = dialogue_line.translation_key
label.text = ("[wave amp=10.0 freq=5.0][shake rate=4.0 level=3] " + tr(translation_key))
label.show()
# 因为版权问题,有些 mp3 文件打不开,所以使用 ogg 格式
var audio_path = "res://asset/audio/peiyin/ogg/%s.ogg" % translation_key
if FileAccess.file_exists(audio_path):
var stream = load(audio_path)
audio_player.stream = stream
audio_player.play()
await audio_player.finished
await get_tree().create_timer(1.0).timeout
else:
push_warning("No audio file found for " + translation_key)
await get_tree().create_timer(3.0).timeout
label.hide()
dialogue_ended.emit()