Разработка графического интерфейса

Теперь, когда вы освоили основы, мы рассмотрим, как построить пользовательский интерфейс игры (GUI) с многократно используемыми компонентами: шкала здоровья, энергии, и счетчики бомб и кристаллов. К концу этого урока у вас будет GUI, готовый к управлению с помощью GDscript или VisualScript:

../../_images/ui_gui_design_final_result.png

Окончательный результат

Вы также научитесь:

  1. Создание гибких компонентов UI
  2. Использовать наследование сцен
  3. Построение сложного UI

Скачайте файлы проекта: ui_gui_design.zip и извлеките архив. Импортируйте проект start/ в Godot, чтобы следовать этому руководству. Папка `end/`содержит конечный результат.

Примечание

Вы можете посмотреть это руководство как видео на Youtube.

Разбивка UI

Давайте разберём окончательный UI спланируем, какие контейнеры мы будем использовать. Как и в: Дизайн начального экрана, начнём с MarginContainer. Затем мы видим три столбца:

  1. Слева счетчики здоровья и энергии
  2. Шкалы здоровья и энергии
  3. Справа счётчики бомб и кристаллов

Но счётчики и шкалы являются частями одного и того же элемента UI. Таким образом, у нас остались две колонки:

  1. Слева шкалы здоровья и энергии
  2. Справа счётчики бомб и кристаллов

Это облегчает вложение контейнеров: у нас есть некоторые поля вокруг границы экрана с помощью MarginContainer, а затем HBoxContainer для управления нашими двумя колонками. Две шкалы ложатся друг на друга внутри VBoxContainer. И нам понадобится последний HBoxContainer в правой колонке, чтобы поместить счетчики бомб и кристаллов бок о бок.

../../_images/ui_gui_step_tutorial_containers_structure.png

Мы получаем чистую компоновку UI только с 4 контейнерами

Нам понадобятся дополнительные контейнеры внутри некоторых компонентов UI, но это дает нам структуру основной сцены GUI. С этим планом мы можем перейти в Godot и создать наш GUI.

Создание базового GUI

Есть два способа создания GUI: можно проектировать каждый элемент в отдельной сцене, или же сделать прототипы всех элементов в одной сцене и разбить это на сцены позже. Я рекомендую работать с одной сценой, ведь это позволит вам экспериментировать с пропорциями и я расположением элементов UI. Как только вы добьётесь желанного результата, можно будет сохранить целые разделы дерева узлов как отдельные сцены, которые можно будет переиспользовать. Мы сделаем это немного позже.

Сейчас давайте начнем с нескольких контейнеров.

Создайте новую сцену и добавьте MarginContainer. Выберите узел и назовите его GUI.

Мы хотим, чтобы наш интерфейс был привязан к верхней части экрана. Выберите узел GUI и нажмите кнопку «Макет» в верхней части окна. Выберите опцию Top Wide. Узел GUI будет привязан к верхнему краю родительского элемента, по умолчанию — к видовому экрану. Он будет автоматически изменять размер по вертикальной оси, чтобы дать пространство для его дочерних компонентов.

Сохраните сцену как GUI.tscn. Мы оставим весь GUI в нём.

Выбрав MarginContainer, направляйтесь к инспектору и прокрутите вниз до раздела пользовательских констант(custom constants). Разверните его и щелкните на поле рядом с каждым из свойств Margin. Установите их все на 20 пикселей. Затем добавьте узел HBoxContainer. Он будет содержать наши две шкалы слева и отделять их от двух счетчиков справа.

We want to stack the bars vertically inside the HBoxContainer. Add a VBoxContainer as a child of HBoxContainer and name it Bars. Select the parent HBoxContainer again and this time, add another HBoxContainer as a child of it. Call it Counters. With these four containers, we have the base for our GUI scene.

../../_images/ui_gui_containers_structure_in_godot.png

У нас должны быть 4 контейнера, которые выглядят так

Примечание

We can work this way because we first broke down our UI design and took a few moments to think about the containers we’d use. When you follow a tutorial like this, it may seem weird. But once you’re working on real games, you’ll see it’s an efficient workflow.

Создание базы для шкал прогресса

