Механики ловушек и интерактивных объектов в Godot Engine. Часть 2

  • Tutorial
Приветствую вас во второй части механик ловушек и интерактивных объектов в Godot Engine.
Я решил пока-что выпустить эту часть, чтобы выпустить эту часть, чтобы показать механики, которые отвечают за направление уровня в играх. Я имею в виду двери, ключи и движущиеся платформы. В данном случае движущиеся по желанию игрока. Такие платформы можно будет ронять, использовать как мост и другое.

Для того чтобы всё работало мы будем использовать NodePath. Только в этом случае не для перемещения игрока, а для перемещения объектов относительно текущего положения.

Предыдущие статьи:


Переключатель


Для начала создадим переключатель. Это будет Area2D со спрайтом и коллизией. Он будет иметь метод interact(_interactor: Node), для того чтобы взаимодействовать с другими объектами, на которые будет указывать NodePath. Вот скрипт этого переключателя:

tool
extends Area2D

export (NodePath) var dependent_node: NodePath
export (bool) var toggle: bool = false
var prev_toggle: bool = false

func _process(_delta: float) -> void:
	if prev_toggle != toggle: # Отвечает за воспроизведение нужной анимации. Нуждается в доработке
		if toggle == true:
			$AnimatedSprite.play("toggle_on")
		else:
			$AnimatedSprite.play("toggle_off")
		prev_toggle = toggle

func interact(_interactor: Node) -> void:
	if !$AnimatedSprite.is_playing(): # Если Анимация воспроизводится и есть метод "toggle" у dependent_bode 
		if get_node(dependent_node).has_method("toggle"):
			self.toggle = !self.toggle # поменять значение toggle
			get_node(dependent_node).toggle(toggle) # Вызвать метод toggle у dependent_node и передать toggle

А так выглядит сцена переключателя



Улучшение шипов


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

# Добавьте в конец того скрипта шипов
func toggle(toggled: bool) -> void:
	self.showed = toggled

Теперь скрипт будет выглядеть следующим образом:

tool
extends StaticBody2D

export var showed = false
export (bool) var timer = false

var prev_showed = showed

func _physics_process(_delta):
	if timer and $Timer.is_stopped():
		$Timer.start()
	if showed != prev_showed:
		if showed:
			$AnimatedSprite.play("show")
		else:
			$AnimatedSprite.play("hide")
		prev_showed = showed

func _on_Area2D_body_entered(body):
	if body.name.ends_with("Actor") and showed:
		body.dead()

func _on_Timer_timeout():
	if timer:
		showed = !showed
		$Timer.start()

func toggle(toggled: bool) -> void:
	self.showed = toggled

Как-то так. Теперь игрок может менять состояние шипов.

Ключи и двери


Ключи


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

extends Area2D # Как всегда спрайт и коллизия среди детей корневого узла сцены

func _on_Key_body_entered(body):
	if body.name == "Actor": # Если подобравший ключ - Actor
		body.key_picked_up() # Вызови метод подбора ключа
		self.queue_free() # Удалить с поля ключ

Теперь если войти в ключ — он автоматически подберется. И держите скриншот того, как выглядит мой ключ.



Двери


По-началу двери могли только открываться, но это было в начале. Теперь я придумал как позволить им закрываться.

extends StaticBody2D

export (bool) var key_can_used: bool = true
onready var shape = $CollisionShape2D

func open() -> void:
	if !key_can_used: return
	self.visible = false
	shape.disabled = true
func close() -> void:
	if !key_can_used: return
	self.visible = true
	shape.disabled = false
func toggle(vis: bool) -> void:
	self.visible = vis
	shape.disabled = !vis
	return

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



Заключение


В данной статье я рассказал про переключатель, ключи и двери, а также показал улучшенную версию шипов. Следующей будет выпущена пятая часть механик персонажа, следом за которой я расскажу о предметах, которые можно поднять. Спасибо за внимание и удачи.

Средняя зарплата в IT

110 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 8 657 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

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

    +2
    Подобные способы взятия узлов ($AnimatedSprite, $Timer и прочие $...) стоит кэшировать, например:
    onready var this_sprite = $AnimatedSprite
    onready var for_timer = $Timer

    чтобы обращаться к ним так:
    this_sprite.play(«show») вместо $AnimatedSprite.play(«show»)

    Становится менее наглядно, но следует помнить, что каждый такой $… аналогичен вызову get_node() и при использовании в цикле потери времени на это могут стать заметными. Попутно от подобного кэширования дополнительная польза на будущее, если целевой узел вдруг сместится в иерархии, то не надо будет править пути к нему по всему коду.
    А так, вне циклов, обращения через $… более оправданы, в том плане, что так проще/нагляднее и потери могут быть почти неощутимы.
      +1
      Спасибо о рекомендации кэшировать взятия узлов, если они будут использованы в циклах. Я о таком не знал, так что очень благодарен за данный совет.
        +1
        Просто в различных примерах, да и в исходниках, любят писать наглядным образом, везде используя $… Но есть вот такие нюансы, малозаметные пока подобных обращений в коде немного и они не начинают массово скапливаться в цикле.

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

    Самое читаемое