Серия «Мобильный геймпад»

2

Мобильный геймпад на Godot. Часть 3: Сервер, клиент, Broforce

Серия Мобильный геймпад

Чтож, вот и финал. Спустя клиента на Godot, который может отправлять данные о нажатия, нужен сервер - для приема и отправки на ViGem.

Сервер

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

  • get_ip - функция получения текущего ip сервера. ip назначается маршрутизатором, потому может меняться и желательно знать актуальный ip для того, чтобы показать его клиенту;

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

Так как способ отправки данных из прошлой части имеет нюанс - Json объект может отправляться кусками, то на сервере мы его собираем: строки 105, 130-134. То есть собираем данные пока не получим символ } - конец объекта.

Функции left_joystick_float, right_joystick_float, press_button и release_button встроены в библиотеку vgamepad, которую можно спокойно установить через pip. И все. Сервер принимает данные, смотрит какая метка в j_data['M']:

  • LJ - левый стик;

  • RJ - правый стик;

  • P - кнопка нажата;

  • U - кнопка отжата.

Остальные данные это координаты стика или же конкретная кнопка. Дальше данные передаются драйверу. На этом магия кончается.

Заключение

Написание такого рода материала для меня хороший способ поднять мою ленивую жэпу и поделать какие-то дела, напрячь мозг хоть немного. Ещё так удобно закреплять знания в голове. Для меня сплошные плюсы, а вам... может узнали что-то новое. Честный обмен :) Д-а-а-а, там еще есть части с экспортом в apk, установками sdk, настройками окна в проекте, но опять же это все для формата туториала, чем данный цикл статей, увы, не является. Теперь, как и обещал, ссылка на полный код. Хотел на git, но потом решил на ЯндексДиск скинуть сразу и готовый apk, если не хотите собирать самостоятельно, и код и драйвер.

Ссылка на видео с игрой в Broforce на таком вот импровизированном геймпаде, на случай, если вам кажется игра на этом деле невозможной.

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

Показать полностью 2
2

Мобильный геймпад на Godot. Часть 2: Сцены, Json, Сеть

Серия Мобильный геймпад

Введение

Продолжаю небольшой цикл с рассказом о том, как я делал из своего телефона геймпад, чтобы просто поиграть с друзьями в Broforce на ноутбуке. Сегодня поговорим о переключениях между сценами, чтению и записи в json-объект и передачу данных по сети.

Json

После первой + 1.5 статей у нас есть сцена с кнопками. Её мы назначим главной, чтобы при запуске приложения она нас сразу встречала после запуска программы. Теперь создадим сцену с настройками. В этот раз это будет узел Control, вместо Node2D, потому что в Control входят так нужные нам строки с записью текста. Зависимости такие:

  • Menu - узел Control содержащий все элементы

  • IP_line - узел LineEdit, строка куда пользователь впишет IP адрес

  • PORT_line - узел LineEdit, строка куда пользователь впишет порт

  • Save_data - узел Label, строка с текстом-статусом выполнения

  • buttons - Node2D узел, включающий в себя кнопки TouchScreenButton. Подтверждение введенных данных и возвращение на предыдущую сцену, соответственно.

Получить данные, которые пользователь будет писать в строках IP_line и PORT_line довольно просто, буквально две строки.

  • @onready var input_ip = $IP_line

  • @onready var input_port = $PORT_line

Создадим функцию для обработки события нажатия OK_buttons. Можете сделать это быстро нажав на кнопку->узел->двойное нажатие по событию pressed() (нажата)

Программа попросит выбрать к кому будет привязана кнопка - выбираем скрипт нашего "меню".

data - наш Json объект. Json в целом очень удобный формат хранения данных, представляющий из себя список словарей. То есть множество из пар вида КЛЮЧ: ЗНАЧЕНИЕ. Либо один единственный словарь, как в нашем случае. data содержит два поля ip и port. Значение пользователя получаем через ранее созданные input_ip и input_port, добавим к каждому .text - уточняем, что мы хотим получить текст из узла LineEdit.

Открываем файл на запись (FileAccess.WRITE) через встроенный FileAccess.open, проверяем, что файл получилось открыть или создать (если файла не было, он автоматически будет создан), и записываем туда данные. Остальное, надеюсь, в комментариях не нуждается, да и в целом подробное описание каждого чиха лучше ощущается в видео формате.

Чуть не забыл о Label! Подключим его строкой:

  • @onready var savedata_result := $Save_data

Функция _ready сработает сама при первом заходе в сцену. Она спрячет на Label, так как пользователь его видеть не должен. Та самая заглушка которую можно было видеть выше, будет скрыта если запустить приложение. Функция show_message принимает два параметра - сообщение, и Label, который должен выйти из скрытности и показать сообщение. Реализовал так, чтобы не приходилось писать под каждый отдельный Label свою функцию. Теперь, когда будет нажата кнопка ОК, под строками покажется сообщение-статус.

Сцены

Для кнопки BACK_button - возвращения на предыдущую сцену - все куда проще:

  • get_tree().change_scene_to_file("res://Controller/controller.tscn")

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