Каждая шкала делится на два подэлемента, которые выравниваются по горизонтали: ярлык с количеством здоровья слева и датчик справа. Еще раз, HBoxContainer является идеальным инструментом для работы. Выберите узел Bars и добавьте новый HBoxContainer внутри него. Назовите его Bar.

Сама метка требует по крайней мере трех узлов: a NinePatchRect для фона, над которым мы добавим текстуру слева, для HP или EP, и еще Label справа для значения. Мы могли бы вложить Control узлы, как нам угодно. И даже использовать NinePatchRect в качестве родителя для двух других элементов, так как они включают в себя их. Но все же, вместо этого нужно использовать контейнеры, поскольку их роль состоит в том, чтобы помочь упорядочить компоненты UI. Нам понадобится MarginContainer позже в любом случае, чтобы добавить некоторое пространство между количеством жизни и датчика. Выберите Bar и добавьте MarginContainer. Назовите его Count. Внутри него, добавить три узла:

  1. NinePatchRect с именем Background
  2. TextureRect с именем Title
  3. И Label с именем Number

Чтобы добавлять узлы на один и тот же уровень, всегда сначала выбирайте узел Count.

../../_images/ui_gui_step_tutorial_bar_template_1.png

Ваше дерево сцены должно выглядеть так. Мы готовы добавить несколько текстур

Наша сцена по-прежнему пуста. Самое время, чтобы поместить в неё какие-нибудь текстуры. Для загрузки текстур, направляйтесь в файловую систему слева от окна. Перейдите вниз к папке res://assets/GUI.

../../_images/ui_gui_step_tutorial_textures_in_FileSystem_tab.png

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

Выберите Background в панели сцены. В инспекторе вы найдите свойство Texture. Из вкладки Файловая система перетащите label_HP_bg.png на параметр Texture. Картинка будет сжата. Родительский MarginContainer будет уменьшать его размер до нуля, пока мы принудительно не изменим элементы внутри контейнера, чтобы получить минимальный размер. Выберите узел Background. В инспекторе прокрутите вниз до раздела Rect. Установите Min Size на (100, 40). Вы должны увидеть изменение размера Background вместе с его родительскими контейнерами.

Next, select the Title and drag and drop label_HP.png into its Texture slot. Select the Number node, click the field next to the Text property and type 10. This way, we can see both nodes in the viewport. They should stack up in the top-left corner of their parent MarginContainer.

../../_images/ui_gui_step_tutorial_bar_label_stacked.png

Если вы выберите оба узла, вы должны увидеть что-то такое

As they have a container as their direct parent, we cannot move them freely: the Count node will always reset their anchors, their size and position. Try to move and resize the nodes in the viewport. Then, select any of the three textures and press Ctrl Up or Ctrl Down to reorder them in the Scene dock. They’ll snap back to their previous size and position.

Родительские контейнеры управляют размером, масштабом, отступами и якорями их дочерних элементов. Чтобы изменить узлы, необходимо вложить их в обычный элемент управления Control или другой элемент UI. Мы будем использовать Background в качестве родителя для Title и``Number``. Выберите Title and Number, и перетащите их на Background.

../../_images/ui_gui_step_tutorial_bar_nesting_inside_background.png

Используя узел Background в качестве родителя для двух текстур, мы берем под контроль Count который является MarginContainer’ом

Select the Title and in the Inspector, change its Stretch Mode property to Keep Centered. Next find the Rect category in the Inspector and change the Size property to (50, 40) so it only takes the left half of the background. Next, select the Number node. In the viewport, click the Layout menu and click Full Rect. The node will resize to fit the Background. Head to the Inspector and change its Align property to Right, and the VAlign property to Center. The text should snap to the center of the Background’s right edge. Resize the node horizontally, so it takes the right half of the Background and there’s a bit of padding with the right edge.

../../_images/ui_gui_step_tutorial_bar_placed_title_and_label.png

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

Замена шрифта у Label

Шрифт у метки(label) слишком мал. Нам нужно его изменить. Выберите узел Number в инспекторе, и прокрутите вниз до класса Control и найдите категорию Custom Font. Щелкните на поле рядом со свойством Font и выберите New Dynamic Font. Нажмите на поле еще раз и выберите Редактировать.

