Как создать массив данных в Game Maker Studio 1.4.9?
Пытаюсь понять как работать с гамаком, местами это похоже на юнити, а местами на Stencyl,
что очень забавно.
Хочется понять как создать список какого-нибудь класса? (возможно класс это объект, я пока не совсем понял структуру) чтобы перезагрузка уровня не удалила и не сбросила его (типа глобально)
И чтобы эти объекты не торчали на уровне.
- 25 февраля 2020, 11:41
- 01
В Tic-80 Lua это выглядит так:
В Юнити примерно так:
Можно ли создать в Game Maker программные объекты, которые будут храниться в каком-то списке, чтобы был всегда доступ к ним, и чтобы они не удалялись при перезагрузке уровня. Или же тут объекты это и графические объекты одновременно, просто я не до конца понимаю концепцию гейм мейкера?!
Вообще так и есть, нам обещали lightweight objects, но пока их не добавили в движок. С другой стороны, люди уже 20 лет делают игры без них, просто создавая объекты вне экрана и делая их невидимыми. Потребление процессорного времени, которое происходит при вычислении нулевого изменения координат при нулевом изменении скорости и угла движения, при нулевой же гравитации и сопротивлении - довольно незначительно.
Безусловно, сюда может набежать толпа любителей партиклов, или любителей хранить в оперативной памяти "просто 100000 объектов" без конкретной игровой цели. Но для партиклов уже 15 лет как существует своя система, а просто 100000 объектов на практике бесполезны - как правило это означает что задача была неправильно поставлена и для этого следовало завести или 100000 списков, или 100000 словарей.
Ещё можно создавать БД в памяти вручную, но непонятно какая в этом нужда - на дворе не 2005 год.
Ну а так, твой лимит - 34000, по моим тестам:
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
В Game Maker:
(Объект o_box нужно создать в списке ресурсов предварительно)
В процессе игры можешь обращаться к любому из них типа box[3].любая_переменная = 123.
Это пример с массивом, можно заводить их в списке:
Или в словаре, или в сетке, но это зависит от того, что ты проектируешь. Для двухмерного инвентаря лучше использовать ds_grid, для одномерного - ds_list, для просто перечисления всего подряд по ключевым словам (слотам, см. основная экипировка как в Diablo) - ds_map.
О, Спасибо! Надо потестить)
Только это не класс, если что. Хотя в данном случае это неважно
Просто думаю, как хранить в гейм мейкере например список инвентаря, или например список захваченных замков на карте мира, или список передвижения врагов, на той же карте. Или например список своих компаньонов с именами и прочими статами, но чтобы всё это не торчало на уровне визуально, а было только в виде данных.
Я для этого использую структуры данных.
ds_list
ds_map
ds_queue
Это основные
Бывает ещё ds_grid для карты, например.
Но в них только простые типы данных хранятся - числа, строки. Но каждая их этих структур при создании имеет свой ID, который цифра и который можно использовать в другой структуре. Так можно создать список словарей.
В своём последнем опыте для сущностей как ты говоришь я сделал скрипты, которые создавали ds_map с нужными полями, а потом делал из них списки, массивы и т.д. Примерно так:
А потом ты такой
А потом ходишь по списку когда нужно. Но в данном случае я бы немного по-другому инвентарь делал, чтобы не было повторов. Смысл был - показать как со структурами работать.
Это типа как объекты в JS, только без функуций. Можно как с JSON работать, но там всё хитровыебано, несомтря на наличие функционала для этого.
Это вообще легально? Может поломаться однажды, лучше argument_count проверять.
И ты привёл частное решения для переменных. Приведенный мной метод ставить инстансы в координаты (-100500, -100500) работает без какого-либо дополнительного кодинга, причём что важно - работает с заранее неизвестными типами и количеством переменных.
Легально если передавать все аргументы. Тут либо делать скрипты на апдейт каждого параметра отдельно, либо так. Делать скрипт с опциональными параметрами такое себе.
Инстансы легко проебать. Всё-таки если речь идёт о инвентаре, карте, захваченных замках и любых мета-данных - то лучше делать по-нормальному. Без инстансов.
Лучше в релизе, но в прототипе постоянно менять формат БД - неэкономно. Когда уже игра финализирована как концепт с тонкостями - однозначно согласен. Просто мне кажется что Алекс не на том этапе ещё.
Ого! Спасибо большое, чего мне точно не хватает в гамаке, так это примеров кода!
На Тик-80 у меня быстрее обучение шло, ибо я сразу скачал куча исходников и начал их ломать и портить) ,
а потом когда понял что можно делать на движке, оттуда и отталкивался.
скачай туториалы стандартные, они вроде сейчас где-то на оф сайте скачиваются (насколько знаю их из самой программы сейчас скачать нельзя) К тому же в зависимости от задачи, примеры достаточно не сложно гуглятся обычно. (а иногда даже готовые решения)
А они будут работать для Game Maker 8.1 или Game Maker Studio 1?
Просто сейчас эти версии не актуальны больше, зато тут не 30 дневная демка,
как у Game Maker Studio 2, как бы можно не торопиться с изучением материала.
посмотрел, и кажется (почему-то) теперь тебе просто пишут ссылку на туториал при попытке "создать"(скачать) его. собственно видимо всё немного проще чем я думал)
И как это отвечает на вопрос Алекса по-твоему?
Ответ: понятия не имею, потому что Рс имел в виду непонятно какие туториалы. Встроенные (которые показал я в недавнем комментарии) будут работать с ГМС1 и 2.
я начал отвечать, а потом стёр и, заметил что информация данная раньше была не совсем верна. Смилуйся, войди в положение не доспавшего человека!
Ну, мог бы просто зайти в ГМС1 и посмотреть заново тогда.
это и сделал... пожалуй я изначально непонятно написал... (в основном из-за ложных данных))
забей короче, ты лучше ответил)
Да там к сожалению не скачать так просто( ну ладно, я потом разберусь.
Есть массив через [], и список ds_list. Почитай доки.
https://docs2.yoyogames.com/
Разделы:
Scripting -> GML Overview -> Arrays
Scripting -> GML Reference -> Data structures -> DS Lists
Звучит круто! Спасибо! Попробую потестить, есть ли это в первой студии.
Судя по докам, есть.
Это было ещё в Гейм Мейкере 5.2, 17 лет назад, то есть в 2003 году.
Ты имеешь в виду список экземпляров объекта.
Сделай объект персистентным - галочку поставь Persistent в окне объекта слева.
А ты и не ставь их на уровень - ставь их в координаты типа -100500, -100500. Ещё есть флаг visible.
А если их много нужно, то они так и будут все торчать на -100500 координате?
А в чем проблема? Ты не представляешь в скольких играх куча объектов висит где-то на окраинах игрового мира.
Будучи художником, я бы тоже подумал что это может быть чревато. И в каком-то смысле он прав - выше я написал, в каком.
У меня так раньше всегда было, и я пытался от этого избавиться, и меня немного пугает тот факт, что оказывается я нормально делал игры, а мне всегда казалось что неправильно)
если они работают правильно значит и сделаны правильно х)
Правильно и достаточно долго.
что ты подразумеваешь под
?
Дольше чем у юзера (его компьютера) возникнут проблемы.
Да, так и будут. Другое дело если у них есть события коллизий друг с другом - тогда они будут на это реагировать, да и вообще жить за экраном, но в этом изначально нет никакого смысла - персистентные комнаты сохраняют положение и состояние объектов автоматически.
Танцуй от геймдев-задачи, слишком много общих вопросов задаёшь.
Говори - хочу чтоб враги оставались в предыдущей комнате, когда я пришёл в следующую; чтобы когда вернулся в первую, они были ровно в тех же положениях и с теми же хитпоинтами. Эту задачу решает персистентность комнат.
Или - хочу чтобы враги респаунились каждый раз в комнате с одинаковыми хитпоинтами в одинаковых (возможно немного варьируемых) местах; но чтобы был такой враг, который меня преследует по другим комнатам. Эту задачу решает персистентность объекта - в данном случае, того врага который должен уметь преследовать.
А сейчас непонятно, зачем тебе "просто хранить просто объекты с переменными". Для баз данных предметов нужно действительно писать базы данных, по принципе как Хейзер привёл, но там переусложнено - можно же просто взять Эксель-таблицу, в неё прописать все предметы и характеристики, и сделать чтоб игра читала CSV-файл, благо это просто файл из строк разделенных точками с запятой.
Распиши свои задачи, полностью, все. Тогда будет ясно что тебе нужно.
Окей! Хотя мне хотелось бы разобраться что можно, а что нельзя в гейм мейкере, сразу.
У меня несколько задач:
1) как раз это нужно запоминать всех врагов в локациях на подобии метроидвании,
но чтобы у врагов сбрасывались координаты, но не сбрасывался HP,
в принципе я понял, пошёл гуглить персистентность
2) вторая задача, она как бы не относится к текущей теме, но я просто дошёл до этого места:
как сделать комнаты по типу метроида, самый простой вариант
PS вообще я вначале хотел сделать карту мира с передвижениями по ней неписей и отрядов, как в Mount n Blade, и во время боя там другая комната, но при возвращении мы бы вернулись на карту мира, но я решил забить на эту идею, пока-что наверное сложно на первый раз в качестве эксперимента
я бы не стал "заморачиваться" с комнатами и просто рисовал бы бой по верх всего отключая взаимодействие мыши с тем что не на кране боя.
А как рисовать поверх? У объектов гейм мейкера есть SetOrder (порядок отрисовки спрайтов) как у Unity, или ось Z?
есть depth можно в объекте на прямую указать а можно собственно в коде.
У каждого экземпляра любого объекта есть переменная depth. При создании объекта присваивается depth объекта, но можно динамически менять эту глубину в процессе игры, у разных экземпляров независимо друг от друга. По сути, это и есть ось Z.
лол
прим. Это будет влиять только на последовательность событий рисования, а не на весь экземпляр. На событие Step переменная depth не влияет. Последовательность Step'ов зависит от значения id экземпляра в GMS1 и от значения object_index объекта (грубо, от положения в дереве ресурсов) и уже во вторую очередь от id экземпляра в GMS2.
Не совсем понял, чей вопрос ты здесь пытался решить, и каким именно способом. Алекс вроде такого не спрашивал, и не похоже что ему понадобится менять порядок событий, только порядок отрисовки.
Да и так можно, просто всё со временем, поэтапно. Вообще ты описал такое как было сделано, например, Дрейком в конкурсной игре "Галактические Лорды", 6 лет назад: https://gamin.me/posts/12085
Там 7 основных карт с двигающимися юнитами, а каждый бой между юнитами проходит на отдельном экране, плюс ещё есть совсем внешняя карта кампании, но с ней всё совсем тривиально - это как экран выбора боссов в Мегамене.
Делай маленькие шаги и сделаешь то что требуется. Тише едешь - дальше будешь.
Попробую сделать игру в духе Hero Core,
![TOEwr44](https://i.imgur.com/TOEwr44.png)
скрестив с ещё пару играми, типа Guardian Legends и Comix Zone.
Я давно думаю над подобной игрой и делал небольшую заготовку на Tic-80:
Честно говоря на этом скриншоте не видно никакой игры - просто фон и персонаж. Для шмапа не хватает выстрелов. Но картинка классная, тут ничего не скажешь, рисовать-то ты умеешь хорошо.
https://www.dropbox.com/s/fc3p9qfcx2m56jy/Alexsample.gm81?dl=0 - оно?
О, спасибо, Ксит! Надо потестить)
Не знаю пока что это, но мне пока тупо не хватает материала для обучения.
В том же Construct 2 вместе с редактором поставлялись и примеры, а в гейм мейкере походу нет.
есть но, в общем есть...
Да вот же они в ГМС1, прям при запуске надо вкладку открыть и всё. Работает и в ГМС1 и 2.
В проекте что я скинул есть один баг - нельзя зайти в комнату 33. Но это потому что я прописал условие неправильно, а суть того что ты хотел там показана во всех остальных комнатах - игрок ходит по разным комнатам, враги возвращаются на места, их хитпоинты сохраняются.
я пытался нажать на Tutorial, и там мне просто пишут ошибку и какую-то ссылку,
![WlhumJd](https://i.imgur.com/WlhumJdg.png)
но я пока не пытался вводить её, ибо она слишком длинная и не скопировать, текст не выделяется, надо бы ввести вручную потом, может там будут все примеры, я хз)
https://help.yoyogames.com/hc/en-us/articles/217571368
Я помню что сам когда-то их там качал. Вот ссылка сейчас прямая с той страницы:
http://store.yoyogames.com/downloads/gm-studio/StudioAllDemosTutorials.zip
Кроме Туториалов там в архиве есть ещё и Демо. Так что мало не будет. Другое дело что там местами код не самый адекватный, но я не могу одновременно писать реальные проекты и заниматься просветительской деятельностью. Будут проблемы - спрашивай.
О, Спасибо) То что нужно!
Спасибо, Ксит) С этим примером много чего понял, как оно тут устроено. Да и другие уроки посмотрел.
Правда не понял как кодом исправить тот твой баг, но если просто добавить один пустой уровень, то баг исчезает.
Рад что помогло, обращайся. По багу простейший способ - скопировать то что в цикле while, чтоб ещё один раз после цикла while выполнилось. Там нужно на самом деле переприсвоить переменную, но мне щас неудобно это смотреть, а в релиз этот код явно не идёт.
с постоянными вещами нужно кстати осторожным быть, была у меня проблема когда игра всякую дич делала из-за постоянного объекта в постоянной комнате...
Это профилируется в дебаггере, если что. Или там тоже дичь была?
не знаю о чём ты, я имел в виду например дублирование постоянного объекта... и это может создавать самые разные проблемы... из за этого пришлось убирать постоянность у комнаты а пол написанного кода переделывать... с тех пор стараюсь не пользоваться комнатами х)
Ну, тут изначально непонятно какую задачу ты решал и как тут могла пригодиться двойная персистентность. Прежде чем что-то делать, стоит это обосновать.
если я верно понял, ты хочешь список того что есть на уровне (грубо говоря)
собственно, все объекты по умолчанию в "списке" со своим ид, но если нужно что-то за мудрёное, я обычно создаю объект контроллер. Также есть глобальные переменные в которые можно записать лист, мап, грид, или массив.
Не, он хочет хранить метаданные, которые не привязаны к игровым объектом напрямую.
ну, если так то вероятно глоблы.
Да, поначалу я хотел чтобы были данные, которые бы всегда работали,
например глобально перемещающиеся монстры по карте мира, пока мы мирно сидим в доме,
а потом выходим на карту и там уже произошли соответствующие изменения.
Подумал, что может я всё таки смогу сделать, если просто отключать визуальную часть объектов,
но продолжать все объекты двигать. Но на первый раз это сложно и я решил на потом оставить
это не очень сложно реализовать через "главный объект". зависит правда от силы желаемой проработки врага... можно например: создавать кучу врагов при запуске "игры" на всей карте, и де активировать все объекты, и активировать только те что в области вида (или в области вокруг игрока).
это достаточно топорная реализация но она весьма проста и в реализации и в работе.
roo
Можно же просто объект инстансить, но не отрисовывать его на экране или где либо. При этом все параметры доступны и можно его "настраивать", а потом просто делаешь add_child(node_instance). Или такого нет в GM?
Какого "такого"? Этот код мне ничего не говорит. Вижу только что это не Юнити, и на Unreal Engine не похоже.
А этот код и не должен ничего говорить. Здесть ключевое слово "инстансить", а уже потом все остальное. Я хотел сказать, может ли GM загружать объект в память, не рисуя его на экране, а потом в нужный момент присоединяя его к... чему-то, к чему можно присоединить.
Может. И присоединять может. И отсоединять. Что бы это ни значило...
А в Game Maker реально всю игру из одного объекта написать?
Ну то есть там же вроде есть обычные операторы рисования как в Tic80?!
Можно ли весь код написать для одного объекта, чтобы это была полноценная игра?
Я пока ещё не уверен как тут работает обычный код на Lua Tic80, типа, ибо мне нужны функции:
Не совсем понял, те ли это функции:
https://docs.yoyogames.com/source/dadiospice/002_reference/001_gml%20language%20overview/401_16_functions.html
или это нечто другое, и работают ли в Game Maker функции настолько же быстро как в других программах, или они аналог SendMessage в Unity, то есть как бы получатели месседжа/команды.
Просто я привык очень часто использовать разные функции в играх, надеюсь тут это тоже не проблема.
Конечно, только зачем? Вся суть ООП в том чтобы объекты были отдельно друг от друга, и ты писал код от врагов в объектах врагов, а код от выстрелов в объектах выстрелов. Можно ещё игру в текстовом режиме делать как в DOS'е. А ещё музыку PC-Speaker'ом играть. Один вопрос - что тебе это даст, чем это лучше?
Обычные это какие? Ты можешь рисовать как спрайты, так и просто линии, круги, точки.
Можно. Я могу любую игру написанную на ГМе переписать под один объект, только вот изначально разрабатывать игру в виде одного объекта - это тебе придётся скроллить сначала 100 строк ивента, потом 200, потом 500, потом 1000, а потом у тебя поломается колесо мыши и кнопки Page Up, Page Down, Home и End.
Нет такого понятия "обычный код". Если ты хочешь ни за что не использовать объекты, ты можешь использовать один объект так, будто его не существует, просто тасовать переменные туда-сюда. Так и писали игры в 1985 года, когда не было ещё C++, и все писали на обычном C без классов и объектов.
Это раздел справки о встроенных функциях. Чтобы писать свои, тебе нужны скрипты:
https://docs.yoyogames.com/source/dadiospice/001_advanced%20use/006_scripts.html
Работают. Медленнее чем в других программах, в 100 раз. Но быстрее чем в Юнити, в 200 раз. :yak:
Извини, но вопросы такие бесячие, что отвечать на них всерьёз становится уже трудно. Откуда я знаю о каких других программах речь? Гамак "достаточно быстрый", это я тебе точно говорю, 34000 объектов вот тестировал.
Пиши уже "обычный код" как "в других программах", посмотри исходник который я для тебя с нуля закодил за 15 минут; главное чтоб ты решал задачу, а не околачивался вокруг да около. По-моему уже всё что можно перемололи в этой дискуссии.
Примерный аналог SendMessage это:
http://docs.yoyogames.com/source/dadiospice/002_reference/objects%20and%20instances/objects/generating%20events/event_perform_object.html
Тут это называется скриптами - это куски кода который можно вызывать сколько угодно раз из других кусков кода.
Порядок отрисовки и всех команд лучше контролируется вручную, чем случайно хаотично раскиданными объектами по уровню, ибо хз какая функция будет работать раньше другой. В Tic-80 мне так было легко сделать меню паузы и другие вещи, в отличии от Unity.
Просто не надо брать движки где объекты "хаотично раскиданы". В этом смысле ГМ такой же как TIC-80.
Может мы не совсем друг-друга поняли.
Я просто имел ввиду, что в Tic80, можно одним махом прекратить отрисовывать объекты,
например у комнаты прекратить отрисовывать объекты, но продолжать обновлять её.
А в юнити пришлось бы много костылей ставить, к примеру пройтись по всем объектам и отключить рендеринг.
Вот к примеру как я бы поступил создавая Mount n Blade в Tic80, то есть игру с глобальной картой по которой ходят враги, и когда встречаешь их, то мы бы переместились бы в локацию, и карта бы осталась не тронутой,
просто бы не отрисовывалась в текущий момент, но возможные события бы там происходили бы,
если нам нужен был бы реалтайм на карте мира тоже, а в юнити пришлось бы намного сложнее продумывать такую систему, пришлось бы скрывать объекты или размещать их где-то ещё, чтоб не пересекались:
Отсюда также можно видеть насколько легко контролировать обновления, вначале обновляется карта мира (WorldMap), а потом только локация/комната (Room). В юнити пришлось бы больше думать над тем, как создать такую простую вещь. Там просто объекты лежат на уровне как попало, и ты не уверен что первое из них обновится, в гейм мейкере тоже лежат объекты на уровне, и не совсем понятно как они будут обновляться, в каком порядке.
Честно говоря, никогда не приходилось контролировать обновления, хотя у нас в замке 216 комнат и каждая сохраняет, открыт ли в ней сундук, убиты ли враги, есть ли там артефакт, и так далее. Отсюда думается мне, что и клонировать Mount & Blade в 2D вполне реально без управления обновлениями. Если что-то не вычислено на текущем шаге, то можно просто подождать ещё один. Кроме того, в ГМе есть разные суб-кадры одного кадра:
https://kolenka.net/posts/tochnaya-proverka-korotkikh-intervalov-vremeni-v-game-maker
Цифрами 123 я обозначил доступные тебе моменты внутри одного кадра. Если одни юниты будут в Begin Step, а другим нужно опираться на вычисления первых, то ставь вторых в Normal Step. А если третьим нужно на вторых и/или первых, то ставь их в End Step. Решений, в общем, много. Пока что ни одну задачу, которую ты поставил, не было сложно решить в ГМе.
За картинку и статью лайкус
В GML это можно сделать в две строки:
Или в другие две строки, чтобы убрать растровую часть рендера, но оставить векторную:
Обратно соответственно true и 1.
Можно просто поставить все объекты в координаты за экраном (скажем, отнять от всех координат 100500 и они будут где-то далеко-далеко наверху слева), и они не будут отрисовываться (я имею в виду, даже тратить время на рендер в application_surface), потому что находятся за экраном; но будут работать, так как не теряют своих координат, масок коллизий, ивентов и кода. Просто стоят где-то там.
Но знаешь, я что-то очень сильно сомневаюсь, что в Mount & Blade объекты, находящиеся на далёких локациях, действительно существуют в памяти в виде таких же объектов, как на текущей локации. То есть, когда ты в одной крепости, в другой в это время (помимо рендера) не идёт просчёт реальных коллизий, не воспроизводятся звуки на громкости зависящей от расстояния до игрока, и самое трудоёмкое - не существует реалтаймового ИИ.
На это просто не хватило бы процессора, поэтому я практически уверен, что как только ты выходишь на глобальную карту, а тем более на другую локацию, все юниты, ландшафт и конструкции - преобразуются в простые числа в массивах и так и воюют с обновлением своей логики, скажем, раз в секунду, а не 60 раз в секунду.
А как опять включать? И как проверить что уже отключал, получается нужно больше проверок и переменных?!
Спасибо за пример с With, я так понял это внутри объекта работает и просит все объекты одного типа отключить или как? Пошёл гуглить про with, ибо пока-что для меня это какая-то новая команда в моей практике программирования, не помню аналогов в других языках.
visible=!visible переключает в 1 если сейчас 0, и переключает в 0 если сейчас 1.
Нет. with all отключает ВСЕ объекты всех типов. Если тебе нужно отключить отрисовку объекта врага, пишешь:
И ещё не стоит путать отключение отрисовки и отключение логики объекта. Чтобы отключить отрисовку вместе с логикой, нужно использовать функции активации/деактивации:
https://docs.yoyogames.com/source/dadiospice/002_reference/objects%20and%20instances/instances/deactivating%20instances/index.html
А потому что их и нет. Ближайший аналог в Юнити это вот этот монстр:
https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html
Который ещё и тормозит:
Note: This function is very slow. It is not recommended to use this function every frame. In most cases you can use the singleton pattern instead.
Жаль. Я просто в Unity с помощью SendMessage отправлял данные об уроне по врагу или любому объекту.
А как тут конкретное число урона отправлять ещё не знаю, но думаю с теми примерами что скачал сегодня, разберусь, может там есть примеры.
Давай сразу в корень проблемы - зачем отправлять число урона? Ты хочешь отнять хитпоинты - тогда просто отними их из одного объекта у другого объекта. Если там сложная формула - то пропиши скрипт который будет отнимать хитпоинты, броню, и прочие резистансы. А именно Message слать не обязательно.
самое простое в стандартном ивенте коллизии делать что-то вроде
other.hp--;
Спасибо! То что надо) Хорошо что тут не надо ещё дополнительные строки писать чтобы просто вначале получить доступ к скрипту как в юнити, а сразу обращаемся к переменной, люблю когда нужно меньше писать кода)
Ну в целом, я разобрался) Тут легче, чем в юнити получать доступ к переменным другого объекта