Всё ещё учусь работать в Game Maker (GMS 1.4.9), параллельно участвуя в конкурсе на GCup.
1)Немного неприятно, то что разрешение экрана и FPS нужно менять в каждом уровне отдельно,
по логике это должно выноситься в опции и быть общим для всех уровней.
2)Также немного прокачал рисование персонажа для кастомизации, хотя возможно это всё будет лагать при 60 FPS на слабом ПК, я не уверен:
- 18 июня 2020, 17:21
- 04
Ещё тут один странный момент с нарезанием спрайтов, неудобно вводить цифры, я может даже не знаю
какое разрешение у спрайта, но GMS настойчиво просит ещё и разрешение ввести(
другим редакторам достаточно лишь указать количество кадров по оси X и Y и они сами автоматом нарежут
Ты можешь автоматизировать подгрузку внешних спрайтов во время выполнения игры, с помощью функции sprite_add(). Там достаточно указать количество кадров, а остальные аргументы просто пиши 0 (ну или такой origin который тебе нужен, это смотря по ТЗ/диздоку).
О, крутая функция! Спасибо :)
Красивая графика какая!
Спасибо :)
Я взял вдохновение из старых игр (Earthworm Jim, Metroid, Ristar), не грех подсмотреть как рисуют мастера старой закалки. Сейчас учусь рисовать пиксельарт и набрал с разных игр скрины, очень помогает вдохновляться работами и выбрать лучшую гамму или стиль:
А я обычно рисую как бог на душу положит.
Думаю это заметно.
бога нет
А черт есть?
это надо анализировать, чего там на душе лежит
Есть пару лайвхаков:
1) набрать скринов разных игр и копировать оттуда гамму, цветовую палитру
2) чем меньше цветов, тем игра выглядит более профессиональнее, даже если рисовка не дотягивает
(2,3,4 цвета норм) но лучше гамму стырить с профессиональных скринов
Идеальный скрин:
3) чем меньше пикселей в спрайте - тем легче рисовать
4) я когда рисую без референсов, то рисую как курица лапой, а если обложусь вокруг референсами, то
графика заметно улучшается, главное не тырить напрямую, и тем более не обводить, а просто пытаться вдохновиться стилем. Важно: При рисовании, даже профи художник, всегда обкладывает вокруг референсами.
Сверху чужое, снизу моё, пытаюсь взять самую лучшую гамму и стиль у профи художников, если бы рисовал без референсов, то получилось бы раз в 10 хуже, это не преувеличение.
лол, общее количество референса (то что очень понравилось из пиксельарта) у меня выглядит вот так
финальное изображение 4200 на 3200 пикселей насобирал скринов за год или больше:
вот ещё хороший пример 2-х цветной палитры:
GameBoy палитра тоже шикарная, но там сложнее рисовать,
ибо 2-х цветную палитру почти нереально испортить:
На геймбое всё же 50 4 оттенка серого было.
Ну всё равно прикольно, когда эти цвета не чисто серые, я тут недавно для своей мини игры на Tic-80 интересную палитру подобрал:
В GMS2 это уже так.
Не должно, это всего лишь 8 спрайтов.
Отрисовка постобработки fullHD =)
Не лагает
Ого как много всего)
Кстати ещё, рекомендуется все вот эти циферки в отрисовке запихивать в константы какие-то, чтобы потом, недель/месяцев через N вспомнить что это такое вообще, и почему там +5, а не -7. Это применительно к любому языку, не только гмл
Просто эти циферки ничего не означают кроме смещения от родительского объекта, и получается каждой константе надо давать много имён? Допустим, константы:
Я согласен, что это хороший метод, но не уверен, что не запутаюсь больше, в данном случае.
Написание читабельного кода может занимать больше времени, чем просто работающего кода)
А чего нечитабельного в координатах, если ты знаешь что в вызываемой с ними функции задаются только координаты, только в пикселях?
Написание читабельного кода занимает всегда больше времени чем нечитабельного, так же как и эффективного в противоположность неэффективному. Вопрос, надо ли тратить это время, когда ты человек-оркестр и тебе тут надо порисовать, там музыку поделать или хотя бы подобрать - тоже работа. Дел очень много в инди-геймдеве.
ты всю жизнь будешь использовать смещение от родительского объекта и всю жизнь будешь использовать одни и те же имена. тут невозможно будет запутаться
Блин, неужели еще кто-то получает удовольствие от драу_что-то_там(x+vh+50, y+vh+50, w+vh*2+40, h+vh*4+60). Ну это же пиздец, братцы...
Альтернатива?
Я не знаю как там в GMS, что сделано, но обычно спрайты просто расставляются в тех местах где они должны быть, как например в Godot. В gms разве нельзя "руками" делать сложную структуру? Ragdolls не реализован?
В той версии что юзаю я GMS 1.4.9 с этим сложно, проще ввести кодом, но я люблю такие функции, и хотел бы в юнити. Например если я хочу показать какую-то надпись или спрайт в GMS, то просто беру и показываю,
а в юнити пришлось бы создавать отдельный объект и не забыть его удалить потом.
С чем сложно-то? Вы тут щас странные оба - один спрашивает сам не знает что, а другой отвечает за движок который ещё не изучил, причём отвечает непонятно на что.
По пунктам объясняю:
Там можно скомпоновать составной объект из частей вообще без всяких вызовов функций и ручного выставления оффсетов.
Ну и это одна маленькая задача в рамках огромного проекта.
Ксит, я имел ввиду про визуальное создание иерархии спрайтов/объектов, как в юнити или годот,
хотя возможно я просто не нашёл этот функционал, я хз:
Минуточку. Это если нужно в другой комнате такой же герой с такой же иерархией, то придётся копипастить. Разве не префабами это надо делать?
Префабов в ГМ нет, это правда. С другой стороны, в GMS2.3 уже есть не только они, но и возможность составлять из них анимации, см. таймкод и снизу слева трек-панель - поверх чувака поставлены отдельно в иерархию меч и щит. Так что тебе это недоступно только потому что ты учишься на старой версии, на которой из-за этого менее удобно, а значит менее приятно учиться.
штош
ага, префабами)
Ну так вот префабы в ГМС2.3+ теперь есть.
Ну ладно) я буду покупать только тогда, когда научусь и определюсь с GMS, буду ли в будущем на нём работать и понравится ли мне (и сейчас с финансами не очень), пока только учусь сделаю одну-две игры и посмотрим. И хз можно ли там делать мобильные и ПК игры, не докупая каждый год снова лицензию, просто я не уверен насчёт мобилки, а вроде как на ПК постоянная лицензия.
Подписка у Гамака только на самое дорогое - консольные экспортеры по $800 в год, причём без региональных цен как у всего остального в Стиме у них.
Стимовские региональные цены в РФ - ОЧЕНЬ щадящие:
https://steamdb.info/app/585410/
https://steamdb.info/app/585620/
А потом на них ещё и скидка падает.
Вообще можно импортировать костные анимации вроде.
По удобству когда как. Иногда удобно как ты говоришь, а иногда удобно рисовать всё в одном объекте.
Не "вроде", а импортировать векторные анимации можно из Spine, и из совместимых с ним прог, например DragonBones.
Пример: https://twitter.com/kittariagame/status/1270455841712246785
В смысле, удовольствие? Где это ты в ГЕЙМДЕВЕ видел удовольствие, "братец"? XDDDDDDDDDD
В игры хорошо только играть. Делать их - боль и проклятье, особенно двухмерные на трёхмерных движках.
всё же мне кажется 3х мерные, на 2х мерных сложнее)
Ирония доходит до того, что скоро в ГМС2 будет проще делать трёхмерные, чем в Юнити двухмерные.
это скоро ещё должно вырасти до сейчас.
Ну хз, иногда лучше работать с готовым объектом, но иногда лучше рисовать через draw, смотря какое действие, я бы очень хотел такие функции в юнити, а в годот они вроде есть, встречал в документации.
В юнити придётся свои костыли делать.
Если в юнити я захочу сделать тоже самое, то мне нужно:
1) на уровне создать 8 спрайтов и сделать их родителя (в принципе пока просто),
не забыть все спрайты размещать на некотором расстоянии друг от друга по оси Z, чтобы они
не отрисовывались раньше других, а sprite order не трогаем, ибо он нам понадобится для других целей,
чтобы весь объект выглядел целостным и части его спрайтов не пересекались с другими частями других объектов (смотреть, в пункте 4);
2) при смене направления персонажа можно было бы только родителя по scale переворачивать, но нужна
дополнительная проверка, чтобы второй раз подряд не менять направление, что-то типа:
3) анимацию можно сделать в аниматоре в юнити, с одной стороны проще, с другой стороны для небольших пиксельных объектов обращаться к таком сложному функционалу не очень хорошо. Или если я захочу настроить слои, то есть например, чтобы руки анимировались отдельно, лицо отдельно, то для таких пару пикселей настраивать аниматор со слоями не самое лучшее дело. Если я захочу чтобы появлялся какой-то объект в анимации, какого тут нет, то мне придётся создать этот дополнительный объект заранее и скрыть его,
возможно даже придётся много сразу объектов создать и скрывать их, чтобы в определённый момент анимации их показывать, либо придумать в скриптах создание и удаление объектов, но также через аниматор надо настроить костыли поведения и прописать функции.
А тем временем с draw, можно рисовать только когда работает триггер, всего 1 строка кода:
(хотя придётся повозиться с настраиванием правильной позиции, везде свои плюсы и минусы)
4) Чтобы спрайты этого объекта не пересекались со спрайтами например врага, то нужно каждому новому врагу, через скрипт всем спрайтам врага сделать другой Order, что-то типа:
А тем временем с рисованием draw таких проблем вообще нет, и не нужно создавать костыль порядка отрисовки для этого, спрайты разных объектов никогда не будут пересекаться при draw методе.
PS так что есть везде свои плюсы и минусы, что-то легче делать визуально, а что-то лучше делать кодом.
Что значит спрайты разных объектов никогда не будут пересекаться? У каждого спрайта уже есть некая область коллизии?
1) А что если коллизия в виде триггера, допустим все враги опасны, но я могу сквозь их пролетать?!
Или сквозь героя пролетают пули.
2) Если я прохожу мимо NPC, с которыми не сталкиваюсь, то будут видны все пересечения спрайтов.
В моей игре на юнити например куча NPC, которые ходят по городу и можно легко переходить сквозь них,
и неписи сами друг через друга иногда проходят, и видны косяки с пересечением спрайтов между ними,
чтобы это убрать мне приходится ещё помимо Sprite Order также случайно менять позицию Z, чтобы было меньше пересечений, но иногда у при пересечении пару неписей и почти одинаковой Z позиции этот косяк снова всплывает(( а с отрисовкой draw такой проблемы никогда не будет.
3) Если в игре есть Y/Z Order, (то есть чем ниже объект, тем у объекта больше Z Order, например для изометрических RPG), в таком случае, если мы приблизимся к другому объекту, у которого не будет коллизии, то спрайты там все друг с другом пересекуться.
Что-то сложна.... Какие-то заморочки, что даже в это вникать не хочется. Ты меняешь Z чтобы что-то там исправить, триггеры коллизий, коллизии триггеров, триггерные триггеры коллищий... 🙄🤯🤕
Что касается Годот. Есть физические объекты: кинематик, статик и ригид. Хочешь сталкиваешься, хочешь нет - реализуется через слои. Есть. Area2d которую проходишь, но она регистрирует столкновение и выход из объекта. Все. Просто и дешево.
Дело не в коллизии, а то что её может не быть, и тогда персонажи могут находиться на одинаковой координате и их спрайты могут друг в друга влезать. С годотом я тоже пока не разобрался, потом буду думать, но там есть много интересных моментов, которые мне понравились.
Чтобы они друг в друга не влезали создаются разные сущности: player, npc1, enemy. Они никак не будут влезать друг в друга. У гмс я не знаю, в годот точно такого нет.
Спеэффект взрыва ДОЛЖЕН влезать поверх спрайта персонажа, если этот персонаж сейчас получил ракетой в лоб. Зачем тебе делать взрыв который автоматически выталкивается из своего текущего положения, если он как раз должен пересекаться с тем что повреждает?
Я как раз в GMS сейчас гуглю, как сделать так чтобы вновь созданный объект был выше по приоритету отрисовки остальных, а то у меня пуля где-то за всеми объектами отрисовывается,а нужно чтобы она была выше даже, чем главный герой. По умолчанию я думал так, если создаёшь новый объект то он сразу рисуется поверх всех объектов, но видимо тут другая система, либо я не так что-то сделал.
Он рисуется поверх всех ранее созданных объектов, существующих на той же глубине (depth). Пример типичного распределения:
Враг ниже всего, игрок выше, пули игрока ещё выше. Наследуется всеми конкретными врагами и пулями от абстрактного врага и пули соответственно.
Спасибо) а я думал там надо скриптом делать
Вот допустим классический пример из моей игры, когда координаты по Z оси случайно оказались одинаковыми
у двух неписей и они стоят рядом:
Возможно тут можно придумать какую-то проверку при пересечении неписей, чтобы позиция по оси Z, никогда у них не была одинаковой, если они пересекаются (потому-что разбрасывать случайно по позиции Z не всегда помогает). Так что никуда не деться от этих костылей)
И да, у них нет коллизии, ибо они как персонажи игры River City Ransom, то есть идут слева направо или наоборот справа налево без проверки столкновения для симуляции толпы.
Проверку пересечения? Неужели ты не представляешь масштабы происходяшего - сколько писанины тебе предстоит... По моему не в том направлении двигаетесь, товарищ...
По-моему ты забыл что он говорит про Юнити, а не про ГМС. И в пользу последнего, а не первого.
Странно видеть такое в 2020 году, но у тебя движок гмс старый, так что вполне возможно. Срочно переходи на студию - игры нужно делать, а ты ерундой занимаешься🤣
этож вроде как скрин из юнити...
Это да, Юнити)
а сунуть каждому коллайдер и пускай стукаются, не?
да, но вопрос вроде как про то как сделать это без подобного....
Перемудрил ты с порядком отрисовки, используй SortingGroup. Да и с направлением движения переусложняешь, пожалуй.
А как с направлением движения работать?
то есть если вот так оставить, то не будет лишней траты ресурсов?
Пример на UnityScript (JS был в Unity до 2018.2 версии):
Пример на C# (ибо C# не может работать с одной осью):
Мне кажется не оптимально так каждый кадр для каждого персонажа прокручивать, или же есть другой вариант?
То есть, SortingGroup поможет вообще убрать эти пересечения спрайтов, даже если группы находятся на одной Y координате? Если так то круто, не знал, хотя не уверен есть ли такая опция в 2018.2 версии юнити, ибо я пользуюсь той версией из-за того что она последняя понимает JS, а мой долгострой написан на UnityScript((
Но в новой игре, на новой версии юнити возможно даже будет полезно, Спасибо!)
Да, SortingGroup используется чтобы спрайты разных объектов не перемешивались при отрисовке. Просто на родителя надо повесить компонент. Судя по документации в 2018.2 SortingGroup есть.
У тебя же там по сути написано
if (transform.localScale.x != direction) { transform.localScale.x = direction; }
от oldDirection можно избавиться. У объектов без коллайдеров и прочей физики можно и каждый кадр размер менять, с физикой вроде бы как не стоит.Мне просто нужна переменная direction чистая, то есть там должно быть либо 1 либо -1, без плавающих чисел.
А, ты там потом ещё scale домножаешь на что-то. Ну тогда
if (Mathf.Sign(transform.localScale.x) != direction)
.В принципе, как вариант)
хотя от таких проверок в юнити всё равно сложно избавиться, например, если надо проверять отключить объект или нет, допустим это лампочка, можно ли спамить без проверки вот такую функцию каждый кадр,
если таких лампочек ещё и много?
lamp.SetActive(LampOnTrigger);
или лучше мой способ с:
хотя возможно тут по аналогии тоже что-то можно придумать с методом GetActive, хотя хз
может опция называется enabled? типа
В принципе если это работает то прикольно, Спасибо за совет) а то я реально постоянно накидываю проверки типа "old...MyVariable"
В данном случае свою переменную заводить не надо. У гейм обжекта есть поля activeInHierarchy и activeSelf, можно проверять одно из них, то, которое подойдёт в конкретной ситуации. Если на десятке-другом простых объектов будешь просто SetActive без проверок дёргать, то ничего страшного не случится. Если у тебя буллет хел с тысячами патронов, то там будет куча мест где и чего оптимизировать, и об активности объекта ты будешь знать и без проверок.
Мне кажется, ты пытаешься оптимизировать не там, где будет тормозить. И, возможно, раньше времени.
Первый и четвертый пункты чет перемудрены. Кроме sorting order, есть еще sorting layer, и вот layer глобально используется для того, чтобы разделять объекты на группы по приоритету отрисовки. То есть, можно вынести layer для персонажа и layer для противников, и если layer противников будет ниже layer персонажа, противники уже никогда не будут рисоваться поверх персонажа. А order используется уже внутри самого layer, например, чтобы задать порядок отрисовки отдельных элементов.
Я кстати заметил, что у меня нет отдельного слоя для врагов (а надо бы), я просто дал персонажу ордер 10 или типа того, и это кстати тоже вполне сработало бы (просто начинаешь с большого значения для персонажа), но со слоями это куда проще.
Я думал SortingLayer это тоже самое что и SortingOrder, только как константы потому и никогда не пользовался,
но всё же, а что если мне надо каждого непися фильтровать друг от друга, чтобы они не пересекались между собой, на каждого непися отдельный SortingLayer делать?
Посмотрел, похоже решение с Sorting Group выше должно работать нормально.
В настройках можно сделать сортировку по Y. + на персонажа вешать сортинг груп. И у спрайтов не забудь выставить ориджн поинт а не центр. Этого всего достаточно чтоб никто ни с кем не конфликтовал.
Возможно я мазохист :D , но мне почему-то больше нравится отрисовывать через draw, хотя конечно не нравится вручную настраивать координаты, можно было бы так чтобы размещать по координатам было бы как в юнити (визуально в редакторе размещать), а управлять отрисовкой спрайтов как в GameMaker, то было бы супер.
Да, это принципиальная разница в подходах - {создавать и удалять объекты для любого элемента картинки} против {прописывать что рисовать каждый кадр в коде}.
У обоих вариантов свои плюсы и минусы (и свои поклонники и противники), лично мне больше нравится второе, а в идеале видимо должна быть возможность легко делать и так и так. Впрочем, в юнити вполне можно один раз запилить велосипед который будет вызываться как draw_sprite_ext() каждый кадр, а внутри сравнивать новые вызовы со списком вызовов из прошлого кадра и создавать\удалять требуемые объекты. И да, тормозить не будет.
У гмс и юнити такой возможности нет?
Насчет ГМС я без понятия, в юнити (как и любой среде с первым подходом, я для SFML такое сделал) можно сделать свой велосипед для immediate режима, хотя он, возможно, будет менее удобен чем родные методы.
В юнити всё окей с созданием объектов, но нет отрисовки draw.
Но в GMS я хз, кажется нету создании визуальной иерархии объектов в редакторе,
но лично мне нравится метод draw, хотя я хочу чтобы работали сразу 2 метода,
когда я не хочу париться с созданием ста мелочей, то просто пропишу в коде отрисовку без создания и удаления этих мелочей, этих ста объектов просто физически не будет существовать.
И кажется именно в годоте есть оба метода, и отрисовка и создание объектов, поэтому меня годот тоже очень заинтересовал)
Нет уж... Давай осваивай гмс, раз начал, а то так и не напишешь никогда игру своей мечты.
вроде в гмс2 что-то такое в вели недавно, но я не совсем уверен насколько это то, так как сам не пробовал...
Нету там такого. Но руками несложно допиливается, если нужно.
в 2.3 но оно вроде ещё в бете или типо того... некий animation curve но опять же возможно вы правы)
В новой бете вводят.
В GMS объекты по-другому устроены в отличие от юнити.
В юнити ты можешь сделать пустой объект и навешивать на него компоненты. В GMS объект сразу идёт со всей своей обвязкой. Поэтому городить в GMS иерархию дорого по производительности.
Лично мне не нравится иерархия в юнити. Точнее так. Я понимаю для чего она нужна и для 3Д игр она необходима. Но 2Д игры на юнити всегда были злом. И там можно запросто обойтись без иерархий.
К тому же, в GMS её можно сделать вручную по мере надобности. А в юнити рисовать как GMS не получится =)
Мне иерархия в юнити на 2д нужна для кастомизации и ленивой анимации, чтобы одна анимация работала для 100-200 разных персонажей в игре, конечно это зло, я понимаю, но кастомизация это моя слабость, в юнити я не знаю как иначе сделать без иерархии) А в GMS норм без иерархии благодаря отрисовке на лету)
Это о ГМС до 2.3, теперь это устарело и структуры данных существуют отдельно от объектов, производительность страдать не будет. Я так понимаю, пост мой ты про 2.3 не читал, или не вник в его суть, а стоило бы.
Золотые слова.
У этих структур данных нет ни полиморфных методов, ни наследования, поэтому иерархию на них не забабахаешь.
Хейзер под иерархией имел в виду не наследование, а композицию. Так что забабахаешь.
да на юни и 3д не всегда гуд =) (хотя возможно это разрабы перемудряют, но всё-же...)
Какая визуальная иерархия? Вроде бы речь идёт о слоях - они есть. Насколько я понял, SortingOrder из Юнити это переменная depth в объектах ГМа, а SortingLayer это слои инстансов в ГМе.
В твоём конкретном случае достаточно написать просто:
И всё, у тебя порядок отрисовки меняется в зависимости от Y-координаты.
А по поводу того что можно сделать игру не используя draw_sprite ни разу - разумеется можно. Я так первые свои игр 5 сделал.
Спасибо! Как раз с отрисовкой пули и взрыва надо было решить вопрос)
было бы прикольно такое замутить, но я придумал только сложный метод, который будет нагружать проц)
ну он будет на сколько-то нагружать, но тысячу раз за кадр сделать "if" - это вообще ни о чем. Сделать dictionary в котором ключом будет спрайт и координаты, при вызове draw_sprite_ext искать в нем текущий вызов, если не найден - добавлять новый объект. А в конце обработки кадра удалять объекты которыеза этот кадр не вызвали. Точнее не удалять а прятать, чтобы потом переиспользовать когда понадобиться добавить новый объект.
Чтобы прятать нужно ещё какой-то список спрятанных объектов сделать, в целом возможно этот вариант не так плох, хотя по ощущениям кажется что много ресурсов это всё будет кушать)
Режим с созданием объектов в любой случае более оптимален чем непосредственный - меньше данных пересылается на видеокарту. В одном случае пересылаем когда что-то добавилось\удалилось, в другом - каждый кадр пересылаем всё (если конечно в draw_sprite_ext под капотом нет аналогичного механизма).
Но если объектов порядка тысячи, шустрый скриптовой язык и сделать без явных косяков, то тормозить особо нечему.
Сейчас гуглю, как работать с коллизией в GMS, place_meeting вроде ок, только надо понять как заставить фильтровать во что врезаться, а что игнорировать) Надеюсь эта функция проверки коллизии очень быстрая, ибо в коде её надо вызывать 2 раза для проверки X и отдельно Y скорости, прям как в моих самописных проверках коллизии для Tic-80 и BlitzMax, где проверка по разным осям идёт отдельно, но если что-то не предусмотреть то можно застрять в стене, например если стена будет двигаться на персонажа)
да, норм по скорости... у тебя какой гмс?
GMS 1.4.9.
У меня почему-то в редакторе подтормаживает при запуске игры, если включен хром, может быть это из-за моего слабого ноута, но это пустое приложение без ничего, кроме перса, а иногда работает очень плавно и хорошо, хз с чем связано.
Надо потом потестить в билденной версии вне редактора, и параллельно хром включить.
Всем известно, что Хром прожорливая скотина способная даже при пустом окне съесть всю твою память и даже не подавиться...
смотри диспетчер... а так фиг знает...
так же чтобы определять с кем столкновение, можно использовать "кнопочную" коллизию с идентификаторами self.inst (obj name something other), other.
Спасибо, попробую разобраться с этой функцией! Я тут как раз думаю над тем, как сделать так, чтобы часть объектов игнорировалось при коллизии:
Например я нашёл функцию, которая сталкивает только с объектами "solid"
и есть такой способ, чтобы проверять более сложную коллизию, но не уверен быстро ли он работает
и нормально ли то что я вначале place_meeting проверил, а потом сделал вторую проверку (для оптимизации),
или может это не важно и можно сразу делать проверку на instance_place:
В данном случае первая проверка не нужна. Если говорить про оптимизацию то это просто лишнее условие. Скорее всего обе функции отрабатывают по скорости примерно одинаково.
Насчёт solid-объектов, как мне кажется этот функционал лучше не использовать. Лучше сделать через наследование объектов. place_meeting отлично работает, я сам пользуюсь периодически, хотя чаще всего collision_ функциями.
Не выдумывай, тебе достаточно collision_rectangle(x,y,x+hspeed,y+vspeed, obj_точтонужно, 1, 1)
Зачем collision_rectangle-то?
ну, он "легче"
Точная инфа? Я думал, что наоборот, особенно если для маски объекта не используется точная проверка столкновений, повторяющая его форму. Так-то при столкновении всё равно движок, по идее, обрабатывает bbox_* переменные, фактически - прямоугольные границы (если не была изменена форма коллизии), что равнозначно collision_rectangle. Я бы даже сказал наоборот - place_meeting возвращает true/false, а от collision_rectangle ещё и айдишник объекта, с которым сталкивается, то есть это place_meeting + instance_place.
Когда place_meeting возвращает true, движок внутри себя уже знает id этого объекта, т.к. проверяет каждый конкретный объект по списку id. По скорости нет разницы что он возвратит - id или true. По крайней мере, я не вижу иной оптимальной схемы работы движка.
Задержка может быть только в том, сколько экземпляров он проверил перед тем, как нашел нужный.
Вот кстати о множественной одновременной коллизии - если писать кодом, то нужно будет получать СПИСОК объектов с которыми столкнулись и с каждым из них выполнять код. Если делать через событие коллизии, то оно автоматически выполнится для всех объектов с которыми столкнулись, не надо будет писать цикл по ним. Так что пока что вообще не обосновано написание отдельного кастомного кода для того чтобы реагировать на коллизии.
Обычно это делают против нежелательного туннельного эффекта, когда слишком быстро летящая пуля со слишком маленькой маской пролетает через слишком тонкие стены. В проекте Алекса такого, насколько я видел, нет, а может и не предвидится. Зачем же мудрить?
Второе "обычно это делают" - это когда нужно детектить пол в платформерах и отдельно левую, правую и верхнюю грань коллизии. У Алекса не платформер, там перемещения на манер битэмапа/RPG по примеру Beyond Oasis (только вид таки сбоку).
А еще можно использовать стандартный механизм коллизий для получения этого СПИСКА в одной строчкой кода, чтобы потом использовать его в самописных коллизиях. Но я честно хз, что происходит первее ev_collision или ev_step (normal)
Для самописных коллизий пока что не видно причин использования в проекте Алекса. А так да, можно всё писать вручную, а с ГМС2.3 при желании вообще можно выкинуть всё встроенное и писать почти как на голом C++ уже обвязанном библиотеками вывода графики, звука и всего остального. Причём кроссплатформенно ключая игровые консоли.
https://docs2.yoyogames.com/source/_build/2_interface/1_editors/events/index.html
См. Event Order - про коллизии на данный момент ничего официально не пишут. Полагаться ни на какой порядок нельзя, но с другой стороны это всегда можно отладить для конкретной версии ГМа на которой идёт работа.
https://kolenka.net/posts/tochnaya-proverka-korotkikh-intervalov-vremeni-v-game-maker - но в ГМ8.1 они абсолютно точно работают после Step и до Draw.
А зачем place_meeting?
А можно из той коллизии получать свойства объекта при столкновении?
Мне просто нужно знать с кем столкнулся и провести некоторые проверки или переслать сигналы.
И можно ли вместо "obj_точтонужно" поставить, например типа свойства "solid" или по другим свойствам?
А то мне не нравится когда спрашивают с каким объектом сталкиваться, ибо я не знаю что это будет за объект, но я знаю какие нужны будут свойства этого объекта, чтоб столкнуться.
1) Например я хочу чтобы моя пуля сталкивался с 4-мя типами объектов: Стены, Другие Пули, Враги, Герой.
Должен ли я писать 4 функции для этого или хватит просто им проставить ну например свойство solid?!
2) Ещё я не уверен, можно ли как-то послать сигнал объекту, когда столкнулся с ним, потому-что кажется что внутри объектов в GMS нет классических функций, как в юнити происходит методом
SendMessage
илиGetComponent<Class>.MyFunction();
,мне нужно послать сигнал урона, к объекту с которым столкнулась пуля, типа
MinusHP(5);
Пока я сделал через переменные, но выглядит немного как костыль и не уверен нужно ли стенам тоже добавлять эти переменные типа HurtHP,HurtSX,HurtSY, чтоб не выскочила ошибка, хотя стены не уничтожаются и им это не нужно, разве что можно ещё одну сделать переменную типа Type, которая будет говорить,
что это тип стена Type = "Wall" и чтобы не было проверки на HurtHP:
Флаг solid вообще не для того - всё что ты обозначаешь как solid, будет выталкивать из себя все столкнувшиеся с ним объекты автоматически, причём это выталкивание может работать не так как тебе нужно, и настроить его нельзя. По большому счёту это вообще лишний функционал, тянущийся из старых Гамаков 15-летней давности чтобы не нарушать обратную совместимость.
По поводу твоего случая - ну, если бы я рассуждал таким образом, то я бы писал 1000 разных веток столкновений для 25 видов оружия и 40 видов врагов в моём проекте Void Source, но всё делается намного проще.
Если твои пули не летят с гигантской скоростью, то коллизии с ними (и чем угодно другим) легко можно поручить событию Collision (как ни странно), поэтому код проверки коллизии писать вообще не понадобится, сразу будешь писать действия которые при этом надо совершить.
Далее - тебе нужна абстракция, то есть некий объект, "то с чем может столкнуться пуля", а чтоб это было валидным названием объекта, назовём его o_shootable, дословно "то, во что можно стрелять". Теперь мы берём эти твои 4 типа объектов: "Стены, Другие Пули, Враги, Герой", и каждому из них назначаем объектом-родителем этот самый o_shootable, вот здесь:
Теперь идём в объект-пулю, создаём там событие Collision с o_shootable и пишем туда код, ну скажем:
Теперь, с кем бы ни столкнулась пуля, она уничтожится сама, а потом уничтожит тот объект с которым столкнулась. Естественно, можно выполнять любой код как с пулей, так и с другим объектом, типа - отнять щит вместо хитпоинтов, вообще говоря проверить меньше ли хитпоинты нуля, прежде чем уничтожать объект, снизить скорость пули вместо уничтожения и летать дальше, и так далее.
Тут может стать вопрос - что если видов стен и врагов много, всем наследовать o_shootable? Нет! Тебе нужен объект абстрактного врага, объект абстрактной стены, и так далее. Они наследуют o_shootable, а каждый конкретный враг наследует o_enemy, тогда как каждая конкретная стена - o_wall. Нафига, спросишь ты. Для того чтобы вместо 40x25 коллизий у тебя только в абстрактном выстреле была только одна коллизия с абстрактным врагом, и все конкретные выстрелы, враги, стены, и так далее - автоматически наследовали это поведение.
У объектов в GMS есть пользовательские события, делаешь так:
Потом в событии коллизии пули с o_shootable вместо того что я выше написал, делаешь так:
И у объекта происходит обработка повреждений - такая, какую ты ему прописал в событие User Event 0, например:
Учитывая наследование, которое я описал выше, писать это нужно в абстрактные объекты, а не в конкретные, чтоб не копипастить всё по 200600 раз.
Альтернативный вариант:
И создаёшь скрипт receive_damage() в котором пишешь то же самое, что и в предпоследнем куске кода - отнять хитпоинт, если закончились - исчезнуть. Ведь скрипты в ГМе - это и есть функции (примечание - только до версий раньше ГМС2.3 - начиная с 2.3 в одном скрипте может быть даже несколько функций).
А это, кстати, для чего тебе передавать нужно? Или точнее - что это, скорость урона в координатах...???
У меня Пули и Враги имеют уже родителя (parent), то есть например:
Laser имеет родителя ShotCore (как бы подвид выстрела, а в ShotCore основной скрипт), EnemySpaceBunny имеет родителя EnemyCore (как бы подвид врага и главный AI всех врагов), стены пока не имеют скриптов, но видимо придётся добавлять.
Если это и есть "родитель всех категорий врагов", куда вынесена самая общую для всех врагов логика, то используй его в схеме описанной выше. Если это только некая категория врагов, но не все конкретные враги это наследуют, то нужно создать более абстрактного врага и унаследовать все категории врагов от него. То есть будет:
EnemySpaceBunny -> EnemyCore -> EnemyVoobshe
Laser -> ShotCore -> ShotVoobshe
Важный момент: объекты надо называть с префиксами типа o_ потому что спрайт Laser и объект Laser будут конфликтовать, и ты в коде не поймёшь на что ссылаешься. Либо спрайты называй на s_, но обычно объектов в проекте меньше чем спрайтов, так что и лишних нажатий при наименовании меньше будет.
Вопрос про HurtSX актуален - что это такое и как используется в твоей архитектуре геймплея?
видимо пока не поздно надо всё переименовать с "s_" "o_", чтобы не запутаться потом)
у меня пуля не сразу уничтожается, вначале прокручивается таймер и анимация эффекта уничтожения
Такое поведение удобно делать с отдельным объектом: пуля ведь не может продолжать сталкиваться с чем-то ещё, если она уже столкнулась? Значит пора бы её действительно уничтожить, а в событии Destroy этой пули сделать instance_create(x,y,o_shot_effect) который уже просто будет проигрывать анимацию, ни с чем не пытаясь сталкиваться и не разбираясь во флагах надо ему сталкиваться или нет. Просто другой объект-пустышка с событием Animation End в котором instance_destroy(). Не забыть в Create поставить image_speed=0.25 или сколько нужно.
Если объектам делать сложную parent структуру, то может и правда стоит делать новые объекты для уничтожения пули, чтобы это всё не занимало ресурсов и не было проверок на коллизию.
Я тут для иллюстрации набросал схему. Сложно читается, но думаю суть ясна. Не важно сколько уровней наследования ты используешь, на каждом из них ты экономишь силы при расширении функционала конкретных объектов, за счёт изменения абстрактных объектов.
Меняешь o_damageable - влияешь на всё "живое".
Меняешь o_wall - влияешь на все стены.
Меняешь o_enemy - на всех врагов.
o_enemy_swimming - только на плавающих.
Ну а меняешь конкретные объекты влияешь точечно, именно на них.
В этом вообще смысл наследования в ООП.
Мне только немного странно с GMS 1.4.9, что если например есть переменная HP в o_damageable,
и я её указал при старте
HP = 10;
но почему-то, если я не укажу туже самую строку при старте o_enemy (хотя в родителе уже инициирован HP)
HP = 10;
то почему-то без этой строки в наследнике компилятор выдаёт ошибку, неужели у одного родителя не достаточно этой строки при Start Event?
Create Event ты имел в виду наверное.
Да, тут есть один минус - для того чтобы наследники выполняли код родителя, нужно писать команду event_inherited(), но с другой стороны - зачем тебе враг без хитпоинтов, тебе их всё равно придётся прописать в каждого врага - лично его живучесть, как и все другие статы.
В событиях, которых у наследника нет, код родителя выполняется автоматически (вот на этом и экономится та тысяча комбинаций коллизий), в остальных - event_inherited() пиши где нужно. Можно до своего кода, можно после, можно даже несколько раз в разных местах.
точно, я забыл про эту штуку) хотя в примере было про это, когда учился inheritance на GMS
наглядно) сохраню
Вот это офигенно), но жаль что этих функций ограниченно.
С 2006 года делаю игры на ГМе и ни разу не задействовал даже половину из них - нет таких архитектур и геймдизайнов в которых нужно столько всего. С другой стороны циферные обозначения это вообще неудобно - для этого есть скрипты, и вот их уже действительно можно создать неограниченное количество.
Для того чтобы оттолкнуть врага или героя в зависимости от скорости и силы пули или урона в противоположную сторону.
Ого, это крутая механика, продуманно.
Не обязательно что-то там передавать, если можно просто от имени пули:
Как вариант, hspeed/2 и vspeed/2.
точно, хотел погуглить как hspeed и vspeed ставить на паузу при открытии меню
Никак. Придётся использовать Unreal Engine 5. :yak:
instance_deactivate_all(true)
и
instance_activate_all()
То же самое с _object вместо _all, если в проекте несколько уровней вложенности паузы, или сложная система игровых состояний.
А, ну ты щас спросишь - а как чтоб объекты отображались на фоне паузы. Тогда:
https://docs.yoyogames.com/source/dadiospice/002_reference/windows%20and%20views/screen_save.html
И отрисовывай скриншот.
Если же ты хочешь чтоб они ещё и анимировались, ну это тебе придётся весь код писать так, чтоб объекты можно было произвольно "запаузить" - бэкапить их таймеры чтоб они не срабатывали во время паузы, но при этом не трогать image_speed, при паузе делать global.paused=!global.paused и прописывать в Step каждого объекта if global.paused exit. Это всё реализуемо, главное сразу говори в точности что тебе нужно.
>>instance_activate_all()
Я немного не понял, а в кнопках в меню тоже остановится скрипт с этой функцией? Потому-что мне нужно
не только поставить игру на паузу, но и при этом лазить в меню и продолжать работать со скриптами,
но только теми, что относятся к меню.
Например для ручной скорости у меня есть решение, вот код из управления героем:
if (global.Menu != noone) exit; //Pause Correction
то есть дальше этой строки не читаем и персонаж не двигается и не анимируется вручную,
но пуля у меня на автоматической скорости c hspeed/vspeed, и я думаю возможно придётся её тоже делать вручную...
Я предполагал что меню у тебя одним объектом вместе с кнопками. В таком случае:
Чтобы не писать все кнопки вручную (меню ведь может меняться на протяжении разработки игры), опять-таки, создай абстрактную кнопку и унаследуй все кнопки меню от неё. Вне зависимости от того, какие из них ты будешь использовать в игре, активироваться будут они автоматически и в любых комбинациях.
Проще при паузе делать:
А при снятии паузы обратно:
Наверное тогда проще использовать вместо hspeed/vspeed, свои переменные SpeedX/SpeedY,
видимо точно придётся избавить от всех переменных автоскорости в проекте
хотя в таком случае, надо подумать как изменить эти строки кода с автоматической скоростью, на ручную при создании выстрела
Ну вот видишь. Не проще.
Ты много хочешь изначально, я не представляю как это всё кодилось бы в Юнитях-Годотах, несмотря на то что всегда кто-то выкрикивает из толпы "да это же элементарно!". Ну и как это сделать?
И всё же, у тебя достойная цель, поэтому я тебе написал как это делается, в десяток строчек и один дополнительный объект.
лол, у меня есть костыль, но выглядит тупо) забрать данные у hspeed и отключить)
Этот код вызывает пару вопросов...
Почему мы стреляем от имени прицела, а не от имени игрока?
Почему -180 отнимается в image_angle, а не в _ang?
Но вообще, это должно работать. Только я напомню, ты решаешь сейчас задачу, которая тебе накидывает на горб обязанность во ВСЁМ проекте, ВСЕГДА для всех останавливаемых на паузу объектов прописывать свою "неавто"-скорость. Подумой.
Если ничего не надумоешь (а зря), то вот штатное решение, которое на 1% облегчит использование твоего дорогого и трудоёмкого костыля:
наверное, если сделать так, то не надо будет и -180 делать, это просто мой косяк, ибо это стреляет враг по герою, а не герой по врагу
Мне кажется это решение немного странным. Я наверное просто избавлюсь от всех hspeed/vspeed, если только потом не окажется что частицам (если частицы вообще работают на моей бесплатной версии GMS 1.4.9 :P ) для паузы тоже нужен такой способ, какой ты предложил. Я хотел просто отключить логику объектов, но продолжать рисовать спрайты.
Чего кажется странным, рабочее решение, просто не анимированное.
Есть ещё вариант для анимированного: забываешь про глобальный флаг паузы и exit, действительно всё кроме меню и кнопок деактивируешь, но ровно перед этим делаешь вот что:
o_decoration это объект, в ивенте Draw которого прописано:
Он будет просто "торговать лицом", используя код объекта поставленного на паузу, пока пауза не вернёт к жизни тот объект который он отрисовывает. При снятии с паузы нужно сделать
with o_decoration instance_destroy()
соответственно.что-то жесть какая-то) возможно решение со скриншотом легче или хз
Не знаю, вот тебе три разных решения, выбирай на вкус.
А я думаю что у меня объекты иногда странно отталкиваются, не так как я прописал) надо убрать эти галочки
Чтобы скорость в GMS начала проседать нужно быть очень плохим программистом.
Если ты понимаешь что делаешь, то смело используй практически любые функции столкновений. Пока у тебя в комнате счёт на объекты не перевалит за тысячу-другую вообще не переживай.
Ну и проверки столкновений в циклах используй аккуратно (вот там много итераций цикла тебе fps не простит)
Упорядочил спрайты :3 и другие объекты с дополнительными символами "s_" "o_" "b_"
А еще можно делать красивые иконочки для объектов
Выглядит прикольно)
Теперь точно не перепутаешь, и в коде тебе будет подсказывать только те типы ресурсов которые ты хочешь. Не будет такого что ищешь индекс объекта, а тебе выпадает список всего - спрайтов, звуков, фонов, комнат на заданную букву.
Понял чем ещё плохи переменные автоскорости: hspeed/vspeed
Их не только сложно на паузу поставить, но также и если я захочу добавить замедление времени,
то лучше избавляться от таких автопеременных и делать переменные вручную, типа:
x += SpeedX*timeSpeed;
y += SpeedY*timeSpeed;
Да, только так и нужно делать замедление времени. Таких изи-штук как в юнити в гамаке увы нет. В юньке это одной переменной делается, в.т.ч. и пауза.
Да в принципе, нормальный способ. Просто решил полностью отказаться от использования в GMS переменными hspeed и vspeed, ибо чтобы ими управлять нужны всё равно дополнительные переменные, когда можно сразу
сделать 2 дополнительные переменные типа SpeedX и SpeedY и вручную скорость делать)
Вообще иногда эти переменные полезны. Когда нет слоумо, например. То вся кинематика уже заложена в speed,vspeed,hspeed,direction,friction,gravity,gravity_direction. И функционал типа motion_add. Всё это бывает полезно на понятных кинематических задачах. В платформерах и аркадах этого бывает хватает за глаза.
Не вижу причин не использовать vspeed и hspeed как тупо переменные в самописной физике как у тебя, при условии, что после обсчета координат добавлять строку speed = 0, чтобы скорость не меняла координаты повторно. Плюс в том, что у тебя остается доступ к актуальной speed и direction.
Я немного не понимаю как работает hspeed/vspeed и speed. Если
speed=0
сделать и если при этом hspeed не поменяется, то это было бы решение с паузой, надо потестить взаимозависимы ли эти переменные или нет, и как они вообще друг на друга влияют.Каждый раз как ты меняешь hspeed ИЛИ vspeed, меняются также speed И direction. Верно и наоборот - меняешь speed ИЛИ direction, меняются hspeed И vspeed. Но я же уже тебе говорил - не юзай эти перееменные совсем, а для перевода расстояния в его компоненты по осям используй lengthdir_x / y.
Щас вы его научите - не юзай hspeed, не юзай self.
Переменные speed и direction, в совокупности, являются направленным вектором движения. Соответственно hspeed и vspeed - это горизонтальный и вертикальный компоненты этого вектора. Когда ты меняешь что-то одно, меняется и все остальное. Ты можешь нарисовать вектор на бумаге, а потом посмотреть как он изменится, если изменить, скажем, горизонтальный компонент вектора. Меняется и длинна вектора (скорость) и его направление.
Ты можешь использовать все, что пожелаешь. Все это удобные инструменты предоставленные нам разработчиками из Yoyo. Помогают ли они решать технические задачи или просто делать код более читабельным, не стоит ими пренебрегать.
Ты прав. Просто Алексу хоть убей в текущем проекте нужно сделать такую паузу, чтоб скорости где-то хранились, но при этом не использовались движком автоматически. И ладно бы просто деактивацию инстансов делать - нет, ему надо чтоб они ещё и рисовались на паузе! И решение со скриншотом, успешное применяемое, например, в Aborigenus и в Pixel Gladiator, почему-то смущает тоже.
Это у него такой авторский уникальный случай, нехарактерный для большинства игр которые прекрасно делаются на ГМе.
Не иначе как делает убийцу Pause Ahead
То вы - лох. Смотрите видеопрохождение:
...займитесь некромантией и воскресите у себя флэш.
Мне интересно, а почему надо делать скриншот уровня чтобы поставить игру на паузу?
Нельзя ли просто deltatime сделать 0 чтобы все объекты перестали обновляться?
В GMS-е нет deltaTime. Есть room_speed, но... В общем вряд ли у тебя что-то с этим получится. Можешь поизучать вопрос если хочешь.
Есть ещё всякие хитрые штуки. В GMS1 точно есть. Есть keyboard wait или что-то типа такого. И можно в step сделать цикл - тогда игра подвисает до тех пор пока не нажмёшь кнопку.
А почему ты хочешь сделать паузу именно так? Это какой-то элемент геймплея или просто твой дизайнерский изыск?
P.S. В юнити это вроде не delta_time, а что-то типа timeScale.
keyboard_wait() туфта, он obsolete ещё в GMS1 и не подходит для геймпадов. Больше никаких хитрых штук нет.
Прикольно что вы отсутствие какой-то элементарной паузы в этом вашем гакаме объясняете "зачем тебе это надо?".
Мне нужна нормальная пауза.
В love2d это делается элементарно. Как это сделать в ваша гамаке без костылей?
Переводишь комнату в состояние persistent, переходишь в другую комнату с паузой. Можешь с application_surface предварительно спрайт создать и подложить в новой комнате в качестве фона.
Ещё можно через instance_deactivate_all и instance_activate_all.
Не понимаю почему это сразу костыль. В гамаке есть функции которых нет в юнити, в юнити есть функции, которых нет в гамаке. Это вообще нормально.
Если тебе ТАКАЯ пауза прям critical feature - так делай на love2d, в чём проблема?
Ты же сам движок подбираешь под свои задачи =)
P.S. Чисто технически это как раз костыль в юнити, потому что там у тебя события объектов отрабатывают с нулевым delta_time, а в гамаке ты можешь сделать паузу легковесной, т.к. деактивированные объекты и объекты в другой комнате в рассчётах не участвуют.
Так там нет редактора уровней.
Вы с Кситилоном постоянно утверждаете что гамак лучше юнити и love2d, и что это вообще чудо чудное - я вижу что не совсем.
Твой вариант с комнатой - тоже костыль, эмуляция паузы. А вся проблема в том что для разработчика вся игра на гамаке вертится вокруг объектов. Хочешь паузу - создавай объект в комнате. Хочешь меню - создавай объект в комнате. В то время как ни то ни другое - объектом уровня не является. В гамаке нет глобальной сущности, управляющей всей игрой разом, все делается только через объекты.
Какие? Гамак - конструктор, юнити - движок, априори во втором возможностей будет больше.
Бред несёшь. Почему ты считаешь что истинная пауза - это только timeScale в ноль убрать? Только потому что так сделано в юнити и лёве?
ЛОЛ, при том что все объекты в юнити - это тоже объекты, отнаследованные от MonoBehaviour, насколько я помню =) И вроде ты не можешь написать скрипт просто так в вакууме, его нужно к объекту приаттачить.
Нужна управляющая сущность - создай. Я всегда создаю o_resources_controller с галкой persistent для этих целей. Это чисто практика программирования, а не отсутствие возможностей.
Начнём с того что Гамак слабо типизирован и ты можешь всякие штуки с переменными делать. А самое главное - не протаскивать весь каскад встроенной иерархии объектов чтобы сделать элементарные вещи. Когда в юнити был JS то можно было, а в шарпах нельзя, увы.
Названия ресурсов в юнити нельзя использовать напрямую (раньше так было по крайней мере), передавай в скрипт как аргумент. Настаёт момент когда это начинает заёбывать.
Прописывание событий - редактирования довольно длинной портянки с кучей синтаксического мусора. В то время как в GMS - это наглядный список событий. Скрипты хранятся отдельно от объектов. Типа на случай переиспользования, ага, что реально на практике всего в 1 объекте из 100 пригодится. А искать каждый раз какой скрипт к каким объектам подвязан тот ещё гемор.
Работа с глобалами в юнити мне не понравилась. Это нужно писать скрипт со статическими переменными, который потом непонятно к какому объекту прикреплять. Или как советуют - создавать синглотон. И это ты мне рассказываешь потом что дескать в ГМ всё крутится вокруг объектов. Ха-ха. В GM в любом месте globalvar сделал и потом обращаешься к ней из любого места без неймспейсов и прочего.
Редактор сцены. ууууу. Если сравнивать в плане 2Д игр, то в GM есть крутая фишка со слоями, а в юнити лишь иерарахия в которой навалено всё в кучу без элементарной группировки. Ах да, там можно создать пустой объект и внутрь него поместить что нужно. Но это же ни разу не костыль, "потомуштаюнити", видимо XD
Про Pixel perfect много было сказано. Его в юнити попросту нет. Или он достигается лютыми костылями.
Как выяснилось, в гамаке не нужна сортировка спрайтов для адекватной орисовки, там всё автоматом сортируется как нужно.
Я могу довольно долго продолжать список того что мне не нравится в юнити. Так же как и список того что мне в юнити нравится. Но т.к. я делаю 2Д игры то выбираю GMS, т.к. именно 2Д игры делать в нём проще, быстрее и практически без костылей.
Потому что только в этом случае игра полностью останавливается.
Можешь. Статические функции. Только его код тоже придется из другого объекта вызывать, как в гамаке со скриптами.
Вот! Чтобы тебе не требовалось сделать - надо создать объект внутри какой-нибудь комнаты.
А потом таскать его все время с собой.
LUA тоже слабо типизирован.
В Юнити есть яваскрипт, во всяком случае был.
И где-то читал что его поддержку никуда не убрали, а только удалили возможность создать JS-файл.
Во всяком случае с Boo - точно.
Никуда прикреплять не надо, создаешь статический класс и в нем - обьявляешь публичные статические переменные.
И по мне это лучше - все глобальные переменные в одном файле, а не разбросаны по объектам.
И чем тебе это не группировка? Тем что используется иерархия объектов, которой нет в GM? Если бы была, то уверен, так же сделали как в Юнити.
Ну нет же. Нет гарантий что где-то нет кода, на который timeScale не действует. В случае со скриншотом у тебя эти гарантии есть.
Тогда в чём отличие? Если тебе всё равно где-то в какой-то левой сущности нужно его вызвать. И объект этот поди ещё должен быть на сцене чтобы это запустилось? В чём отличие от:
Тоже не верно. Ассеты и тайлы я могу располагать в комнате без объектов. А так то мы живём в мире ООП и мыслим объектами, не вижу проблемы в выделении объекта на конкретную функциональность. В любом движке сделано именно так.
ЛОЛ, ты сам себя слышишь? В юнити есть яваскрипт, вы только не можете скрипты на нём создавать и код писать, а так он есть XD
То же самое можешь сделать и в гамаке. Создать persistent объект и в нём переменные и обращаться через его имя. При том что в Юнити нельзя сделать как а гамаке - объявить глобал в любом месте и обращаться в нему напрямую. Мы же говорим о том что ЧТО МОЖНО СДЕЛАТЬ В ГАМАКЕ ЧЕГО НЕЛЬЗЯ НА ЮНЬКЕ =)
А дальше уже твоя самоорганизация кода. Мне удобно различать глобалы по капсу, а не по наличию приставки global или названию класса. Код чище и читается легче.
Группировка со своими плюсами и минусами. Только вот слоёв в юнити нет, а в гамаке есть. У тебя был конкретный вопрос
У меня конкретный ответ. Вопрос закрыт? Нашли то что может делать гамак чего не может юнити?
Слои отстой*, depth был лучше. Его ещё не выпилили, но всё к этому идёт.
* не пригождались в моих проектах никогда
К слову, не помню в какой игре (на love2d, не на гамаке конечно), делал 2 иерархии для объектов.
Одну - для обновлений (от корня к ветвям), вторую - для отрисовки (просто списки 1, 2, 3).
Это можно сделать и в ГМе тоже, просто чем обосновать это решение?
А причем тут гамак, я же сказал "к слову".
Понадобилось сделать так чтобы один объект мог двигаться вместе с другим и при этом могли отрисоываться в нужном порядке.
Ты упускаешь уточнение - "для двухмерных игр". Повторюсь, что тот тип паузы и таймскейла на который ты и Алекс почему-то рассчитываете, разбалованные Юнитями, не характерен для двухмерных игр вообще. Подавляющее большинство двухмерных игр делаются проще в Гамаке чем в Юнити, это попросту факт.
Потому что в ГМе есть драг-н-дроп, а в Юнити нет? Тогда смотри, в Анриале есть блюпринты - это тоже конструктор по-твоему? А как тогда?
И да, нет ни в жизни, ни в софте, никаких "бОльших возможностей", возможности есть только "разные".
Блин, я об этом даже не подумал. То есть это уже где-то четвёртый способ сделать то что нужно.
Не какой-то элементарной, а конкретного изощрённого подвида паузы трёхмерных игр, которого нет практически ни в одной двухмерной игре (мы ведь о них говорим?) - пауза, в которой остаётся прорисовка кадра, да ещё и пассивные анимации. Обычная пауза это ты вышел в главное меню и ничего в игре не видишь, такую паузу в нём делали ещё в те времена когда не было никакого Юнити, Лава и вот этого всего новомодного.
Нельзя ли просто сказать: "Горшочек, не вари!"?
Алекс сейчас занят именно деланием своего дельта-тайма, хотя возможность паузы именно с сохранением отображения всего на экране, да ещё и с анимациями - это далеко не кор-геймплей, да и вообще не геймплей игры. Любить игру будут не за анимированную паузу, и не за наличие оконного режима.
Сим-салабим, делайся игра сама без человеческого вмешательства! Хачу убийцу фортнайта!
И кнопочка такая "Сделать всё заебись"
Чувак хочет сделать анимированную паузу. Нафига вы его отговариваете?
Либо помогите ему это сделать, либо прямо скажите что в гамаке это невозможно.
Да я уже и забил, раз в GMS это сложно.
Можно и не анимированную, просто для меня непривычно подставлять скриншот во время паузы,
никогда так раньше не делал в других движках и за всю мою практику геймдева в: BlitzMax, Blitz 3d, Unity, Stencyl, Construct, MMF, Tic-80, Pico-8. Но попробую разобраться со скриншотом)
Если чо, в love2d это делается элементарно:
В этом примере как раз отключается обновление всей игры, кроме того фрагмента, который тебе нужен, а объекты при этом продолжают отрисовываться.
Покажи ещё, как делается "элементарно" весь остальной функционал GMS, за который его и любят.
То есть вам нечего ответить?
Сказали бы - "да, увы, пауза в гамаке делается через жопу, ничего не поделаешь".
Что мешает в гамаке отдельной функцией или переменной остановить все step? Или сделать room_speed = 0, почему нельзя?
А потому что это конструктор, а не движок и там можно только то что разработчик конструктора реализовал. Не реализовал - значит пиши плагин, ковыряйся сам в кишочках конструктора без исходных кодов или просто смирись с этим.
Насколько я понимаю, только теми методами, которые выше описали, "через жопу". Более знакомые с GMS люди, надеюсь, ответят тоже.
Но это не приговор для GMS, я вот что имел ввиду комментарием выше. То что в love2d есть дельтатайм не делает его суперудобным движком.
В love2d можно не вызывать update и ввод когда надо, и целиком, и выборочно.
Что мешает автору гамака сделать такую простую вещь как пауза? Или, хотя бы разрешить room_speed = 0?
Только то что игроделы научились делать это сами через костыли?
Допустим, есть анимированная пауза.
Вот есть эффект взрыва, который сделан не частицами, а анимированным спрайтом. Как правило, такой объект должен удаляться после завершения анимации. Что будет во время паузы? анимация взрыва отыграется и объект удалится? Или она зациклится?
Если она отыграется - значит это не честная пауза! Если она зациклится - это будет выглядеть как баг. Если фризить анимацию для врзывов - это менеджить твой геймлуп как раз и, во-первых выглядит как РЕАЛЬНЫЙ костыль(обработка одного кейза из множества), во-вторых часть спрайтов анимированных вовремя паузы, а часть - нет - это выглядит хуёвенько, нет единообразия в решении.
Как ты решишь эту задачу?
Во время паузы все анимации остановятся, время будет обновляться только для объектов, для которых не вызывается update.
А как ты тогда сделаешь анимированную паузу на гамаке чтобы при этом все остальные спрайты рисовались, но перестали обновляться?
Опа-па. Что за костыли пошли? Теперь тебе нужно менеджить объекты на те для которых вызывается update и для тех у которых не вызывается. Это ты называешь "простой метод"?
Если во время паузы все анимации остановятся, то всё-таки не нужна пауза с анимациями объектов? Тогда чем плох метод со скриншотом?
Я бы сделал скриншот, деактивировал бы всё кроме объекта паузы и рисовал бы скриншот а поверх него UI.
А если бы мне вдруг зачем-то понадобилось сделать как в юнити с timeScale, то я бы делал так:
0) Заведу глобал TIMESCALE
1) Сделаю объект o_timescalable
2) Заведу в нём Variables в духе t_speed, t_direction и т.д. Так же потребуется заменить массив t_alarm, причём на сколько угодно таймеров.
3) В End Step добавлю их обработку с учётом TIMESCALE
4) Всё то что должно зависеть от TIMESCALE я унаследую от моего o_timescalable и дальше буду работать как обычно но для кинематики буду использовать свои переменные.
5) Объект паузы будет делать TIMESCALE=0
Наверное то что пауза с видимыми анимациями никак не влияет на продажи игр, когда уже есть обычная пауза всех устраивающая? Назовите игру где именно такая пауза. Ты думаешь разрабы Гамака просто сидят на печи и делают что попало? Нет бизнес-обоснования для этой блажи, без которой обошлись и UnderTale, и Katana Zero, и ещё тысячи других игр на Гамаке.
Ксит, у меня наверное самая главная претензия, если есть автоскорость hspeed/vspeed, то почему нет паузы этой скорости, например для физики они сделали паузу, но для этой функции нет,
это немного странно:
physics_pause_enable(flag)
Но в остальном, если не будет автоскорости, то и не будет проблемы, сделал давно вручную метод управления, хотя через небольшой костыль)
Костыль в последних двух строках) я запускаю пулю как будто работаю с hspeed/vspeed,
чтобы было легче угол направления делать, а потом забираю сразу всю скорость у этих переменных, переводя на ручное управление, потом может подумаю, как сделать вручную расчёт угла скорости, чтобы вообще не юзать hspeed/vspeed/speed/direction
Хотя возможно из-за того что я только начал изучать GMS и устал, тут некоторые строки реально лишние, потом на свежую голову попробую переписать код.
Может потому что эта фича непопулярна? Йойо делают в Гамаке то, о чём 1) долго и 2) много людей просят. И не надо думать что в Юнити поступают как-то иначе, просто там другие люди с другими хотелками (ну и в 100 раз больше сотрудников, соответственно они могут делать в 100 раз больше хотелок но вместо большинства из них продолжают делать кватернионы вместо матриц и скриптаблобджекты вместо простых скриптов).
Установка всех скоростей в 0 одной командой тебя не спасла бы, потому что помимо неё тебе нужно чтобы и Step перестал выполняться, но что самое главное - тебе нужно чтобы отрисовывательная часть Draw-событий продолжила выполняться, а не-отрисовывательная прекратила! Ведь в Draw можно вписать любой код, в том числе меняющий переменные обычно находящиеся в степе. Что тогда - искусственно запрещать писать в Draw всё кроме рисования, или фильтровать это при установке флага "фсемстаять"? Любой из вариантов уже совсем не так просто реализовывается, как тебе сейчас взять и сделать:
Об этом говорилось раз, два, и говорю третий:
http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/maths/number%20functions/lengthdir_x.html
http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/maths/number%20functions/lengthdir_y.html
Ну и обратно:
http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/maths/vector%20functions/point_direction.html
http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/maths/vector%20functions/point_distance.html
Спасибо! Я хотел погуглить, что за lengthdir такой,. Да забыл)
Я не понимаю твоей агрессии по данному вопросу. Будешь так орать - отправишься в мой личный игнор.
Как ты привык сделать нельзя. Но это не значит что "через жопу".
Через жопу - это когда нет никаких мануалов и практик и ты сам сидишь и выдумываешь решение проблемы. Или когда тебе говорят что вообще нельзя сделать так как ты привык. В данном случае можно и не так сложно как кажется. Просто этого никто не делает потому что есть возможность снять скриншот и поставить его фоном. В юнити и лёве можно так сделать одной строчкой кода? КЭП подсказывет, что нельзя. Потому что юнити вообще не умеет с полпинка текстуры на лету генерировать, например. Через жопу сделано?
Так-то можно до чего угодно доебаться.
или
Гамак любят не за супер-универсальный функционал, а за удобство разработки. Заложенного функционала хватает для разработки 2Д игр за глаза.
Но ведь ты ввёл в игру новую переменную. А Алекс уже три дня назад писал что он с этой целью (как твой is_pause) использует
if (global.Menu != noone)
. Кто тебе сказал что это "элементарно" в реальном полновесном проекте? У тебя просто код из двух с половиной спичек, естественно его легко поддерживать - это не игра, в нём ничего нет. Да это даже не ООП, это процедурное программирование где ты предполагаешь отрисовывать всю игру из контекста рендера, а не предоставлять каждому объекту свой Draw Event. Это разве удобно?За последние дни перечислено 4 (ЧЕТЫРЕ) способа это сделать, ты читал хоть на что отвечаешь?
Короче, я так понял что есть 2 варианта сделать паузу:
1) Заводить глобальную переменную и во всех событиях объектов делать exit если эта переменная равна 0.
Во-первых, мне влом перебирать все события у всех объектов и вставлять туда одинаковую строчку. А во-вторых, даже после этого один объект, который движется по path все равно продолжает двигаться.
Получается что такой вариант работает только если все перемещения объектов управляются из скриптов.
2) Отключать/включать все объекты при нажатии кнопки.
Но, блядь, они перестают рисоваться! Почему нельзя просто отключить обновление всех объектов?
Поэтому, видимо, и надо делать скриншот.
Еще есть room_speed, управляющий скоростью обновления комнаты, как раз то что надо, но движок выдает ошибку когда присваиваешь ей 0.
Да уж, в гамакере не смогли реализовать нормальную паузу, оба варианты работают через жопу.
А дело-то, всего-лишь перестать обновлять все объекты.
На дворе 2020 год, почему до сих пор нет нормального 2D-движка, а есть только конструктор с кучей ограничений и фреймворки, где надо все делать руками?
тот же вопрос, я думал это легко реализовать
Я примерно так паузу делаю:
Почти то же самое но без перехода в другую комнату можно сделать по официальному гайду:
https://www.yoyogames.com/blog/551/coffee-break-tutorials-pausing-your-game-gml
И я не пойму, чем этот способ плох и чем он не подходит? Он не отражает запаузенность или что?
Если прям очень нужно чтобы спрайты были анимироваными, то с некоторыми оговорками можно попробовать что-то такое:
Оговорки из серии "простое рисование", "без постобработок","не использовать image_index для условий" (иначе взрывы будут плохо отрабатывать).
Phaser, Flixel - вот тебе фреймворки, там где ты можешь всё что хочешь сделать. Только ручками допиши =)
Про ограничения я не очень понял. В гамаке можно сделать так же как в unity, но вручную, обсчитывая для всех объектов свои переменные и заведя свои скрипты для их обсчёта. Делается довольно просто через объект-прототип, в который закладывается вся эта функциональность.
Я про движки. Есть конструкторы (ограничения), есть фреймворки (все ручками пиши), а нормального движка для 2d - нет.
Переход в пустую комнату - тот же костыль что с отключением всех объектов.
Мне надо чтобы игра просто останавливалась и все объекты переставали двигаться и обновляться пока игра на паузе. У вас для этого скриншот надо делать, потому что остановить вызов step отдельно от draw - нельзя.
Начинаю знакомиться с гамаком и уже натыкаюсь на ограничения.
Не поверишь! Я работаю с Unity и уже натыкаюсь на ограничения! Работаю с JS и уже натыкаюсь на ограничения!
Не "у нас", а в движке. Это единственная задача, для которой тебе нужен этот функционал?
Нормальный движок для 2D это Гамак. Анимированная пауза это блажь, а обычная там легко делается.
Даже анимированная там легко делается. Но анимированная пауза - это непоянто что с точки зрения UX и геймдизайна. Непонятно зачем, и есть непонятные штуки такие как анимированные взрывы, частицы и прочее - что с ними делать во время анимированной паузы - ХЗ.
Анимированные взрывы, выходит, надо останавливать. Делить объекты по отдельному списку взрыв-невзрыв, частицам давать отдельные команды, путям ставить скорость 0. Интересно, в Юнити все партиклы тоже подвержены таймскейлу из коробки? А в Лаве? Если нет, то даже хвалёный "простой" таймскейл - это неполная пауза.
Частицы в юнити аффектятся TimeSacel-ом насколько я помню. Я не уверен насчёт setTimeOut только. По крайней мере в JS таймеры делались так. А сейчас походу единственный способ сделать таймер - это в Update вручную их считать. Заебись удобно! Зато паузу можно сделать через timeScale =)
В юнити всё норм с timeScale и частицами.
Есть.
ностальгия) давно юзал :3
В слово "нормальный", каждый вкладывает свой смысл. Для меня Godot Engine очень нормальный. Если бы это было иначе я бы пользовался чем то другим, например: phaser или pixi.js. GMS можно считать очень нормальным, ведь в одно время на нем было создано много игр, пока не появились всякие Юнити, Анрилы. Все еще зависит от уровня знакомства с документацией к конкретному движку.
Мне кажется пауза с переходом в другую комнату не очень, ибо где-то слышал на гамине, что есть какие-то проблемы с persitent, на всякий случай не буду рисковать, а остальные методы возьму на вооружение. Спасибо!
Да там есть небольшой лайфхак с persistent, но я всегда пользуюсь и всё в порядке. Никто не жаловался на проблемы с паузой.
Если верно помню, то если иметь персистент обж и персист комнату и пермещаться, то всякая дич произходит... Возможно дублирование обекта, возможно хуже, не помню точно.
Господа, к чему писать "не помню" и "где-то слышал"? Есть конкретная проблема - есть конкретное решение. Про персистентность я закодил Алексу исходник ещё 4 месяца назад для демонстрации как она должна работать. При этом персистентны и все комнаты, и объект игрока, но не объекты врагов, и никаких багов там нет.
Незнаю, у меня проблемы были... Возможно это с хтмл было связан. Чесно сейчас не скажу точно...
Дай исходник - я скажу, фигня вопрос.
1) Фиг его найдёш
2)(это уже критично) комп на котором он сломан-в процессе попытки починки...
Так что увы... Но щас уже с уверенстью вспомнил что это в хтмл было... (Так что 90% что не ошибаюсь Хд) хотя возможно в 1.49 это починили кстати, но фиг знает. Я с тех пор отказался от многокомнатности.
Не, ты всё равно скинь. И не придётся ни от чего отказываться, оно ж точно должно работать если правильно настроить.
С удовольствием, но у меня шнура для диска нет понимаешь...
Шнура??? А у тебя есть кеды или кроссовки?
Угу, чтоб этот диск как второй к материнке подключить...
Может шнурки подойдут?
Не, без кабеля не вариант...
Пора делать новый абстрактный объект o_pausable родителем и наследовать все объекты первой степени абстракции от него. Тогда не надо ничего копипастить. Чтобы не оверрайдить степ, поместить проверку флага в Begin Step ли End Step. Можно даже в какой-то из пицот видов ивента Draw.
Ну так надо же не только скорость остановить, но и скорость пути. Всё это пишется в o_pausable и наследуется автоматически.
Ты только забыл - нафига ТЕБЕ такой тип паузы? Алекс придумал что-то там себе что он хотел, у него это авторская идея. А у тебя это откуда взялось? Это что, единственный способ сделать паузу?
Напомню тебе третий вариант: это слить application_surface в скриншот и отображать его.
Ты Уася, в "гамакере" никогда не решали эту задачу, потому что она взята из воздуха и не приносит денег. Деньги приносят игры, а не паузы, и чтоб игровые движки существовали, машина должна крутиться, а разработчики кушать еду, одеваться и где-то жить. В Юнити пауза есть не потому что это важно, а потому что они могут себе это позволить "на сдачу" для неприоритетных фич - он финансируется вагонами денег (более миллиарда долларов, см. ссылку далее).
Всё что ты сейчас делаешь это критикуешь движок созданный 10-50 людьми (а в оригинале, до ГМ8, вообще одним профессором из Нидерландов) на какую-то неигровую тему, в сравнении с движком созданным 1000-5000 людьми. Потому что тебе что-то там кажется через жопу сделанным. Ну-ну.
Скорее всего там она есть как техническое средство, которое задумывалось для слоумоэффектов и отладки анимаций, но потом кто-то придумал делать так паузу.
ну так это проблема профессора, что он не может сделать нужный людям коммерчески успешный продукт и оттого не может включить даже простейший необходимый минимум.
пауза через скриншот это действительно через жопу
Объясни мне почему "через жопу"? Только тем что так делают в юнити и лёве?
"Через жопу" - это глобалы объявлять в объекте и иметь доступ к ним только через неймспейс.
"Через жопу" - это вызывать функцию сортировки отрисовки вместо раположения спрайтов на слоях
"Через жопу" - это слать сообщения, вызывая какие-то там события у объекта вместо того чтобы выполнить код напрямую в его контексте.
"Через жопу" - это иметь доступ к своим ассетам через параметры скрипта или грузить их с диска
"Через жопу" - это не иметь возможности отрисовать хпбар юнита в самом юните, а городить иерархию доп-объектов
А делать паузу при помощи скриншота - это не "через жопу", а один из способов делания паузы причём гарантированный. С учётом того, что сделать паузу через отключение события обновления в GMS тоже можно.
потому что концепт пауза абсолютно никак не связан с концептом скриншот. наличие множества других жоп в других продуктах, как и наличие удобных решений этой проблемы в других продуктах мало на это влияют
вызывать функцию сортировки отрисовки вместо расположения спрайтов на слоях - это похоже на какую-то сильно специфичное решение специфичной задачи. для чего это делать?
хпбар - приаттачил компонент на нужный объект и делай с ним что хошь, рули с любого скрипта
Пауза - это статичная картинка. Скриншот - тоже статичная картинка. По-моему это гораздо более связанные концепции чем "пауза - это когда игра рисуется но не обновляется".
Ну я понял, ты просто не можешь выйти за рамки контекста юнити, поэтому любой другой подход тебе сразу видится неправильным. Дальше не о чём с тобой разговаривать.
пауза - это статичное время
Ты не прав. Картинка может не меняться, а игра обновляется.
И картинка может меняться и быть анимированной, а игра при этом - не обновляется.
Ты просто к этому привык за все время работы в гамаком и любой другой подход тебе видится неправильным.
Если ты с кем-то не согласен, это не значит что ты прав.
Знаешь, вообще-то именно в этом месте люди правы. Мне самому не нравится делать паузу скриншотом, а на Иксбоксе другая система сёрфейсов и так это решение не работает - ну так и лолшто, я убрал фон на паузе ВООБЩЕ и заработал те же самые денежные знаки, даже больше чем в Стиме где этот фон на паузе есть.
Неправы люди в другом - они думают что раз где-то паузу сделать легко, то там и остальную игру сделать легко, ведь пауза это просто, значит дальше в ГМе будет вообще ужас. А всё с точностью до наоборот.
Тут я не согласен. Паузу в GM сделать легко. По крайней мере легче чем потом ебаться с тем чтобы выделять объекты которые будут останавливаться и те которые не будут. И всё это менеджить. Если бы в у меня была возможность в лёв или юнити делать паузу через скриншот - я бы так и делал. А то потом окажется что какие-то объекты (от самописных классов, например) не учитывают TimeScale. Ищи ошибку три тыщи лет.
Я не знаю как у тебя, но у меня на иксбоксе точно такая же система сёрфейсов как и на ПК.
Ну значит это у Дурбека такой код просто был, что переставал работать. Тут главное другое, я его вырезал - игру на забросали помидорами за это. Всем* плевать что отображается у игры на паузе, пауза сделана чтоб пойти попить чай.
* кроме единиц эстетов, не влияющих на платёжеспособное большинство
Это как?
Может, application_surface_enable(false), но я пока не совсем вижу как это тут применимо.
Как-как, жопой об косяк.
Ну окей, нечерезжопный ты наш.
Я хочу сделать паузу, но так чтобы у меня игра чуток размывалась. Можно это быстро сделать в юнити или лёве?
чтобы у тебя игра чуток размывалась добавь эффект чуток размывания на камеру. чо как дитя
тока опять же. даже если бы это было невозможно сделать, это никак не отменяло бы черезжопности необходимости задействовать скриншот при паузе.
Я ждал подобного ответа =)
Потому что в этом случае твоя камера будет размывать каждый чёртов фрейм игры сжирая производительность просто так.
А я просто сделаю размытие своего скриншота один раз при создании и всё.
разумеется, ибо он как раз логичен. и размытие я могу использовать и контролировать везде где захочу, в паузе, инвентаре, попадании, опьянении, анимации смерти, переходах, диалогах. Причем свободно регулировать ее на разных леерах и по глубине
но какое отношение имеет ничтожная по эффективности оптимизация к паузе? Если твоя задача пауза + дополнительная экономия ресурсов, то тогда такое решение удобное и подходящее и плохо то что некоторые движки не имеют возможности в одну строку делать скриншот в текстуру
В лёве можно, если ты всё написал нормально
Вот примерно так же можно сказать и про паузу в гамаке через timeScale
Ну и как это сделать?
Ага, ага. Безусловно, программа на которой уже 20 лет делаются игры с десятками тысяч отзывов, коммерчески безуспешна и нуждается в подобных советах. Минутка ликбеза:
https://store.steampowered.com/app/391540/Undertale
https://store.steampowered.com/app/460950/Katana_ZERO/
https://store.steampowered.com/app/274170/Hotline_Miami_2_Wrong_Number/
https://store.steampowered.com/app/248820/Risk_of_Rain/
https://store.steampowered.com/app/242680/Nuclear_Throne/
https://store.steampowered.com/app/447530/VA11_HallA_Cyberpunk_Bartender_Action/
https://store.steampowered.com/app/751780/Forager/
https://store.steampowered.com/app/356670/Spookys_Jump_Scare_Mansion/
И что, хоть в одной из этих игр есть "простейший необходимый минимум" - анимированная пауза? А там где есть пауза через скриншот, это кому-то испортило настроение, здоровье и карьеру? Нет же, люди просто сделали то что надо сделать, а не судачили по три часа как старые бабки - это костыль, это некостыль, а вот по такой траектории алгоритмов мы уже приближаемся к черезжопному критерию костыльности.
разумеется это была ирония после твоих слов, что у юньки есть ресурсы на такое, а у гамакера нет.
следующая ирония, на которую не стоит реагировать без юмора это сравнение картинки Risk of Rain и Risk of Rain 2.
Картинка, хаха. Да не было бы никакого Risk of Rain 2, если бы не Гамак, на котором удобно спрототипировали модель геймплея и сделали полновесную первую двухмерную часть. Тем же самым обязана серия Enter/Exit The Gungeon, игре Nuclear Throne. Равно как и, например, Spelunky, которого я не привёл потому что его 8-битная версия в Стиме не размещается.
Exit The Gungeon!!! уиии
какого wtf ваще? 2d(unity лол) платформер на мобилки? в это можно играть? :(
так это же прекрасно. тут никто не спорил с потенциальным утверждением, что выпусти разрабы ганжн и рейн2 на гамаке они были бы в сто раз лучше.
Risk of Rain 2 сделан на юнити потому что он 3Д и это вполне логично, т.к. в гамаке делать 3Д игру - всё равно что на юнити делать 2Д.
В последнее время я всё склоняюсь к утверждению, что и в Гамаке делать 3D игру проще, чем на Юнити 2D-игру. В Гамаке 3D есть ещё с середины 2000-х годов, там дальше только стоит уже вопрос "красивое 3D" или "некрасивое". Ну и отсутствие редактора трёхмерных уровней встроенного, увы. Однако, проскакивающая сейчас мода на лоу-поли и "полигоны как на PlayStation 1-2" может дать интересную нишу для "нетрёхмерного" Гамака. Я как раз собираюсь сделать проект чтобы проверить эти возможности.
лол, ну в целом я ещё не отказался от идеи скриншота и отключить инстансы, но ещё и не пытался реализовывать, просто в других движках я не делал скриншоты ради паузы, и поэтому не привычно
и кажется будто что-то не то делаю...
ещё не знаю, будет ли скриншот работать с моим сурфейсом, который находится в PostDraw главного скрипта
отрисовки всей игры, это я сделал для того чтобы был автозум окна и pixelperfect, надеюсь эти эффекты не будут конфликтовать
А как эта строчка влияет на автозум и pixel-perfect?
Вообще это рулится размерами view и его порта.
У меня кнопка Resize у окна разблокирована и можно окно как угодно менять, в этом объекте есть также:
а в скрипте scrResize
и потом в конце отрисовывается скорректированный surface
то есть я проверяю разницу между размером окна и старыми данными,
и обновляю размер surface умножая на ровное значение x1 x2 x3 x4 и т.д.,
мне главное чтобы скриншот паузы с моим surface не конфликтовал)
но в целом я пока ещё не пытался реализовать паузу на скриншоте, может там вообще нет проблем
Только непонятно зачем его рисовать, если application_surface сам автоматом рисуется (если только ты принудительно не выключил отрисовку). В остальном всё правильно выглядит.
Ты не пробовал убрать это событие Post Draw? Результат меняется?
Я ещё это добавил на старте:
application_surface_draw_enable(false);
пустой экран будет
В целом, получается как на моих любимых эмуляторах)
ну вот если эту строчку убрать и Post Dra убрать? Что-то поменяется?
автоматически будет на весь экран увеличиваться отрисовка, меньше пустого места будет, но не pixelperfect (пиксели разных размеров, например на цифре "82")
а в моём случае, если места на экране меньше, чем можно увеличить на round значение,
то экран не увеличивается, зато соблюдается pixelperfect, я такое кажется в Tic-80 и Pico-8 ещё видел,
в данном случае размер окна чуть не дотягивает, чтобы экран мог увеличиться ровно в x2 раза,
(это конечно минус, что так много пустого места, зато пиксели ровные, лол)
Всё, я догнал. Ты в комнате бордеры делаешь чёрные если окно больше игры.
Ага, просто я часто видел игры на GameMaker где в опциях есть кнопки Zoom x2 Zoom x3 Zoom x4 на ПК, подумал что пусть лучше игра автоматически этот размер ставит, хоть до Zoom x100, если разрешение монитора позволит.
Я тоже делал пару раз zoom X, но я именно окно под игру подгонял без чёрных рамок, и делал проверку на размер экрана, чтобы окно не становилось больше него.
Это как вариант. Я не говорю что твой вариант не верный. Можно и так и так.
Я в своей игре в опциях даю выбрать скейл только если игра в окне, а если фуллскрин то она тоже скалируется, но автоматически, по максимуму. Разрешение 640х352, получается 640*2 = 1280, 640*3 = 1920, в принципе в большинство мониторов попадет, мне кажется.
Как вариант, только не знаю как ставить размер автоматически по максимуму в окне,
или находил, но забыл, надо погуглить, а то у меня окошко вначале очень маленькое.
Кстати, про FullScreen пока ещё не знаю, как там делать, но вроде игра при нажатии alt+Enter нормально отображается и без дополнительных строк кода, или хз.
В гм просто делается - window_set_fullscreen(true или false). А если set заменить на get то можно наоборот проверять в фуллскрине игра или нет.
Вот исходник сделал в gmz формате, потестировать или покритиковать:
https://drive.google.com/file/d/1RO5PJ7qBAr_6COkrJT2om0_lJUK9nWUF/view?usp=sharing
Так, я посмотрел.
MAIN -> Create:
А для чего нам глобально эти три переменные, если у нас уже есть YesObject, в котором их можно хранить? У тебя тут место для потенциальной несостыковки скриптов в будущем - может выйти так что global.YesObject уже noone, но global.YesAct всё ещё хранит значение от предыдущего, и запаришься искать ошибки.
Не-не, ни в коем случае не i=1, должно быть i=room_first, ну а если кроме первой (видимо ты полагал что нумерация начинается с нуля, и тогда 1 это вторая комната), то делай i=room_next(room_first).
if (room_next(room) != -1)
Только room_exists(room_next(room)), все эти цифры типа i=1 для комнат и -1 вместо индексов ресурсов - зло.
MAIN -> Step:
Ты передаёшь тут название объекта, но:
1) Делаешь это строкой - тебе нужен asset_get_index("o_menu_pause") чтобы получить индекс объекта из строки;
2) На самом деле тебе достаточно просто писать не в кавычках, и тогда asset_get_index() уже не нужен;
3) Скрипт menus ничего потом не делает с этим аргументом кроме сравнения с пустой строкой, ты вроде как сделал пустые слоты для чего-то в будущем, но непонятно для чего.
То же самое на строке 15 в скрипте Talk. Идём далее:
Монструозный скрипт, думаю ты запарился его выверять пока написал. С другой стороны, ты выставил ориджин спрайта в центр и прописал поворот через градусы, так что тут даже не к чему придраться. Молодец!
o_FoeCore -> o_HeroGirl Collision
Собственно, это и есть lengthdir (вот это подстава, правда?):
Правильно организовал наследование o_coll, тут тоже молодец.
Скрипту drawGirl() не нужен аргумент - ты вызываешь его только из её объекта, да и само название говорит о том что он уместен только там. Если убрать из скобок self, а из тела скрипта var _self = argument0; и все "_self.", то работать код будет точно так же само.
Для того чтобы обращаться к переменным вызвавшего объекта, не обязательно писать ни self.dir, ни id.dir, ни пропускать это через скрипт и делать _self.dir, хотя все эти три способа тоже будут работать. Просто пишешь dir и скрипт, обладая контекстом вызова, сам достаёт эту переменную из вызвавшего инстанса.
o_BoxCore -> Create
Это ты делаешь два флага для того чтоб на второе использование давать другой результат? Не очень понятно для чего это предназначено.
Фигово я переменные называю, ибо начал забывать что это значить) в общем это объект чтобы туда переслать сигнал "Use" при диалоге, но не меню, я немного тут сам себя запутал потому-что вначале планировал сделать только Yes/No проверку для меню, а теперь добавил и в диалог.
YesObject, чтобы туда (это может быть как дверь, так и персонаж, так и другой объект) отправить сигнал согласия, и там бы уже какие-то переменные обработались, если нажать выбор "Yes"
Может стоит ещё раз эту часть кода переписать, более понятно, или хз
Да, у тебя исходник выглядит так, будто ты тестируешь много всего параллельно. Но если ты уже потерял понимание, что именно тестовое, а что нет, то начни с удаления того что явно не нужно. Бэкап сначала стоит сделать конечно.
вначале я сделал просто без кавычек, но в некоторых случаях у меня там была ошибка, забыл какая, а с кавычками ошибка ушла, ну я так и оставил)
Видимо ты сравнивал с "", вот оно и ругалось на попытку сравнить o_menu_pause со строкой, а o_menu_pause без кавычек это число, присваиваемое Гамаком автоматически, разрабу его знать ни к чему, это типа как указатель на ячейку памяти - кто там знает что в нём? Потому и обращаются по переменной, а ты вводишь в код какую-то новую, неизвестную движку строку, которая совпадает с названием объекта, но он-то об этом не знает. Пиши без кавычек и убери сравнение с "", сравнивай с noone. Хотя... по ходу ты поэтому и писал его, чтоб "" было быстрее набирать чем noone?
Можно сделать другой скрипт, в котором этот аргумент вообще не нужен, вместо чтоб обрабатывать полный скрипт где куча аргументов пустая или ни о чём. Таким образом можно более частным скриптом уточнять более общий. Но пока что неясно как ты построил архитектуру вызовов, нарисуешь схему может?
лол, да, noone раздражает каждый раз писать) в null и то меньше символов)
Это название временное, я забыл, что правильное название у этого эффекта 9-slice)
но почему-то в голове всплыло это странно название "9x9", лол xD
правильнее было бы что-то типа "Draw9Slice"
Слушай, а я и не знал. Теперь знаю, круто!
Спасибо за аналогичный пример моему коду) буду знать как это работает, а то я думал вначале что за lengthdir такой)
первое использование это я нажимаю кнопку А на объекте
второе использование после нажатия Yes (на "вопрос")
таких использований может быть и больше, в зависимости от целей
Тогда понятно. Стоит обозвать переменные более конкретно, типа isUse и isUseConfirming или isUseSure.
Слушай, я лоханулся тут. Всё он там делает, вот же:
А для того чтобы не писать впустую ни noone, ни "", сделай скрипт menus0 с таким кодом:
И вызывай просто
menus0("close")
,menus0("end")
и так далее.первый раз вижу такой функционал, не совсем понял как это работает, хз, попробую потестить
Ну это я от себя там ноль дописал, ты можешь вообще назвать скрипт m(), но не стоит. Это просто другой скрипт который вызывает твой первый главный скрипт меню, просто не требует второго аргумента для вызова и вместо него всегда пробрасывает "" в menus.
Я, например в гамаке не ебался с камерами так как я это делал в Phaser или той же юнити.
Точно так же как я в гамаке не ебался с отрисовкой GUI так как я это делал в юнити через передачу хуелиона аргументов в ебучий скрипт, в котором ещё нужно было поизвращаться с отрисовкой этого дела.
Вот так я рисовал UI бомбарды на юнити. Массивы текстур, иначе никак, ведь имена ассетов нельзя в скриптах использовать.
Вот результат
В половине движков у спрайтов origin не поддерживается и тебе нужно руками это учитывать.
Все движки разные в реализации каких-то фич.
Шикарно выглядит!
И да в юнити куча своих проблем)
PS если не ошибаюсь вроде как можно имена ассетов в скриптах использовать, если ресурсы закинуть в папку "resources", или я не понял про что идёт речь
Ну вот и начинается. В то время как я в гамаке пишу просто
sprite_index= spr_glass
Причём там можно менеджить группы текстур сразу, выгружая и загружая в память по необходимости.
Мне это понравилось в гамаке) я вообще люблю просто писать обычный текст (String) в коде,
чтобы указывать на переменные или объекты. Если постараться, то можно сделать в юнити упаковщик всех переменных и объектов/ассетов в словарь (Dictionary) и вызывать по именам, я как раз над этим работаю в юнити сейчас.
Ну вот да. О том и речь, что в любом движке ты будешь допиливать функциональность под себя если ты видел для себя решение более удобное. Меня на самом деле в юнити и таймеры вырубают. По крайней мере в js нужно было писать setTimeout, и я вообще не уверен, что timeScale будет её аффектить.
Задать таймер через alarm[0]=40 куда проще ИМХО. Но и минус есть. Там можно было анонимную функцию отписать, а в GMS нужно в событии прописывать.
а я таймеры в GMS и Unity пишу вручную, переменными D:
потому-что в юнити не люблю и плохо понимаю корутины, а в GMS пока даже не пробовал изучать alarm
Вот тебе мини-лекция по alarm
В коде пишешь: alarm[0]=30 что значит что он каждый степ/фрейм будет отниматься на 1 и сработает через 30 таких фреймов.
А сработает - значит выполнится событие alarm0 для объекта. После этого переменная alarm[0] станет равной -1, что значит что таймер не запущен. Тоже можно проверять.
Массив alarm[0] для каждого объекта свой и их можно создать до 12 штук на объект. Удобство ещё и в том что его можно использовать как счётчик - а это довольно много доп возможностей. Будешь заходить на мои стримы - узнаешь каких именно =)
Спасибо! Я тут как раз счётчик вручную сделал, может перенесу в alarm)
Он не совсем точный, потому-что нужно отнимать каждый кадр не -0.0166, а где-то -0.0166666666666667 и хз можно ли ставить после запятой столько значений, но хотя может это мелочь и даже за 100 часов эта разница будет незначительная, но наверное проще это в таймер alarm закинуть
Довольно оригинальное решение, без подкола сейчас. Не думал о таком.
Начиная с ГМС2.3, есть in-line функции.
Я вот по основной работе сейчас занимаюсь HTML/CSS
И относительно недавно открыл для себя PUG и SASS - то где не нужно ставить точки с запятыми и уёбищные скобки, где теги можно объявлять без <>. В общем каеф. Код читается в разы лучше и выглядит приятнее.
О, это то за что я полюбил GameMaker 6.0 в 2006 году! (в том числе)
Честно говоря это не особо в чём-либо убеждает, т. к. стены текста могут быть нужны просто потому что они одинаково в этом месте нужны и в ГМе, и в Юнити, и в других движках. Тут бы пояснить что именно ужасного в том коде, я вот не догнал.
Начать можно с этой дичи:
Я должен передавать в скрипт название шрифта и массивы текстур, потому что иначе ресурсы в Unity задействовать в коде нельзя...
Далее:
Кто-то мне сегодня утром кукарекал что в гамаке ВЫНУЖДЕН создавать объекты на любой чих =)
А тут смотри чё происходит - я создаю объект Color, чтобы потом его передать в качестве поля в объект GUIStyle чтобы потом его передать в функцию рисования. Куда уж коду на гамаке сравниться:
Итого три строки кода вместо семи, т.е. более чем в два раза меньше.
Конечно, в стилях что-то такое есть и даже может показаться что это удобно. Может быть если бы это была вёрстка сайта, то да. Но это игра, разовое место во всей игре для отрисовки UI...
Двигаемся дальше:
Мне нужно всегда обозначить прямоугольник. Я не могу нарисовать текст свободно в любой точке.
ScaleMode принимает три значения со смыслом "вписать", "растянуть" и "обрезать". Т.е. функции зеркального рисования тут нет, поэтому мне пришлось создавать зеркальные ассеты. Тогда я начал понимать, почему игры на юнити так много весят. Про оптимизацию не слышали.
А из-за этих постоянных вложенностей, создания объекта и передачи его куда-то там код раздувается и выглядит некрасиво. Ну вот что это за пиздец то?
Time.deltaTime или transform.position.z или rigibody.velocity - это же обосраться просто!
И это в JS только! В шарпах тебя вообще заставят все неймспейсы писать и там просто лютый ад.
Вот ещё пара примеров:
Да в рот ебал я такое писать. Какое-то высранное недоразумение программировать на ООП в стиле функциональщины. Точнее так - я понимаю что ООП - это подразделение всего на объекты. Но цвет - это просто перебор. Скоро для каждого байта информации начнут объекты создавать. Ну а чё, оперативка то резиновая! Нужно - растянется =)
Мне вот очень импонирует модель названий констант в GMS.
fa_left, vk_right, c_red и т.д.
И ёбанаврот! Можно писать без этих дебильных префиксов, потому что все и так всё знают, а не тащат это из синтаксиса C# только для того чтобы можно было делать игры на языке, который заточен под ентерпрайз аппликухи. Конечно же блядь программисту не понятно что FloorToInt - математическая функция, как Cos, Sin, Abs, Sqrt и нужно явно указать, а то вдруг ты у себя в объекте реализовал свой метод Cos, который считает его по отличной от общепринятой формуле. Или функция FllorToInt внезапно превращает пол в уровне в международный.
А потом всякие типа трупрограммисты будут рассказывать мне что это единственно правильный способ, что ВСЕ ТАК ДЕЛАЮТ, а остальное не православно. Да ОК, нет проблем. Только я на своём коммерчески неуспешном гамаке в котором всё делается через жопу буду писать для 2Д игр кода в три раза меньше и в три раза быстрее чем на юнити. Ну а вы пишите эти непонятные конструкции, тратье часы на чтение кода и создавайте лишнией ассеты, передавая их в параметричсекие массивы, зато всё ПРАВИЛЬНО сделаете, не через жопу, молодцы!
Вот теперь понятно.
Только теперь вот это не понял, какое зеркальное рисование?
Когда ты можешь текстуру отзеркалить. В гамаке это делается занчением -1 в параметре xscale функции draw_sprite_ext
у текстуры вроде есть свойство offset = -1; или с подобным названием, но я чаще переворачиваю объект по scale к которому эта текстура прикручена) хотя если это с GUI, то я хз как там работать, у меня весь GUI обычные объекты префабы никак не связанные с UI юнити, ни со старой, ни с новой системой
Возможно, есть способ отразить текстуру в моём коде, при помощи шейдеров, например. Но я его не нашёл.
Рисовать UI при помощи префабов? Т.е. плейнов с текстурами?... absolutely not kostyl solution XD
Глянул тутор по GUI через объект canvas. Да, стало гораздо лучше, чем было =)
Я может тоже когда-нибудь доберусь до туторов по GUI. Хотя пока мне привычнее юзать обычные объекты и вторую камеру.
Но всё равно по мне очень много телодвижений нужно сделать. В гамаке я просто нарисовал всё в нужных частях экрана в одном событии. А с новой системой GUI мне всё равно нужно накидать в этот канвас объектов, каждый отдельно настроить, в каждый добавить текстуру (правда здесь уже есть зеркалирование), а если там есть какая-то логика отображения или использование переменной - для каждого такого объекта ещё и отдельно в скрипте прописать это.
В целом, такой подход свои функции "отображения UI" выполняет. Так что я не буду говорить что это какие-то костыли или черезжопное решение. Можно и так. Костыли или через жопу - это если бы у меня был единственный способ сделать GUI - скачать и установить third-party библиотеку из другого движка, в которой этот функционал есть.
Это я о разнице между "другой подход"(есть официальные гайды по тому как это делается) и "через жопу"( когда инструмент не предусматривает механизмов решения твоей задачи).
можно кстати цвет инициализовать один раз в глобальном скрипте и юзать постоянно во всех скриптах, если он часто нужен, и в гамаке мне всё равно не нравятся заранее прописанные цвета, и приходится свои создавать, я уже привык создавать цвет с нуля, в гамаке столько же кода надо писать на цвет)
Не столько, в Юнити нужно ставить точки, а в ГМе не нужно! :yak:
JS Unity
var color : Color = Color(.5,.5,0,1);
C# Unity
Color color = new Color(.5f,.5f,0,1);
Game Maker
var color = make_colour_rgb(127,127,0);
да в целом строки кода почти одинаковы)
Про точки я шутил, но вот теперь минутка занудства от старого фанатика Гамака:
И вуаля, теперь вместо:
ты можешь во всём проекте писать просто
Что, можно так в Юнити? Не-а, нельзя.
Если принципиально нужно задавать цвет от 0.0 до 1.0 вместо от 0 до 255, то тогда скрипт rgb:
и код будет:
Итого тут один раз написано слово color, без скрипта rgb - два, но в Юнити - три! Чего ради?
В юнити создаёшь скрипт Game, с функцией:
потом в другом скрипте, вроде должно сработать, но не тестил:
либо я не понял про что идёт речь, но если про то что диапазон цвета 0-255, то мне без разницы,
мне нравятся оба диапазона цвета, что 0.0f-1.0f что 0-255, и это в функции юнити тоже можно сделать
Не должно, у тебя RGB принимает Vector3, поэтому и вызывать надо:
На самом деле надо прописать:
Тогда будет как ты хочешь. Но всё равно надо color писать два раза, а в ГМе один. Да ещё вдруг какой-то Game появился. Такие дела,
color = rgb(127,127,0)
по-любому удобнее.лол, да, ошибся)
Ты можешь макрос добавить на свой цвет и использовать как константу.
В gms2 есть директива
А в gms1 в специальном интерфейсе всё то же самое делается.
Это может быть не всегда удобно, так как поди разбери какие константы в каком объекте используются сходу. Для такого нужно их называть начиная с подходящего слова. Но так тоже можно, да.
Макросы же к объектам не привязаны. У контроллера просто создаёшь их сколько нужно. ФИшка в том что ты задаёшь цвет точно так же как заданы встроенные цвета, по-моему, вплоть до цветового отображения в коде.
Ну это верно.
но вообще да, в юнити много где приходится писать длинные строки кода, хотя там много визуальных инструментов для создания контента, того же UI
В юнити много крутых инструментов, которые я бы хотел видеть в гамаке.
То что я написал о недостатках выставляет меня в глазах читателей хейтером юнити. Я написал только про код и язык, который мне не кажется удобным. То что игра запускается и отлаживается прямо в редакторе сцены - это очень круто. В гамаке можно только анимации объектов посмотреть, ну в 2.3 ещё твины.
Система компонент сама по себе довольно крутая.
Возможность драг-н-дропа ресурсов в поля визуального редактора. в GMS2 это частично можно делать и есть альтернатива делать это кодом, а в Юнити это практически единственный способ использовать названия ресурсов в коде.
Работа с частицами супер-круто сделана.
Есть много крутых фич. Но весь функционал заточен на 3Д игры. Это самая главная причина по которым я использую гамак, а не юнити.
Хаха. Вот щас чисто обидно было, без всякой иронии. В 2013 году я написал GMXD - "игровой встраиваемый дебаггер", который позволяет добавлять ивенты в объекты на лету. Я там даже автоподсказки делал для того чтоб функции автоматически подставлялись. Кто-то стал его юзать? Нет конечно, потому что гыыыыыы уэээээ ГОМЕ МОКЕР СТУДИА, а там больше нету execute_string(), на который опирается 99,9% функционала проги, т. к. это динамическое выполнение кода.
В ГМе все эти долбаные годы, начиная с того как execute_string появился, и до Студии 1 (около 10 лет!) была возможность разрабатывать игру прямо во время её работы. И теперь в 2020 Хейзер, сидя в Студии 2, мне заявляет что это есть в Юнити и это очень хорошо. Ну ахереть просто.
https://yellowafterlife.itch.io/gamemaker-live - при том что есть ещё и такое.
а, так такой жуткой хераборы c onGUI и заданием в нем всех параметров нет давно в юньке. на все есть готовые компоненты, с кучей опций и настроек. В общем случае ты создаешь объект нужного типа, слайдер или баттон или текст, ручками прямо на сцене раздвигаешь его, задаешь цвета вешаешь спрайты, анимации, и потом через скрипт крутишь только те параметры, которые тебе нужны. Заодно сетки для упорядочивания, помещение объекта на камеру или в пространстве игры все доступно без кодинга.
Была жопа, но сейчас такой UI запилить это самый бегиннер уровень
Да? Тогда что не так с этой неделю назад представленной игрой в плане интерфейса, сделанной на свежей версии Юнити?
Там автор в комментарии пришёл, и говорит что задолбался там всё править.
понятия не имею что там, это надо у дева спрашивать. может быть и дев, но это не точно. К тому же он пишет про баги (которых как ты, сам понимаешь в продукте за миллиард немного) и input - проблем с XInput я не встречал, но я и не ковырял сильно
Ну, выглядит неплохо.
Это точно. А ещё чем больше денег вложено, тем обратная совместимость лучше. (нет)
Если честно я запутался, self или id?! Или без разницы?!)
Да, и мне объясните. В 8.1 я пользуюсь self и все работает.
Я написал про id в контексте того, что self не работало у Алекса, но сам код не проверял. Как проверил Rs, данный код с self работает, просто Алекс, судя по всему, где-то в другом месте ошибся. Вообще я использую self, когда объект вызывает сам себя для определённого действия как аргумент для скрипта. Ну и по идее id более универсальная переменная.
Я там просто просто опечатался)
self работает быстрее. Вообще не очень понимаю зачем её использовать, разве что как в примере, если ты переменные именуешь как дегенерат, мешая всё подряд. Если взять за правило глобалы именовать капсом, локальные строчными, а все переменые, объявленные через var начинать с почерка то и проблем нету. Можно какие-то другие правила выработать.
Я не использую self и не использую id для обращения к переменным объекта, так что мне кажется это вообще избыточный функционал.
Тот же пример но без self
Тут прикол в том, что всё что объявлено через var в таких конструкциях доступно не зависимо от скоупа и имеет более высокий приоритет. Именуйте переменные правильно и не ебеись с self.
Интересный пример с with! Надо запомнить.
Я часто self использую чтобы отправить все переменные разом из объекта например в скрипт.
DamageObject(self,5);
А зачем?
Скрипт DamageObject выполняется в том же контексте и подхватывает все переменные объекта.
Если тебе нужно вызвать его в контексте другого объекта то делаешь просто
with (objId) DamageObject(5)
А как внутри скрипта работать c этим?
То есть у меня в функции/скрипте "DamageObject" нужно проверить сколько Defense и HP у объекта.
что-то типа:
Работать так как если бы ты этот код написал внутри объекта:
Гамак - это по большей части не про лишнюю писанину. Считай что скрипт - это просто параметризированный макрос =)
Рекомендую использовать argument именно как массив. Это даст возможность сделать скрипты с плавающим количеством аргументов. В GMS2.3 это скорее всего поменяется.
Пока таких прогнозов нет, старые скрипты работают так же как новые, только оборачиваются в функции.
Есть одно исключение - в коде коллизии если ты пишешь:
то это более однозначно чем
Просто по самой логике чтения текста (без проверки есть там где-то наверху по тексту или стеку вызовов var dmg или нету). На движок это конечно никак не влияет.
Я так не пишу. Мне достаточно написать other чтобы понять что это переменная из другого контекста, а все остальные из теукщего. Но если без привычки, может ты и прав.
Столкнулся со странной проблемой в Game Maker. Хочу сделать проверку с каким объектом сейчас сталкиваемся для взаимодействия, например: NPC, ящик с сокровищем, дверь, вещь, интерактивный объект.
Чтобы при нажатии на кнопку "А" совершить действие с тем интерактивным объектом, который сейчас выделен.
У главного объекта при рисовании Draw Event сделал:
У интерактивного объекта сделал в Step Event:
И почему-то
if (global.Active != noone) {
не работает.self - это древнее зарезервированное слово для целей совместимости со старыми проектами, которое всегда возвращает -1. Вместо self можно попробовать id.
Спишу уточнить, что может ключевое слово и древнее, но про него не забыли. В справке актуальных версий указано, что self предпочтительно использовать вместо id для чтения идентификатора экземпляра, т.к. механизм который выдаст значение через self работает чуть быстрее оного на id. Если вывести на экран draw_text(x, y, self), появится именно id экземпляра (что-то вроде 100008). Но, как сегодня выяснилось, в обновлении Game Maker Studio 2.3 этот self теперь работает по другому. Ты все еще можешь обратиться к переменным экземпляра через self.переменная, но если отрисовать содержимое self, выводиться немного другая информация.
Я думал self это нормальный указатель, типа this или gameObject для Unity.
То есть лучше не использовать self?
Лучше не использовать. Просто следи в контексте какого объекта ты находишься.
Спасибо! Пойду избавляться от self)) жаль я уже много их везде в коде добавил)
Автозамена же есть =)
Я вообще не знаю для чего это было придумано. Судя по всему для тех языков, которые не умеют адекватно работать с контекстами. Тот же JS, например там есть this, который нужен потому что там нет нормального ООП и так ты типа разделаешь контекст объекта и общий контекст.
В ГМС1 автозамены по всему проекту нет, только по отдельным кускам. В 2 есть. Можно везде заменить self на пустую строку (ничего не вводить) - сработает.
Точно, нету.
Поиск только есть и он лучше, чем в GMS2, т.к. можно искат ьв отдельных частях проекта да ещё и не учитывать комментарии.
Незнаю, я проверил у меня работает. И кстати, зачем глобал если можно в героя посылать... Типо obj_hero.active
Не срабатывает, ты имеешь в виду. Ну да - у тебя тут Active, а Step Event'е - Action.
Ещё названия этих переменных ничего не говорят - хорошо было бы сделать, например, CurrentActiveInstance. Тогда ни с чем не перепутаешь. Мало ли, захочешь глобально какое-то другое действие хранить или настройку.
И Раззл прав - используй id, не надо self.
лол, да, простая невнимательность)
Спасибо! В целом я доделал активацию, и даже диалоги прилепил)
Я обычно баланс соблюдаю между понятностью и краткостью. Такие длинные названия для переменных я редко использую, ибо из-за этого строки кода увеличиваются и читаются сложнее для меня,
чем короче строка, тем легче сразу понять что тут написано
И даже сделал выбор Да/Нет в диалогах,но это максимум что могу сделать в короткие сроки,
да и непривычны в GMS многие вещи. Например я тут так и не нашёл нормального аналога
SendMessage
,а простейшая строка (на картинке ниже), вообще не работает, что немного странно,
а зачем тогда
event_user
, только чтобы изнутри программы использовать и всё?!Или я просто не так делаю.
Такие штуки делаются путём обращения через with, простым обращением, как к переменной, этого не добиться. Может в гмс 2.3 что-то поменялось, но пока так.
Спасибо большое!
А если я хочу не other, а скажем использовать другой идентификатор другого объекта тоже можно с with?
PS и я нашёл позже вот такой способ в гугле, но ещё не тестировал:
event_perform_object(object, ev_other, ev_user0);
Да, with работает как c id конкретного объекта, так и с other (который на самом деле тот же id), так и с названием ресурса объекта - тогда применяется ко всем экземплярам и экхземплярам потомков.
event_perform_object(object, ev_other, ev_user0) - выполняет событие другого объекта object в заданном контексте, .т.е выполнится код для того объекта из которого эту функцию вызываешь. Почти никогда не используется. По крайней мере я не испытывал такой потребности. Ну может раз на 30 проектов делал.
Меня, кстати в юнити эти штуки sendMessage вырубали постоянно. Как-то с with удобнее работать. Причём функция капец какая универсальная. Поставил id объекта - проваливаешься в его контекст и выполняешь код для него. Поставил id ресурса - то же самое только для всех экземпляров и экземпляров потомков этого объекта.
А эти SendMessage насколько я помню - полная жопа, потому что этот месседж нужно ещё принять и обработать. А это значит - писать код на двух сторонах вместо одной. Нам в гамак такого дерьма не надо.
А мне всё равно придётся на двух сторонах вместо одной работать:
1) в первой стороне нужно отправить функцию активации, например я отправляю сигнал "Talk" другому персонажу, чтобы с ним поговорить;
2) а у второй стороны в функции "Talk" может быть совершенно разные диалоги и обрабатывать совершенно разные переменные, например:
*Дворецкий - откроет дверь и скажет что-то типа: "Прошу, проходите!"
*а Парикмахер поприветствует и предложит меню Парикмахерской
я и не уверен как сделать из одной стороны такой скрипт, когда не знаю что будет в функции второй стороны заранее
Вместо того чтобы менеджить диалог на двух сторонах проще сделать o_dialogue_manager, который и будет брать на себя все функции отыгрыша диалога. Тогда диалоговая система строится на паре списков и нескольких обработчиках событий. Я бы именно так делал. У меня был бы скрипт типа
create_dialogue куда бы я скармливал айдишники всех объектов-участников и список с репликами. У меня бы создался этот самый o_dialogue_manager, который бы залочил движение если нужно, управлял бы камерой и отрисовкой текстов. А при конце диалога бы самоуничтожался и возвращал управление и камеру. Так же можно сделать изи функцию скипанья.
Если там будет прям диалоговая СИСТЕМА с выбором или множественным выбором - тоже не проблема. Всё менеджишь в объекте o_dialogue_manager
Есть разные ветви? Вместо списка делаешь дерево и граф. Делов то =)
А ещё туда можно зашить какие-то названия скриптов, которые будут дёргаться и как-то вилять на игровой мир меняя значения глобальных переменных.
Я пока не совсем понял как работать с массивами, может позже если разберусь то попробую
читать из текстового файла и заносить в массивы инфу и оттуда управлять событиями и диалогами.
Но помимо диалога бывают и другие общие механизмы, например использование "Use",
где мне нужно второй стороне отправить событие Use:
у Яблока своя функция Use, которая отличается от яда, или от фотоаппарата, но у всех есть как бы общая функция Use, но внутри разная.
Это то как принято делать в Юнити, но нет никакого общего геймдевелоперского принципа по которому нужно строить всё именно так. В ГМе действительно нет сообщений между объектами, но организовать требуемую систему можно как минимум тремя разными способами (кроме деградантского - не использовать ООП вообще, и всю игру описывать в одном объекте):
1) В том объекте, который нужно применить, сделать User Event с номером, можно искусственно договориться что в проекте ВСЕ User Event'ы под номером 0 это реакции на "Use", ВСЕ User Event'ы под номером 1 это реакции на "Talk", и тогда тебе придётся следовать такому договору, но ты легко сможешь сориентироваться где реакция на что. Примерно это ты сейчас и делаешь - вызывающий объект должен делать with other event_user(номер);
2) Не считать что существует какое-либо передаваемое между объектами сообщение, сделать скрипт, назовём его например talk_system, и он будет принимать на вход в качестве аргумента тот инстанс, с которым происходит разговор. Вызывать ты его будешь так: talk_system(other.id), а делать он будет следующее:
Это просто другой порядок (иерархия) описания действий. Соответственно для другого действия надо создать другой скрипт, типа "Use", и там будет уже другое. Это хорошо тем что ты сразу видишь возможные результаты действий по разным объектам, открываешь один скрипт - и скроллишь все результаты одного действия. Плохо это тем что иногда тебе может понадобиться видеть не "вширь", а "вглубь" - описывать результаты действий исходя из типов объектов в первую очередь, а из выбранного действия во вторую.
Тогда нужно опять же делать скрипт butler_action(действие) т. е. вызов будет butler_action("Talk"), в сприпте писать:
3) И ещё один принципиально другой способ - подобно тому как Хейзер говорил про менеджер диалогов, создавать объекты-менеджеры любых действий. o_controller_talk, o_controller_use, и так далее. Как это будет работать?
В этих контроллерах нужно писать функционал, реализующий то что на них возложено. В целом, это больше похоже на контроллеры интерфейса, чем на скрипты-переключатели, и да, тут снова придётся делать User Event'ы.
В общем, мне вариант (2) кажется наиболее оптимальным (оба из его вариантов иерархии). И, как видишь, все перечисленные варианты сенд_месседж не делают, а значит он не необходим.
А можно использовать макросы или enum и не ебаться с запоминанием. А просто писать
Можно в объект-прототип заложить весь функционал, сделать отдельные скрипты на use и talk, которые по object_index будут делать те или иные вещи. Но там проще просто
Можно ещё кучей способов построить удобную систему. Это, конечно, напоминает костыли. Но костыли эти будут во много раз лучше чем строить диалоги на sendmessage.
Про макросы и enum ты прав (и enum будет очевидней), а о прототипе нифига не понял тебя - ты имеешь в виду что это будет парент? Ну тогда будет куча пустых объектов-наследников и много писанины в скрипте. ХЗ будет ли удобно, но тут все способы имеют свои как плюсы, так и минусы.
Общее правило - надо смотреть какая часть проекта "широкая", а какая "узкая", чтобы кодить приходилось только "узкую", а "широкая" решалась автоматикой. Нельзя автоматизировать всё, но можно выбрать более выгодный порядок абстрагирования.
Больше объектов? Надо начинать с действий.
Больше действий? Надо начинать с объектов.
Ну а если некуда девать время, то можно и без ООП писать. А если совсем супер-некуда, то и на более сложных движках.
Мне вот просто интересно. Ты так делаешь по какой причине?
Сам придумал? Перетянул опыт с другого движка? Кто-то научил в универе?
Сам придумал, но я не оптимально обычно программирую, но в целом думал о такой логике:
если есть человек, то можно ему подать общие сигналы: Talk
если есть разные вещи в инвентаре, то можно им дать общий сигнал: Use
если есть дверь, то ей тоже можно отправить сигнал Use
PS а у каждого объекта свои функции со своими обработками, хоть называются одинаково,
более лучшего вариант не придумал
Если тебе нужно передать "сигнал" заведи для него переменную в объекте, а потм можно и: other.signal="Talk" типо того.
Ему нужно не только передать тип действия, но и фактически его выполнить в этом же кадре. Иначе может быть задержка и рассинхронизация, типа на стороне игрока он уже уйдёт в следующую комнату, а сюжетный предмет ему выдасть не успеет перед порталом. (конечно кто сказал что так вообще надо делать, но чем раньше в архитектуре проекта стыковать всё плотно, тем меньше будет мест для ошибок и затягиваний проекта потом)
Эти проблемы людей с кучей комнат... ХД
В исходнике 9 комнат, это мало? Если поставить ещё 100, проблем тоже не будет - это проблемы людей которые где-то забыли поставить галочку, а где-то забыли снять.
Вопрос - а нельзя ли просто сделать ивент коллизии с другой стороны, то есть коллизия o_BoxCore с o_HeroGirl сразу выполняет код, даже без юзер-ивента 0?
Коллизию я сделал для теста, на самом деле мне для других целей, для того чтобы использовать
какие-то объекты по нажатию кнопки А или поговорить с ними.
В конечном итоге я пока без интернета сидел вчера, таким способом сделал (через переменные):
1) первая сторона отправляет переменную isUse
2) а вторая сторона принимает сигнал:
теперь конечно я постараюсь без переменных сделать, а с with и user event
Это вполне рабочий метод, но может приводить к несостыковкам по времени, как я уже писал - мгновенные телепорты в другую комнату, например, при этом будут запрещены, или придётся писать специальную очередь действий которые надо подождать перед переходами. В общем, лучше скриптами это делать, ИМХО.
Добавляю интерфейс, выглядит конечно топорно, но ок)
надо поглядеть как в нормальных файтингах и играх с боссами полоска здоровья выглядит, а то мне кажется, будто я застрял с дизайном и он кажется слишком слабым и статичным
Ещё Game Maker сохраняться стал дольше, но объектов тут не так много и спрайтов вообще мало, если все собрать то и не будет 1024 на 1024 пикселей из всех картинок атлас.
Может у меня ноут просто слабый и медленный, но юнити в этом плане моментально сохраняется,
это немного неприятно, особенно для того кто часто по привычке сохраняется как я, раз в полминуты. :D
Тут написано что создаётся бэкап - есть такая галочка в настройках. У тебя медленно сохраняется потому что он по сути сохраняет как минимум раза - текущий заново, а предыдущий отправляет в архив. А учитывая что по умолчанию сохраняется аж 5 предыдущих версий исходника, то там происходит смещение очереди каждый раз. Отключи встроенные бэкапы и бэкапь сам.
Спасибо) и в конечном итоге оказалось, что просто моя винда и ноут тупит)
но опции возможно пригодятся
А, ну иногда бывает что это окошко просто само висит, хотя уже ничего не сохраняет. Тогда его закрываешь и всё нормально.
Я думаю, у тебя та же проблем что и у меня. У меня очень медленно сохранялся проект. Бывало до пары минут доходило. Саппорт мне не помог и я забил - перешёл на GMS2.
2 минуты это жесть D:
Какой это проект вообще был?
Доделал HUD, смотрится не очень, но работает)
Странно, хотел получить имя у объекта, чтобы потом его сохранить, и на новом уровне создать снова этот объект используя имя, но при тестировании вместо имени в обоих вариантах получил "<undefined>"
этот скрипт находится в родителе o_BoxCore, а по сути настоящий объект это o_Box,
но хз как получить доступ к чайлду от этого скрипта родителя, или здесь другая ошибка
Тебе наверное, нужно там вместо self написать object_index (или self.object_index, без разницы) - по сути это айди ресурса-объекта. Когда ты пишешь в коде название ресурса-объекта - то это тоже айди, т.е. номер ассета по порядку в дереве ассетов справа. Если перенесёшь ресурс то этот нормер поменяется. Это внутренняя кухня для понимания. Иногда попутаешь в функции instance_create порядок аргументов и утебя херня создастся.
Так что вот смотри:
object_index - это айди ресурса. Его можно передавать в instance_create функции
object_get_name(object_index) - строковое название ресурса, его ты передать в эти функции не можешь. Но есть функция asset_get_index, которая по этой строке найдёт id ресурса.
Если ты хочешь это использовать для сохранения состояния игры то лучше получать строку. Если в рамках одной игровой сессии то проще будет object_index хранить.
Спасибо сработало)
Звучит как собственный костыльный механизм персистентности. Хейз уже объяснил в чём ошибка, но - зачем тебе такая штуковина в принципе? Очень интересно стало.
Если бы ты не сказал "на новом уровне", я бы просто подумал - ага, значит можно прятать объекты в сундуки, как бы погружая их в стазис, а потом вызывать обратно. Но ты говоришь про другой уровень...
Взять ящик в руку и например сохраниться или перейти на другой уровень.
Нужно сохранить String название объекта, чтобы уметь воссоздать объект из текстовой информации.
Если при перезагрузке уровня можно сделать объект неуничтожаемым, то при сохранении и загрузки игры это не сработает, так что решил что при старте героя будет генерироваться "Box" в руках (какой-то инструмент, который можно бросить во врага или использовать), если он есть
Глобальная переменная после смены уровня не обнуляется... Нужно либо ручное обнуление, либо полный рестарт. Надеюсь, ты понимаешь к чему я веду... А ещё есть дата структуры и куча всего, чтобы не сохранять string название
Мне это как раз и нужно, хочу сохранить в что-то типа
global.BoxName = "o_Box";
С дата структурами пока ещё не разобрался, думаю на днях попрактиковаться с этим,
я так понял речь идёт про массивы и списки.
Опять таки, зачем тебе нужен этот string? Что-то типа global.item = o_box будет сильно просто? Не усложняй себе жизнь. В случае необходимости сохранить более сложную структуру - можно использовать массив
А как сохранить это o_Box не в string формате при сохранении игры?
Это смотря как ты будешь делать сохранение) Как по мне, самый простой способ, это использовать ds_map. Более сложный способ - буфер. Но нигде не нужен этот string.
Ты просто сохраняешь переменную (например global.item). За остальные нюансы не беспокойся - gm сам со всем разберётся и при считывании сохранения присвоит правильные значения. Главное, при обращении к переменной, проверить существует ли такой объект с помощью функции object_exists
Просто я ещё не изучал вопрос сохранений, но в других движках (в которых работал Unity, Stencyl, Blitzmax) обязательно надо сохранять либо в string, либо в int/float значениях, потому заранее подстраховаться пытался.
Если тут можно вообще споконо id объектов сохранять, и эти id никогда не собьются, то хорошо), то есть если я вдруг начну менять, часть объектов переназывать, удалять или заменять или добавлять новые.
Если для сохранений игры то в строках храни названия объектов. Я обычно словарь создаю, чтобы как раз при переименованиях ничего не слетало
Оооо. Я это делал в Мёртвой Звезде XD
Почему именно string? Можно сохранить просто индекс, без кавычек.
А чтобы воссоздать переменные инстанса, используй ds_map и:
http://docs.yoyogames.com/source/dadiospice/002_reference/file%20handling/json_encode.html
http://docs.yoyogames.com/source/dadiospice/002_reference/file%20handling/json_decode.html
Конкретно в случае алекса я думаю можно просто ящик и игрока сделать персистентными - тогда всё будет сохраняться из комнаты в комнату.
У меня в Мёртвой Звезде случай посложнее - там можно таскать объекты из комнаты в комнату и более того - там же их оставлять, так что помимо перехода игра должна должна запоминать в какой комнате на какой позиции игрок оставил предмет. Делается не так чтобы уж сложно.
Жесть, я такое в первый раз не буду пытаться осилить)
Спасибо, хотя пока я не дошёл до сохранений, с другой механикой застрял, не могу придумать как сделать нормальное выталкивание объекта из другого объекта если он застрял в нём, разные велосипеды придумываю,
но вроде бы нашёл решение или хз)
Collision Event с тем из чего хочешь выталкиваться:
Это мягкое выталкивание по 1 пикселю за 1 степ. Можно добавить while, но там сложнее отлаживать будет, начни с простого (а если на нём удастся и закончить во всех нужных игровых ситуациях, то и отлично).
о, Спасибо) а то я там больше кода навернул) раза в 3-4 больше
Ну да, по сути это костыль персистентности)
Всё-таки обычная физика лучше, чем вручную писать, и криво получаются отталкивания и лишняя трата сил)
и много кода
Да уж. Читая все вышенаписанное, наверное реально уже GMS (Game Maker Studio) более-менее хорошо изучить ;) Не совсем понял - что за обычная физика и чем хуже - когда её вручную пишешь. Есть твой же собственный способ о котором ты писал про рисование. Если что-то не умеешь сам - делай как делают другие :))) Но тут проблема в том, что невозможно всегда делать как делают другие. И вот ты уже как раз столкнулся с такими проблемами. То есть рано или поздно тебе придется и что-то свое писать, а не только делать как делают другие или использовать готовые решения. Именно поэтому движки с открытым кодом лучше, чем движки с закрытым. Но тут, как говорится, каждый волен впадать в любые крайности. Не хотел ничего плохого сказать про GMS и твой выбор изучать его. С чего-то ведь надо начинать. И конечно, поскольку знаний программирования, как я понял у тебя не слишком много (не хочу конечно обидеть, если что извини), и изучать глубоко программирование тебе не интересно, то вот так и будет - вечная дилемма - или использовать чужие (но не всегда такие, как тебе хочется) решения или пробовать писать свои (но это гораздо сложнее если делать на таких движках как GMS). Опять же, не хочу никого обидеть. Это лишь моя личная точка зрения, я не пытаюсь никому ничего доказывать :)))) Я вот тоже (если мой опыт тебе будет интересен) - сначала изучал готовый движок (но правда там был открытый код), но когда я его изучал (DelphiX - такой движок), то знаний у меня было слишком мало. Первая игра на нем была Road2City - дорога в город. Делал её несколько лет. Зато когда закончил - знаний было уже достаточно чтобы начать писать свой движок. И потом уже все игры делал с использованием своего движка. Движок был сначала Delphi Direct X (написанный практически с нуля). DelphiX - был для 7 DirectX, Delphi DirectX уже для 8.1, а fle game engine уже написал на c++ и работает он под DirectX 9.
Понятно что у каждого свой путь. Но лично у меня был вот такой опыт. Потом уже (чисто профессионально) писал движки для сайтов или делал сайты на готовых движках (но чаще дорабатывал). Также писал разные другие веб приложения. Сейчас вот последние 2-3 года уже заинтересовался не только dektop приложениями, но и html 5 играми (на javascript). Лично я предпочитаю движки с открытым исходным кодом, просто потому что мне так понятнее и удобнее.
Вот такие мысли. Заранее прошу простить если кого-то чем-то задел или обидел. У каждого своя личная точка зрения и не надо обижаться на чужие :))))
Не поэтому. На Гамаке с закрытым исходным кодом прекрасно можно писать свою физику. А лучше движки где есть свой язык программирования, чем движки где своего языка программирования нет - это отличие полноценного игрового движка Гейм Мейкера (и, кстати, Годота) от конструкторов сред разработки опирающихся на языки общего назначения, типа Юнити и Анриала. К чести последнего, когда-то свой скриптовый язык у него был, но уже нет, увы.
Мне сложно судить, т. к. мой опыт работы с GM стремится к нулю. У вас он вижу намного намного выше. Но я высказал мнение. И мне кажется, что по сути оно правильное. Если исходный код движка открыт - то решения делать проще, чем на движке с закрытым - писать код, который обходит те или иные ограничения. Выше очень много было сказано про разные движки :)))) И каждый, кто хорошо знаком с тем или иным движком обязательно докажет, что его движок - лучше. Вы по сути это и делаете сейчас. ;) Однако посмотрите на цитату которую вы процитировали с другой точки зрения и сравните со своим личным опытом. Вы всегда использовали готовые решения в GM (и GMS) ? Или все же больше и чаще писали что-то свое ???
Количество различных применений движка не настолько большое, чтобы постоянно приходилось что-то решать или обходить ограничения.
Для этого надо посчитать все решения во всех проектах, а их много - и решений, и проектов. Ну в среднем могу сказать что бывало и так и так, и не сказать что редко одно или другое. Свою систему коллизий я писал только в платформерах, и то не для всего, а только точечно, и опять же на встроенных функциях проверки столкновений по заданным линиям. Свою отрисовку интерфейса надо, безусловно, писать везде и всегда - нет ведь готовых интерфейсов где уже всё выводится как твоей игре надо. Поиском пути я не занимался никогда, потому что не работал в жанрах где это нужно. Но если бы начал, то вполне мог бы приспособить тот поиск методом "A*", который туда уже встроен. И так далее.
Что вообще есть готовое решение, а что неготовое? Где грань?
Анимация кадров изображения подряд - это готовое, а анимация их в зависимости от того куда смотрит персонаж - неготовое? Но ведь я написал это "неготовое" на основе другого готового - мне в языке программирования Game Maker Language дают возможность задать любую другую логику переключения кадров, и я просто пишу:
И получается что я поменял порядок отрисовки, без какого-либо переписывания движка игры, и в то же время не превозмогая какие-то страшные горы ограничений. Таких примеров можно привести много - того что можно сделать обладая встроенным скриптовым языком, для движка с закрытым исходным кодом. Потому что исходный код движка это всего лишь машина, а заставить её работать как нужно позволяет промежуточный скриптовый язык.
Именно поэтому количество готовых и неготовых решений, использованных мной, ничего не скажет, да и не послужит аргументом в пользу своих самописных движков. Это количество будет говорить только о том, каких жанров игры я делал - более просто реализуемые в движке, или менее просто реализуемые.
Я имел в виду буквально - то есть все то, что можно нагуглить. Хорошо, собственно я не пытался никого переубедить. Каждый пользуется тем, что ему ближе, понятнее и удобнее (и еще тысяча причин :))) ). Лично мне ближе движки, где код можно "потрогать" - просто потому что можно реализовать те или иные особенности лучше понимая как оно устроено изнутри. Кроме того, движки с открытым кодом не дают вам быть зависимым от движка. Легко можно перейти на другой. В случае с движками закрытого кода - GM, Unity 3d - вы целиком и полностью зависите от движка. И будет сложно сделать что-то что движок не позволяет. За вашу жизнь в геймдеве вы просто не делали игр, у которых были бы такие возможности, которых нет в движке. Я не говорю, что это плохо или что-то подобное. Просто лично мне всегда интересно знать что и как устроено изнутри. Именно поэтому я выбираю движки с открытым кодом и они ближе. Ну а вам это неинтересно :))) Вам интереснее делать игры используя только те возможности, которые движок предоставляет. Ну а то, что касается самых простых задач - наподобие вывода интерфейса - эти задачи не настолько сложные, чтобы движок мог чем-то помочь. По сути он в данном случае не играет вообще никакой роли :))))
Как будто это что-то плохое)), для меня куда хуже с нуля движок писать, ведь разработка простой инди игры может растянуться в 2-4 раза дольше. И да, кому-то ближе движки делать, кому-то игры) Я сейчас хочу наоборот ещё больше упростить разработку, чтобы только скриптинг уровней писать, а основные модули чтобы уже были готовы, раз и навсегда, что-то типа Bitsy, только более навороченная, но всё также должна ускорять разработку коротеньких инди проектов.
Скорее в 20-40 раз, если не в 200-400 =)
Очень много рисков при отладке. А поддержку платформ и прикручивание чужого API (тот же Steam API) тупо заебёшься делать.
То что юзеры гамака полностью зависят от движка, а тру-программисты - нет. Это иллюзия. На деле точно такая же зависимость от "движка", которым выступает язык программирования и среда разработки. Начать с того что синтаксис любого языка беден в силу своей формализованности чтобы быть понятным комплиятору. Вот на естественном языке можно сказать гораздо больше! Можно слова местами переставлять, например, использовать склонения, спряжения, делать мелкие отчепятки.
А в том же Си ты никогда не сможешь написать того что можешь написать на Асме. А на асме порой невозможно сделать то, что делается распайкой платы.
Вот хочу я картинку за один такт процессора обрабатывать. Может ваш Си или JS это сделать, на чём угодно? Хуй-то там. Фуууу, дерьмо-фреймворк и дерьмо-язык!
А ещё я хочу чтобы у меня один бит принимал три значения, а не два. И чтобы можно было быстро управлять троичной системой, а не двоичной. Ваши процессоры интел и амд - говно, раз такое не могут.
Ебать, сколько ограничений я нашёл в этих ваших хвалёных фреймворках! Вот вы целиком зависите от вашей железки и его набора инструкций!
Вот вы читате и думаете что я сошёл с ума, что вам и в голову не придёт использовать троичную систему вместо двоичной или никогда не понадобится картинку за такт процессора обрабатывать. Так вот нам, юзерам гамака точно так же не придут в голову какие-то супер-редкие задачи, еле связанные с разработкой игр. В контексте работы с гамаком задача "останавливать апдейт но не останавливать рисование" - как раз одна из таких ненужных и бесполезных. Там просто другими категориями и абстракциями мыслить нужно и не пытаться проектировать и писать код так как вы привыкли в языках общего назначения.
Я считаю, что тема "зависимости от движка" на этом должна быть закрыта
Лол, я это не учитывал, тогда реально в десятки раз сложнее)
Отладка тоже очень много времени сжирает. Учитывая, что в "нормальных тру-пацанских движках" ты порой не можешь вообще нормально инспектировать некоторые структуры данных (текстуры, сложносочинённые поля объектов).
Серьёзно? Давайте возьмём вот таблицу игровых движков с Википедии, отфильтруем её по типу лицензирования, и посмотрим с чего на что можно пробовать перейти:
https://en.wikipedia.org/wiki/List_of_game_engines
С движка файтингов на движок шутеров? Точно нет. С языка FreeBASIC в одном движке на язык NScripter в другом? Вообще никак.
Нет игровых движков, которые разрабатываются бесцельно.
Каждый движок решает свой ряд задач, и именно потому неуместно считать Юнити адекватным для двухмерных игр, как и Гамак для трёхмерных. И даже если бы все они были с открытым исходным кодом, это бы никак не помогло переходить с одного из них на другой.
В случае с процессорами Intel или AMD - вы целиком и полностью зависите от аппаратной архитектуры которую никак не можете поменять. Почему люди не делают свои процессоры? Потому что существующих хватает. Так и с движками.
Да нет, мне это интересно, но только в формате экскурсии, а не чтоб писать это всё руками заново самому. Я так-то и процессор когда-то 8-битный проектировал, в учебном проекте. Я действительно знаю как это делается, и при наступлении зомби-апокалипсиса могу вытравить печатную плату с какими-нибудь несчастными 1МГц тактовой частоты, правда для этого нужна элементная база из уже существующих микрочипов, реализующих логические операции, мультиплексирование и синхронизацию. Но это всё не про нашу реальную жизнь на сегодняшний день.
Я время от времени продолжаю разрабатывать игру для NES, известную у нас как Денди. Это порт на неё, нашего Замка Невозврата 1. Хотите расскажу в отдельном посте?
"Вам интереснее делать игры которые максимум заработают всего лишь несколько миллионов долларов и соберут всего лишь сотни тысяч отзывов в Стиме. Не более чем! Вы ограничены вот такой вот скучной планкой, потому что не хотите смотреть на движки с открытым исходным кодом!"
Я бы это почитал, ибо мне до сих пор интересна разработка игр на NES, хотелось бы самому что-нибудь там написать. Хотя есть один интересный конструктор NES, забыл название, который упрощает разработку, потом хочу как-нибудь приобрести его.
NESmaker, как ни странно.
точно)
Ты на нём делаешь Замок Невозврата?!
Нет, я использую злостную связку древней магии, куда не ступала нога обычного человека.
http://hype.retroscene.org/blog/282.html
Именно это мне позволяет смотреть на аргументы типа "свой движок лучше всего" с очень большим (потому что обоснованным) скептицизмом.
Жесть) Я лучше NES Maker потом куплю)
Я не совсем разобрался, но похоже там есть библиотека физики что-то типа Box2D (а может и она и есть)
а вручную, это что-то типа, когда сам определяешь с какой скоростью нужно отталкиваться объектам и в какую сторону, и поскольку я с математикой совсем не дружу, то получается не так хорошо, как могло получиться у математика.
Да, это именно бокс 2д
Я только хотел предостеречь от надежд, что движок все сделает за тебя :))) Такого не бывает. И даже если тебе говорят - вот движок - в нем все делается легко или по крайней мере так кажется, то, поверь мне, такого не бывает. Ты всегда захочешь сделать так, как до тебя никто не делал и поэтому движок тут будет не помощник, а скорее обуза :)))) Понятно что есть набор функционала, который позволяет сделать типовую 2d игру и GM за глаза этого хватает. Например можно сделать игру на html5 в GM. Вопрос только: зачем ? Если все то же самое можно сделать просто в блокноте и браузере :)))) Так что движок - а именно GM не всегда может быть тем инструментом, который поможет тебе сделать игру своей мечты (ну или игру которую бы ты смог сделать). И даже если там есть какой-то функционал из коробки, я не уверен, что все это тебе пригодится. Движок в данном случае будет тебя не поддерживать, а ограничивать. Те кто к нему привык, понятно на это закрывают глаза. Ну а если приходит человек со стороны, имеющий другие взгляды, то ему становится очевидным, что ни GM, ни Unity 3d не являются движками мечты :))) Это инструменты, но даже если рассматривать их просто как инструменты, то и тут мы наткнемся на грабли. Все дело в том, что совершенных движков в природе не существует. И в случае движков с закрытым кодом мы попадаем в клетку. Нас ограничивают настолько, что мы уже не сможем сделать все так, как захотим. Понятно что каждый выбирает сам, в какие рамки он себя загонит. И я лишь высказываю свою точку зрения и ни в коем случае не считаю, что игры надо делать на чем-то одном и этот инструмент - самый лучший. Надо попробовать все. Просто из того, что я умею и знаю я сделал для себя именно такие выводы. Движок с открытым кодом - всегда лучше. Операционные системы с открытым кодом - тоже лучше. Да и вообще чем меньше ограничений, тем лучше. А ограничения, увы, есть всегда и везде.
Для меня, как художнику, на самом деле даже Unity3d и GMS сложен, потому-что очень много приходиться программировать, а в случае с движком с нуля это "много" может растянуться до бесконечности)
По части открытого кода, мне не нравится, что там часто куча разрозненных библиотек или тонна неоткомпилированных файлов, в которых надо ещё научиться разбираться, и ещё надо поставить тонну сторонних инструментов, мне нравится когда в одном инструменте всё и сразу или хотя бы порог вхождения должен быть делом 5 минут для не программиста, у меня например даже Visual Studio на винду не поставлена и другие внешние компиляторы не ставлю, не влезая глубоко в дебри программирования)
Если рассматривать движок для художника и пытаться на нем сделать что-то что движок не позволяет, да еще не обладая достаточным уровнем знаний. Вот как раз пост https://gamin.me/posts/21100 где я задался вопросом подобного рода. То есть что мы все делаем, когда наши представления оказываются бесполезными.
Вообще, если вспомнить, то из движков с открытым кодом, кажется есть один, что мне нравится - Годот.
Благо там почти все инструменты внутри, даже кодинг (кроме рисования спрайтов). Но пока сильно не пытался его изучать, закончить бы со старыми проектами на Unity и GMS для начала, а там посмотрим)
Чем больше движков знаешь, тем лучше, выбрать какой-то один - трудно, тем более не обладая достаточными знаниями ни по одному из них. Не зная хорошо программирования и прочее и прочее. Соглашусь с тем, что Unity и GMS были созданы программистами для непрограммистов. Только вот проблема любого движка - это то, что его сначала надо изучить :)))) Если пытаться решать с наскока, то можно лишь писать простейшие прототипы с задействованием самого простого функционала, который есть из коробки. Но я хотел высказать вот какую мысль. Все движки - это как "каша из топора". То есть любой движок в той или иной мере это "топор", а кашу мы вынуждены варить используя его сами :))))
Или можно всю жизнь произучать движки, но так и не сделать ни одной игры. Или ни одной успешной игры,
которая, если не принесёт много денег, то принесёт много фанатов или благодарных людей.
Время не резиновое, к сожалению.(
Что значит рисование спрайтов?
Я имею ввиду что спрайты надо рисовать отдельно, забей, это можно было даже не писать) это не придирка, просто меня приучили Game Maker и Tic-80, что можно спрайты рисовать прямо в редакторе, но это не критично, в Юнити и Годоте я не прошу, чтобы ещё и сделали внутренний редактор спрайтов.)
Отвечу, что можно. Я уже тебе дааавно это объяснял и показывал. В Godot есть возможность создания объектов, как через редактор, так и через код. Единственно, в редакторе все настраивается, через инспектор, в котором все настройки ноды видны, а в коде все необходимое нужно прописовать самому.
Если тебе нужен пиксельный редактор в движке, то есть плагины. Цельных две штуки, правда они не имеют широких возможностей, как в паинте, но развиваются.
Рисовать спрайт через код проще некуда:
Я про редактор. А так да, видел там специальные функции рисования в годоте (не создавая отдельный объект), там действительно лучше с этим, чем в юнити.
Надо сказать что это действительно со мной произошло, и в довольно серьёзном масштабе. В начале 2019 года надо было релизить игру на Иксбокс, а сделать я этого не мог потому что Microsoft поменял API не предупредив об этом YoYoGames (владельцев Гамака). В итоге я как дурак писал в техподдержку подробнейшие отчёты на английском, ждал несколько месяцев, пока они починят привязку Гамака к этому API, хотя теоретически мог бы сам в Visual Studio переписать нужную мне часть движка. Однако, здесь речь не о том чтоб сделать игру, и игра которую я сделал, определённо заняла бы долгие годы вместо чтоб уже быть выпущенной даже с такой задержкой и принести вполне ощутимые, как для пост-СССР, деньги.
Увы. От такого никто не застрахован. Случиться может что угодно. Завтра все перейдут на linux или еще какую-то новую ОС. Вообщем да. И тут вы правы - не играет роли открытость/закрытость, а скорее какие-то совершенно малозависящие от наших усилий факторы.
Ещё раз переделал физику. И теперь есть анимация бросания ящиков или использования предметов.
Ящик - это объект инвентаря. Сделал чтобы героиня могла взять всего один предмет инвентаря,
что-то типа Марио 3 на NES, это может быть как ящик, так и холодное оружие, бомба или лечилка.
Ты, я вижу, и до партиклов добрался. Хороший прогресс.
Кстати, партиклы я ещё не учил ^_^'
это просто 10-20 объектов "o_parts" с переменными, я не уверен быстрые ли партиклы в GM,
просто в примере к GMS 1.4.9 есть пример партиклов, и почему-то это всё выдаёт слабый FPS
на моём ноуте, поэтому я пока не уверен, стоит ли юзать их.
А вторая причина я ещё не гуглил - смогу ли я сделать паузу на частицы.
Пока также ещё не разбирался со скриншотом на паузе, хотя видимо всё равно придётся это добавлять в проект.
Я имел в виду партиклы как элемент геймдизайна. Как элемент Гамака они мне никогда не нравились, и на паузу их ставить надо тоже отдельно.
А почему не нравились? То есть их можно вообще не использовать, и достаточно обычных объектов вместо частиц?!
Если их не тысячи одновременнно, то да, можно.
Да. Вдогонку:
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
Мне очень понравился GM, и понял что на нём можно сделать простые игры, но пока не уверен,
можно ли делать более сложные игры, как я пытаюсь на юнити:
1) Вывезет ли Game Maker, если на уровне будет где-то 2000 отдельных объектов и у каждого объекта свой
Depth
(Z Order)? Если мой комп еле вытягивает Morrowind и Mount & Blade: Warband. При том что юнити работает со скоростью 100 FPS с этой моей картой в 2000 объектов и у каждого свой Order (порядок отрисовки). Потом хочу провести эксперимент с GMS и запихать тонну объектов на локацию.2) Легко ли редактировать такой уровень в GMS, где много объектов друг с другом пересекаются? И много контента, и всё это без TileSet и TileMap элементов (потому-что тайлы не люблю, их делать сложно, чтобы они аккуратно друг к другу подходили и не повторялись), а то пока я в Game Maker немного запутался в редакторе, то ли там неудобно сделано, или я просто ещё не привык.
3) И можно ли в редакторе GMS настроить порядок отрисовки сразу не включая игру? А то я пока не понял как сделать так, чтобы одни объекты рисовались раньше других в редакторе и чтобы это также выглядело в игре при запуске. В моей игре леталке на GMS легко, потому-что объекты не пересекаются друг с другом.
Попытался сделать пока без Depth скрипта, и получился порядок отрисовки совершенно разный,
слева в редакторе справа в игре. Но если в игру прикручивать скрипт Depth от Y оси, то как прикрутить это так, чтобы это выглядело также и в редакторе?
PS лол, комменты уже лагают в гугл хроме) пора завязывать с этой темой)
Такого функционала в GMS пока нету, увы.
А сторонние библиотеки создания уровней есть?
PS Я слышал есть Tiled, и возможно можно прикрутить к GMS, но не уверен, что в самом Tiled есть функция создания тонны объектов (без тайлов) с функционалом Depth или Order и чтобы это выглядело один в один как и в редакторе, так и в игре. Надо бы погуглить инфу про Tiled.
Можно свой редактор на том же гамаке сделать
одно время я делал редактор на Blitz Max, сделал, но больше не хочу) долго и муторно
ХЗ. Я на гамаке много редакторов сделал уже. И то до GMS2 в основном. А там уже встроенных средств дофига для этого.
1) Вообще большие игры на GMS делать можно(см. тот же Hyperlight Drifter). Вряд ли прям с большим открытым миром, лучше делить игру на локации/комнаты. Можно реализовать руками динамическую подгрузку.
Сам GMS 2000 вывезет но редактор комнаты может начать подтормаживать.
2) Если по слоям грамотно раскладывать, то просто редактировать.
У меня не совсем большой открытый мир, а скорее большой остров, его можно пройти где-то секунд за 15-30 из одной части локации в другую. Не люблю слишком огромные миры, лучше пусть они будут насыщенные, чем огромные но пустые)
Я думаю одна большая локация Hypelight Drifter, как у меня весь остров по размеру, просто у меня насыщенность объектов большая. Я пока боюсь за количество объектов, они ещё и разные и с разной Depth, и если GMS это вытянет, то хорошо :3
Ну так Hyper Light Drifter целиком на GMS1.4 сделан. Так что всё вытянет.
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
https://kolenka.net/posts/na-chto-sposoben-vash-dvizhok-gamak-derzhit-34000-obektov-na-59fps
В GMS2 легко - там можно задавать конкретно слои для объектов и передвигать целые группы объектов послойно. В GMS1 такого нет, только depth, и в редакторе всё будет выглядеть как попало. Однако, сделать свой редактор действительно проще простого - тебе же по сути ничего не нужно кроме расположения объектов по x, y и depth? Во встроенном редакторе можно ещё поворачивать объекты на угол и масштабировать по двум осям.
Ничего сложного на скриншоте не увидел. Я думал ты там что-то вроде Factorio покажешь, где на экране 100x100 клеток и внутри каждой какие-то процессы ещё идут.
Ну ладно, я пока не буду заморачиваться со своим редактором, это долго, надо сохранение и открытие файла смотреть, потом придумывать интерфейс и как загружать картинки с теми же названиями что и из игры, это морока, лучше буду пока простой проект делать, то есть для начала эту леталку допилю.
А не надо ничего загружать - это просто будет одна из комнат самой игры, в том же проекте. От интерфейса тебе что нужно? Просто список всех объектов, разве нет? В файлы всё пишется через
https://docs.yoyogames.com/source/dadiospice/002_reference/data%20structures/ds%20lists/ds_list_write.html
и читается через
https://docs.yoyogames.com/source/dadiospice/002_reference/data%20structures/ds%20lists/ds_list_read.html
Тут делов-то на один вечер. Хейз, скажи?
Ну нет, там и кнопки надо расставлять, чтобы выбирать в этих кнопках объекты для расставления по карте мышкой, я ещё даже незнаю как мышкой по кнопке попадать, и скроллинг объектов надо думать как делать ибо объектов будет много) также я ещё не делал скроллинг самой карты полюбому там много того что я не учёл есть, там много всего будет того, что отвлечёт от игры) я лучше простые игры поделаю на GM
Да легче лёгкого. Ивент Left Pressed делаешь и всё - как только попадаешь по пикселю спрайта объекта, срабатывает код.
Ты имеешь в виду список для расстановки, список уже расставленных (тогда это список инстансов), или двухмерная прокрутка самого уровня на котором ставятся инстансы?
Там на самом деле комплексная задача для не программиста, но программисту наверное легче с такими вещами. У меня разработка такого редактора займёт примерно от месяца, до полугода. Даже если на GMS легче это делать, то я его не изучил нормально, а кнопки я делаю простым рисованием спрайта без какого-либо объекта, который можно проверить на коллизию с мышкой, там наверное надо проверять в каком районе находится мышка и попадает ли она в координаты кнопки X,Y,W,H
Но даже если забить на меню и сделать весь выбор через клавиатуру, то всё равно много работы)
Сохранение, загрузка.
Хотя я представил один простой вариант, если сделать управление клавиатурой:
Move Keys - скроллинг (перемещаем сразу объект)
Z - cоздание объекта
A - удаление?
X C - скроллинг объектов
S - save (не представляю как сделать сохранение легко)
L - load (загрузка тоже сложна)
Ну и загрузка библиотеки спрайтов не представляю как сделать. Тем более ещё не пробовал делать игру со скроллингом на GMS, там наверное для отрисовки HUD и отдельно отрисовки локации ещё надо учитывать что-то.
Всё это делается изи. Есть событие DrawGUI где всё движение камеры уже учтено. Это не ебаные фреймворки на HTML5 где нужно вручную всё пересчитывать.
Сохранение делается через with, лёгкий набросок:
Загрузка примерно так же только нужно будет распарсить строку.
Для тех объектов что должны сохраняться нужно парентом указать o_saving_prototype
Переменная asset_name должна хранить название актуального объекта. Я бы не стал полагаться на название самих ассетов и сделал бы словарь соответствия строка-объект.
Чтобы не парсить строку можно воспользоваться структурами данных примерно так:
Способов много разных есть
Ну ты поторопился, косяков много: asset_name вместо id и open_read вместо open_write.
В общем, я решил что хватит уже мучать этот пост, раз у Алекса браузер подвисает, и создал отдельный, для развития конкретно этой системы. Так что переходим туда.
Я использовал твой код, только поправил его чтоб он работал, и работал именно так, как надо. Добавил третий словарь и конвертацию между именем и индексом объекта.
Последнее - да. А вот asset_name - это строка которая хранится в объекте и по ней при загрузке сцены создавать нужные объекты.
Я назвал это obj_name, хотя по идее это может быть и набор объектов, но индекс-то всё равно один. Проще создавать один объект, который будет создавать уже группу - то о чём постоянно Алекс говорил насчёт префабов в Юнити.
Конечно каждый раз ухмыляюсь с этого заголовка. "Ваш" движок и "наш". "Вашим" и "нашим" их делает, конечно же, использование "нами" и "вами", да. Сразу приятно становится на душе, что "наши" "ваших" этсамое, и мы за компанию, да.
"Наших" там не уточняется, но комментарий прикольный. :yak:
Как-нибудь можно перейти в другую комнату чтобы предыдущая продолжала обновляться?
Или придется делать одну комнату с иллюзией что это 2 разные локации?
Самое простое что мне приходит на ум:
в одном уровне все или несколько комнат сразу, они разделены какими-то объектами, за которые камера не может выйти или просто скриптом заблокировать движение камеры, тем самым кажется что это несколько комнат. Но это пока в теории.
То есть 2-ой вариант?
Нет.
Да.
Ответный вопрос: а в каком вообще игровом движке можно обновлять одновременно две "сцены"?
На Love2D можно. Причем это будут именно 2 отдельных уровня и объекты первого уровня не будут видеть объекты второго.
Окей, и в каком жанре игр это имеет применение?
Ну я, например, задумываю стелс где игрок будет переключаться между двумя уровнями и прятаться на обоих.
Поднял тревогу здесь - свалил на другой уровень. Поднял тревогу там - свалил обратно, тут как раз все успокоились.
А если без тревоги будешь телепортироваться - есть риск появится прямо перед носом стражника. Так что лучше телепортироваться в безопасных местах, а не посреди улицы.
Вообще это звучит логично, но стоит рассмотреть как эту механику делали в жанре до того. В Metal Gear Solid, например, в самых первых частях просто плевали на состояние врагов, а в следующих в памяти были просто все комнаты одновременно.
Но, раз Лав это позволяет, вполне можно сделать это и встроенными средствами. В ГМе нельзя. Можно попробовать развернуть уровень на всю комнату, просто расставить далеко друг от друга все доступные места.
Оказалось что с моим методом автоматического размера Viewport под размер экрана не работает скроллинг,
то есть все локации будут размером с экран, не больше, иначе изображение деформируется.
Ну ладно, для первого проекта и так сойдёт, на одном экране многое можно сотворить,
в конце-концов например игра "Hero Core" сделана без скроллинга.
Я не понял в чём проблема. Всё тамо тлично делается. Выставляешь размер комнаты какой хочешь, а размер камеры в комнате определяешь отдельно, точно так же как и размер вьюпорта
У тебя код скроллинга неправильный, надо переделать. Должно работать.
Да я не понял в чём прикол, решил пока забить на это, просто хотел посмотреть как работает со скроллингом моя игра, и добавил в Viewport уровня следить за объектом o_HeroObject, но вместо слежения получил растяжение, лол)
Подумал, что для первой игры это не критично, пусть всё будет на одном экране происходить, всё равно я жанр Boss Rush выбрал.
Так бывает если ты view не включил =) Или если у тебя где-то ширина view камеры переписывается шириной комнаты.
Да, перепроверь что вид включил вообще. Enabled.
Действительно, вручную забыл включить, просто я выключал с оператором "room_set_view", а вручную забыл включить, теперь всё работает) вижу что некоторые объекты интерфейсы скроллятся, буду править)
А вообще загадка room_set_view , в документации вроде не нашёл нигде упоминания про это, я как-то давно в сети нашёл и юзал этот код без особых изменений:
а теперь думаю поменять room_set_view, а этого в документации нет, и хз что это за переменные тут,
мне всего-лишь надо было:
1) изменить размер всех View во всех комнатах моим размером screenH и screenW
2) + включить View
3) + теперь уже следить за o_HeroObject
Я вот эти функции никогда не использовал. Просто потому что менять размер видам можно на лету. И для поддержки нужных разрешений я у контроллера как раз и делаю все проверки и тут же делаю ресайз всех сурфейсов.
это в GMS 2? Просто я не нашёл более быстрого способа поменять вид сразу на всех локациях иначе.
В любом GM так можно. На GMS1 есть view_enable[0..7], view_width[0..7], view_wport[0..7] и т.д.
Тут вопрос зачем менять вид на всех локациях, когда можно менять вид в текущей локации.
кстати да, хороший вопрос, надо понять как старт новой локации отлавливать,
возможно что-то в эвентах есть, чтобы к глобальному объекту прилепить,
и тогда можно код туда поместить
Событие "room start" есть во вкладке other
Затем чтоб при переходе в новую комнату ничего не мерцало с "проектного" размера на новый. Впрочем, я всегда делал именно room_set_view при старте игры на все комнаты, может это проблема времён ещё GM8.1 и теперь её нет. А может есть, надо проверять.
У меня не мерацает ничего. Но я транзишн всегда делаю через спецэффект, может потому и не видел.
Но вообще не должно, т.к. событие отрисовки выполняется позже всех остальных событий.
Если делать переход во время отрисовки то может быть. Но делать в отрисовке что-то кроме отрисовки - это bad smell.
Нет, я не об этом. Конечно в отрисовке я ничего не делаю, но в момент перехода в другую комнату может проскочить кадр с начальными видами этой комнаты.
Ничего такого не видел. А раньше на GM8.1 сталкивался такой проблемой тоже.
кстати да, моему проекту ещё не хватает красивых переходов (транзишны всякие),
надо бы погуглить как они делаются
Взял из GM8.1:
Можно ли как-то отдельным комнатам задавать флаги, которые потом проверять в скриптах и от этого менять поведение объекта?
Мне надо чтобы один и тот же объект в одной комнате вел себя так, а другой - по-другому.
Я так и знал... что предложат именно такой вариант.
Если у меня 10 комнат, я их все захардкожить должен? А если я решил их переименовать или какие-то удалить? Мне что, лезть в скрипт и там что-то править?
Мне надо в step чтобы можно было вот так:
Можно и так, только не room, а global.
Прописывай в Room creation code нужной тебе комнаты global.can_jump=true и в условия то как ты выше написал, только с global вместо room. Будет работать.
Но тогда во всех комнатах в create придется писать или global.can_jump=true или global.can_jump=false, что не очень удобно.
Еще мне надо чтобы при переходе за нижнюю границу уровня уровень начинался сначала (пропасть), левая была твердой, а за правую - переход в другую комнату.
Я понял как это сделать, но в другой мне, например, надо чтобы все границы были твердые.
Как сделать? В каждой комнате хранить объект, в переменных к-го хранить тип границ комнаты?
И при входе в любую комнату читать его?
Не "во всех комнатах в Create", а именно в коде начала комнаты как комнаты, в этом коде:
В принципе, это такое же решение как и прописывать Room Creation Code - один фиг нужно писать флаги и откуда-то их читать. Просто в случае с кодом комнаты оставаться будут предыдущие значения переменных и не обязательно их менять в следующей комнате. Ну и соответственно что-то по типу:
И еще вопрос. Мне надо переименовать или найти переменную/функцию в своем коде. С файлами на диске все понятно - открываем поиск по папке, вводим название которое ищем, и находим.
А в Гамаке как это сделать? Открыть все скрипты и искать глазами?
CTRL+SHIFT+F, искомое название.
Средней кнопкой мыши на название в коде -> открывается скрипт/объект/спрайт и т.д.
По функции -> открывается хелп
Это как открыть ресурсы из кода, или справку, а ему вроде именно имена нужны.
Теперь другая проблема, уровень скроллится, и задник почему-то тоже, а нужно чтобы он всегда стоял посередине экрана. Видимо придётся вручную задник рисовать или хз.
хз что тут менять, вроде всё пробовал, но задник не стоит на месте в любом случае
В твоём случае тебе нужно куда-то в контроллер комнаты добавить что-то в духе
Ну или там другую формулу сделать если тебе нужно как-то особо его позиционировать.
Спасибо, правда надеялся что это автоматически будет работать, но да ладно, можно и кодом написать)
Какая-то странная опция, есть движки где это автоматически работает?
Я бы наверное сделал отдельный объект который рисует background_index[0] на своей глубине в точке view_xview[0], view_yview[0]. То есть ты устанавливаешь фон в комнату, но видимым его не делаешь, видимым его будет делать контроллер фона со своим
draw_background(background_index[0], view_xview[0], view_yview[0])
. В любом случае ведь контроллер делаем.Например в Stencyl есть такое (если правильно помню), ибо часто задник нужен как реально задник, чтобы не скроллился вообще и всегда был виден (или скроллился параллаксом медленно) и там были облака или горы какие-нибудь.
Первый раз слышу, во всех платформерах и шмапах старой школы задник скроллится. Стенсил... надо будет его мне ещё раз рассмотреть. Я когда-то его пробовал, но по производительности что-то было совсем не то.
Может я ошибся с задником, давно было, и да, производительность там слабая)
Да скорее всего придётся просто сделать рисование вручную объектом, у меня уже 95% всех объектов такие, пора и задник переводить на ручное управление отрисовки.)
Пользуюсь GMS 1.4.9999, задолбало все время закрывать окно Welcome перед и после запуска.
Нагуглил что отключить его можно только в Pro-версии.
Написал прогу, которая 10 раз в секунду ищет окно с "GameMaker: Studio" в заголовке и закрывает его.
Убивать через диспетчер задач.
https://www.dropbox.com/s/w76e85g4szz5jdr/CloseWindow_WelcomeGameMaker.exe?dl=0
Вдруг кому пригодится.
Если лень качать, можете сами скомпилировать:
Они не с тем программистом связались.
Гениально!
а мне это окно помогает быстро открывать последний проект, чтоб в браузере не искать его.
Но всё равно прикольный код.
Откроешь. А потом запускаем этот exe-шник, убиваем при завершении работы.
Ну все. Больше 5-ти комнат создать не дает.
Что делать?
И я так понимаю, триальная версия стучится в интернет, просит зарегистрироваться и войти чтобы проверить - не кончилось ли 30 дней и какая у тебя лицензия?
Я скачал GMS 1.4.9999, и вроде всё норм, сейчас проверю можно ли больше пяти комнат делать.
Может я по какой-то акции получил лицензию или хз, оказывается у меня там давно регистрация была, но триальная или нет, я до сих пор не понял, ибо не встречал ограничений, может сейчас встречу, накидаю ресурсов и потестирую.)
Вроде бы эта ссылка: https://store.yoyogames.com/downloads/gm-studio/release-notes-studio.htm
Вроде комнаты не ограничены, или хз, может надо больше их сделать.
И ещё сверху у меня написано Standard Version 1.4.9999
Ну вот! А у меня Free Edition.
Я как-то раньше находил страницу с ограничениями Free-версии, но сейчас не могу найти.
После регистрации на сайте и входе из самого конструктора пишет что "у вас не куплено ни одной версии", что логично.
Дело не во Free Edition, у тебя не 1.4.9999, скачай её. Алекс, дай ему ссылку где ты качал.
Help -> About Gamemaker
Тогда надо посмотреть что на этом экране у Алекса, сверить.
У меня это выглядит так, никаких лишних модулей:
Я с этой страницы перешёл на 1.4.9999 версию
https://www.game-maker.ru/viewpage.php?page_id=89
кликнув надпись
Released Notes: Game Maker Studio v1.4.1804 (13/03/2018)
хз поменяется ли что если зайти через неё или я реально в какую то акцию давно попал, но забыл
Думал, что GMS 1 бесплатная, но видимо ошибся.
В целом на крайняк, в стиме GMS 2 стоит 1600 рублей, дешевле чем на официальной странице,
(но лучше спросить у кого-нибудь реально ли весь функционал в стимовской версии есть)
https://store.steampowered.com/app/585410/GameMaker_Studio_2_Desktop/
Стим версия ничем не отличается от обычной. Более того ты можешь зарегаться на сайте YoYo, привязать свой стим-акк и получить оффициальную лицензию на их сайте, т.е. скачивать и ставить гамак отдельно от Стима.
Верно. И так и нужно делать, Стимовская с региональной ценой всегда дешевле.
Ну как, получилось установить другую версию, не триальную? Или это не работает?!
Я именно оттуда и качал 1.4.9999, кликнув на название версии.
А аккаунт на yoyogames есть? Там стандартная версия по-любому привязывается к аккаунту.
Я уже писал что входил в зарегистрированный аккаунт, конструктор говорит что на аккаунте нет купленных лицензий.
Ну, походу таки прикрыли лавочку.
А эта Free Edition через 30 дней не превратится в тыкву?
Понятия не имею, оказывается у них разные версии и Алексу досталась одна бесплатная, тебе другая бесплатная. В любом случае, ты за 30 дней уже можешь сделать для себя вывод, оно тебе надо или нет, не так ли?
Добавил экспериментальные тайлы со своего старого скетча левелдизайна и оказывается там не обязательно делать эти нудные повторяющиеся тайлсеты, а можно свободную графику пилить (не люблю делать тайлы из-за того что сложно разработать повторяющиеся тайлы и чтобы они не повторялись (как в Earthworm Jim на мегадрайве например), лол как бы это парадоксально ни звучало) ну и заработал нормально скроллинг уровня. Спасибо! :3
Хотя придётся ещё с коллизией разобраться ибо тут отдельный гемор с созданием коллизии для тайлов, ну это потом.
В чём гемор с коллизиями-то? Есть даже с точностью до пикселя встроенные коллизии.
Ну я пример открыл и там вот это вот, в массив надо заносить, в Tic-80 я также делал вручную.)
Забудь этот ужас, посмотри как устроен мой EX-802, который я когда-то написал на КОД за пару дней. Мало того что там нет этой дури с тайлами, так там ещё есть генерация. Считай, процедурный генератор данжей у тебя уже есть, можешь себе забирать.
Спасибо гляну, а твой вариант быстрее чем просто массивом?
Нет, но мой вариант поддерживает динамическое изменение координат тайлов, плюс любую форму этих тайлов. И ты сравниваешь между собой, грубо говоря, 100,000 проверок в секунду и 10,000 проверок в секунду - для игры твоего масштаба это не составит никакой разницы, ведь максимум с чем сталкивается объект игрока это, не знаю, 8 тайлов с разных сторон? А на экране в 320x180 замощённом полностью тайлами 8x8 (очень мелкими) тебе понадобится всего 900 проверок если прям в лоб проверять, чего опять же у меня в коде не делается.
посмотрел и не понял какой скрипт или объект отвечает за коллизию тайлов, потом гляну подробнее, а то уже спать хочется, весь день пытался придумать управление как мячом (как в бильярде) с помощью мышкой в GMS, да что-то всё не то, то скорость не та, то управление придётся делать сложнее, чем просто через клик, упоролся малость
o_player > Step
Прикольно, но будет ли сильно тормозить если много NPC и каждый будет в пол проваливаться,
долго ли код будет пытаться вытаскивать всех наверх?!
Много это сколько? 3000 на одном экране тебе хватит? Потому что тех, которые за экраном, не обязательно так точно проверять, они будут либо сразу до конечной точки телепортироваться (если туда есть путь), либо вообще спать.
(сверху FPS=60, где-то на 3400 врагах на одном месте начинает тормозить)
В таком виде более понятно, думаю.
Найс!
Объединил первые 3 комнаты в одну, прокручиваю view вперед когда игрок заходит за правую границу.
При переходе на след. экран сохраняю точку респавна игрока
После рестарта комнаты сразу меняю координаты игрока на точку респавна, но экран либо прокручивается лишний раз, либо не прокручивается вовсе. Текущую X экрана храню в переменной игрока.
Уже везде делал отладочную печать - все переменные правильные, ощущение как будто вот эта строчка из скрипта:
view_xview[0] = self.screen_pos
не работает.
Вот это помогло:
Но это скроллит только вправо. Вот в обе стороны:
(всё верно, одна строка ВМЕСТО двух)
А вот вертикально:
div - это целочисленное деление?
Да.
прикольно, надо запомнить