You will enter the Dynamic Font resource. Unfold the Font category and click the field next to Font Data. Click the Load button. In the file browser, navigate down to the assets/font folder and double click Comfortaa-Bold.ttf to open it. You should see the font update in the viewport. Unfold the settings category to change the font size. Set the Size property to a higher value, like 24 or 28.

We now need the text’s baseline, the number’s lower edge, to align with the HP texture on the left. To do so, still in the DynamicFont resource, you can tweak the Bottom property under the Extra Spacing category. It adds some bottom padding to the text. Click the Number node in the Scene tab to go back to the node’s properties and change the VAlign to Bottom. To adjust the text’s baseline, click on the font field under the Custom Font category again and tweak the Bottom property until the text aligns with the Title node. I used a value of 2 pixels.

../../_images/ui_gui_step_tutorial_number_baseline.png

При значении Bottom, равным 2 пикселям, Number выравнивается по Title

С этим, мы закончили самую сложную часть. Поздравляю! Давайте перейдем к более простым узлам.

Добавление шкалы прогресса

Нам нужен один последний элемент, чтобы закончить нашу шкалу жизни: собственно сам датчик. Узел TextureProgress имеет все, что нам нужно.

Выберите узел Bar и добавьте в него TextureProgress. Назовите его Gauge. В инспекторе разверните раздел Textures. Направляйтесь в файловую систему и перетащите текстуру lifebar_bg.png в гнездо Under. Сделайте то же самое с lifebar_fill.png и поместите его на слот Progress. Под классом Range в инспекторе измените свойство Value на 50, чтобы увидеть, что датчик заполняется.

С только пятью узлами „ „ Control „ „, наша первая шкала готова к использованию.

../../_images/ui_gui_step_tutorial_bar_final.png

Вот и все, наша шкала здоровья готова. Последняя часть была быстрой, не так ли? Это благодаря нашей хорошей установке контейнера.

Design the bomb and emerald counters

The bomb and emerald counters are like the bar’s Count node. So we’ll duplicate it and use it as a template.

В узле Bar выберите Count и нажмите Ctrl+D, чтобы дублировать его. Перетащите новый узел под Counters в нижнюю часть дерева сцены. Вы должны увидеть как он изменит размер автоматически. Не беспокойтесь об этом сейчас, мы исправим его в ближайшее время.

Rename the Count2 node to Counter. Unlike the bars, we want the number to be on the left, and an icon to sit on the right. The setup is the same: we need a background (a NinePatchRect), the title, and the number nodes. The Title node is a TextureRect, so it’s what we need to display the icon. In the scene tree, select the Title node, and rename it to Icon.

../../_images/ui_gui_step_tutorial_counter_design_1.png

Вот так древо узлов должно выглядеть на данный момент

With the Icon node selected, in the inspector, scroll to the top to see the Texture slot. Head to the FileSystem dock on the left and select the bombs_icon.png. Drag and drop it onto the Texture slot. In the Scene Tab select both the Icon and the Number nodes. Click the Layout menu in the toolbar at the top of the viewport and select Full Rect. Both nodes will update to fit the size of the Background.

../../_images/ui_gui_step_tutorial_counter_design_2.png

The nodes anchor to the entire Background, but their position is off

Let’s change the Number’s align properties to move it to the left and center of the Background. Select the Number node, change its Align property to left and the VAlign property to centre. Then resize its left edge a little bit to add some padding between the left edge of the Background and the text.

../../_images/ui_gui_step_tutorial_counter_design_3.png

Узел Number выравнивается по центру слева

Чтобы перекрывать иконку и фон, нам нужно кое-что подправить. Во-первых, наш фон несколько высокий. Это потому, что он находится внутри MarginСontainer’a, который контролируется самым верхним узлом GUI. Выберите узел GUI в верхней части дерева сцены и уменьшите его по вертикали так, чтобы он был как можно тоньше. Вы увидите, что датчик мешает вам сделать его слишком маленьким. Родительский контейнер не может быть меньше минимального размера его дочерних. Поля контейнера также учитываются.

Select the Icon, click the Layout menu, and select Full Rect to re-center it. We need it to anchor to the Background’s right edge. Open the Layout menu again and select Center Right. Move the icon up so it is centered vertically with the Background.

