ГОДО — как отключить перемещение игрока, когда диалоговое окно активно, и снова включить его, когда оно неактивно

#godot #gdscript

Вопрос:

Ладно, я действительно плохо разбираюсь в кодировании. Я особенно новичок в ГОДО и пытаюсь создать 2d-игру. Я смог установить cant_move в значение false при воспроизведении диалогового окна, проблема, с которой я сталкиваюсь, заключается в том, чтобы снова сделать cant_move истинным. Я даже не знаю, где поместить done = true в сценарий диалога (я просто поместил его в случайное место и надеялся, что это сработает). Вот мой код собачьего дерьма. (решение, вероятно, простое, я просто очень тупой)

сценарий npc

 `extends Area2D var done = true   func _ready():   Global.npc1 = self func _exit_tree():  Global.npc1 = null   var can_interact = false const DIALOG = preload("res://dialoguebox.tscn")  func _physics_process(delta):  $AnimatedSprite.play()  func diaplay():  if done == false:  Global.player.can_move = false  print("test")   if done == true:  print("test2")  can_interact = false  Global.player.can_move = true  func _on_Area2D_body_entered(body):  if body.name == "player":  $Label.visible = true  can_interact = true  func _on_Area2D_body_exited(body):  if body.name == "player":  $Label.visible = false  can_interact = false  func _input(event):  if Input.is_key_pressed(KEY_E) and can_interact == true:  done = false  diaplay()  $Label.visible = false  var dialog = DIALOG.instance()  get_parent().add_child(dialog)  dialog.position = $Position2D.global_position  

сценарий диалога

 extends Control var dialog = [  'sampletext',  'sampletext2', ] var done = false var dialog_index = 0 var finished = false   func _ready():  load_dialog()   Global.DialogBox = self   func _exit_tree():  Global.DialogBox = null  func _physics_process(delta):  $"Ind".visible = finished  if Input.is_action_just_pressed("ui_accept"):  load_dialog()  func load_dialog():  if dialog_index lt; dialog.size():  finished = false  $RichTextLabel.bbcode_text = dialog[dialog_index]  $RichTextLabel.percent_visible = 0  $Tween.interpolate_property(  $RichTextLabel, "percent_visible", 0, 1, 1,  Tween.TRANS_LINEAR, Tween.EASE_IN_OUT  )  $Tween.start()  if dialog_index gt;= 0:  Global.npc1.done = true  else:  queue_free()  done = true  dialog_index  = 1   func _on_Tween_tween_completed(object, key):  finished = true  

Ответ №1:

Если я правильно понимаю, вы открываете пользовательский интерфейс с помощью этого кода:

 var dialog = DIALOG.instance() get_parent().add_child(dialog) dialog.position = $Position2D.global_position  

Поэтому добавьте туда инструкцию сделать can_move false ( Global.player.can_move = false ).

И, по-видимому, все это делается здесь:

 queue_free()  

То есть пользовательский интерфейс удаляет его самостоятельно. Когда пользовательский интерфейс удалится, он выйдет из дерева сцен, мы собираемся воспользоваться этим преимуществом. Подключите tree_exited пользовательский интерфейс к функции, которая can_move снова устанавливает значение true:

 Global.player.can_move = false  var dialog = DIALOG.instance()  dialog.position = $Position2D.global_position  dialog.connect("tree_exited", self, "dialog_exited")  get_parent().add_child(dialog)  func dialog_exited() -gt; void:  Global.player.can_move = true  

Этого должно хватить.

В качестве альтернативы вы можете создать и подать сигнал, чтобы уведомить, когда игрок сможет снова двигаться. Обратитесь к документации по сигналам.


Дополнение

Я думаю, что у меня есть то, что еще не работает. Смотреть на load_dialog :

 func load_dialog():  if dialog_index lt; dialog.size():  # ... some code ...  if dialog_index gt;= 0:  Global.npc1.done = true  else:  queue_free()  done = true  dialog_index  = 1  

Первая проверка ( dialog_index lt; dialog.size() ) заключается в том, есть ли еще текст диалогового окна. Если нет, то это сделано. Так что измените его на этот:

 func load_dialog():  if dialog_index lt; dialog.size():  # … some code …  else:  Global.npc1.done = true  queue_free()  done = true  dialog_index  = 1  

Я надеюсь, что в этом есть смысл.


Вы также упомянули , что у вас произошла ошибка Global.player.can_move = true , я полагаю, это произошло при закрытии игры, этот код был запущен и Global.player больше не действителен.

Независимо от ситуации, вы можете проверить, является ли игрок действительным:

 var player = Global.player  if is_instance_valid(player):  player.can_move = true  

Комментарии:

1. похоже, у меня это не работает. Он удаляет движение, когда игрок взаимодействует, но он все равно не будет двигаться, когда диалог будет завершен. Я добавил именно то, что вы мне сказали добавить, но когда диалог будет завершен, он все равно не позволит мне снова двигаться

2. я получаю ошибку Invalid set index 'can_move' (on base: 'Nil') with value of type 'bool'. , которую я не знаю, почему я получаю, потому что я тупой и не знаю кода так хорошо

3. @JacobWhisenand см. добавление.

4. Спасибо! У меня это работает

Ответ №2:

У меня недостаточно репутации, чтобы комментировать, но я просто хочу добавить, что у вас есть две разные done переменные. Один в NPC, а другой в диалоге. Вы установили их истинными здесь:

 if dialog_index gt;= 0:  Global.npc1.done = true  else:  queue_free()  done = true  

Я думаю, что проблема также может заключаться в том, что диалог done больше никогда не будет установлен. Но я тоже нуб, и Тераот всегда дает хорошие советы, так что проверьте его ответ еще раз.

На самом деле он уже решил эту проблему:

 if dialog_index lt; dialog.size():  # … some code … else:  Global.npc1.done = true  queue_free()  done = true dialog_index  = 1  

Для ясности я бы попытался использовать только одну done переменную, вероятно, связывая скрипты с сигналами также, как сказал Тераот.