SignalBus?

Хорошо, я постараюсь написать это сообщение на португальском и английском языках.

Английский

Поехали!

Что такое SignalBus и почему у меня в голове шумит, когда я думаю об этом паттерне и, что более важно, как реализовать его в Godot?

Итак, какова концепция этого паттерна?

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

Первоначальная мысль приходит в голову: «Это работа для сигналов!», поэтому на своем уровне вы находите узел игрока, а затем соединяете его с UI. Все работает, но теперь у вас где-то есть фрагмент кода (уровня, игрока или UI), который вам нужно знать и организовать.

Таким образом, этот код запутывается.

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

Но у меня появился зуд в голове, этот шум в мозгу, это может быть лучше, но как?

Именно тогда я услышал термин SignalBus. Теперь у нас есть проблема, и мы собираемся решить ее немного более элегантно, а затем подумать о последствиях этого.

В данном случае у нас есть Singleton, что для движка делается просто созданием скрипта (который мы назовем SignalBus.gd и добавим список автозагрузки, таким образом скрипт будет всегда запущен и его можно будет вызвать в любом другом скрипте.

Затем давайте добавим нашему другу сигнальной шине что-нибудь очень интересное, например:

#SignalBus.gd
extends Node2D

signal PlayerDamaged(total_hp, current_hp)
Войти в полноэкранный режим Выйти из полноэкранного режима

Довольно коротко, верно?
Но как насчет нашего друга-игрока?

#Player.gd
class_name Player extends KinematicBody2D
#...
func receive_damage(damage):
  #...
  SignalBus.emit("PlayerDamaged", max_hp, current_hp)
  #...
#...
Вход в полноэкранный режим Выход из полноэкранного режима

Как видите, класс игрока знает только о SignalBus, но он не знает пользовательского интерфейса, не знает уровня, и, честно говоря, ему это и не нужно. Уровню также больше не нужно знать игрока, не говоря уже о пользовательском интерфейсе.

Теперь давайте посмотрим на класс пользовательского интерфейса,

#UI.gd
class_name UI extends Control
#...
func _ready(damage):
  #...
  SignalBus.connect("PlayerDamaged", self, "on_update_player_life")
  #...
func on_update_player_life(max, curr):
  # Update ui with actual values
#...
Вход в полноэкранный режим Выход из полноэкранного режима

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

Представьте, что у нас теперь есть враг, который ждет, пока игрок получит урон, а затем стреляет? Или нам нужно сделать новую анимацию сотрясения экрана, когда игрок получает урон, все это можно сделать с помощью того же сигнала, которым управляет наш друг bus.

Português

Vamos lá,

O que é um SignalBus e porque todo esse barulho em minha cabeça quando penso nesse padrão e o mais importante, como implementar ele em Godot?

Какова идея?

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

В своем первоначальном воображении вы думаете: «Это работа для синаев!», а затем на своем уровне вы локализуете nó jogador и подключаете его к пользовательскому интерфейсу. Все работает, но теперь у вас в любом месте (на уровне, в жогадоре или в пользовательском интерфейсе) есть тречо де кодиго, которое нужно знать и организовать.

Ou seja, acoplamento de código.

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

Mas eu tinha essa pulga atrás da orelha pensando, isso pode ser melhor, mas como?

Foi então que ouvi o termo SignalBus. Agora temos um problema e iremos a solução do problema um pouco mais elegante, e depois vamos pensar nas implicações disso.

В данном случае мы имеем Singleton, который для движка можно реализовать, просто создав скрипт (который мы создадим из SignalBus.gd и добавим список автозагрузок, таким образом, скрипт будет постоянно выполняться и может быть добавлен в любой другой скрипт.

Мы предлагаем вам добавить еще один интересный вариант для нашего друга — busão de sinais, смотрите пример:

#SignalBus.gd
extends Node2D

signal PlayerDamaged(total_hp, current_hp)
Вход в полноэкранный режим Выход из полноэкранного режима

Bem curtinho, né?
Mas e o nosso amigo jogador?

#Player.gd
class_name Player extends KinematicBody2D
#...
func receive_damage(damage):
  #...
  SignalBus.emit("PlayerDamaged", max_hp, current_hp)
  #...
#...
Вход в полноэкранный режим Выход из полноэкранного режима

Как можно видеть, класс джогадоров знаком только с SignalBus, но не знаком с пользовательским интерфейсом, не знаком с уровнем, и, искренне говоря, не заинтересован в этом. Уровень там же не требует более глубокого знания jogador и гораздо меньшего знания UI.

Agora vmaos a classe do UI,

#UI.gd
class_name UI extends Control
#...
func _ready(damage):
  #...
  SignalBus.connect("PlayerDamaged", self, "on_update_player_life")
  #...
func on_update_player_life(max, curr):
  # Update ui with actual values
#...
Вход в полноэкранный режим Выход из полноэкранного режима

Agora temos um código que está acoplado apenas no SignalBus, com isso podemos mover coisas para outros lugares e inclusive colocar mais coisas ouvindo o sinal do player.

Представьте, что у нас теперь есть враг, который ждет, пока игрок получит урон, прежде чем выстрелить? Или нам нужно поместить на экран новую анимацию дрожания, когда игрок получает урон, все это можно сделать с помощью того же сигнала, которым управляет наш друг bus.

Надеюсь, вам понравился этот фрагмент.

(()=>())()

Оцените статью
devanswers.ru
Добавить комментарий