Попробовал GM 1.4.9, результаты
За неделю сделал что хотел, работает с багами, но уже лень ковыряться.
Как конструктор для 2-дневных конкурсов — сойдет. Сделать очередной платформер, скролл-шутер, пострелушку — пойдет. Для левелдизайна из готовых кусочков — самое то.
Для чего-то большого, серьезного и сложного — вряд ли.
Так и не пропало чувство что сижу в какой-то программе и пытаюсь подстроиться под ее возможности вместо того чтобы делать игру.
Основная проблема, с которой столкнулся — ограничения, из-за которых нельзя создать больше 5-ти комнат.
Запарился писать так чтобы правильно игрок правильно респавнился где надо, сначала работало, потом сломал, оставил как есть.
Если бы не это, сделал бы на день раньше.
+ Легко делать уровни. Все стоит так же как будет в игре.
Единственное что не понравилось — отдельное окошко для текущего объекта. Почему нельзя выбрать объект в списке и ставить его?
+ Коллизии с отдельными типами объектов — удобно.
— Встроенный граф. редактор убогий, рисовать очень недобно, ластик отдельным инструментом, почему на колесико мыши или ПКМ не сделали? В след. раз буду рисовать в Aseprite, посмотрим будет ли удобно импортировать.
— Громкость при импорте звуков можно менять их громкость (но при предварительном воспроизведении она не меняется), а музыки — нет.
— Конструктор в 50% случаев не хочет закрываться, приходится грохать в диспетчере.
— Игра после закрывания крестиком в 50% случаев — падает.
— Отключил в настройках показ Splash Screen при старте игры — все равно показывается.
+ Не надо мудохаться с камерой и изменением размера окна.
+ Готовые функции обнаружения пересечений.
— В текстовом редакторе почему-то не переключается язык, все время английский. Не работает Shift+Insert (вставка).
— Вырвиглазная подсветка синтаксиса, глаза устают.
— Ресурсы разных типов почему-то находятся в одном пространстве имен. Приходится спрайт объекта и сам объект называть по-разному.
— Параметры комнатам не задашь (потому что это контейнер, а не объект), куда-то self передается, куда-то — нет, нельзя свои функции создавать, скрипты всегда передают self того объекта откуда вызвал.
— Вроде как идеально подходит для платформеров, а всю механику все равно руками писать приходится.
— Координаты мыши почему-то относительно комнаты, а не окна. Что мешало сделать 2 переменные — одна относительно окна, другая — относительно комнаты.
— Нет констант, приходится объявлять макросы в отдельной форме.
— У объектов Creation Code почему-то вызывается после события Create, а не до.
— ПАУЗА!
— Нельзя поменять стартовую комнату — кодите переход в коде первой!
В общем, удобство создания уровней компенсируется неудобством программирования.
В след. раз попробую 8.1 и сравню.
Отдельная благодарность SaintHeiser за стрим на twitch, который сподвиг меня попробовать эту шарманку.
И остальным кто помогает разобраться с очередными проблемами и непонятками.
- 26 июля 2020, 18:25
- 03
Прошу помочь побороть баг (Game Maker 8.1).
Начал переносить функции сажания и вылезания из машины в скрипты.
Один раз выход и вход из машины работает, а второй раз ссылка на управляемый объект, почему-то теряется (global.control == -1).
Не пойму почему.
https://www.dropbox.com/s/9wo2uc9jsm9fdqc/DriverRoad_12_bug.gm81?dl=0
И чем instance_exists(inst) отличается от (inst != noone) ?
Помогает только car_inst.human = my_human после вызова human_mount.
Но этот скрипт тоже это делает:
car.human = self
self.is_active = false
но не работает, ссылка car.human остается == -1.
Оказывается в скриптах вместо self надо использовать id.
Хороший сюрприз.
интересно, не совсем понимаю разницу, но уже слышал про такое на гамине, что лучше не юзать self
хотя вроде бы в 1.4.9 ещё не встречал проблем с этим, ибо всегда юзаю self
Скорее всего ты его используешь по назначению - адресация локальных переменных, что можно делать без self. Скорее всего ты никуда сам self не передавал. Поэтому и проблем не знал.
Или self.id если тебе нравится использовать self.
С хуя ли это сюрприз? Справку читал?
self можно использовать только для адресации локальных переменных, т.е. реально
self.x = 10
Звучит как
(-1).x = 10
В то время как id инстанса - довольно большое число.
Если ты в левый объект передаёшь self то ты передаёшь эту -1 а не id инстанса. В твоём примере это car.human. И если ты будешь использовать эту переменную в контексте объекта car, то там будет -1 и указывать будет на свой контекст, а не на контекст конкретного инстанса как ты задумывал.
self - это пережиток прошлого, что и написано в справке. Так что просто забудь про него.
Нет. Я пользуюсь GM 8.1, причем даже упомянул об этом. Там есть отличия.
Все равно читая одну лишь справку многое остается непонятным.
"Сюрприз" в том - зачем использовать разные ключевые слова в скриптах и коде обработчиков событий?
Разве не логично сделать self и там и там?
То есть в другие скрипты лучше передавать id экземпляра, а потом уже instance_id[id]?
Чем это логично? self применяется только к экземплярам объектов. И так было во всех ГМах уже лет 15 точно, может больше. В справке об этом написано в ГМ8.1 тоже.
я незнаю что там у вас и как но мне кажется что self имеет смысл использовать только там где есть other что собственно и удобно и понятно.
Логично не использовать self вообще, тем более об этом в справке написано =)
Господи, зачем тебе вообще instance_id[] ?
Чтобы для тебя не было "сюрпризов" вот тебе ещё одна выдержка из справки:
Чтобы обращаться к переменным другого объекта тебе достаточно знать только id объекта. Его же возвращает функция instance_create. Ну и ещё несколько функций. Перебирать массив instance_id на практике нет никакого смысла. Скажи какую задачу ты хочешь решить?
А как тогда отличать переменные объекта от локальных?
a = 10 - это запись в переменную объекта или в локальную?
Мне надо помнить все текущие локальные переменные и переменные объекта наизусть?
Вот self.a = 10 - это 100% запись в переменную объекта.
Не понял вопроса.
Локальные переменные - это те, которые у тебя объявлены через var внутри блока кода или внутри куска кода или внутри скрипта. Они у тебя всегда перед глазами.
Все остальные переменные считаются локальными для объекта где бы ты и как бы ты их не объявлял и self писать необязательно для этого.
Лично моя практика на всякий случай переменные для var именовать начиная с "_".
Тут наверное стоит сказать что в GMS нет "просто кода" как в привычном программировании (через функцию main). Код всегда относится к тому или иному объекту. В этом плане GM - более ООП, лол. Поэтому и self не нужен. В скриптах всегда используется контекст того объекта, который этот скрипт вызывает.
А то что у тебя у объекта есть переменная a и в блоке кода ты решил использовать переменную var a=10, это просто плохой код. Чисто технически для этого пойдёт self, но зачем так делать если можно написать var _a = 10 ?
Не всегда. Я могу открыть только одно окно для кода.
Это не плохой код. Это плохой язык не позволяет явно разделять области видимости - локальную и объекта.
Программист, который пишет код, не обязан знать - есть у меня или нет переменной a у объекта. Он должен объявить любую переменную, не совпадающую со встроенной, и спокойно писать a = 10, не боясь что в другом месте что-то сломается.
Я может уже забыл что у объекта есть такая переменная? А конструктор не выдаст мне предупреждение и игра сломается в рантайме.
Все локальные переменные, объявленные через var и будут этом окне для кода. Считай что это их область видимости по умолчанию если они не расположены явно в блоке {}
Язык не хуже и не лучше других. Это конкретно плохой код, причём в любом языке. Использование паттерна пересекающихся имён в разных контекстах - это просто хуёвый и неэффективный паттерн, который только запутывает код и его чтение. Но для того чтобы некомпетентные программисты вроде тебя могли так делать - и оставили ключевое слово self.
Область видимости в GM точно такая же как в 90% ЯП. Наличие self, this и прочего подобного - это хуёвая организация контекста в ЯП. В GM с этим проблем нет, т.к. ты почти всегда находишься в контексте какого-либо объекта. За исключением "creation code" - который опять же на практике используется почти никогда.
Нет, пространства имён полезны на больших объёмах кода. Но это не обязательно про объекты, а просто возможность рассовать имена по папкам. Тогда не надо никакие подчёркивания. Global::a и a.
а приведи реальный пример в котором имена переменных могут так пересечься. var a это пиздец в квадрате же
В Create:
где-то потом
или
чтобы такого не было и точно всегда обращаться к локальной переменной - придется писать local.a = 20;
Подчеркивание в начале имено переменной - это костыль, с которым просто удобнее, чем все время писать local.
В Lua, например, всегда приходится писать self.a - это всегда обращение к переменной a объекта self,
просто a - всегда обращение к локальной переменной.
Блядь, зачем ты на ровном месте создаёшь проблемы?
Почему бы не написать
self.alpha
а где-то потом
var a;
a=20;
Зачем ты одно и то же имя используешь? Это какой-то профит к производительности, читаемости кода или что?
У каждого языка свои правила. В GM - self.a или a - это обращение к локальное переменной. Если переменная a была объявлена через var то просто a - это обращение к локальное переменной.
Если в Lua для обращения к локальной переменной всегда нужно писать self - это же лютый пиздец. Это называется "синтаксический мусор", который ты каждый раз вынужден писать потому что иначе твой ЯП не понимает. И после этого ты мне рассказываешь что GML - плохой ЯП. Ну-ну. Там то этой хуйнёй страдать не нужно.
Вот почитай про области видимости: https://docs.yoyogames.com/source/dadiospice/002_reference/001_gml%20language%20overview/variables/index.html
В GM8.1 то же самое всё.
Наоборот. Для обращения к переменной объекта нужно писать self. Для обращения к локальной - не нужно.
В GML язык сам решает к какой переменной он обратится, в зависимости от того объявлена она у объекта или нет. А что бы точно обращаться к локальной, надо писать local.a.
Зачем использовать одно и то же имя? Ну, например, чтобы в цикле менять переменную у всех объектов.
a - это может быть и угол и прозрачность.
Мне вот что-то не хочется каждый раз выдумывать другое название переменной если у объекта такая уже есть.
Я это и имел в виду. Что если ты хочешь обратиться к переменной объекта - ты КАЖДЫЙ РАЗ пишешь self. Не заёбывает?
В GML язык сам решает к какой переменной он обратится, в зависимости от того объявлена она у объекта или нет. А что бы точно обращаться к локальной, надо писать local.a.
Чтобы точно обращаться к переменной - не нужно создавать коллизии имён. Это же так просто.
Чем вот этот код хуже твоего?
Или вот этот
Не говоря уже о том, что этот кусок кода - полная херня и просто 10 раз переписывает переменную x без всякого смысла.
То что ты намеренно порождаешь такую двусмыслецу уже говорит о том что твой код - полная хуйня.
alpha - прозрачность, angle - угол. Есть автокомплит для ленивых.
Вот опять, по поводу переменных
Что если у a уже есть переменная result?
Куда запишется результат, в self.result или во внешний result?
А если я перебираю разные объекты и у какого-то из них окажется есть result?
Мне что, каждый раз local писать?
Запишется в var result, потому что переменная, объявленная через var имет самый высокий приоритет контекста.
Для переменных, которые ты через var объявляешь просто ставь префикс "_" и не еби мозги. Серьёзно говорю.
Кстати, в луа как раз с этим беда вроде. Там нестандартный порядок видимости, что глобальное аж приоритетнее локального. :D
Это как?
Если что, то всегда можно сделать _G.name = 4 чтобы записать точно в глобальную область видимости, если в локальной, вдруг, name уже объявлена.
Но так во всех нормальных языках. Локальная переменная перекрывает глобальную.
А, извините, значит, перепутал с чем-то ещё.
upd. Там, похоже, дело не в видимости, а в том, что надо не забывать писать local при объявлении.
Это правда беда
instance_exists(inst)
Ты проверяешь конкретный инстанс на существование. Условно ID туда подаёшь (или noone). Но при сравнении с noone ты только с ним и сравниваешь без проверки на существование.
Например.
human = instance_create(...);
instance_destroy(human);
a1 = instance_exists(human); // Тут будет false
a2 = human != noone; // тут будет true
Вот у меня есть ссылка human на экземпляр.
Как правильнее мне проверять что она ненулевая?
Или получается так что объект по ссылке мы можем удалить, а ссылка все еще будет ненулевая? Это как? Получается что объект не удалился.
Или тут дело в том что все ссылки, которые указывали на только что удаленный экземпляр, обнулятся только после выхода из обработчика события?
Грубо говоря, есть встроенный счётчик инстанса, который увеличиваетя кажды раз после вызова instance_create(). Поэтому id инстанса - это значение этого счётчик, т.е. довольно большое число, а не ссылка. И да, она не сбрасывается в -4 (именно это значение для noone) после удаления инстанса. Поэтому нужно проверять instance_exists(). Можно, конечно, вручную пройтись по встроенному массиву объектов но это дольше будет.