还是无法自动滚动,我把代码给你看看分析一下吧
extends CanvasLayer
# 完整文本内容(保持原始格式)
var lines = [
"欢迎来到我的游戏!",
"点击空格或鼠标继续...",
"游戏正式开始!",
"第一章:晦夜长明",
"羲和驭日,沐乎汤谷,爰止爰息,是为昼明。",
"然‘万古之晦’至,金乌泣血,光耀蒙尘。",
"今汝为‘无归之魂’,凭依万类,行于晦夜……唯愿‘长明’。",
"传说,日御羲和,生十日,轮值天穹。",
"九日陨,余一子。",
"其名,金乌。",
"",
"【画面微亮,映入眼帘的是一片狼藉】",
"你“醒”了过来。",
"或者说,你“存在”的意识,第一次感受到了自身。",
"",
"没有身体,没有重量,只有一片虚无的感知,如同一缕被遗弃的青烟。",
"",
"你正漂浮在一座残破不堪的殿宇中。借着从破损穹顶漏下的、清冷如水的月白色光芒,你能看清这是一座祭祀场所——望舒祠。神台上,那位驭月女神望舒的玉像已然倾颓,半张脸庞破碎,只余下一只清冷的眸子,无声地凝视着这片死寂。",
"",
"空气中弥漫着浓重的血腥味、木头焦糊味,以及一种……更为深邃的、仿佛源自灵魂腐朽的“晦涩”气息。",
"",
"你的“目光”扫过地面,三具尸体以一种绝望的姿态陈列其间,显然刚经历了一场如同野兽撕扯般的残酷袭击。",
"",
"【系统提示:发现可凭依的“躯壳”)】",
"",
"第一具,倒在神台旁。",
"一位身着月白流云袍的年轻女子,心口处是一片触目惊心的撕裂伤。她手中紧紧攥着一枚散发着微弱温润光芒的玉佩,脸上凝固着施法时的专注与惊愕。她的袍角绣着药草与银针的纹样——一位 【沐月医者】。她似乎试图用最后的力量守护着什么,但失败了。",
"",
"第二具,匍匐在通往大门的路径上。",
"这是一个身材魁梧的男性,穿着镶嵌了月光石的残破铁甲,背后的甲胄完全被利爪撕开,深可见骨。他手中紧握着一面几乎断裂的藤盾,盾面上满是深刻的爪痕,至死都保持着护卫的姿态——一位 【守夜人】。他用自己的脊背,为身后的人争取了最后几秒。",
"",
"第三具,蜷缩在倒塌的书架旁。",
"一位戴着单边眼镜、身着青色文士长衫的少年,身体扭曲,脖颈处有诡异的紫黑色瘀痕。他身边散落着几张焦黑的符纸和一个空空如也的符袋——一位 【初阶符师】。他似乎没能成功释放出任何一个像样的攻击法术。",
"",
"袭击者……不像人类。地面上残留着焦躁的、带有腐蚀性的爪印,以及几缕沾染着不祥暗红色光泽的野兽毛发。",
"",
"【环境互动提示:感知到躯壳内未散的“执念”)】",
"",
"当你将意识靠近这三具尸体时,微弱的记忆碎片如同冰针,刺入你的感知:",
"",
"来自医者:“……光……变了……快启动……‘太阴敛息阵’……”",
"",
"来自骑士:“……挡住……不能让它们……亵渎神祠……”",
"",
"来自法师:“……符法……为什么失效了……那红色的光……”",
"",
"清冷的月光,透过破洞,在你虚无的“身体”上流淌,带来一丝奇异的安宁感。而祠外,透过门缝与墙隙,你能“听”到一种低沉、混乱、充满渴望的嘶吼,以及……那令人心悸的、仿佛能直接灼烧灵魂的暗红色微光。",
"",
"你,无归的旅魂,于此晦夜苏醒。",
"前方,是三具通往现世的钥匙,与一个在疯狂边缘燃烧的世界。",
"",
"选择,你的第一具“躯壳”。"
]
var current_line_index = 0
var char_index = 0
var is_printing = false
var timer = Timer.new()
var rich_label
var scroll_container # 新增滚动容器
var accumulated_text = ""
const APPEND_MODE_START = 7 # 第7行开始追加模式
func _ready():
# 创建主容器
var main_container = MarginContainer.new()
main_container.anchor_right = Control.ANCHOR_END
main_container.anchor_bottom = Control.ANCHOR_END
main_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
main_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
main_container.add_theme_constant_override("margin_left", 20)
main_container.add_theme_constant_override("margin_right", 20)
main_container.add_theme_constant_override("margin_top", 20)
main_container.add_theme_constant_override("margin_bottom", 50)
add_child(main_container)
# 创建滚动容器 - 解决遮挡问题
scroll_container = ScrollContainer.new()
scroll_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
scroll_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
scroll_container.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
main_container.add_child(scroll_container)
# 创建富文本标签
rich_label = RichTextLabel.new()
rich_label.name = "DialogueLabel"
rich_label.bbcode_enabled = true
rich_label.autowrap_mode = TextServer.AUTOWRAP_WORD
rich_label.scroll_active = true # 启用内置滚动
rich_label.scroll_following = true # 自动跟随新内容
rich_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
rich_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
rich_label.custom_minimum_size = Vector2(0, 600) # 宽度设为0,允许自动扩展
rich_label.fit_content = true
# 样式设置
rich_label.add_theme_font_size_override("normal_font_size", 32)
rich_label.add_theme_color_override("default_color", Color.WHITE)
rich_label.add_theme_constant_override("line_separation", 5) # 更大的行间距
# 将标签放入滚动容器
scroll_container.add_child(rich_label)
# 定时器设置
timer.wait_time = 0.05
timer.one_shot = false
add_child(timer)
timer.timeout.connect(_on_Timer_timeout)
# 窗口大小变化处理
get_viewport().size_changed.connect(_on_viewport_size_changed)
# 开始打印第一行
start_printing_line()
# 在脚本顶部添加此函数
func scroll_to_bottom():
rich_label.scroll_to_line(rich_label.get_line_count() - 1)
# Godot 4 专用方法,确保渲染完成后再滚动
await get_tree().process_frame
rich_label.scroll_to_line(rich_label.get_line_count() - 1)
# 响应窗口大小变化
func _on_viewport_size_changed():
var viewport_size = get_viewport().size
# 设置滚动容器高度为屏幕的70%
scroll_container.custom_minimum_size = Vector2(viewport_size.x * 0.95, viewport_size.y * 0.7)
# 确保标签宽度匹配容器
rich_label.custom_minimum_size.x = scroll_container.size.x - 40
rich_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
# 开始打印新行
func start_printing_line():
if current_line_index >= lines.size():
return
is_printing = true
char_index = 0
# 前6行覆盖显示,第7行开始追加显示
if current_line_index < APPEND_MODE_START:
rich_label.text = ""
accumulated_text = ""
timer.start()
# 定时器回调 - 逐字打印
func _on_Timer_timeout():
if char_index < lines[current_line_index].length():
if current_line_index < APPEND_MODE_START:
# 覆盖模式:单行居中显示
var current_text = lines[current_line_index].substr(0, char_index + 1)
rich_label.text = "[center]" + current_text + "[/center]"
else:
# 追加模式:多行连续显示
accumulated_text += lines[current_line_index].substr(char_index, 1)
rich_label.text = accumulated_text
# 滚动到最新内容
scroll_to_bottom()
char_index += 1
else:
# 行结束处理
timer.stop()
is_printing = false
if current_line_index >= APPEND_MODE_START - 1:
accumulated_text += "\n" # 添加换行符
scroll_to_bottom()
# 输入处理
func _input(event):
# 空格或鼠标左键推进文本
var should_advance = (
(event is InputEventKey and event.pressed and event.keycode == KEY_SPACE) or
(event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT)
)
if should_advance:
if is_printing:
# 立即完成当前行
if current_line_index < APPEND_MODE_START:
rich_label.text = "[center]" + lines[current_line_index] + "[/center]"
else:
accumulated_text += lines[current_line_index].substr(char_index)
rich_label.text = accumulated_text
accumulated_text += "\n"
# 滚动到最新内容
scroll_to_bottom()
timer.stop()
is_printing = false
elif current_line_index + 1 < lines.size():
# 准备打印下一行
current_line_index += 1
start_printing_line()
最新发布