Godot:根据输入读取并输出 JSON 文件作为 Textbook
Godot: read and output JSON file as Textbook according to the input
我希望能够通过此 JSON 文件中指定的编号调用特定短语,因此当我调用 go(1) 时,它仅显示具有 'Num' 的文本设置为 1.
我的JSON文件:
[
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST1"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST2"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST3"},
{"Num":1, "Name":"Afely", "Emotion":"Neutral", "Text":"2TEST1"}
]
文本框代码:
extends ColorRect
export var dialogPath = ""
export(float) var textSpeed = 0.005
var dialog
var phraseNum = 0
var finished = false
func go(phraseNum):
$Timer.wait_time = textSpeed
dialog = getDialog()
assert(dialog, "Dialog not found")
nextPhrase()
var f = File.new()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
func _unhandled_input(event):
if event is InputEventKey:
if event.pressed and event.scancode == KEY_Q:
if finished:
$NEXT.play()
nextPhrase()
else:
$Text.visible_characters = len($Text.text)
func getDialog() -> Array:
var f = File.new()
assert(f.file_exists(dialogPath), "File path does not exist")
f.open(dialogPath, File.READ)
var json = f.get_as_text()
var output = parse_json(json)
if typeof(output) == TYPE_ARRAY:
return output
else:
return []
func nextPhrase() -> void:
if phraseNum >= len(dialog):
queue_free()
return
finished = false
$Name.bbcode_text = dialog[phraseNum]["Name"]
$Text.bbcode_text = dialog[phraseNum]["Text"]
$Text.visible_characters = 0
while $Text.visible_characters < len($Text.text):
$Text.visible_characters += 1
$TEXT_AUDIO.play()
$Timer.start()
yield($Timer, "timeout")
finished = true
phraseNum += 1
return
我怎么称呼它:
$TextBox.show()
$TextBox.go(1)
最后,我遵循的教程:
https://www.youtube.com/watch?v=GzPvN5wsp7Y
我该如何处理?
你问的
你问的问题需要做一些额外的工作。让我们从 JSON 文件开始:
[
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST1"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST2"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST3"},
{"Num":1, "Name":"Afely", "Emotion":"Neutral", "Text":"2TEST1"}
]
这将解析为 Array
([
和 ]
之间的所有元素),其中每个元素都是 Dictionary
([=25 之间的元素) =] 和 }
)。这意味着您将需要遍历 Array
,检查每个 Num
.
在我们这样做之前,我们需要承认我们将使用名称 phraseNum
来表示两件事:
- 索引在
dialog
Array
- 想要的值
Num
我们处于这种情况是因为您使用的来源 material。他们将 phraseNum
作为参数(此处:func go(phraseNum)
)隐藏了 phraseNum
字段(此处为 var phraseNum = 0
)。
这阻碍了交流。如果我告诉你用 phraseNum
做这个,它是哪一个?那势必会给我们带来麻烦。
我将重写 go
所以它需要一个 Num
而不是 dialog
Array
中的索引,所以我会保留 phraseNum
为 dialog
Array
中的索引,并为 go
.
的参数命名
让我们开始重写go
:
func go(num):
pass
现在,让我们得到所有的对话:
func go(num):
dialog = getDialog()
我们将迭代它们。由于我需要 phraseNum
的索引,因此我将使用索引进行迭代:
func go(num):
dialog = getDialog()
for index in dialog.size():
pass
我们需要检查 Num
是否匹配。如果是,我们得到索引:
func go(num):
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
break
我们需要处理我们没有找到它的情况。现在,嗯……来源 material 只有一个 assert
,我将保留该方法。所以我们需要一种方法来知道代码没有找到它……
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
接下来你调用nextPhrase()
,确定:
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
nextPhrase()
还有一个没用过的var f = File.new()
,我就不加了。
并且你设置了肖像纹理。当然:
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
nextPhrase()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
我已经跳过了定时器的东西,我现在将它插入:
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
$Timer.wait_time = textSpeed
nextPhrase()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
其他
现在,您说您只想要 具有给定 Num
的短语。这是开放的解释。
需要说明的是,上面的代码将使对话框在您要求的 Num
的第一个实例处启动。但它不会结束 - 也不会跳过 - 当它找到不同的 Num
时。不知道你要不要。
我们有几种方法可以做到这一点。我们可以记住什么是 num
并在 nextPhrase
中检查它。我真的不想那样做。所以,我会给你一个替代方法:让我们制作一个对话框数组,只包含我们想要的元素。
看起来像这样:
func go(num):
var every_dialog = getDialog()
dialog = []
for candidate in every_dialog:
if num == candidate["Num"]:
dialog.append(candidate)
assert(dialog, "Dialog not found")
phraseNum = 0
$Timer.wait_time = textSpeed
nextPhrase()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
请注意,在这个例子中我们没有读取 getDialog()
到 dialog
。相反,我们正在构建一个只包含我们想要的条目的 dialog
数组。我们通过迭代 getDialog()
的结果来做到这一点(我们用 append
添加到数组)。
这是 dialog
含义的细微变化,因为它不再代表 JSON 文件中的每个条目。相反,它仅代表将要显示的条目。之前这两个东西是一样的,但这次改变后它们就不同了。
你没问的
函数getDialog
从JSON文件中读取。每次调用 go
时都会这样做。您可以 而 在 _ready
.
中执行一次
重要的是您了解每个变量代表什么,以及您在哪里读取和写入它们。 上面我提到dialog
对替代变化有微妙的意义。您需要考虑到这一点才能进行此更改。
我坚信 nextPhrase
应该处理计时器和肖像。应该不需要设置 go
.
我希望你考虑这个替代方案JSON文件结构:
[
[
{"Name":"Afely", "Emotion":"Neutral", "Text":"TEST1"},
{"Name":"Afely", "Emotion":"Neutral", "Text":"TEST2"},
{"Name":"Afely", "Emotion":"Neutral", "Text":"TEST3"},
],
[
{"Name":"Afely", "Emotion":"Neutral", "Text":"2TEST1"}
]
]
然后你会得到 Array
个 Array
,其中嵌套 Array
的每个元素都是一个 Dictionary
。然后您可以“简单地”通过索引获取嵌套数组,而不必遍历每个元素。
您得到的结构类似于 JSON 文件的结构。这也意味着您将不得不改变使用它的方式。例如,可以 dialog[num][phraseNum]["Text"]
.
而不是 dialog[phraseNum]["Text"]
现在考虑来源 material。在这种情况下,我们有一个节点既负责解析 JSON 又负责显示角色对话。如果这些代码彼此分开,修改这些代码会更容易。大概作者的意图是你会为不同的对话有不同的 JSON 文件,所以你会在必要时切换 JSON 文件(这也解释了为什么他们每次都读取 JSON 文件时间)。
但你问的不是这个
我希望能够通过此 JSON 文件中指定的编号调用特定短语,因此当我调用 go(1) 时,它仅显示具有 'Num' 的文本设置为 1.
我的JSON文件:
[
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST1"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST2"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST3"},
{"Num":1, "Name":"Afely", "Emotion":"Neutral", "Text":"2TEST1"}
]
文本框代码:
extends ColorRect
export var dialogPath = ""
export(float) var textSpeed = 0.005
var dialog
var phraseNum = 0
var finished = false
func go(phraseNum):
$Timer.wait_time = textSpeed
dialog = getDialog()
assert(dialog, "Dialog not found")
nextPhrase()
var f = File.new()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
func _unhandled_input(event):
if event is InputEventKey:
if event.pressed and event.scancode == KEY_Q:
if finished:
$NEXT.play()
nextPhrase()
else:
$Text.visible_characters = len($Text.text)
func getDialog() -> Array:
var f = File.new()
assert(f.file_exists(dialogPath), "File path does not exist")
f.open(dialogPath, File.READ)
var json = f.get_as_text()
var output = parse_json(json)
if typeof(output) == TYPE_ARRAY:
return output
else:
return []
func nextPhrase() -> void:
if phraseNum >= len(dialog):
queue_free()
return
finished = false
$Name.bbcode_text = dialog[phraseNum]["Name"]
$Text.bbcode_text = dialog[phraseNum]["Text"]
$Text.visible_characters = 0
while $Text.visible_characters < len($Text.text):
$Text.visible_characters += 1
$TEXT_AUDIO.play()
$Timer.start()
yield($Timer, "timeout")
finished = true
phraseNum += 1
return
我怎么称呼它:
$TextBox.show()
$TextBox.go(1)
最后,我遵循的教程: https://www.youtube.com/watch?v=GzPvN5wsp7Y
我该如何处理?
你问的
你问的问题需要做一些额外的工作。让我们从 JSON 文件开始:
[
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST1"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST2"},
{"Num":0, "Name":"Afely", "Emotion":"Neutral", "Text":"TEST3"},
{"Num":1, "Name":"Afely", "Emotion":"Neutral", "Text":"2TEST1"}
]
这将解析为 Array
([
和 ]
之间的所有元素),其中每个元素都是 Dictionary
([=25 之间的元素) =] 和 }
)。这意味着您将需要遍历 Array
,检查每个 Num
.
在我们这样做之前,我们需要承认我们将使用名称 phraseNum
来表示两件事:
- 索引在
dialog
Array
- 想要的值
Num
我们处于这种情况是因为您使用的来源 material。他们将 phraseNum
作为参数(此处:func go(phraseNum)
)隐藏了 phraseNum
字段(此处为 var phraseNum = 0
)。
这阻碍了交流。如果我告诉你用 phraseNum
做这个,它是哪一个?那势必会给我们带来麻烦。
我将重写 go
所以它需要一个 Num
而不是 dialog
Array
中的索引,所以我会保留 phraseNum
为 dialog
Array
中的索引,并为 go
.
让我们开始重写go
:
func go(num):
pass
现在,让我们得到所有的对话:
func go(num):
dialog = getDialog()
我们将迭代它们。由于我需要 phraseNum
的索引,因此我将使用索引进行迭代:
func go(num):
dialog = getDialog()
for index in dialog.size():
pass
我们需要检查 Num
是否匹配。如果是,我们得到索引:
func go(num):
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
break
我们需要处理我们没有找到它的情况。现在,嗯……来源 material 只有一个 assert
,我将保留该方法。所以我们需要一种方法来知道代码没有找到它……
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
接下来你调用nextPhrase()
,确定:
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
nextPhrase()
还有一个没用过的var f = File.new()
,我就不加了。
并且你设置了肖像纹理。当然:
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
nextPhrase()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
我已经跳过了定时器的东西,我现在将它插入:
func go(num):
var found := false
dialog = getDialog()
for index in dialog.size():
if num == dialog[index]["Num"]:
phraseNum = index
found = true
break
assert(found, "Dialog not found")
$Timer.wait_time = textSpeed
nextPhrase()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
其他
现在,您说您只想要 具有给定 Num
的短语。这是开放的解释。
需要说明的是,上面的代码将使对话框在您要求的 Num
的第一个实例处启动。但它不会结束 - 也不会跳过 - 当它找到不同的 Num
时。不知道你要不要。
我们有几种方法可以做到这一点。我们可以记住什么是 num
并在 nextPhrase
中检查它。我真的不想那样做。所以,我会给你一个替代方法:让我们制作一个对话框数组,只包含我们想要的元素。
看起来像这样:
func go(num):
var every_dialog = getDialog()
dialog = []
for candidate in every_dialog:
if num == candidate["Num"]:
dialog.append(candidate)
assert(dialog, "Dialog not found")
phraseNum = 0
$Timer.wait_time = textSpeed
nextPhrase()
var img = dialog[phraseNum]["Emotion"] + ".png"
$Portrait.texture = load(img)
请注意,在这个例子中我们没有读取 getDialog()
到 dialog
。相反,我们正在构建一个只包含我们想要的条目的 dialog
数组。我们通过迭代 getDialog()
的结果来做到这一点(我们用 append
添加到数组)。
这是 dialog
含义的细微变化,因为它不再代表 JSON 文件中的每个条目。相反,它仅代表将要显示的条目。之前这两个东西是一样的,但这次改变后它们就不同了。
你没问的
函数
中执行一次getDialog
从JSON文件中读取。每次调用go
时都会这样做。您可以 而 在_ready
.重要的是您了解每个变量代表什么,以及您在哪里读取和写入它们。 上面我提到
dialog
对替代变化有微妙的意义。您需要考虑到这一点才能进行此更改。我坚信
nextPhrase
应该处理计时器和肖像。应该不需要设置go
.我希望你考虑这个替代方案JSON文件结构:
[ [ {"Name":"Afely", "Emotion":"Neutral", "Text":"TEST1"}, {"Name":"Afely", "Emotion":"Neutral", "Text":"TEST2"}, {"Name":"Afely", "Emotion":"Neutral", "Text":"TEST3"}, ], [ {"Name":"Afely", "Emotion":"Neutral", "Text":"2TEST1"} ] ]
然后你会得到
Array
个Array
,其中嵌套Array
的每个元素都是一个Dictionary
。然后您可以“简单地”通过索引获取嵌套数组,而不必遍历每个元素。您得到的结构类似于 JSON 文件的结构。这也意味着您将不得不改变使用它的方式。例如,可以
而不是dialog[num][phraseNum]["Text"]
.dialog[phraseNum]["Text"]
现在考虑来源 material。在这种情况下,我们有一个节点既负责解析 JSON 又负责显示角色对话。如果这些代码彼此分开,修改这些代码会更容易。大概作者的意图是你会为不同的对话有不同的 JSON 文件,所以你会在必要时切换 JSON 文件(这也解释了为什么他们每次都读取 JSON 文件时间)。
但你问的不是这个