Сеть

В сцене контроллер для подключения к серверу я сделал функцию connect_to_server, но само подключение осуществляется через встроенную connect_to_host. Чтобы ей пользоваться необходимо создать объект StreamPeerTCP

  • var peer : StreamPeerTCP = StreamPeerTCP.new()

Замечательно, теперь можем подключаться к TCP-серверам. Но это ещё не все.

Чертов poll. На самом деле не помню как точно обнаружил эту ошибку, но крови она мне выпила много. Дело в том, что в официальной документации на StreamPeerTCP забыли уточнить, что сервер желательно пинать, чтобы подключение не было отрублено. С одной стороны - логично. С другой - начинающий хлеб об этом не думает. _process ещё одна функция/фича Godot. Функция выполняется на фоне и делает это постоянно. Таким образом, если в теле оставите .poll и проверку статуса подключения (строки 39 и 40), то будет вам счастье. Строки с 41 по 44 были когда-то нужны для отладки - смотрел прием данных с сервера. Кто знает, когда пригодится.

Хорошо, подключили, как отправить данные? Тут на помощь приходят функции начинающиеся на put_ и также входящие в StreamPeerTCP. Чтобы было чуть понятнее, вот пример использования:

  • peer.put_utf8_string(message)

Таким образом отправляется сообщение в формате UTF-8. Это довольно примитивный уровень, но для закрытия текущей задачи его хватает.

Заключение

Чтож, следующая статья будет последнее. В ней я немного расскажу о том, как устроил сервер и ещё немного об обработке нажатий. Там же будет ссылка на исходные коды на финальные версии сервера/клиента. К сожалению, исходя из последних новостей, в новых версиях ОС для мобильников хотят полностью запретить возможность установки сторонних приложений, а значит собрать на дому и "поиграться" становится все меньше и меньше возможностей.

Показать полностью 6
1

Мобильный геймпад на Godot. Часть 1.5: Кнопки - Бонус

Серия Мобильный геймпад

Один хороший человек указал на довольно грубую ошибку с моей стороны. Я умудрился обложиться костылями пока делал кнопки. А все из-за банальной невнимательности.

Все это время у TouchScreenButton был чертов Shape2D! А значит области можно было назначить в одном узле и не городить кучу зависимостей. В общем настало время убрать за собой мусор.

Расположение элементов

Но начнем мы издалека. Представим, что мы очень ленивые люди ( мне и представлять не надо, родился с преимуществом, хех ). Нам нужно переместить кнопки нашего мобильного контроллера. И вот незадача - опять высчитывать пиксели, чтобы кнопки стояли ровно, по уровню. Можно ли как-то решить эту проблему? И да и нет. Дело в том, что узел Node2D и его дочки не дает таких возможностей. Данная привилегия осталась у узла Control. В обычной ситуации создается дочерний узел из состава Container (входит в Control). Одни позволяют выстраивать элементы по диагонали, другие по вертикали и так далее. Такие дочерние узлы - контейнеры - не видят элементы из состава Node2D. И вот тут в дело вступает магия костылей! Мое любимое.

Если закинуть кнопку, в нашем случае TouchScreenButton, в узел Control, то вы сможете привязать вашу кнопку к контейнеру. В моем случае я выбрал MarginContainer (Left_Buttons и Right_buttons в левой колонке зависимостей) для расстановки кнопок. Много играться не стал, успокоился и на этом. Что-то мне и такого хватило "_"

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

Область обработки

Как уже сказал, у узла/кнопки TouchScreenButton есть встроенный Shape2D (@_@), благодаря которому можно и без Area2D сузить область обработки нажатия.

И да, в TouchScreenButton заодно встроены сразу поля для текстур состояний нажатия и ожидания. Без кода. Зато мы познакомились с Area2D :DDD

Я люблю Paint3D

Такой мини-бонус. К бонусу. Если помните, в прошлой части кнопки из левой половины контроллера были совсе-е-ем другие. Они мне не очень нравились и я сделал свои. Так как я довольно криворукий, пришлось подключать смекалку. Итак. Есть кнопка A - будет треугольником теперь, немного кисточки и заливки из Paint и вуаля.

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

Хочу также обратить ваше внимание на очень удобную функцию "Волшебное выделение", которое позволяет автоматически определять выделяющиеся объекты и вырезать их из фона. Может быть полезно в некоторых ситуациях.

Показать полностью 6
4

Мобильный геймпад на Godot. Кнопки. Часть 1

Серия Мобильный геймпад

Введение