../../_images/ui_gui_step_tutorial_counter_design_4.png

Иконка бомбы крепится к правому краю фона. Измените размер контейнера Counter, чтобы увидеть как узел Icon прилипает к его правой стороне

Поскольку мы продублировали Counter как Count, шрифт узла Number сломался. Снова выберите узел Number, перейдите к свойству Font и щелкните по нему, чтобы получить доступ к DynamicFont. В разделе Extra Spacing измените значение Bottom на 0, чтобы сбросить шрифт. Теперь наш счетчик работает, как должен.

Let’s make the Counters anchor to the right edge of the viewport. To do so, we need to set the Bars container take all the available horizontal space it can. Select the Bars node and scroll down to the Size Flags category. In the Horizontal category, check the Expand value. The Bars node should resize and push the counter to the right side of the screen.

../../_images/ui_gui_step_tutorial_counter_design_5.png

Расширяясь контейнер забирает все пространство, которое он может взять от своего родителя, толкая все остальные объекты

Turn the bar and counter into reusable UI components

У нас есть одна шкала и один счетчик. Но нам нужно по два. Нам придется изменить конструкцию шкал или их функциональность. Было бы замечательно, если бы мы могли иметь одну сцену для хранения UI шаблона, и дочерние сцены для работы над вариациями нашего интерфейса. Godot позволяет нам делать это с помощью наследования сцен.

Let’s save both the Counter and the Bar branches as separate scenes that we’ll reduce to create the LifeBar, the EnergyBar, the BombCounter, and the EmeraldCounter. Select the Bar HBoxContainer. Right click on it and click on Save Branch as Scene. Save the scene as Bar.tscn. You should see the node branch turn it to a single Bar node.

Совет

A scene is a tree of nodes. The topmost node is the tree’s root, and the children at the bottom of the hierarchy are leaves. Any node other than the root along with one or more children is a branch. We can encapsulate node branches into separate scenes, or load and merge them from other scenes into the active one. Right click on any node in the Scene dock and select Save Branch as Scene or Merge from Scene.

Then, select the Counter node and do the same. Right click, Save Branch as Scene, and save it as Counter.tscn. A new edit scene icon appears to the right of the nodes in the scene tree. Click on the one next to Bar to open the corresponding scene. Resize the Bar node so that its bounding box fits its content. The way we named and placed the Control nodes, we’re ready to inherit this template and create the life bar. It’s the same for the Counter.

../../_images/ui_gui_step_tutorial_bar_template_scene.png

Без каких-либо лишних изменений, наша шкала готова к использованию

Use scene inheritance to create the remaining elements

Нам нужны две шкалы, которые работают одинаково: они должны иметь Label слева, с некоторым значением и горизонтальным счетчиком справа. Единственная разница заключается в том, что один имеет HP Label и он зеленый, а другой называется EP и он желтый. Godot дает нам мощный инструмент для создания шаблонов для повторного их использования для всех шкал в игре: Наследование Сцен.

../../_images/gui_step_tutorial_gui_scene_hierarchy.png

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

On an inherited scene, you can change any property of every node in the inspector, aside from its name. If you modify and save the parent scene, all the inherited scenes update to reflect the changes. If you change a value in the inherited scene, it will always override the parent’s property. It’s useful for UIs, as they often require variations of the same elements. In general, in UI design, buttons, panels etc. share a common base style and interactions. We don’t want to copy it over to all variations manually.

Рядом со свойствами, которые вы переопределяете, появится значок перезагрузки. Щелкните его, чтобы сбросить значение на по-умолчанию родительской сцены.

Примечание

Подумайте о наследовании сцены, как о древе узлов, или ключевом слове в GDScript``extends``. Унаследованная сцена делает все, как и ее родительский элемент, но можно переопределить свойства, ресурсы и добавить дополнительные узлы и скрипты для расширения функциональности.

Наследование Bar для создания шкалы здоровья

