Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Управляйте маятником, чтобы построить самую высокую (и устойчивую) башню из падающих сверху постов. Следите за временем на каждый бросок по полоске справа: если она закончится, пост упадет мимо башни.

Башня

Аркады, Строительство, На ловкость

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • SergeyKorsun SergeyKorsun 12 постов
  • SupportHuaport SupportHuaport 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня

Gamedev + Программирование

С этим тегом используют

Инди Разработка Инди игра Игры Unity Компьютерные игры YouTube IT Программист IT юмор Python Картинка с текстом Юмор Все
632 поста сначала свежее
0
MiheevSanity
MiheevSanity
2 года назад
Лига Разработчиков Видеоигр
Серия Zealous Sanity

Серия 0.13 Строительство, устройство, пистолет⁠⁠

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

[моё] YouTube Программирование Gamedev Unreal Engine 4 Видео
4
22
GrimmIronwill
GrimmIronwill
2 года назад
Лига Разработчиков Видеоигр
Серия Gamemaker Studio 2: серия гайдов

GameMaker Studio 2. Урок 6. Алгоритмы поиска путей. Оптимизация игры⁠⁠

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

Сразу оговорюсь, что многое из того, что вы будете видеть - это моя адаптация того, что можно было свободно найти в интернете, в том числе скрипты. Я не являюсь их создателем или первооткрывателем, а потому везде будут присутствовать ссылки на те источники, что я использовал сам в своё время.
Может, вам их будет проще понять :)


Ссылки на предыдущие гайды:

Первый гайд - Знакомство.

Второй гайд - События отрисовки, коллизия, скрипты.

Третий гайд - Камера и разрешение экрана.

Четвертый гайд - Иерархия объектов. Глобальные переменные.
Пятый гайд - Структуры данных. Сетка комнаты и размещение объектов по сетке.

Оглавление:
- Поиск путей. Что это и как работает?
- Встроенные средства для работы с путями.
- Алгоритмы поиска путей. Какие существуют?
- Алгоритмы поиска путей. Скрипты.
- Оптимизация. Что это и зачем?
- Оптимизация. Исправляем ошибки и учимся их избегать.

Поиск путей. Что это и как работает?

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

Итак, представим сетку комнаты, которую мы делали ранее. Это набор точек, каждая из которых имеет собственные координаты.
Так как сетка у нас квадратная, то каждая точка, кроме крайних, имеет четыре (восемь, если учитывать диагонали) "соседей". Таким образом, из одной точки мы можем попасть в любую соседнюю.
Любой алгоритм поиска путей занимается тем, что пытается попасть из точки А в точку Б, перебирая соседние клетки. Занимая соседнюю клетку, он проходится по её "соседям" и так до тех пор, пока не будет достигнута точка конца или не кончатся "соседи".
На самом деле, необязательно иметь именно квадратную сетку, чтобы поиск путей работал, ведь поиск путей, по своей сути, работает на более высоком уровне: графах.

Граф - это модель, состоящая из множества вершин и множества соединяющих их рёбер.
Ниже - пример графа из заданий по информатике на экзаменах.

GameMaker Studio 2. Урок 6. Алгоритмы поиска путей. Оптимизация игры Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Игры, Стратегия

Таким образом, любая сетка - это лишь определённое представление графа.

Встроенные средства для работы с путями.

Для работы с путями в GMS 2 существует ряд функций, которые начинаются с приписки: mp, которая расшифровывается как планирование движения (motion planning), а также path.
Чтобы была возможность строить пути, прежде всего нужно создать сетку комнаты. Для этого существует команда:

global.grid_mp = mp_grid_create(0, 0, cells_x, cells_y, CellWidth, CellHeight)
Где cells_x, cells_y - количество сеток по осям x, y, а CellWidth и CellHeight - ширина и высота одной клетки.

После создания сетки комнаты, вам остаётся только задать две точки и вы уже сможете строить между ними пути. В step событии любого объекта создайте скрипт, чтобы устанавливать эти точки, а затем в draw событии напишите следующий код:
var new_path = path_add()
var mp_path = mp_grid_path(global.grid_mp, new_path, fcell_coords[0] * CellWidth + 16, fcell_coords[1] * CellHeight + 16, scell_coords[0] * CellWidth + 16, scell_coords[1] * CellHeight + 16, 1)
if mp_path
{
draw_path(new_path, fcell_coords[0] * CellWidth + 16, fcell_coords[1] * CellHeight + 16, false)
}
Где fcell_coords и scell_coords - два массива, хранящие клетки по x,y старта и конца соответственно.
Функция path_add() - создаёт путь.
Функция mp_grid_path() строит путь между указанными координатами по сетке. Если путь существует, то возвращает true, иначе - false. Если путь существует, то сохраняет в переменную пути, указанную в скобках, точки, которые предстоит пройти.

Таким образом у вас будет отрисован путь по клеткам.
Чтобы увидеть сетку, нужно написать:
draw_set_alpha(0.25)
mp_grid_draw(переменная_которая_хранит_сетку)
draw_set_alpha(1)
Чтобы добавить на неё препятствия существуют команды:
mp_grid_add_cell() // Закрашивает одну определённую клетку, делая непроходимой.
mp_grid_add_instances()  // Закрашивает все клетки, на которых расположены определённые объекты.
mp_grid_add_rectangle() // Закрашивает определённую прямоугольную область.
Создать путь - это только первый шаг. Второй - это запустить по нему объект двигаться. Для этого есть функция:
path_start(путь, скорость, что_сделать_в_конце_пути, абсолютный_путь_или_к_текущей_позиции)
Всё. Так легко и просто можно создать сетку, расположить на ней непроходимые объекты и строить пути между точками, в последствии их запуская.

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

Алгоритмы поиска путей. Какие существуют?

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

Жадный алгоритм.
Суть данного алгоритма отражена в его названии. На каждом шаге он делает наилучший на данный момент выбор. То есть, всегда двигается по самым "дешёвым" вершинам графа, пока в итоге не будет достигнута точка конца.

