Пауза в играх

Пауза?

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

Внедрение филигранного контроля на то что может быть приостановлено (а что не может) это куча работы, так что в Godot встроен простой фреймворк для пауз.

Как работает пауза

Чтобы установить режим паузы, нужно установить состояние паузы. Это можно сделать присвоив true свойству SceneTree.paused:

get_tree().paused = true
GetTree().Paused = true;

Это приведёт к тому что:

  • 2D и 3D физика остановятся.

  • _process и _physics_process больше не будут вызываться в узлах.

  • _input и _input_event также больше не будут вызываться.

Это фактически останавливает всю игру. Вызов этой функции из скрипта по умолчанию приведет к невосстановимому состоянию (ничего больше не будет работать!).

Белый список нодов

Прежде чем делать паузу, убедитесь что ноды которые должны работать во время паузы занесены в белый список. Это выполняется через редактирование свойства "Pause Mode" в ноде:

../../_images/pausemode.png

Вы можете достичь того же результата в коде:

func _ready():
    pause_mode = Node.PAUSE_MODE_PROCESS
public override void _Ready()
{
    PauseMode = Node.PauseModeEnum.Process;
}

По умолчанию все узлы имеют это свойство в состоянии "Наследовать" (Inherit). Это означает, что они будут обрабатывать (или не обрабатывать) только в зависимости от того, какое свойство установлено на родительском узле. Если родитель установлен в состояние "Наследовать", то будет проверяться "дедушка" и так далее. В конечном итоге, если состояние не может быть найдено ни в одном из дедушек и бабушек, используется состояние паузы в SceneTree. Это означает, что по умолчанию, когда игра поставлена на паузу, каждый узел будет поставлен на паузу.

Существует три возможных состояния для ноды:

  • Inherit: Процесс зависит от состояния родителя, родителя-родителя, итд. Т.е первый родитель который будет иметь не-Inherit состояние.

  • Stop: Останавливает ноду в любом случае (и потомков в состоянии Inherit). Когда пауза происходит эта нода не будет обрабатываться.

  • Process: Обрабатывать эту ноду в любом случае (и потомков в состоянии Inherit). Вне зависимости от паузы эта нода будет обрабатываться.

Пример

Примером может служить создание всплывающего окна или панели с элементами управления внутри, установка режима паузы на "Процесс", а затем его скрытие:

../../_images/pause_popup.png

Просто установив корень всплывающего окна паузы на "Process", все дочерние и внучатые элементы унаследуют это состояние. Таким образом, эта ветвь дерева сцены будет продолжать работать, когда приостановлена.

Наконец, сделайте так чтобы нажатая кнопка паузы (любая кнопка подойдёт), включала паузу и показывала экран паузы.

func _on_pause_button_pressed():
    get_tree().paused = true
    $pause_popup.show()
public void _on_pause_button_pressed()
{
    GetTree().Paused = true;
    GetNode<Control>("pause_popup").Show();
}

Для отключения паузы, сделайте обратное когда экран паузы закрывается:

func _on_pause_popup_close_pressed():
    $pause_popup.hide()
    get_tree().paused = false
public void _on_pause_popup_close_pressed()
{
    GetNode<Control>("pause_popup").Hide();
    GetTree().Paused = false;
}

Вот и всё!