Перейдите к Сцена -> Новая Унаследованная сцена`, чтобы создать новый тип ``Bar. Выберите сцену Bar и откройте ее. Вы должны увидеть новую [несохраненную] вкладку, которая, такая же как ваш Bar, но со всеми узлами, кроме корневой сцены в сером цвете. Нажмите Ctrl+S для сохранения Новой Унаследованной сцены и назовите ее LifeBar.

../../_images/ui_gui_step_tutorial_inherited_scene_parent.png

Нельзя переименовать серые узлы. Это говорит вам, что у них есть родительская сцена

First, rename the root or top level node to LifeBar. We always want the root to describe exactly what this UI component is. The name differentiates this bar from the EnergyBar we’ll create next. The other nodes inside the scene should describe the component’s structure with broad terms, so it works with all inherited scenes. Like our TextureProgress and Number nodes.

Примечание

If you’ve ever done web design, it’s the same spirit as working with CSS: you create a base class, and add variations with modifier classes. From a base button class, you’ll have button-green and button-red variations for the user to accept and refuse prompts. The new class contains the name of the parent element and an extra keyword to explain how it modifies it. When we create an inherited scene and change the name of the top level node, we’re doing the same thing.

Дизайн шкалы Энергии

Мы уже создали дизайн LifeBar'a с главной сценой``Bar``. Теперь нам нужно сделать EnergyBar.

Давайте создадим новую унаследованную сцену и еще раз выбираем сцену Bar.tscn и откроем ее. Дважды щелкните на корневой узел Bar и переименуйте его в EnergyBar. Сохраните новую сцену как EnergyBar.tscn. Мы должны заменить текстуру HP на EP, и изменить текстуры на шкале.

Направляйтесь к панели файловой системы слева, выберите узел Title в дереве сцены и перетащите файл label_EP.png на слот текстуры(texture). Выберите узел Number и измените его свойство Text на другое значение, например 14.

Вы заметите, что текстура EP меньше, чем HP. Мы должны обновить размер шрифта у Number'ов, чтобы он был более подходящим. Шрифт — это ресурс. Все узлы во всем проекте, в которых используется этот ресурс, будут затронуты любым изменяемым свойством. Вы можете изменить размер на огромное значение, к примеру 40 и переключитесь обратно в сцену LifeBar или Bar. Вы увидите, что текст увеличился в размерах.

../../_images/ui_gui_step_tutorial_design_EnergyBar_1.png

Если мы изменим ресурс шрифта, все используемые им узлы будут затронуты

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

../../_images/ui_gui_step_tutorial_design_EnergyBar_2.png

Используйте этот параметр для создания уникальных копий ресурсов для одного узла

Совет

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

Scroll down to the Custom Font section and open Font. Lower the Size to a smaller value like 20 or 22. You may also need to adjust the Bottom spacing value to align the text’s baseline with the EP label on the left.

../../_images/ui_gui_step_tutorial_design_EnergyBar_3.png

Счетчик EP, с меньшим шрифтом, чем его аналог HP

Теперь выберите узел TextureProgress. Перетащите файл energy_bar_bg.png в слот Under и сделайте то же самое для energy_bar_fill.png и поместите его на слот текстуры Progress.

You can resize the node vertically so that its bounding rectangle fits the gauge. Do the same with the Count node until its size aligns with that of the bar. Because the minimal size of TextureProgress is set based on its textures, you won’t be able to downsize the Count node below that. That is also the size the Bar container will have. You may downscale this one as well.

Последнее, но самое важное. Контейнер Background имеет свойство, задающее минимальный размер. Текущее значение делает элемент немного великоватым. Выберите этот элемент и в разделе Rect измените свойство ``Min Size на 80 пикселей. Размер элемента, а также позиции Title и Number должны измениться автоматически.

../../_images/ui_gui_step_tutorial_design_EnergyBar_4.png

Теперь счётчик выглядит лучше потому-что стал меньше

Совет

The Count node’s size affects the position of the TextureProgress. As we’ll align our bars vertically in a moment, we’re better off using the Counter’s left margin to resize our EP label. This way both the EnergyBar’s Count and the LifeBar’s Count nodes are one hundred pixels wide, so both gauges will align perfectly.

Prepare the bomb and emerald counters

Давайте теперь позаботимся о счетчиках. Перейдите к Сцена -> Новая Унаследованная Сцена и выберите Counter.tscn в качестве базового. Также переименуйте корневой узел на BombCounter. Сохраните новую сцену как BombCounter.tscn. На этом работа с этой сценой завершена.

../../_images/ui_gui_step_tutorial_design_counters_1.png

The bomb counter is the same as the original Counter scene

Go to Scene -> New Inherited Scene again and select Counter.tscn once more. Rename the root node EmeraldCounter and save the scene as EmeraldCounter.tscn. For this one, we mainly need to replace the bomb icon with the emerald icon. In the FileSystem tab, drag the emeralds_icon.png onto the Icon node’s Texture slot. Icon already anchors to the right edge of the Background node so we can change its position and it will scale and reposition with the EmeraldCounter container. Shift the emerald icon a little bit to the right and down. Use the Arrow Keys on the keyboard to nudge its position. Save, and we’re done with all the UI elements.

../../_images/ui_gui_step_tutorial_design_counters_2.png

The emerald counter should look something like this

Add the UI components to the final GUI

Пришло время добавить все элементы интерфейса, на предназначенную для них сцену. Откройте сцену GUI.tscn и удалите узлы Bar и Counter`. В доке FileSystem (Файловая Система) найдите ``LifeBar.tscn и перетащите на контейнер Bars, который должен находиться в дереве сцены. Сделайте тоже самое и для элемента EnergyBar. Вы должны разместить их вертикально.