Поиск в ширину.

Это рекурсивный алгоритм поиска всех вершин графа или дерева. Обход начинается с корневого узла и затем алгоритм исследует все соседние узлы. Затем выбирается ближайший узел и исследуются все неисследованные узлы.
Сам алгоритм:
1. Перейдите на соседнюю нерассмотренную вершину. Отметьте как рассмотренную. Отобразите это. Вставьте ее в очередь.
2. Если смежная вершина не найдена, удалите первую вершину из очереди.
3. Повторяйте шаг 1 и шаг 2, пока очередь не станет пустой.
Если же говорить своими словами, то данный алгоритм равномерно исследует все доступные точки. Такой алгоритм часто применяется при генерации карт, либо для их исследования. Правда, он не строит пути как таковые. Он просто показывает, как мы можем посетить все точки на карте.
Источник

Алгоритм Дейкстры.
Данный алгоритм находит кратчайшие пути от одной из вершин графа до всех остальных. Работает только для графов без рёбер с отрицательным весом, иными словами - не может работать в тех случаях, когда стоимость клетки отрицательная. Это важно.
Таким образом, суть алгоритма заключается в том, чтобы найти найти все возможные пути из точки А в каждую из других существующих, а затем среди них выбрать самые дешёвые.
Алгоритм действенный и полезный, но достаточно медленный, если речь заходит о поиске пути между двумя конкретными точками. Но, это не беда, ведь существует следующий алгоритм.

Алгоритм A* (A star).
Данный алгоритм является вариацией алгоритма Дейкстры, скрещённого с жадным поиском и эвристическим поиском. То есть, он старается выбирать и самые дешёвые пути, и самые "близкие" к конечной точке.

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

Квадратная сетка.
abs(a[0] - b[0]) + abs(a[1] - b[1]) // a[0],b[0] - координаты по оси x, a[1], b[1] - по оси y. abs возвращает абсолютное (всегда положительное независимо от результата) значение.
Гексогональная сетка.
(abs(qa - qb) + abs(ra - rb) + abs(sa - sb)) / 2 // где q, r, s - это координаты в кубической системе.

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

Алгоритмы поиска путей. Скрипты.

Переходим ко вкусному.
Поиск соседей на квадратной сетке.
***
Алгоритм А* на GML.
Небольшая особенность данного скрипта. Если клетка, в которую мы хотим прийти, является непроходимой, то мы всё равно строим до неё путь. Встать на неё мы всё равно не сможем, но получим ближайший к данной точке путь.
Важно. Работает это только для соседних к конечной клеток.
Как работает:
Если найден, возвращает путь в виде массива между двумя точками. Точки старта и конца должны быть переданы в виде их порядкового номера. Если путь не найден, возвращает noone.
Соответственно, чтобы отрисовать путь - нужно будет пройтись по массиву из точек.

Поиск соседей на гексагональной сетке отличается только координатами. Вместо x и y мы используем q, r, s, которые являются трёхмерным представлением двумерных координат.
col - это столбец, row- это строка. x и y по сути.
q = col
r = row - (col - (col & 1)) / 2
s = -q - r

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

По сути - всё. Дальше стандартно: проверяем, что мы не выходим за границы сетки и если стоимость гекса != 0 (или больше 0), то добавляем его.

Оптимизация. Что это и зачем?

Я думаю, каждый знаком с термином "оптимизация". Если же нет, то вики говорит нам:

Оптимизация — процесс максимизации выгодных характеристик, соотношений (например, оптимизация производственных процессов и производства), и минимизации расходов.
Мы, как разработчики, должны позаботиться об оптимизации игры. Первое, что бросается в глаза - это оптимизация кода. Покрывая наши потребности, он должен при этом быть максимально простым и лёгким, чтобы не давать лишнюю нагрузку на ПК.

Конкретно в случае с GMS, есть некоторые моменты, которые стоит запомнить.
- Используйте локальные переменные.
Вместо того, чтобы постоянно получать результат функции, сохраните его один раз в переменную и используйте её в дальнейшем.
Вместо постоянного обращения к глобальным переменным, сохраните глобальную переменную в локальную и обращайтесь к ней. И так далее. Это быстрее.

- Старайтесь использовать объекты по минимуму.
На фоне предыдущих гайдов это прозвучит несколько странно, ведь мы заполняли комнату объектами полностью. Делалось это с целью теста, не более того.
В нашем с вами случаем, ребята, гораздо быстрее хранить информацию о каждой клетке в массиве, а клетки отрисовывать через тайлмап.
Объект, даже если он занимается только отрисовкой собственного спрайта, нагружает систему больше. Поэтому проще отрисовать спрайт отдельно. Прирост ФПС составит до 6 раз. ( Замерял, выросло с 500 до 2500 в среднем :) )

О том, как это работает и реализацию покажу ниже. :)

- Не рисуйте объекты, которые находятся за границами камеры.
Очевидный, но важный совет, так как draw event является крайне ресурсоёмким, как и step.

- Не делайте проверку коллизий там, где это не нужно. Если делаете, то сохраняйте результат в локальную переменную.

Оптимизация. Исправляем ошибки и учимся их избегать.

Первое, что мы сделаем - это создадим один большой спрайт, на котором разместим все наши игровые спрайты. Важно, чтобы первая клетка была пустой!
Затем - создайте объект Tileset и назначьте ему этот спрайт.
На скриншоте ниже показано, почему первая клетка должна быть пустой.

GameMaker Studio 2. Урок 6. Алгоритмы поиска путей. Оптимизация игры Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Игры, Стратегия

Дальше - создайте слой комнаты типа "Тайл" и назначьте ему тайлсет.

GameMaker Studio 2. Урок 6. Алгоритмы поиска путей. Оптимизация игры Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Игры, Стратегия