Итак, это мой небольшой... Да на самом деле довольно большой! Рассказ как я делал из своего телефона контроллер. Небольшая предыстория. Решил я сыграть в Broforce с друзьями и тут понял, что если я притащу свой ноутбук с игрой, то поиграть с комфортом мы не сможем - нет столько контроллеров. В mvideo геймпады для xbox или ps стоили около 5 тысяч рублей. Можно было и китайские купить, которые обещали нормально работать при подключение к компьютеру, но... Но отсутствие доверия к качеству и жалось не то что к 5 тысяч, а к 700 рублям удавили возможность покупки на корню. И тут мы задумались, а можно ли сделать собственный мобильный контроллер. Конечно же мы нашли готовые проекты в google play, но они шли с вшитой рекламой и могли начать портить игровой процесс в самый неудобный момент. Так родился интересный проект для реализации. Был ли у меня опыт с Godot? Нет. Разработчик или хотя бы хоть сколько-то программист? Нет. Удивительно, что можно сделать при беспардонном упорстве и наличии гугла. Проект я в итоге сделал. Потом забил на него. А недавно вспомнил! И решил переделать :) Эта и все последующие статьи как раз пересказ процесса ПЕРЕСОЗДАНИЯ мобильного контроллера. Кусочек результата старого проекта ниже:

Зачем вообще переделывать, а не дорабатывать готовое? Я решил серьезно углубиться в Godot и реально сделать свой проект, игру. Ту в которую я бы хотел сыграть. Все же гнаться за мечтой, даже детской, это несколько романтично, возвышено и тупо. Меня устраивает. Старый контроллер имел серьезные проблемы в самой своей базе. Так же его переработка хороший способ убить сразу несколько зайцев. Структура проекта "Контроллер" осталась старой.

  1. Сервер на Python - принимает подключение телефона, получает нажатия и передает их драйверу ViGEmBus. Сервер поддерживает подключение до 4ех человек;

  2. Контроллер на Godot (далее по тексту клиент) - подключается к серверу, передает ему нажатия. Для хобби-прототипа сильно париться не хотелось. У клиента всего 2 сцены - настройки и сам контроллер;

  3. ViGEmBus - драйвер для эмуляции виртуальных игровых контроллеров в операционных системах Windows. К сожалению, поддержка этого чуда прекратилась, и что будет теперь, мне не ясно. Скорее всего рано или поздно настанет момент, когда драйвер перестанет быть совместим с играми или новой версией ОС. Но пока что наслаждаемся.

Чертовы кнопки

Бесплатные картинки для кнопок взял с https://itch.io/game-assets/free/tag-gamepad. Набор приличный, на любой вкус. Со стиками было проще всего - не стал создавать велосипед и загрузил Virtual Joystick от MarcoFazio через AssetLib. А вот кнопки делал через узел TouchScreenButton - в документации Godot этот узел как раз предназначен для обработки на сенсорных устройствах. Загрузил текстуры для кнопок ииии... И границы текстур оказались слегка больше, чем ожидалось.

К стикам это не относится, так как они созданы через другую сущность Control. Пока не забивайте этим голову.

К стикам это не относится, так как они созданы через другую сущность Control. Пока не забивайте этим голову.

В общем Godot правильно определяет границы - я ведь не обрезал прозрачные лишние части. Вроде и черт с ним, но ведь нажатия будут обрабатываться неправильно - в местах пересечений будет срабатывать несколько кнопок. Вариантов была два (по крайней мере о которых я прочитал):

  1. Обрезать кнопки в редакторе убирая пустоты;

  2. Забить на TouchScreenButton и создавать области вручную через Area2D и CollisionShape2D.

Будучи здравомыслящим(?) человеком, я выбрал второй вариант. Чтоб больше страданий было, хех. Если пошагово, то создавалось все это дело следующим образом:

  1. Для 4ех левых кнопок был создан отдельный узел Node2D (CrossButtons1);

  2. Для каждой кнопки создан узел Area2D (UpArea);

  3. Для Area2D были созданы Sprite2D (UPsprite) - отображение кнопки, и CollisionShape2D (для него я уже поленился название выдумывать) - зона обработки нажатия.

Для узла CrossButtons1, в который входят кнопки, добавляем скрипт со следующим текстом:

зашел сюда по быстрому сделать кнопку? Хотел скопировать текст, а тут картинка? Уж прости, картинка красивее текста выглядела.

зашел сюда по быстрому сделать кнопку? Хотел скопировать текст, а тут картинка? Уж прости, картинка красивее текста выглядела.

Строка 4 нужна для привязки функции обработки нажатия к нашей области Area2D (UpArea). Строки 8 и 10 ловят нажатие и отпускание кнопки.
Это все супер, но как будто лень писать подобный код для каждой новой кнопки. Благо, действительно есть способ попроще.

Пробегаемся по всем подузлам нашего Node2D (CrossButtons1), находим те, что принадлежат типу Area2D и подключаемся функцию _on_button_input для обработки всех кнопок в Node2D. Для нашей задачи главное понимать, какая кнопка была нажата - получаем через button.name.

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

Код +- тот же, но добавляем:

  1. Строка 7 - начальное состояние/начальная картинка;

  2. Строки 12 и 15 для переключения состояния/картинки при обработке нажатия.

Заключение

Все что осталось - томная работа по повторению процесса для создания всех нужных кнопок. В следующей части добавлю новую сцену, ввод текста и сохранение данных в json формате. И немного работы сети. У-о-о-т. Спасибо за чтение. Дельные замечания и советы приветствуются, ибо в плане создания подобного я ещё профан.

Показать полностью 6
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества