Как сделать кнопки libgdx
Android Study
СОЗДАНИЕ ПРИЛОЖЕНИЙ
libGDX. Урок 18. Реализация экрана Меню.
libGDX. Урок 18. Реализация экрана Меню.
Реализация экрана Меню
В этом уроке мы создадим экран меню, с которого будет начинаться наши игра при запуске. Для этого необходимо: две кнопки Start и Exit и задний фон. По нажатии кнопки Start пользователь будет перенаправлен на экран игры. По нажатии кнопки Exit приложение будет завершать работу.
Для того, чтобы реализовать экран меню нужно создать новый класс MenuScreen в пакете com.mygdx.basketball:
Введите следующий код в этот класс:
Чтобы реализовать различные экраны, в libGDX существует интерфейс Screen. А так как это интерфейс, то нам самим придется реализовать его методы. Все эти методы аналогичны методам интерфейса ApplicationListener, которым мы пользовались ранее. Но особое внимание уделим методам show() и hide(). Эти методы вызываются, когда экран отображается/активен (show()) или скрыт/ не активен (hide()). Теперь объявим в этом классе необходимые нам переменные:
Мы объявили текстуры и спрайты для заднего фона и кнопок. Так как в нашем интерфейсе отсутствует метод create(), то инициализацию переменных проведём в конструкторе. Для начала инициализируем объекты camera и batch:
Далее инициализируем текстуры и спрайты в этом же конструкторе:
В классе Sprite существует метод setAlpha(), в котором можно осуществить установку прозрачности спрайта. Значения приходятся на диапазон от 0 до 1. Значение 0 делает спрайт полностью прозрачным, а значение 1 делает спрайт полностью непрозрачным. Теперь нужно отрисовать все инициализированные объекты в методе render():
И наконец не забываем про очистку памяти. Добавьте эти строки в метод dispose():
Реализуем переход/переключение между экранами
Мы с вами создали экран меню, но не создали возможность его отображения и возможность перехода между экранами. На данный момент мы не можем вызвать созданный нами только что класс MenuScreen в классе AndroidLauncher (который в свою очередь служит запуском нашего приложения):
Для этого нам потребуется создать новый класс, который будет наследовать (extend) класс Game из API LibGDX. Создайте класс MainGame в пакете com.mygdx.basketball и введите в него следующий код:
Как видно, в методе create() мы вызываем метод setScreen(), чтобы изменить отображаемый в данный момент экран на экран из класса MenuScreen, передав в качестве аргумента его экземпляр.
И вот теперь вы можете в классе AndroidLauncher поменять аргумент в методе initialize():
Если запустить приложение сейчас, то вы увидите перед собой наш экран меню:
Теперь приступим к реализации переходов/переключений между экранами. Для начала нам необходимо отредактировать класс BasketBall так, чтобы у нас появилась возможность вызвать его с экрана меню. Вместо наследования (extend) ApplicationAdapter нужно унаследовать интерфейс (implements) Screen:
Теперь добавьте недостающие методы, используя помощь Android Studio
После чего удалите все вызовы super в реализованных методах, метод create() сделайте конструктором. Также придется сделать редакцию в сигнатуре (объявлении) метода render():
Можете сравнить то, что получилось у вас с тем, что должно быть:
Теперь в классе MenuScreen объявим экземпляр класса MainGame. Это нам понадобится для того, чтобы у нас появилась возможность вызывать необходимый нам метод setScreen() для переходов/переключений между экранами. Также добавим параметр в конструктор класса MenuScreen, чтобы устанавливать необходимый нам экземпляр класса MainGame:
Дополнительно нужно модифицировать строку в методе create() класса MainGame, где мы устанавливаем вызов нужного нам класса:
Далее обработаем касания по кнопкам. Объявим временный вектор в классе MenuScreen для хранения входных координат:
Теперь добавим метод handleTouch() в класс MenuScreen, в котором будем обрабатывать касания по экрану меню:
В этом методе, после того, как было произведено касание по экрану, мы проверяем сначала было ли это касание по кнопке Start. Если пользователь коснулся кнопки Start, то методом setScreen() мы переносим его на экран игры. Если же пользователь коснулся кнопки Exit, то будет выполнен выход из приложения. Вызов метода handleTouch произведём в методе render():
Метод dispose(), служащий нам для освобождения ресурсов, вызовем в методе hide(), так как он не вызывается фреймворком автоматически. Когда мы переключаемся с одного экрана на другой, метод hide() вызывается для первого экрана:
LibGDX + Scene2d (программируем на Kotlin). Часть 1
И снова здравствуйте. По результатам прошлой публикации, я пришел к выводу что опять совершаю ошибки. Высокие темп публикации неудобен ни мне, ни вам. И попробую еще подсократить теорию, но приводить больше примеров кода.
Небольшое лирическое отступление. LibGDX в значительной части представляет из себя простую обертку над OpenGL. Просто работа с текстурами. Все что мы делаем — это указываем порядок и способ отрисовки текстур. Базовый инструмент для рисования текстур — Drawable.
Drawable
Drawable, это такая штука, которая встречается в Scene2d буквально на каждом шагу. Картинки, кнопки, фоны элементов, всякие элементы слайдеров, панелей прокруток и т.д. — все они используют Drawable для отображения себя на экране. С практической точки зрения, нас не сильно заботит как он устроен внутри. Потому что работать мы будем с тремя конкретными реализациями Drawable. Это TextureRegionDrawable, TiledDrawable и NinePatchDrawable. Вот текстура которую мы хотим нарисовать на экране:
Первый вариант — TextureRegionDrawable. Он просто растягивает текстуру под заданные координаты. Второй вариант — TiledDrawable. Текстура повторяется множество раз, при этом масштаб не меняется. И третий вариант, это 9-Box или 9-Patch. Чем же он хорош и когда его следует использовать?
9-Patch сохраняет внешние элементы в том виде, в котором они определены вне зависимости от размера центрального объекта. Широко используется для кнопок, диалоговых окон, панелей и т.п. Представьте если бы у одной панели внешняя рамка была бы в 2 раза толще или тоньше чем соседняя.
Table Layout
Как я упоминал вчера, сцена это иерархический набор элементов (потомки класса Actor). Все акторы делятся на две группы — Widget и WidgetGroup. Widget это листья дерева, которые не могут содержать дочерних элементов. WidgetGroup — это узлы. То есть все их различие заключается в том, что WidgetGroup умеют «раскладывать» дочерние элементы в определенном порядке. Все обучение Scene2d сводится к умению комбинировать эти объекты. К примеру кнопка в LibGDX это WidgetGroup, наследник Table. Она может содержать и текст, и изображение. Ну и любую другую верстку как любая другая таблица.
Код использует Атлас Текстур/Шкурки для улучшения читаемости. Как настраивать лучше посмотреть в репозитории. Описывать принципы их работы это на целую отдельную статью.
Что мы видим в коде:
Самая распространенная ошибка: забыть добавить setFillParent(true) в корневой элемент
Тот же пример на java
Самое важное отличие — отсутствие форматирования кода согласно логике вложения. Вся портянка элемента выровнена по левому краю и очень легко запутаться, т.к. большинство методов общие на уровне Widget/WidgetGroup.
Методы разметки таблицы
add — добавляет ячейку в ряд. Возвращает Cell к которому можно применять модификаторы
row — добавляет row. Возвращает default Cell для ряда. Модификаторы, примененные к default Cell будут автоматически применены ко все ячейкам этого ряда.
expand/expandX/expandY — «пружинки». Меняют размер ячеек (но не содержимого). По умолчанию содержимое ячеек расположено в центре
width/height — задает размер ячейки фиксировано или в процентном соотношении.
fill/fillX/fillY — заставляет содержимое ячейки принять размер ячейки
left/right/top/bottom — если содержимое ячейки меньше размеров, указывает способ выравнивания
Делаем верстку первого экрана:
Я сделал набор иконок которые поясняют примененные модификаторы к ячейкам
Пружинки — expand/expandX/expandY (раздвигают ячейку)
Стрелки — fill/fillX/fillY (содержимое ячейки заполняет ячейку)
Швеллер — фиксированный размер ширины/высоты (фиксирует размеры ячейки по ширине/высоте)
Container<> Layout
Контейнер может иметь только один Widget. Имеет Drawable background. Поэтому мы будем использовать его чтобы нарисовать на экране header и footer (панель ресурсов/командная панель).
Верстка Loading Screen
Попробуем подойти аналогичным образом к верстке загрузочного экрана:
Вроде даже работает. Но работает не так как нам хотелось бы. Проблема заключается в том, что устройства с разным соотношением сторон будут плющить или растягивать текстуру. Как же будет правильно?
Допустим вот такой вариант. Мы используем изображение, и говорим что масштабировать его надо сохраняя пропорции до тех пор пока меньшая сторона упрется в край. При этом большая сторона будет обрезана. Другой вариант — Scaling.fit. Масштабирование будет идти пока большая часть не упрется в край, меньшая часть будет иметь незаполненные участки (letterbox).
Но что делать если мы, к примеру, хотим разместить Progress Bar где-то в 20% пространства снизу и чтобы он занимал 60% экрана. Никто не запрещает добавить в сцену несколько actor’ов верхнего уровня. Будет так:
На этом на сегодня все. Пожалуйста оставляйте комментарии что бы вы хотели увидеть более подробно и/или предложения как улучшить подачу материала.