Всё, теперь мы готовы использовать вместо объектов - тайлы. Причём сразу для всех видов: и для фона, и для непосредственно отрисовки объектов, и для украшательств: спрайтовых теней.
Теперь в oGrid нужно будет заменить старый код на новый.
Ссылка на код.

Кратко пробежимся по тому, что мы используем и как.
lay_id_blocks = layer_get_id("Название_Слоя") - Здесь мы получаем ID нашего слоя.

var map_id_blocks = layer_tilemap_get_id(lay_id_blocks) - Здесь мы получаем слой тайлов, используя ID слоя.
tilemap_set(map_id_blocks, Tile.ground, _x, _y) - Здесь мы устанавливаем у слоя тайлов, по определённым координатам, определённую картинку. Tile.ground возвращает 1, следовательно будет отрисована первая клетка из нашего тайлсета. Нулевая клетка - пустая, используется для удаления тайлов.
С-но, для получения текущего тайла существует команда tilemap_get(map_id_blocks, клетка_x, клетка_y). Если по указанной позиции установлен тайл, вернёт его номер. Если нет - вернёт ноль. Вернёт -1, если есть ошибка.

Специально не обращаю внимание на то, как пришлось переписывать код, так как по сути изменилось лишь взаимодействие, которое вкратце - описано выше.

Для отрисовки теней используется отдельный слой, где в определённом порядке расположены тени. Это важно, так как используется скрипт для автоматического тайлинга, то есть - автоматического определения того, какую тень нам нужно рисовать.

Ссылка на оригинальный скрипт для интересующихся:
https://github.com/iAmMortos/autotile

Как ускорить проекты, сделанные на Gamemaker Studio 2 под Windows

Здесь есть вся нужная информация. Делается с помощью компиляции под С++.
https://help.yoyogames.com/hc/en-us/articles/235186048-Setti...

Будем прощаться, ребята.

Ссылка на исходник
Там два файла. YYZ - для тех, кто хочет повтыкать в код. В папке - уже скомпилированный проект, для тех, кто просто хочет потыкать и посмотреть, как это всё добро работает.

Темы, которые осталось разобрать:
- Сохранение. Встроенное VS самописное. Работа с файлами.

- Звуки.

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

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

Показать полностью 3
[моё] Разработка Gamedev Программирование Инди Инди игра Gamemaker Studio 2 Образование Длиннопост Урок Игры Стратегия
2
3
Liosik
Liosik
2 года назад
Лига Разработчиков Видеоигр

Как я делаю игру Flappy bird 3d⁠⁠

26 Мая 2022 года я начал разрабатывать 3д породию на некогда популярную игру Flappy bird. В этом посте я раскажу, как проходила(и сейчас проходит) разработка.

После длительного перерыва в разработке игр, я вновь открыл юнити. Предыдущие свои проекты я никогда не доводил до конца, в этот раз я решил не повторять эту ошибку. Чтобы точно довести проект до конца, нужно, чтобы он не был сильно сложным, поэтому я и выбрал Flappy bird. Я создал доску в trello.com и погнал прогать.

Первым делом, я открыл Magica Voxel и используя оригинальную Flappy bird, смоделил птичку. Потом сделал те зеленые трубы и пошел рисовать UI. 2д часть графики я рисовал в программе Krita. Затем я засунул всю графику в игру и принялся писать код птички и спавна труб. Затем добавил меню, экран смерти и партиклы. Потом, под песню Lay all your love on me добавил пост процессинг. Теперь осталось только самое сложное - сделать музон4ик. Я открыл fl studio и начал бить мышку с клавиатурой. Вроде получился биток(Ну если так можно назвать то дeрьмо, которое я сделал).

На данный момент игра на последней стадии разработки. Скоро я возможно выпущу ее в AppGallery и если оооочень повезет - в Google play).

Как я делаю игру Flappy bird 3d Программирование, Unity, Разработка, Android, Android разработка, Игры, Компьютерные игры, Gamedev, Длиннопост
Как я делаю игру Flappy bird 3d Программирование, Unity, Разработка, Android, Android разработка, Игры, Компьютерные игры, Gamedev, Длиннопост
Показать полностью 2
[моё] Программирование Unity Разработка Android Android разработка Игры Компьютерные игры Gamedev Длиннопост
6
3AXAP4EHKO
2 года назад

Синергия и оплата после трудоустройства⁠⁠

Алоха, ребят!

Кароч!
Встретил я на пикабу рекламу Синергии, тип обучайся сейчас бесплатно, а плати после трудоустройства!
В общем я кликнул!
Сегодня связался с менеджером, которая мне рассказала, что все реально так, как в рекламе!
Вроде как у тебя есть пара недель, чтобы решить подходит ли тебе курс,, и если не подходит, то можно отказаться и ни чего не платить. Далее есть условие, что если ты заканчиваешь курс успешно, то тебе подыскивают работу, если за три месяца тебе, при помощи специалистов, не удается найти работу, но ты ни чего не платишь.
А если находишь, то вообще хорошо! Мне нравятся такие условия! Точней, я бы хотел получить работу разработчика, так как уже пару лет изучаю C# и Unity в свободное время!
Ребят, кто что думает об этом предложении?
Я понимаю, что бесплатный сыр только в мышеловке и вообще скептически отношусь ко всем таким обучениям!
Может кто-то уже закончил подобный курс и расскажт свое мнение!

Кароч, хочется делать игры как можно скорей и не хочется прилипнуть на колоссальное бабло!

Договор:
https://drive.google.com/file/d/1fyIHc_u7435A7MQMMo-c0BDanX4...

Вот программа:

https://drive.google.com/file/d/1kiv-mxbDnWhk5YvCASQyztsnySh...

Что думаете?

Показать полностью
Программирование Gamedev Без рейтинга Текст
23
12
Аноним
Аноним
2 года назад

Ищу ментора Unity⁠⁠

