Menu
CoddyTech

Узлы как компоненты

Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 42 из 65.

У узла Node могут быть дочерние узлы. Godot создает игровые объекты таким образом: у узла героя есть по одному дочернему узлу на каждую способность, например здоровье или передвижение. Каждый дочерний узел — это компонент: небольшой узел, который выполняет одну задачу.

# health.gd
class_name Health
extends Node

var hp := 10

func _ready() -> void:
	print("Health ready")

# hero.gd
class_name Hero
extends Node

func _init() -> void:
	var health := Health.new()
	health.name = "Health"
	add_child(health)

func _ready() -> void:
	print("Hero ready, hp: ", $Health.hp)

add_child() добавляет узел в качестве дочернего. Задай каждому компоненту name: get_node("Health") или его краткая форма $Health находит дочерний узел по этому имени. Узел без имени или с именем, которое уже занято соседним узлом, получает автоматическое имя, например @Node@4.

Метод _ready() узла выполняется, когда узел попадает в дерево сцены — дерево узлов, в котором работает игра. main.gd находится в дереве, поэтому добавление героя в него запускает оба метода _ready(), сначала у дочернего узла:

# main.gd
var hero := Hero.new()
add_child(hero)            # Сначала готов Health, затем Hero, hp: 10
print(hero.get_child_count())   # 1

Родительский узел получает доступ к своим компонентам с помощью get_children() (массива дочерних узлов в порядке их добавления), get_child_count() и has_node("Health"). Узлы в дереве освобождаются вместе с деревом, когда игра заканчивается, поэтому компонент, добавленный с помощью add_child(), не требует очистки.

challenge icon

Задание

Легко

Создай робота из узлов-компонентов.

  • Part расширяет Node. Его конструктор получает имя детали и значение мощности: он сохраняет мощность и задаёт узлу name, равное имени детали. Когда деталь попадает в дерево сцены, её _ready() выводит Laser attached.
  • Robot расширяет Node. add_part(part_name, power) добавляет новую Part в качестве дочернего узла. Если у робота уже есть дочерний узел с таким именем, он выводит Laser is already attached и ничего не создаёт.
  • total_power() возвращает сумму мощностей всех его деталей.

Предоставленный код добавляет робота в дерево сцены, считывает количество следующих команд (add Laser 5, power) и в конце выводит количество деталей. Для команд add Laser 5, add Wheels 2, power, add Laser 9, add Arm 3, power он выводит:

Laser attached
Wheels attached
Total power: 7
Laser is already attached
Arm attached
Total power: 10
Parts: 3

Твой код нужно поместить в part.gd и robot.gd. В main.gd находится предоставленный код ввода/вывода, его нельзя редактировать.

Попробуйте сами

extends Node

func _ready():
	# Предоставленный код ввода-вывода: оставьте его без изменений
	var robot := Robot.new()
	add_child(robot)
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "add":
			robot.add_part(parts[1], int(parts[2]))
		else:
			print("Total power: ", robot.total_power())
	print("Parts: ", robot.get_child_count())
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор GDScript