Предисловие.
Этот урок является продолжением предыдущего, в нем мы подробнее познакомимся с узлами и сигналами, а также, разберем создание меню.

Про наследование.
Наследование в программировании, почти ничем не отличается от наследования в реальной жизни.
- Прадед купил квартиру и завещал её деду
- Дед имея квартиру, решил обзавестись машиной, и по наследству все передал отцу
- Отец имея квартиру и машину, решил обзавестись дачей, которую, по наследству передаст сыну.
- Сын владеет квартирой, машиной и дачей переданных по наследству.
В программировании это выглядит так:
extends — переводится как, наследует (англ).
- Объект Praded имеет переменную kvartira
- Ded extends Praded имеет переменные mashina и kvartira
- Otec extends Ded имеет переменные dacha, mashina, kvartira
- Sin extends Otec
Тот же принцип используется у всех узлов Godot.
Про наследование узлов Godot
При создании узла, видно дерево узлов.

По нему легко определить, что от чего наследуется. Например:
- Node2D — наследуется от CanvasItem
- CanvasItem — наследуется от Node
Т.е. Node2D владеет всеми переменными и функциями из CanvasItem и Node, а также, своими собственными.
Это можно увидеть в инспекторе, нажав на узел типа Node2D.

Сигналы, также, наследуются:

А еще, это видно в коде:
extends Node2D
Получаем узел через код
Для получения узла используется функция get_node
get_node(path)
где path — относительный путь до ноды (узла)
Например, чтобы получить путь к Player из ноды World

Нужно использовать.
get_node("Player")
Для получения CanvasLayer->ColorRect
get_node("CanvasLayer/ColorRect")
Для получения родителя, т.е. той ноды в которой находится текущая нода, используется get_parent
get_parent()
Либо .. в пути get_node
get_node("..")
Ну и в качестве примера, допустим, к узлу ColorRect привязан скрипт, в которой нужно получить доступ к узлу Player, для этого пишем следующее.
get_node("../../Player")

Также, get_node можно заменить на $, и получать узел так:
$Player
что куда проще.
Меняем параметры узла через код
Меняя параметры в инспекторе, по факту, мы меняем значение переменной данного узла. В большинстве случаев, название параметра в инспекторе = название переменной в коде, но если это не так. То, вводите тип узла в коде.
CharacterBody2D
С зажатым Ctrl, нажимаем данный текст

В итоге, вы получите справку по данному типу узла.

Доступ к переменным узла, осуществляется через точку.
$Player.position.x = 0
Функции которые вызывает движок Godot.
Godot сам вызывает функцию _ready(), один раз, при создании сцены.
pass — ничего не делает, поставил что-бы компилятор не ругался на пустой блок.
func _ready():
pass
Функцию _process(delta), которая вызывается каждый кадр, частота вызова менее стабильна чем у _physiscs_process (delta больше отклоняется)
func _process(delta):
pass
Функцию _physics_process(delta), которая вызывается в равные промежутки времени, т.е. delta почти не меняется, что позволяет ей надежно просчитывать физику.
func _physics_process(delta):
pass
Это основные, есть еще _draw, _input, но без них можно жить.
Ок, вернемся к практике, отобразив количество собранных предметов.
Добавляем сигнал предмету
Перепишите код предмета на следующее:
extends Area2D
signal got_item #Создал сигнал, который позже, можно будет отправить слушателям
func _on_body_entered(body):
emit_signal("got_item") #Отправляем сигнал got_item всем слушателям.
queue_free()
Код я объяснил в комментариях. Ок, осталось связать этот сигнал со слушателями.
Откройте сцену world, и реорганизуйте дерево узлов, что-бы все предметы находились внутри узла Items, типа Node2D.

Сделали это для удобства, позже поймете.
Теперь, откройте код сцены world, и замените на следующее:
extends Node2D
func _ready():
#В момент загрузки сцены выполняем init_items
init_items()
func _on_area_2d_4_body_entered(body):
get_tree().change_scene_to_file("res://world2.tscn")
func init_items():
#Получили массив детей предмета
var item_arr = $Items.get_children()
#Проходимся по всем предметам массива детей
for item in item_arr:
#Соединяем сигнал got_item из предмета, с функцией _got_item из уровня
item.connect("got_item", _got_item)
func _got_item():
GlobalVals.items_num += 1
#Меняем текст ноды Label на количество предметов, преобразовав в строку str()
$CanvasLayer2/Label.text = str(GlobalVals.items_num)
Дети, в данном случае, это те кто находятся под кем-то.

В данном случае, у Items всего 1 ребенок, это Area2D.
Далее, связали (connect) сигнал got_item с функцией _got_item. Т.е. функция вызовется когда предмет выпустит сигнал (emit_signal) got_item.
В функции got_item, мы увеличили счетчик и изменили текст Label, на значение счетчика. Но т.к. счетчик это число, то его нужно преобразовать в строку, вот так.
str(GlobalVals.items_num)
В итоге, все предметы будут вызывать одну и ту-же функцию _got_item, при столкновении с игроком.
То же самое сделайте для 2-го уровня.
В итоге, при столкновении предмета с игроком, счетчик в углу экрана обновился.

Ок, давайте создадим графический интерфейс т.е. GUI.
Создание главного меню.
Создайте новую сцену, нажав + около вкладок, в качестве корневого узла, выберите зеленый.

У зеленых узлов есть общие черты:
- Они подгоняют позицию детей под размеры контейнера — например, Control будет центрировать вложенный спрайт независимо от размеров экрана (если вы это укажете).
- Связаны с GUI
У зеленых узлов, позиция и их относительный размер задается якорями. Для простоты, будем пользоваться пресетами якорей.
Ок, у узла Control, измените размер контейнера на весь экран, взяв в качестве пресета якорей — полный прямоугольник.

Границы контейнера помечаются оранжевым прямоугольником.
Теперь, вложите в него узел Label, указав ему любой текст. В качестве пресета якорей, используйте центр.

Теперь, проиграйте текущую сцену нажав на кнопку с изображения. Вам предложат сохранить сцену, назовите её MainMenu

Попробуйте поменять размер окна, независимо от него, надпись останется по центру.
Ок, создайте узел VBoxContainer, туда вложите Label и Button

- VBoxContainer — группирует вложенные в него ноды, друг за дружкой, по вертикали
- HBoxContainer — то же самое, только по горизонтали
- Button — кнопка, которая при нажатии, испускает сигнал.
Для VBoxContainer выбрал пресет на заполнение по ширине и по центру.

Для Label, выбрал прижать к центру по горизонтали.

У Button, выбрал заполнение по горизонтали.

Далее, пропишем код меню.
Прописываем код меню.
Привяжите скрипт к корневому узлу (Control), у узла Button, соедините сигнал button_down, с корневым узлом.
button_down — сигнал, который срабатывает в момент нажатия на кнопку.
В скрипте, смените текущую сцену на сцену 1-го уровня, должно получится следующее.
extends Control
func _on_button_button_down():
get_tree().change_scene_to_file("res://world.tscn")
Переход готов, осталось заменить начальную сцену на сцену меню. Для этого, задите в Проект->Настройки проекта, там выберите Запустить->Главная сцена, и замените сцену на MainMenu.

Готово.
Итоговый результат.