На нашем замечательном ресурсе много профессионалов и тех, кто делится своими знаниями по Java, Python, Excel и иже с ним. Может, отыщется кто-то, кто поднаторел в Unity и готов оказывать посильную помощь? Есть ряд вопросов, которые на официальных и околоофициальных форумах не снискали откликов, хотя они не кажутся напрочь неразрешимыми. Возможно, когда-либо в дальнейшем будут попадаться ещё, но обещаю сильно не мешаться под ногами. В команду или в напарники не напрашиваюсь, работу не ищу. С меня любой эквивалент пиццепива или, если таки потребуется, также посильная помощь. Может, это слегка наивно, но все же верю в силу Пикабу.

Unity Unity2d Программирование Игры Разработка Gamedev Помощь Сила Пикабу Инди игра Инди Текст
2
Max13S
2 года назад

Как я сделал игру под Android⁠⁠

Привет пикабу. Я начал осваивать сферу Android разработчики. Изучаю это направления около 10 месяцев. И уже даже успел обзавестись несколькими собственными проектами. Начинал я свой путь с уроков на YouTube и поиска информации на просторах сети. Спустя время начала создавать собственные игры и приложения. Размещаю я их в Google Play. Раньше завести там аккаунт не было проблемой. Платишь 25$, отправляешь паспорт и готово. В новых условиях правила игры изменились. Новый аккаунт из РФ не создать + отключили монетизацию РФ по рекламе и по платным приложения для старых аккаунтов. У меня уже накопилось достаточно много просты проектов, но нужно было что то поинтереснее. Я решил двигаться в сторону головоломок и начал свой путь с игры по поиску слов. Конкуренция в это жанре очень высока и нужно было как-то выделиться. И решение было найдено. Помимо 1100 основных уровней на русском языке, была добавлена возможность создания собственных головоломок из букв и отправки их друзьям для прохождения внутри приложения. Так же добавил переводы на 5 языков(английский, немецкий, французский, португальский, испанский) Количество уровней варьируется в зависимости от языка(Русский-1100, Английский-970, (французcкий, португальский, испанский)-350). Далее пойдут скрины игры на разных языках и ссылка на Google Play, если кому-то понравится буду рад)

Google Play: https://play.google.com/store/apps/details?id=com.max.search...

Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Показать полностью 9
[моё] Разработка Мобильные игры Gamedev Программирование Инди игра Unity Android Инди Игры Игры на Android Головоломка Приложение Приложение на Android Новое Длиннопост История Реклама
6
5
Max13S
2 года назад

Как я сделал игру "Филворды" под Android⁠⁠

Всем привет. Я начинающий Android разработчик. Примерно пол года назад, по совету моего друга, я начал изучать программирование под Android и всё что с этим связанно. Для разработки приложений под Android необходимо знать такие языки как Java и Kotlin, с них я и начал. На первоначальном этапе информации хватает и на русском языке, но чем дальше ты продвигаешься, тем чаше заходишь на англоязычные статьи или видеоролики. Данных по этой теме в сети предостаточно. Google и YouTube могут дать 90% необходимой информации, а если подольше поискать то 100%). В начале пути для понимания всего происходящего я старался писать простые приложения наподобие калькулятора. Спустя время приложения становились всё сложнее и тогда я решил попробовать разместить одно из них в Google Play. Выяснилось что для этого необходимо 1) 25$ (Плата взимается один раз) 2)Скан паспорта 3)Немного времени 3-4 дня, чтобы Google проверил вашу личность. После всех этих шагов вы получаете аккаунт разработчика и можете публиковаться в Google Play. Первые мои 3 игры были жанра "Настольные игры" такие как "Alias", "Правда или действие", "Шпион". Я думаю многие знают их бумажные варианты. Но мне хотелось сделать что то посложнее и интереснее. Выбор пал на Венгерские кроссворды или их ещё называю Филворды. На игровом поле расположены буквы. Необходимо найти слова, выделяя буквы, стоящие рядом, так, чтобы слова целиком заполняли квадрат. Не все, а только загаданные слова подходят для заполнения. Как вы сами понимаете всё очень просто, но с каждым уровнем поиск слов будет даваться все сложнее. Игра усложняется от квадратов 3х3 до 8х8. Также я решил добавить подсказку на случай, если при поиске слова игрок заходит в тупик. Но подобных игр в Google play хватает и нужно было что то особенное. Выбор пал на реализацию создания собственных филвордов и возможности отправить их друзьям для прохождения. + Решил перевести игру на 5 языков(английский, немецкий, французский, португальский, испанский) Количество уровней варьируется в зависимости от языка(Русский-1100, Английский-970, (французcкий, португальский, испанский)-350).  Далее пойдут скрины игры и ссылка на Google Play, если кому-то понравится буду рад)


Google Play: https://play.google.com/store/apps/details?id=com.max.search...

Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Как я сделал игру "Филворды" под Android Разработка, Мобильные игры, Gamedev, Программирование, Инди игра, Unity, Android, Инди, Игры, Игры на Android, Головоломка, Приложение, Приложение на Android, Новое, Длиннопост, История, Реклама
Показать полностью 8
[моё] Разработка Мобильные игры Gamedev Программирование Инди игра Unity Android Инди Игры Игры на Android Головоломка Приложение Приложение на Android Новое Длиннопост История Реклама
1
Партнёрский материал Реклама
specials
specials

Сколько нужно времени, чтобы уложить теплый пол?⁠⁠

Точно не скажем, но в нашем проекте с этим можно справиться буквально за минуту одной левой!

Попробовать

Ремонт Теплый пол Текст
28
GrimmIronwill
GrimmIronwill
2 года назад
Лига Разработчиков Видеоигр
Серия Gamemaker Studio 2: серия гайдов

GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке⁠⁠

Привет! Сегодня разберёмся, что такое массивы и структуры данных. Создадим сетку комнаты, научимся размещать объекты по этой сетке.

