Godot:根据输入读取JSON文件并输出为Textbox

5hcedyr0  于 2023-02-10  发布在  Go
关注(0)|答案(1)|浏览(378)

我希望能够通过在这个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
我该如何着手做这件事?

aiazj4mn

aiazj4mn1#

你的要求

您所要求的内容需要做一些额外的工作。让我们从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{}之间的元素),这意味着您需要迭代Array,检查每个Num
在我们这样做之前,我们需要承认我们将使用名称phraseNum来表示两件事情:

  • dialogArray中的索引
  • Num的期望值

我们遇到这种情况是因为您正在使用的源材料。它们将phraseNum作为参数(此处:func go(phraseNum)),其隐藏phraseNum字段(这里为var phraseNum = 0)。
这样会影响沟通,如果我让你用phraseNum做这个,是哪个?那肯定会给我们带来麻烦。
我将重写go,这样它将使用Num而不是dialogArray中的索引,所以我将保留phraseNum作为dialogArray中的索引,并为参数go使用不同的名称。
让我们开始重写go

func go(num):
    pass

现在,让我们来看看所有的对话:

func go(num):
    dialog = getDialog()

我们将对它们进行迭代,因为我需要一个phraseNum的索引,所以我将使用index进行迭代:

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

我们需要处理我们没有找到它的情况。现在,嗯...源材料只有一个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 s的Array,其中嵌套的Array的每个元素都是一个Dictionary,然后你可以"简单地"通过索引得到嵌套的数组,而不必迭代每个元素。
得到的结构类似于JSON文件的结构,这也意味着你必须改变它的使用方式,例如,可以用dialog[num][phraseNum]["Text"]代替dialog[phraseNum]["Text"]
现在考虑源代码。在本例中,我们有一个节点,它既负责解析JSON,又负责显示字符对话框。如果将它们彼此分离,修改代码会更容易。作者的意图可能是为不同的对话框提供不同的JSON文件。因此您可以在必要时切换JSON文件(这也解释了为什么他们每次都读取JSON文件)。

  • 但你问的不是这个 *

相关问题