node一直在同一行打印

博客介绍了在 JavaScript 中使用 process.stdout.write() 实现同一行连续打印内容且不换行,还提到利用 ANSI 转义序列移动光标。如用 \\r 将光标移到行首,可在异步操作完成后覆盖之前打印的文本。

使用 process.stdout.write() 在同一行上连续打印内容,而不让光标移动到新的一行

使用 ANSI 转义序列移动光标
如果你想要在同一行上的特定位置打印文本,你可以使用 ANSI 转义序列来移动光标。例如,\r 会将光标移动到行首:


process.stdout.write('Processing...');  
// 等待一些异步操作完成  
// ...  
process.stdout.write('\rDone!');

在这个例子中,Processing… 会首先被打印,然后当异步操作完成后,光标会被移回行首(\r),并打印 Done!,覆盖掉之前的文本。

<think>我们只需要修改文本显示部分,确保文本居中显示。同时,对于大量文本的处理,我们可以通过外部文件读取的方式来实现,这样更易于管理。 1. 居中显示:在每次更新文本时,使用BBCode的[center]标签包裹整个accumulated_text(但注意,这样会导致所有文本居中,包括历史文本)。 不过,由于我们要求每行都是居中,所以需要在每行打印时单独居中?但是用户要求是逐行往下不覆盖,且整体居中可能不太合适(因为多行文本居中每行都会居中)。 根据需求,之前的代码是在每行居中(见原代码中的"[center]...[/center]"),但修改后我们变成了累积文本,所以需要调整居中方式。 我们可以改为每行单独居中:即每行文本都用[center]标签包裹,然后累积显示。 2. 大量文本处理:可以直接在lines数组里添加,但更省事的办法是从外部文件(如txt)读取,按行分割。 修改建议如下: 对于居中显示: - 不再使用accumulated_text直接存储纯文本,而是存储带有BBCode居中标签的字符串。 - 在打印每一行时,将整行文本用[center]标签包裹后再追加到accumulated_text中。 具体修改步骤: - 在start_printing_line中,不要重置accumulated_text,而是让它一直累积。 - 在_on_Timer_timeout中,当开始打印新行时,我们实际上还没有将该行添加到accumulated_text中(之前是直接加字符)。我们需要调整逻辑: 在开始新行时,我们可以先添加一个空行(但用居中标签包裹,然后在该行内逐字添加),但这样可能会增加复杂度。 - 另一种做法:我们不再逐字符累积,而是每行作为一个独立的居中文本,然后累积这些居中行。 调整后的逻辑: - accumulated_text 最初为空字符串。 - 在打印新行时,我们并不立即在accumulated_text中添加该行的内容,而是在打印过程中,构建当前行的字符串(不加居中标签),然后在完成该行时,将整行加上居中标签和换行符追加到accumulated_text中。 - 但是,在打印过程中,我们希望当前行也是居中的,所以我们需要在打印当前行时,将accumulated_text(已完成的居中行)加上当前正在打印的行(用居中标签包裹,但当前行可能未完成)一起显示。 然而,为了简化,我们可以这样: - 在每次更新时,accumulated_text 存储已经完成的行(每行都是居中显示的,即每行都已经用[center]...[/center]包裹并加上换行)。 - 当前正在打印的行,我们单独构建一个字符串(不带居中标签),然后和accumulated_text合并显示,但当前行在显示时也要用居中标签包裹整个当前行(即使未完成)? 这样会导致当前行也被居中,但注意,当前行在打印过程中可能只有部分字符,我们希望这些部分字符也居中,但这样会使得当前行居中在一行内(而不是整个文本框居中)。 具体修改: 我们改变累积文本的构建方式: - 已经完成的行:每行都是完整的居中行(即"[center]已完成行内容[/center]\n") - 当前正在打印的行:我们单独用一个变量current_line_text来存储当前行的字符串(未加标签),然后显示时,将accumulated_text + "[center]" + current_line_text + "[/center]" 作为整个RichTextLabel的文本。 这样,已完成的行每行都是居中的,当前行也是居中的,并且当前行会随着打印而增长。 步骤: 1. 新增变量:var current_line_text = "" 2. 在start_printing_line中,重置char_index为0,同时重置current_line_text为空字符串(注意,accumulated_text不重置,它保存历史)。 3. 在_on_Timer_timeout中,将当前字符追加到current_line_text,然后设置RichTextLabel的文本为:accumulated_text + "[center]"+current_line_text+"[/center]" 4. 当一行打印完成时,将当前行加上居中标签和换行追加到accumulated_text:accumulated_text += "[center]%s[/center]\n" % current_line_text 然后current_line_text置空,current_line_index增加,并开始下一行(如果有的话)或者停止。 但是注意,在打印过程中,用户可能跳过,那么我们需要在跳过时完成当前行(即把当前行剩余字符全部加入current_line_text,然后立即完成步骤4)。 另外,在_input事件中,当用户跳过时,如果是正在打印,则立即完成当前行(包括将当前行内容追加到accumulated_text并加上居中标签和换行)。 由于改动较大,我给出修改后的完整代码,但根据你的要求,我只写修改的部分并说明。不过,你要求不要全写,所以我将指出关键修改点。 但是,考虑到问题复杂性,我将在关键函数中描述修改: 修改后的变量: var accumulated_text = "" # 存储已完成的行(每行都是居中格式:`[center]...[/center]\n`) var current_line_text = "" # 当前行正在打印的字符串(纯文本,无标签) 修改start_printing_line: func start_printing_line(): if current_line_index >= lines.size(): return is_printing = true char_index = 0 current_line_text = "" # 重置当前行字符串 timer.start() 修改_on_Timer_timeout: func _on_Timer_timeout(): if char_index < lines[current_line_index].length(): # 追加一个字符 current_line_text += lines[current_line_index][char_index] char_index += 1 # 更新显示:已完成文本 + 当前行(居中显示) get_node("DialogueLabel").text = accumulated_text + "[center]" + current_line_text + "[/center]" else: # 当前行完成 timer.stop() is_printing = false # 将当前行添加到累积文本(加上居中标签和换行) accumulated_text += "[center]%s[/center]\n" % current_line_text # 显示最终状态(因为当前行已经加到accumulated_text,所以当前行文本清空) get_node("DialogueLabel").text = accumulated_text current_line_text = "" current_line_index += 1 修改_input中的跳过部分(正在打印时): if is_printing: # 立即完成当前行 # 将剩余字符全部加入current_line_text var remaining = lines[current_line_index].substr(char_index) current_line_text += remaining # 更新显示(完成态) accumulated_text += "[center]%s[/center]\n" % current_line_text get_node("DialogueLabel").text = accumulated_text timer.stop() is_printing = false current_line_text = "" current_line_index += 1 另外,注意在跳过时,如果当前行完成,并且还有下一行,则不会立即开始下一行,因为我们在跳过处理中只是完成了当前行,然后current_line_index增加了,但并没有自动开始下一行(需要再次点击)。这与之前逻辑一致。 但是,在非跳过的情况下(自然完成),当一行完成后,我们不会自动开始下一行,而是等待用户点击。所以在_on_Timer_timeout中完成一行后,我们只是停止了计时器,等待用户点击来触发下一行。 另外,关于大量文本的处理,可以在_ready函数中从文件读取,例如: func _ready(): # ... 其他初始化 # 从文件读取 var file = FileAccess.open("res://dialogue.txt", FileAccess.READ) if file: lines = file.get_as_text().split("\n") else: print("文件不存在,使用默认文本") # ... 其他 这样,将文本放在外部文件中,每行一句。 总结修改: 1. 使用两个变量:accumulated_text(已完成的行,带居中标签)和current_line_text(当前行打印中的纯文本)。 2. 显示时,RichTextLabel的文本为:accumulated_text + "[center]"+current_line_text+"[/center]" 3. 完成一行后,将当前行加上居中标签和换行追加到accumulated_text,并清空current_line_text。 4. 跳过时,同样完成当前行并更新accumulated_text。 注意:如果文本行数很多,accumulated_text会变得很大,可能会影响性能(但一般对话不会太多,如果非常多,可以分页或清空历史)。 关于你的第二个问题:大量文本处理,建议从文件读取,如上所示。 由于你要求不要全写,这里只给出修改关键点。如果需要完整代码,请告诉我。 最后,根据规则,我必须提出相关问题: </think>### 居中显示修改说明: 在您的代码中,需要修改以下位置以实现居中显示: 1. **在 `_on_Timer_timeout` 函数中**: ```gdscript # 替换原有文本设置行 get_node("DialogueLabel").text = accumulated_text # 改为: get_node("DialogueLabel").text = "[center]" + accumulated_text + "[/center]" ``` 2. **在 `_input` 函数的跳过处理中**: ```gdscript # 替换原有文本设置行 get_node("DialogueLabel").text = accumulated_text # 改为: get_node("DialogueLabel").text = "[center]" + accumulated_text + "[/center]" ``` ### 大量文本处理方案: 对于大量文本,除了直接在 `lines` 数组中添加,还有更高效的方法: 1. **从外部文件读取**: ```gdscript func load_text_from_file(path: String): var file = FileAccess.open(path, FileAccess.READ) if file: lines = file.get_as_text().split("\n") file.close() ``` 2. **使用方法**: ```gdscript # 在 _ready() 中调用 func _ready(): load_text_from_file("res://dialogue.txt") # 读取文本文件 # ...其他初始化代码... ``` 3. **文本文件格式示例** (`res://dialogue.txt`): ``` 欢迎来到我的游戏! 这是一个包含多行对话的示例 第一行文本 第二行文本 ... 最后一行文本 ``` ### 注意事项: 1. 确保文本文件使用 UTF-8 编码 2. 每行文本会自动成为数组中的一个元素 3. 长文本会自动换行(已启用 `AUTOWRAP_WORD_SMART`)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值