P.S. Передаю привет тому человеку, который ставит минусы на всё, что я пишу. Счастья тебе, здоровья.


Ссылки на предыдущие гайды:

Первый гайд

Второй гайд

Третий гайд

Четвертый гайд

Сегодня мы поговорим о следующем:

- Что такое массивы и для чего они нужны? Что такое структуры данных?

- Какие виды структур данных существуют в GMS? Их особенности.
- Реализуем сетку карты.

Что такое массивы и для чего они нужны?

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

Индекс - это порядковый номер элемента в массиве.

Важно знать:

1. Индексы в массивах начинаются с нуля.

2. В массив можно запихнуть массив, в него запихнуть массив и так до бесконечности. Отсюда следует:

2.1. Массив называется одномерным, если в него не вложены другие массивы. Если в массив вложен другой массив, то это уже двумерный массив. Если в массиве есть массив с массивом - трёхмерный. И так далее.

Массив - структура данных. Что такое структура данных?
Структура данных - это "контейнер", который хранит данные в определённом формате. Соответственно, массив - один форматов хранения данных.

Какие виды структур данных существуют в GMS? Их особенности.


Первый структура данных, которую мы разберём называется Array (массив). Его можно создать несколькими способами:

1.array = array_create(10, noone)
2. array = [1, 2, 3, 4] // внутри пишем любые свои значения
3.
array[0] = 1
array[1] = 2

И так далее. Также можно объявить сколько угодно мерный массив:

array[0][0][0][0] = 1.

Такие массивы преспокойно встраиваются в сохранение стандартными средствами GMS. Также здесь в автономном режиме работает "сборщик мусора". И это важно, поскольку в структурах данных (приписка DS) этого нет. Соответственно, их придётся удалять вручную.

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

Structs или структуры.

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

// Create event
mystruct =
{
pos_x : x,
pos_y : y,
count : 1000
};
// Clean Up event
delete mystruct;

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

Обращение к struct для вычленения из него данных похоже на таковое для объектов. Нам нужно назвать структуру, а затем через точку - нужную нам "переменную".

show_debug_message(mystruct.pos_x)

С-но, в каждом значении структуры можно хранить другое значение. Напоминает HTML-код.

mystruct =
{
a :
{
aa : "Example"
},
b :
{
bb : "Another"
},
};

В таком случае, нам нужно будет обратиться к структуре, к значению, а затем к значению внутри значения.

show_debug_message(mystruct.a.aa)

Также для простоты к структуре можно обращаться через with

with(mystruct)
{
a += other.x;
}

Ну и последнее, что стоит сказать. Мы можем использовать функции-конструкторы. Они позволяют создавать новые структуры по шаблону, который будет описан в такой функции.

// Функция-конструктор.
function Vector2(_x, _y) constructor
{
x = _x;
y = _y;
static Add = function(_vec2)
{
x += _vec2.x;
y += _vec2.y;
}
}
// создаем новую структуру
v2 = new Vector2(10, 10);

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

DS Grids или сетки.

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

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

Как создать:

переменная = ds_grid_create(ширина в клетках, высота в клетках)
Ещё раз обращаю внимание, что с помощью DS Grid мы можем назначить каждой клетке отдельное значение. В случае с созданием своего алгоритма поиска путей это означает, что в зависимости от типа местности, алгоритм будет находить наиболее оптимальный путь опираясь на итоговую стоимость пути. Просто как пример.
А ещё сетка используется для создания тех самых "клеток", по которым идёт расположение построек, к примеру.

DS Lists или списки.

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

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

переменная = ds_list_create();
Вставить новое значение:
ds_list_add(переменная, значение)

DS Maps или словари.

Словарь по своей сути похож на struct: он хранит данные в паре "ключ : значение". Если представить это образно, то это две колонки. Первая - это ключ. Второе - значение. Обращаясь к первой колонке, к ключу, мы можем спокойно получить значение. Или получить все ключи по определённому значению.
Мы будем их использовать в следующем гайде, когда будем разбирать пути и будем писать свои функции для их создания.
Способ создания:

переменная = ds_map_create()
Вставить новое значение:
ds_map_add(переменная, ключ, значение)

Мануал рекомендует использовать вместо DS Maps - структуры. Собственно, с ними нам тоже придётся поработать.

DS Queues, DS Priority Queues, DS Stacks

Всё это - "очереди", только по разному работающие. Разберём сначала Stacks и Queues.


Stacks
это структура типа LIFO (last-in-first-out / последним пришёл - первым ушёл). Как и со списками, мы можем "вычленять" последние значения из стаков с помощь команды pop. Особенность LIFO в том, что в таком случае мы получим последнее значение, которое загружали в список.

С Queue ситуация обратная. Там используется FIFO (first-in-first-out / первым пришел - первым ушёл). То есть, забирая значение из queue (очередь), мы получим первое значение, которое вставили.

Важная оговорка. pop - берёт значение из массива, при этом удаляя его из него.

Priority Queue или приоритетная очередь - это та же очередь, но в которой каждое значение имеет свой "вес" - приоритет, что влияет на расположение данных в структуре и позволяет отбирать, скажем, наиболее дешёвые пути. Как говорит мануал, полезно для создания таблиц лидеров или информационных списков. Мы же будем это использовать для написания алгоритма поиска путей А* (A star, А звездочка).

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

Создаём сетку комнаты.

1. У объекта oGameManager пропишем две дополнительные макро переменные, которые будут хранить ширину и высоту одной клетки.

#macro CellWidth 32

#macro CellHeight 32

2. Создадим объект oGrid, который расположим в нашей основной комнате.

3. У этого объекта создадим событие Create, где будем создавать нашу сетку.

3.1. Для наглядности, создадим сетку с помощью команды mp_grid_create
mp в данном случае - это "motion planning" - планирование движения. Система, которая позволяет создать сетку комнаты и сразу же по ней создавать пути, используя встроенные алгоритмы. Они не дают всего необходимого функционала, поэтому этот пункт выполняем исключительно для наглядности.