../../_images/ui_gui_step_tutorial_assemble_final_gui_1.png

LifeBar и EnergyBar выравниваются автоматически

Now, drag and drop the BombCounter.tscn and EmeraldCounter.tscn scenes onto the Counters node. They’ll resize automatically.

../../_images/ui_gui_step_tutorial_assemble_final_gui_2.png

The nodes resize to take all the available vertical space

To let the EmeraldCounter and BombCounter use the size we defined in Counter.tscn, we need to change the Size Flags on the Counters container. Select the Counters node and unfold the Size Flags section in the Inspector. Uncheck the Fill tag for the Vertical property, and check Shrink Center so the container centers inside the HBoxContainer.

../../_images/ui_gui_step_tutorial_assemble_final_gui_3.png

Теперь оба счетчика имеют правильный размер

Совет

Измените свойство Min Size у контейнера Counters для управления высоты фона у счетчиков.

We have one small issue left with the EP label on the EnergyBar: the 2 bars should align vertically. Click the icon next to the EnergyBar node to open its scene. Select the Count node and scroll down to the Custom Constants section. Add a Margin Left of 20. In the Rect section set the node’s Min Size back to 100, the same value as on the LifeBar. The Count should now have some margin on the left. If you save and go back to the GUI scene, it will be aligned vertically with the LifeBar.

../../_images/ui_gui_step_tutorial_assemble_final_gui_4.png

2 шкалы идеально выравниваются

Примечание

We could have set up the EnergyBar this way a few moments ago. But this shows you that you can go back to any scene anytime, tweak it, and see the changes propagate through the project!

Размещение интерфейса на макете игры

Чтобы завершить обучение мы вставим GUI на сцене макета игры.

Отправляйтесь в панель файловой системы и откройте LevelMockup.tscn.

Перетащите сцену GUI.tscn прямо под узел bg и выше Characters. GUI будет масштабироваться по размеру видового экрана. Направляйтесь в меню «Макет» и выберите опцию Center Top, чтобы она привязалась к верхнему краю окна. Теперь измените размер GUI, чтобы сделать его как можно более маленьким по вертикали. Теперь вы можете увидеть, как интерфейс выглядит в самой игре.

Congratulations for getting to the end of this long tutorial. You can find the final project here: ui_gui_design.zip.

../../_images/ui_gui_design_final_result.png

Окончательный результат

Примечание

A final note about Responsive Design. If you resize the GUI, you’ll see the nodes move, but the textures and text won’t scale. The GUI also has a minimum size, based on the textures inside of it. In games, we don’t need the interface to be as flexible as that of a website. You almost never want to support both landscape and portrait screen orientations. It’s one or the other. In landscape orientation, the most common ratios range from 4:3 to 16:9. They are close to one another. That’s why it’s enough for the GUI elements to only move horizontally when we change the window size.