global.grid = mp_grid_create(0, 0, ceil(room_width / CellWidth), ceil(room_height / CellHeight), CellWidth, CellHeight)

3.1.1. Перейдём в событие Draw, где отрисуем сетку.

draw_set_alpha(0.1)
mp_grid_draw(global.grid)
draw_set_alpha(1)

3.1.2. Зайдём в игру и посмотрим, что получилось.

GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Как видно, у нас получилась квадратная сетка. Используя функции mp_grid_* мы можем закрашивать нашу сетку, делая определённые квадраты непроходимыми. Но мы не можем назначать таким клеткам свою стоимость.
Иными словами, если будет два одинаковых по длине пути, но один через условные зыбучие пески, а второй по асфальту, то получим 50/50, что персонаж выберет медленный и потенциально опасный путь, просто потому что мы не можем указать, какой из путей будет приоритетнее.

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

3.2. Удаляем или комментируем то, что мы написали. Сейчас будем работать со структурами данных.
3.2.1. Создаём сетку через ds_grid_create в событии create

var cells_x = ceil(room_width / CellWidth)
var cells_y = ceil(room_height / CellHeight)
global.grid = ds_grid_create(cells_x, cells_y)

Ок. По сути, сетка готова. Теперь по ней мы можем создавать объекты. Давайте же заполним всю нашу комнату oDirt, а дальше уже будем разбираться.
3.2.2. Всё там же в Create нам нужно пройтись циклом по осям x, y, создавая объект oDirt по указанным координатам. Затем мы передадим получившиеся координаты, в клетках, в переменные внутри объектов, для удобства.

for (var _y = 0; _y < cells_y; ++_y)

{

for (var _x = 0; _x < cells_x; ++_x)

{

ds_grid_set(global.grid, c, u, 0) // 0 - это стоимость клетки. Ноль - значит непроходима.

var inst = instance_create_layer(_x * CellWidth + 16, _y * CellHeight + 16, "Instances", oDirt)

inst.coordx = _x

inst.coordy = _y

}

}

Зачем при создании объекта мы плюсовали 16 пикселей?
Напомню, что точка origin - отсчёта - у наших объектов находится в центре их спрайтов. Следовательно, располагая объект по координатам (предположим, (0, 0)), часть объекта будет выходить за границы комнаты.

3.2.3. После запуска всё работает. Проверим координаты каждой клетки. Для этого вернёмся к игроку и в событии Draw GUI сделаем проверку: если позиции мыши по x,y (относительно комнаты) содержит в себе oObject, то выводим на экран coordx и coordy.
if instance_position(mouse_x, mouse_y, oObject)
{
var inst = instance_position(mouse_x, mouse_y, oObject)
scrOutlinedText(dmxg + 10, dmyg + 10, c_white, c_black, string(inst.coordx) + " " + string(inst.coordy), depth, fontArialRusSmall, fa_left, fa_top)
}
Проверяем.
GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Работает! Впрочем, это только первая часть того, что нам нужно, не так ли? Помимо создания карты, мы должны иметь возможность располагать объекты самостоятельно, удалять их при необходимости. Да и с расположением земли не всё так гладко, как хотелось бы. Мы ведь совсем не добавили фон!

Начнём с конца, ибо это, на самом-то деле, достаточно просто.
У нас с вами есть два пути.
1. Мы создаём слой для спрайтов, на котором у нас будут спрайты фона.
2. Мы создаём для каждого нашего объекта "переднего плана" дубликат для заднего фона. По сути, увеличиваем количество объектов в комнате в два раза, соответственно увеличивая и нагрузку.

Работать мы будем с первым вариантом по той причине, что он будет работать быстрее, а также предоставляет нам весь необходимый функционал, потому и смысла во втором варианте нет.

Первый вариант, несмотря на преимущество в скорости работы, имеет существенный минус. Мы не сможем обращаться к спрайтам по их координатам, да и в целом будем сильно ограничены в работе с ними. Придётся хранить ID каждого отрисованного нами спрайта. Для этого нам придётся создать вторую переменную, которая будет хранить координаты клеток (по x, y), а также id спрайта.
Так как мы знаем размер одной клетки, мы можем легко получить индекс той клетки, на которую сейчас наведены. Следовательно, можем получить и ID текущего спрайта - удалить его или назначить новый.

Получаем порядковый номер клетки. Для этого берём координату x текущей клетки, к ней плюсуем произведение текущей координаты y и максимального размера сетки по x. Т.Е. формула:

cell_id = x + y * max_x

В коде же это будет выглядеть следующим образом:

var cell_id = mouse_x div CellWidth + mouse_y div CellHeight * ceil(room_width / CellWidth)

Итак, работаем.

1. Создаём новый слой - Asset Layer, который назовём Backs.
2. Перейдём к объекту oGrid.
3. Добавим ещё одну глобальную переменную сразу после объявления сетки - global.grid_array = []
4. Чуток допишем цикл. Сделаем так, чтобы в список у нас добавлялись значения x и y.

var cells_x = ceil(room_width / CellWidth)

var cells_y = ceil(room_height / CellHeight)

global.grid = ds_grid_create(cells_x, cells_y)

global.grid_array = []

for (var _y = 0; _y < cells_y; ++_y)

{

for (var _x = 0; _x < cells_x; ++_x)

{

ds_grid_set(global.grid, _x, _y, 0) // 0 - это стоимость клетки. Ноль - значит непроходима.

var inst = instance_create_layer(_x * CellWidth + 16, _y * CellHeight + 16, "Instances", oDirt)

inst.coordx = _x

inst.coordy = _y

array_push(global.grid_array, [_x, _y])

}

}

5. Ок. Осталось ставить спрайты на "фон". Мы могли бы делать это и в цикле, при создании объектов, но зачем нам лишняя нагрузка? Правильно, незачем. Перейдём к объекту oDirt и у него создадим событие Destroy. Этот код будет выполняться перед уничтожением объекта.
С-но, алгоритм прост. Рисуем спрайт, сохраняя его ID. Узнаём индекс нужного нам массива и в него вставляем ID нарисованного спрайта.

var back = layer_sprite_create("Backs", x - 16, y - 16, sDirtBG)
var cell_id = coordx + coordy * ceil(room_width / CellWidth)
array_push(global.grid_array[cell_id], back)
ds_grid_set(global.grid, coordx, coordy, 1) // Делаем проходимым
6. Чтобы проверить, что всё работает, перейдём к игроку и сделаем так, чтобы по нажатию на кнопку мыши, у нас удалялся объект. Это пишется в step.
if instance_position(mouse_x, mouse_y, oObject)
and mouse_check_button_pressed(mb_right)
{
var inst = instance_position(mouse_x, mouse_y, oObject)
with(inst)
{
instance_destroy();
}
}
GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Как видим, фон рисуется исправно. Так как мы сохранили ID спрайта, мы можем к нему обратиться и в любой момент можем его удалить. Впрочем, последнее сейчас нам нужно исключительно в целях отладки нашего проекта.
По аналогии, мы можем размещать объекты, но я бы предпочёл сразу сделать систему, которая позволит нам ставить любые объекты, которые мы захотим.

Если упрощать, то нам нужно сделать следующие шаги, чтобы данную систему реализовать в полной мере.
1) Реализовать глобальную переменную, чтобы мы могли отслеживать событие: открыто сейчас какое-либо меню или нет. Простой переключатель, который будет закрывать старое меню при переключении на новое.
2) Сделать родительский объект или функцию для всех меню, так как логика взаимодействия у нас не отличается.
3) Расписать отдельно логику для каждого пункта. Конкретно сейчас, нам нужно таким образом реализовать меню строительства.

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

После того, как будет готов вывод объектов - нужно будет настроить логику взаимодействия с этими объектами. Выглядеть оно должно следующим образом:
- Нажали ЛКМ по объекту - объект, на который мы сейчас наведены, стал активным. Если был иной объект - он заменяется на новый.
- Нажали ПКМ где угодно - выбранный объект сбросился.
Если же нажали ЛКМ по игровому полю - то поставили активный сейчас объект, удалив при этом старый.
Для удобства также желательно отрисовывать спрайт активного объекта под курсором мыши.

Непосредственно реализация.

Начнём с того, что заблокируем наш пользовательский интерфейс на нужных нам значениях. Пусть это будет FHD. Тогда, в объекте oGameManager, в Create, нужно будет добавить одну строку кода:

display_set_gui_size(1920, 1080);
Её же нужно будет убрать в oSSize.
Всё, теперь наш GUI заблокирован на FHD. Даже если размер окна меньше или больше, координаты мыши будут подстраиваться под данные значения.
Также это означает, что наш пользовательский интерфейс не будет скакать при изменении размеров окна, следовательно - не нужно париться над его перерисовкой.

Дальше. Сделаем само меню и разместим его.
GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Нового здесь ничего нет, поэтому повторяться не буду. Всего это шесть новых объектов.
В oGameManager пропишем переменную-тумблер:

global.placing = noone
Переменную "активности" кнопки нам следует прописать у каждого объекта-меню, чтобы мы могли отслеживать, какой именно из объектов сейчас рисуется.

Теперь логика меню. Возьмём за основу кнопку "Строительство".
Сделаем список из нескольких объектов, которые мы бы хотели выводить в списке. Дополним их названиями, так как они нам пригодятся позже.
object_list = [["Земля", oDirt], ["Камень", oRock], ["Металл", oMetal], ["Уголь", oCoal]]
Реализовывать кнопки мы будем через отдельный объект - oCell.
Для этого, его нужно создать. Задать ему спрайт в виде квадрата. Сделать так, чтобы он отрисовывался в событии GUI и при этом хранил следующие значения:
Объект, который он должен рисовать, название этого объекта, какое сейчас меню открыто.
object_name = noone
object_to_draw = noone
menu = noone
Вернёмся к объекту меню строительства.

Код в step:
dmxg = device_mouse_x_to_gui(0)
dmyg = device_mouse_y_to_gui(0)
if instance_position(dmxg, dmyg, self) and mouse_check_button_pressed(mb_left)
{
// Если не активно - делаем активным
if !active
{
active = !active
global.placing = "Building";
var startx = x + sprite_width * 2 + 5
var starty = y - sprite_height
for (var i = 0; i < array_length(object_list); ++i)
{
var inst = instance_create_layer(startx + 64 * i + 5, starty, "Instances", oCell)
inst.object_name = object_list[i][0]
inst.object_to_draw = object_list[i][1]
inst.menu = "Building"
}
}
else
{
active = !active
global.placing = noone
}
}
Теперь у oCell:
step:
if menu != noone and global.placing != menu
{
instance_destroy();
}
Draw GUI:
draw_self()
if object_to_draw != noone
{
draw_sprite(object_get_sprite(object_to_draw), 0, x + 32, y + 32)
}
Результат:
GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Это только часть того, что нам нужно, верно?
Во-первых, мы не выводим название. Делать мы это будем отдельно, конечно же.
Во-вторых, у нас нет ограничения для объектов по оси X, а по оси Y они не двигаются вообще.

Начнём с первого, так как это просто. Выводить название объекта мы будем при наведении на него.
Для этого дополним Draw GUI у oCell. Если мы наведены на объект - нарисовать чёрный полупрозрачный прямоугольник и поверх него текст для лучшей отчётливости. И немного настроим "глубину", чтобы не было перекрытия этого текста.

if object_to_draw != noone

{

draw_sprite(object_get_sprite(object_to_draw), 0, x + 32, y + 32)

if instance_position(device_mouse_x_to_gui(0), device_mouse_y_to_gui(0), self)

{

depth = -1000

draw_set_font(fontButtonText20)

var width = string_width(object_name)

var height = string_height(object_name)

draw_set_alpha(0.33)

draw_set_color(c_black)

draw_rectangle(x, y - height, x + width, y, false)

draw_set_color(c_white)

draw_set_alpha(1)

scrOutlinedText(x, y - height, c_white, c_black, object_name, depth, fontButtonText20, fa_left, fa_top)

}

else

{

depth = 0

}

}


Второе.
Вернёмся к объекту меню строительства.
Так как мы знаем конечное количество объектов, мы можем посчитать, какое количество пикселей они будут занимать. Всё, что нам остаётся - определиться с количеством объектов на одну строку. Я предлагаю 10.
Мы не хотим, чтобы эти объекты создавались ниже определённой границы, потому точку старта по Y будем считать относительно неё. В общем, нужно будет заменить всего пару строк при создании объектов.
var starty = display_get_gui_height() - 64 - 64 * (array_length(object_list) div 10)
И
var inst = instance_create_layer(startx + 64 * (i mod 10) + 5, starty + (i div 10) * 64, "Instances", oCell)

Конечный результат меню:

GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

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

Нам нужно завести ещё одну переменную, которая будет хранить объект, который мы хотим использовать. Иными словами, при клике на объект oCell, мы должны из него "вычленять" тот объект, который он хранит. Как следствие, получим спрайт, который будем отрисовывать в качестве "призрака".

Сделаем же это. Для этого у объекта oPlayer пропишем переменную:

place_object = noone;
Дальше - просто. В oCell в Step делаем проверку. Если нажали на себя - oPlayer.place_object = object_to_draw;
Код:
if instance_position(device_mouse_x_to_gui(0), device_mouse_y_to_gui(0), self)
and mouse_check_button_pressed(mb_left)
{
oPlayer.place_object = object_to_draw;
mouse_clear(mb_left)
}
Теперь у oPlayer настроим отрисовку объекта. Для этого в draw пропишем код:

if place_object != noone

{

var cell_x = mouse_x div CellWidth * CellWidth

var cell_y = mouse_y div CellHeight * CellHeight

draw_sprite(object_get_sprite(place_object), 0, cell_x + 16, cell_y + 16)

// Обводочка по границам объекта, для удобства.

draw_set_color(c_white)

draw_rectangle(cell_x, cell_y, cell_x + 32, cell_y + 32, true)

}

Результат:
GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Может выглядеть кривовато, но это из-за спрайта земли. Проверял на простых квадратах - всё встаёт четко в границы. :)

Всё, что осталось - настройка логики.
Нажали ЛКМ - разместили объект. При этом, фон нам нужно очистить в любом случае. Нажали ПКМ - удалили объект, на который наведены. Если объекта нет, то удаляем фон.
Естественно, всё это сейчас - в целях теста. В дальнейшем мы будем ставить не сами объекты, а их призраки, которые человечки будут строить. В общем, целиком код выглядит так:

Step у oPlayer:

var cell_x = mouse_x div CellWidth
var cell_y = mouse_y div CellHeight
var cell = cell_x + cell_y * ceil(room_width / CellWidth)
if mouse_check_button_pressed(mb_right)
{
// Сбрасываем объект или удаляем объект/фон
if place_object != noone
{
place_object = noone
}
else
{
// Если в текущей позиции нет объекта - удаляем фон, иначе - объект
var inst = instance_position(cell_x * CellWidth, cell_y * CellHeight, oObject)
if inst
{
with(inst)
{
instance_destroy();
}
}
else
{
if array_length(global.grid_array[cell]) > 2
{
layer_sprite_destroy(global.grid_array[cell][2])
array_delete(global.grid_array[cell], 2, 1)
}
}
}
mouse_clear(mb_right)
}
if mouse_check_button_pressed(mb_left)
{
var place_x = mouse_x div CellWidth * CellWidth + 16
var place_y = mouse_y div CellHeight * CellHeight + 16
if place_object != noone
and !instance_position(device_mouse_x_to_gui(0), device_mouse_y_to_gui(0), oGBuild)
{
// Удаляем объект, если находим.
var inst = instance_position(cell_x * CellWidth, cell_y * CellHeight, oObject)
if inst
{
with(inst)
{
instance_destroy()
}
}
// Удаляем фон
if array_length(global.grid_array[cell]) > 2
{
layer_sprite_destroy(global.grid_array[cell][2])
array_delete(global.grid_array[cell], 2, 1)
ds_grid_set(global.grid, cell_x, cell_y, 0)
}
// Ставим новый объект
var new_inst = instance_create_layer(place_x, place_y, "Instances", place_object)
new_inst.coordx = mouse_x div CellWidth
new_inst.coordy = mouse_y div CellHeight
mouse_clear(mb_left)
}
}

Собственно говоря, система размещения объектов сделана. Осталось её дорабатывать напильником.
Результат:

GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

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

GameMaker Studio 2. Урок 5. Структуры данных и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Собственно, OChar - родитель oCharPlayer и oCharNoControl.
oCharNoControl - родитель oCharNeutral и oCharEnemy.

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

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

- Сохранение. Встроенное VS самописное.

- Звуки.

Небольшое объявление. В формате гайда я объясняю, как сам делаю те или иные вещи, как их понимаю. Когда гайды подойдут к концу - останется только заполнить игру механиками, спрайтами, звуками, музыкой. Это я планирую делать в дальнейшем в виде блога или вроде того.

Есть вопросы или что-то не получается - обращайся, помогу.

Есть пожелания или замечания - буду рад выслушать.

Ссылка на скачивание файла проекта для ЛЛ:
https://disk.yandex.ru/d/w31aDLE9ClPy9Q

Показать полностью 9
[моё] Разработка Gamedev Программирование Инди Инди игра Gamemaker Studio 2 Образование Длиннопост Урок
7
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии