Попробовал 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
У меня так со всеми (возможно со всеми движками и конструкторами), ни одного пока вроде не встречал, где можно спокойно делать игру, всегда вначале надо помучить редактор, помучить себя, посидеть в справке и гугле с месяц или два, помучить всех на форуме.) Куча ограничений или вещей к которым надо привыкнуть.
Легче всех был наверное Битси и то там без танцев с бубном не обошлось, прикручивая дополнительные плагины.
Ты забыл сказать что пробовал триальную версию с её ограничениями.
Они есть.
http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/cameras%20and%20display/display/the%20game%20window/window_mouse_get_x.html - в окне
http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/cameras%20and%20display/display/the%20game%20window/window_view_mouse_get_x.html - в виде
Берёшь и ставишь нужную комнату наверх.
По сравнению с чем? Ты Юнити пробовал?
Поэтому сейчас и попробую 8.1
Спасибо, когда сам искал - не нашел.
Это что, я ее каждый раз должен перетаскивать когда мне надо другую комнату протестировать? Тогда порядок комнат поменяется и может что-то сломаться в коде.
Просто по сравнению с программированием на Си и Си#, на полноценном нескриптовом ЯП.
Ну, я не думаю что на этих двух языках проще сделать точно такую же игру как эту.
Я конкретно про программирование, а не деланье игры. Создание игры программированием не ограничивается.
Сейчас сижу в 8.1, а там Creation Code для объектов вызывается ДО события Create.
Как мне проверить - объявлена ли переменная, прежде чем к ней обращаться?
В гугле не нашел.
Зачем Гугл, читай справку.
variable_global_exists(name) Returns whether a global variable with the given name (a string) exists.
variable_local_exists(name) Returns whether a local variable with the given name (a string) exists for the current instance.
Непонятки. Пишу в creation_code комнаты:
Что это? Почему редактор говорит мне что ошибок нет, а во время исполнения игра говорит что 'room.bd' - нет такой переменной?
Что тогда делают первые 2 строчки?
room
- это зарезервированное ключевое слово, содержащее индекс текущей комнаты. Перемеренную с таким именем объявить не получится.Да причем тут переменную, редактор должен сказать что так нельзя, а не говорит.
Выясняется только после запуска. Причем первые 2 строчки ошибок не вызывают.
И где тогда лежит переменная bd и как до нее добратся из другого события/скрипта?
Сорри, да, я имел в виду немного другое.
room
- это не объект, а просто id. Поэтому конструкцияroom.bd
не работает. То, что GM не выводит ошибки на вторую строчку - да, проблема. Скорее всего, он уже только на этапе исполнения пытается найти объект с таким же id, как id текущей комнаты, и крашится.Если переменная из creation_code нужна где-то еще, стоит сделать ее глобальной. Здесь не могу сказать точно, но локальная переменная даже без
var
вероятно видна только в самом creation_code.Не должен. Может быть ты, забив на справку, переобъявил встроенную переменную как глобальную или var, присвоил ей идентификатор экземпляра объекта, и что-то хочешь оттуда достать - как он должен догадаться, что именно ты там делаешь? Сама архитектура такая, и да, она далеко не идеальна. Но редактор из такого положения мало что может тебе сказать в принципе.
Комнаты в ГМе это не объекты, у них нет собственных переменных и в них нельзя ничего писать. Нужны переменные - заводи контроллер на каждую комнату. Можешь меня обрадовать, если назовёшь в каком движке есть встроенное понятие комнаты (сцены, уровня) именно с пользовательскими (любыми, а не предварительно заданными движком) переменными.
Если
room
— это зарезервированное ключевое слово, на вторую строчку можно было бы и поругаться.В Godot у любых сцен (в т. ч. уровней) могут быть любые переменные, если наследовать соответствующий класс.
Это не ключевое слово, это встроенная переменная.
Анрил :yak:
Иногда я вспоминаю о ZZT и думаю - что пошло не так, неужели вот этот умный человек не мог сделать сначала пиксельный двухмерный движок вместо текствого в 80x25, а потом уже трёхмерный? Или хотя бы параллельно с ним, потому что два измерения это прям значительно проще.
Как сделать нормальные коллизии?
Если делать так
то не срабатывают collision-события, поскольку спрайт с ними никогда не пересекается.
Если делать по-другому, то collision срабатывают, но мы можем пролезать сквозь объекты.
По-другому это как? Есть множество способов сделать по-другому. Ну так понятно, что мы можем либо пролезать через объекты либо не пролезать. Нужно определиться с логикой взаимодействия, т.к. сейчас нет никакого противоречия.
Place_free по определению избегает столкновений. Такой код есть смысл сделать для объектов, с которыми никогда не столкнёшься. Как вариант - другие случаи можно рассмотреть в коде при условии else.
Буквально вчера думал написать пост о том, когда нужно использовать какие коллизии в ГМе. Совпадение? Не думаю. Но на пост времени всё равно не появилось, так что отпишу главное:
1) Событие коллизии в объекте: просто создаёшь Collision Event с нужным тебе другим объектом и в него пишешь что тебе нужно. Я вижу тебе нужно выталкивать объект из другого объекта, значит пиши туда то же самое:
2) place_free - работает только с объектами у которых включена галочка Solid. Но эта галочка пришла из древних версий ГМа и существует по большей части для совместимости со старыми проектами, так что лучше не используй её, а соответственно и эту функцию, никогда.
3) place_empty - работает с любыми объектами, используй лучше её. Ещё обе эти функции работают только если у обоих объектов есть маска коллизий (если она "same as sprite", то должен быть назначен спрайт чтобы была маска).
4) position_empty тебе даст ответ о коллизии в конкретной точке без учёта маски проверяющего объекта, а только с учётом масок всех остальных.
5) Если тебе нужны ОЧЕНЬ точные коллизии, и с проверкой по типу объекта, но не через встроенное событие коллизии как в пункте 1 (хотя этого в большинстве случаев вполне достаточно), то используй эти функции:
collision_circle
collision_ellipse
collision_line
collision_point
collision_rectangle
6) Если тебе надоело возиться со спрайтами, ты можешь прописать всю игру на чистой геометрии, без масок и спрайтов вовсе, как в старые добрые времена:
point_in_rectangle
point_in_triangle
point_in_circle
rectangle_in_rectangle
rectangle_in_triangle
rectangle_in_circle
Проблема в том что у меня:
- или срабатывают события Collision, но перс цепляется за все остальные объекты.
- или перс не цепляется за объекты, но зато не срабатывают Collision.
Решил проблему проверяя столкновения только со стенами (place_meeting), а у люстры убрал solid.
Короче, не так уж много на себя берет этот GM, все равно приходится много за него решать.
Вместо того чтобы со всем этим ковыряться я бы давно сам написал коллизии математикой.
Причина в том что объекты сталкиваться и растаскиваться должны если у обоих объектов есть флаг solid, то есть они оба твердые, а Collision должно вызываться только 1 раз.
Если твердый только один (или ни одного), то столкновение должно регистрироваться вызовом события Collision, но объекты не должны растаскиваться друг от друга.
В таком случае тот кто делает уровни сам решает - какие объекты не должны проходить через друг друга, как в Юнити.
Но разрабы GM сделали по-другому и растаскивается если хотя бы один объект solid. Из-за чего уже программисту приходится захардкоживать логику и вручную расстаскивать объекты и прописывать реакцию на события Collision для всех объектов которые есть на уровне и могут двигаться, на случай если они пересекуться.
Это если у меня 10-20 типов таких объектов, то я для каждого свое событие должен писать?
Вот и приходится всю логику перемещения делать не через hspeed, vspeed, а через свои переменные и вручную проверяя пересечения всякими функциями.
Да не надо использовать флаг Solid, я же по-русски написал что это древность из ~2005 года. Просто никогда его не используй.
Нет, это значит что у всех них должен быть общий родитель "объект из которого надо растаскивать" и написать нужно событие только одно - "сталкиваться с объектом из которого надо растаскивать".
К слову, для растаскивания ещё есть удобная встроенная функция вместо твоего while:
https://docs.yoyogames.com/source/dadiospice/002_reference/movement%20and%20collisions/movement/move_outside_all.html
А в направление туда удобно вписать point_direction(other.x, other.y, x, y).
Я тут как раз мучаюсь с внедрением коллизии стен. Надеюсь про коллизию тайлов тоже будет написано.
У меня просто какая обычная ситуация:
1) есть столкновение с врагами, и враги часто немного выталкивают и выталкивается герой
2) из-за этого выталкивания на 1 пиксель, мы часто влезаем внутрь стен.
ЗЫ я сейчас думаю запилить коллизию стен через массив, и сделать 100% запрет попадания в стены, несмотря на выталкивания из других коллизий
Для чего массив? Просто выталкивай из стен тоже с помощью
move_outside_all(point_direction(other.x, other.y, x, y), 100)
ну получается такая последовательность кода иногда:
1) выталкивается из стены
2) выталкивается из врага
И если из врага выталкивается позже, чем из стены (как в этом примере последовательности),
то герой в конечном итоге сильно вгоняется в стену и может там застрять, или я просто не так что-то сделал, хз, надо перепроверить.
Поменяй местами (1) и (2).
Как кодом создать новый объект?
instance_create создает новый вместо уже существующего.
UPD: Все, понял в чем дело
Прошу помочь побороть баг (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(). Можно, конечно, вручную пройтись по встроенному массиву объектов но это дольше будет.
Пытаюсь работать с канвасами (сурфейсами по-вашему), чтобы из скрипта рисовать свет из фар машин в темноте.
Скрипт draw_darkness:
Свет рисуется правильно, но почему-то вместе с машиной игрока начинает ехать вправо и весь интерфейс что рисуется после.
Если закоментировать код между 1 и 2, то интерфейс перестает сьезжать.
Что не так? Подозреваю что все дело в вызове surface_reset_target, который помимо завершения рисовать в сурфейс делает что-то еще.
Скинь код где сам интерфейс рисуется.
surface_rest_target здесь вряд ли причём. Эта функция только говорит что "теперь рисуем как обычно"
Короче, после вызова draw_darkness почему-то все следующие функции рисования начинают привязываться к положению view.
Точнее все, что имеет depth меньше чем тот, что у объекта, в Draw которого вызывался этот draw_darkness.
Если draw_darkness не вызывать, то приходится к координатам спрайтов для ГУИ прибавлять view_xview и view_yview.
Можешь ещё пару скринов скинуть для пояснения "интерфейс начинаетехать вправо вместе с машиной игрока"?
Если ты это рисуешь в DrawGUI, то у тебя явно ошибка
Тут координаты относительно комнаты, а должны быть относительно view. Тут же лучше убрать self. Тут же конструкцию with можно использовать без do (я вообще впервые такое вижу);
Ещё пара змечаний по коду:
Как тебе уже писали, instance_id лучше не использовать. with obj_car { ... } отлично сработает.
Функции view_xview и view_yview лучше использовать с индексами массивов view_xview[0] и view_yview[0] впрочем как и все функции view_
А ты здесь точно хотел view_hview, а не view_yview? Ну и снова индексы просрал.
Это GM 8.1, здесь нет DrawGUI.
Я бы его и использовал, если был, поскольку там всегда координаты относительно окна.
Я так понял что это значения текущего используемого view. В документации этого не написано, но почему-то работает.
А view_xview[0] возвращает x для 0-ого вида комнаты. Если я выберу другой view в списке комнаты, а не буду изменять текущий, то вместо 0 придется писать другую цифру.
Нет, правильнее было назвать dh, а не dy.
Сейчас уже не получается воспроизвести баг, едет только вот эта надпись:
Если у ее объекта поменять depth с -1001 на -999 (чтобы был больше чем у объекта, который вызывает draw_darkness).
Вот ссылка на текущий проект.
Вот текущий код:
Сейчас все работает, но за счет того что ГУИ рисуется без dx = view_xview., и при этом оно почему-то движется вместе с игроком, хотя не должно.
Я думаю, что эта строка не работает потому что нужно добавлять координаты вида, т.е. вот так
------------------------
Это работает потому что обращение к массиву без указания номера элемента автоматически возвращает первый элемент, если я правильно помню. Кажется, незадокументированная фича, которая скорее баг, а не фича =)
Я знаю. А она работает.
Она перестает работать если не вызывать draw_darkness, тогда приходится прибавлять view_xview и view_yview чтобы надпись ехала по уровню вместе с камерой.
До того как начал писать рисование в сурфейс, там было такое:
В приведённом тобой коде я не вижу этой строчки, чтобы понять почему такое поведение.
Исходники не могу посмотреть - GM8.1 давно не пользуюсь, а лиценцзию отдал yeo вроде. Впрочем там вроде сервера по лицензированию этих версия давно не работают.
Если у тебя необходимость пройтись по всем возможным obj_car, то скорее всего лучше использовать конструкцию with(объект или инстанс) { твой код в контексте конкретного инстанса }. А то лишние проходы цикла*.
То есть вот твоя переделка была бы как:
То есть внутри with ты как бы "внутри" объекта\инстанса.
* может от этого и проблема с интерфейсом? Кто знает.
Спасибо, сделал так, но ничего не изменилось.
Но пока и так работает.
Нашел похожую проблему, но для студии.
Еще заметил такие причуды:
Вместо ссылок на экземпляры хранятся числа (их id номера).
Если изменили ссылку на объект, то вы на самом деле присвоили переменной другое число.
Поэтому хранить ссылки на объекты во временных переменных нет смысла - после записи другого значения в их источник значение временной переменной останется старым.
Оператор условия
Всегда проверяет оба условия прежде чем пойти дальше.
Если A ложно, то B тоже вычисляется.
Приходится писать так:
Пару раз на этом уже спотыкнулся.
Канвасы (surface) не создаются уже очищенными. Их надо очищать самому после создания.
Чёт я не понял что не так =(
Вот тебе пример переиспользования локальной переменной, которая объявлена через var. Чем тебя не устраивает такое поведение, я ХЗ.
Оператор условия в старых GM работает так, да. В какой-то версии появилась галка в настройках чтобы не допроверять условие если результат сразу понятен. Не помню правда, есть ли она в GM8.1 или появилась в GMS только.
вот это вот _obj - это число (номер экзепляра), а не ссылка на него.
если сделать вот так:
а потом вот так
то потом придется делать еще:
По поводу условий я привык делать так (Lua):
Разумеется, если первое условие не выполнилось, то второе вычислять нельзя, иначе упадет. Во всех нормальных ЯП - так, но в GM 8.1 оно так не работает.
Нихуя ты придумал =)
У тебя поди уже нога вся в дырках. Ты придумываешь всё новые и новые удивительные способы себе туда стрелять. Указатели были в Си, а потом все нормальные ЯП успешно от них ушли. Потому что такое поведение контр-интуитивно. На самом деле в GMS есть указатели, но я ими не пользовался ни разу. А GM8.1 не такой технологически продвинутый. Поэтому и условия так проверяются. Переходил бы ты хотя бы на студию.
А GM сам мне обнулит указатель на экземпляр после его удаления? Нет? Тогда действительно зачем они мне нужны?
Но мне нужнее ссылки, а не указатели, мне не нужно вручную редактировать адрес указателя, только присвоить, обратиться, записать.
За вычетом всякой адресной арифметики и необходимости явного разыменования, указатели семантически ничем не отличаются от ссылок.
Этого ни один язык не сделает, если кто-то специально не будет отслеживать корректность всех ссылок (сам объект или рантайм), что тяжеловесно и никому не нужно. Есть другие способы решить проблему висячих ссылок – GC (и умные указатели как очень частичный случай), или линейные/аффинные типы (самый известный нынче представитель – Rust).
Ну вот в Lua я могу обнулить ссылку на объект и все остальные, к-е указывали на этот же объект - тоже обнулятся.
Прошу пример.
Как ето
Указатели отличаются от ссылок тем, что с содержимым указателя можно выполнять арифметические операции (изменять адрес как число).
В ссылки можно только записать адрес нового объекта или прочитать значение куда она указывает. Арифметические операции с адресом ссылки выполнять нельзя.
Моё сообщение сразу начиналось с
Но ведь и со ссылками то же самое будет,
obj
не станет меняться синхронно сglobal.control
.Не-а.
Вот, только что проверил, в love2d выводит "2", а не "1".
Потому что a и link - это ссылка, я номенял объект и вместе с ним во всех ссылках обновились адреса на этот объект.
В случае с GM возвращается число, равное id объекту.
Даже если записать число, ссылка на него тоже обновляется, так тоже выводится 2.
Интересно, почему так во втором случае, если в lua reference manual:
когда ты пишешь a = b, то по сути a теперь ссылается на b.
И при обращении к a всегда возвращается текущее значение b.
Да, но только для tables, functions, threads, and (full) userdata.
А как же
Здесь link - число, а a - уже ссылка на link.
Там так и написано - "переменные фактически не хранят значения, а только ссылаются на них".
Да ладно? 2 остаётся: https://ideone.com/Lp664y
Да, действительно
Становится еще интереснее, если сделать так:
В a окажется 11. Вопрос переходит в область порядка выполнения инструкций.
Такой код, как и должен, выводит 2 и 10 (для таблиц кстати тоже будет {2} и {10})
UPD2: Разгадка
Значения типа number не хранятся через ссылку. Но я немного о другом.
UPD2: Разгадка
Господи, глупость какая. (это для себя)
AndreyMust19 draw у тебя выполняется каждый кадр, поэтому начиная со второго запуска тебе кажется, что локальная переменная a "следит" за значеним глобальной link.
На твоем примере:
Первая отрисовка: link = 1 -> a = 1, link = 2
Все последующие отрисовки: link = 2 -> a = 2, link = 2
Естественно, первую отрисовку ты не успеешь заметить.
Делай print в консоль.
Вариант с love.draw я просто по-быстрому писал. По-хорошему такие примеры надо писать только в love.load и выводить результат в консоль через print.
Это не отменяет того факта, что первопричина всего треда - твои коммент и неверные из него выводы.
Так вот, если твой пример переписать в love.load, который выполняется один раз, ты увидишь, что выводимые значения отличаются от того, что ты ожидаешь.
Это не так. При наличии нескольких ссылок на один объект, если само объект поменяется, изменения естественно будут видны во всех ссылках, потому что они ссылаются всё на него же. Но если поменять одну из ссылок (переназначить на другой объект), другие ссылки будут указывать на прежний. https://ideone.com/te9xuq то же самое и в других языках.
В общем, не бывает, чтобы после
cc
тоже стал указывать наdd
, а не наbb
.Так Андрей и ij всех обманули, или у них какой-то неправильный исполнятор кода?
Неа, луа у нас тоже гостовский. см. выше
Ты не прав, выше я тебе кидал выдержку из Lua Reference Manual, скину еще раз
По ссылке передаются только таблицы, функции, потоки и (какой-то интересный тип) userdata. Все остальное - nil, булевые значения, числа и строки - по значению.
В твоем примере после A = B, A не является ссылкой, в ней будет храниться копия значения B.
Действительно. Странно, а вчера было по другому.
Но ведь https://ideone.com/UF1ygX
и там, и там - текущее значение в момент присвоения
Все правильно.
Я так и не понял, зачем тебе gm8.1
Про неудобства программирования спорный вопрос. Ты привык к какому-то движку и языку - это ОК. Но если начинать делать чистые замеры по эффективности создания конкретной небольшой игры, то GM скорее всего будет лидировать. В большинстве случаев. Хотя бы потому что там меньше писанины.
Меньше писанины только пока задачи более-менее типичные и решаются встроенными средствами. Шаг влево-вправо – и уже приходится изобретать велосипеды, то и дело утыкаясь в ограничения языка и архитектуры.
(с 2.3 должно было стать сильно получше, конечно, но только в плане языка)
Блядь, я уже 15 лет слушаю. Примеры. Конкретные примеры? За 15 лет мне никто ни одного не привёл. Потому что функционал GMS покрывает 90% задач которые могут возникнуть при разработке игры. 3Д не в счёт. Для 3Д есть другие движки.
Да сколько угодно. Да, он покрывает 90%, но не покрывает другие 90% остальные 10%, которые и делают игру особенной.
Встроенный механизм обработки коллизий удобен, пока нужно попадание пульки обрабатывать, или натыкание на стенку. Как только захочется различать столкновение с полом от столкновения с потолком, или тем паче определить вектор нормали – привет, велосипеды, привет, Yuuri.
Встроенные события нажатия на клавишу удобны, пока делается прототип с простыми реакциями и жёстким управлением. Как только захочется переназначать кнопки – привет, велосипеды, привет, Xitilon.HD408 .
Встроенный спрайт у объекта удобен, пока он один. Как только захочется составлять из кусочков – привет, велосипеды, привет, alexsilent
Встроенная физика хороша, пока хватает скоростей и гравитации. Как только захочется что-то пореалистичнее, с силами и векторами – привет, велосипеды, снова привет я. Или Box2D, который прикручен кое-как и плохо с остальным сочетается.
Встроенная система частиц хороша, пока хватает спецэффектов из коробки. Как только захочется что-то кастомное, например, сложную траекторию частиц или хитрое их взаимодействие – привет, велосипеды, снова привет Кситилон.
И так со всем. Встроенные средства хороши, но практически не поддаются расширению, и хватает их только для самых generic вещей, а что-то посложнее приходится пересоздавать почти с нуля, да ещё на убогом (до версии 2.3) GML.
Насколько я знаю, в GM есть возможность переназначать кнопки функциями типа get_map, set_map.
В love2d я обычно создаю список, в котором действие = кнопка. И проверяю не нажата ли кнопка, отвечающая за действие. В GM, я так понимаю, можно так же сделать.
Все равно приходится выбирать - либо использовать готовый велосипед и привыкать что "налево" на самом деле "направо", либо делать свой полностью с нуля.
Хуже всего когда думаешь что готовый велосипед подойдет, используешь его и потом, оказывается, что лучше использовать свой и пишешь уже свой с нуля. Но время на другой велосипед уже потрачено.
Они лишь делают одну из кнопок «синонимом» для другой, а для этого та уже должна быть назначена, и её уже никак не поменять.
В идеале, чтобы не делать совсем всё с нуля, искоробочный велосипед должен быть настраиваемым и достраевым, позволять менять колёса (и возможно даже их число), подвеску и всё такое. Про Unity почти ничего не знаю, а вот Godot (привет, antonka ) очень хороший пример расширяемости всего-всего, от стандартных компонентов до среды разработки.
Юнити тоже расширяем, но там доступ к исходникам дорогой, а фичи количественные, а не качественные. В итоге для исправления очередного косяка в фиче движка надо скачать плагин из магазина, который реализует ту же фичу заново.
В Годоте же для тяжёлых случаев есть вариант с правкой исходников движка, которым активно пользуются (например, недавно сделал камере матрицу проекции, которой не предусмотрено из коробки - если не отсылать никому полноценный патч, а чисто хак для одной игры, то это две строчки кода).
Ударю по больному. Где твои игры? Помогает ли тебе достраиваемость и настраиваемость делать игры?
А то так вечно можно теоретизировать про абстрактные велосипеды за горизонтом событий.
На http://lurkmore.to/Сперва_добейся не триггерюсь, можешь не ударять.
Вполне валидный вопрос, который не тривиализируется ссылкой на мем.
Тогда ответ: да, помогает. Мини-демку с двумерным временем, которую я тебе показывала, мне полнее и проще получилось сделать в Godot (причём осваивая его с нуля по ходу дела), чем в давно знакомом Game Maker. И прототип Reverside в 3D переделать.
Если «ну так это ж не игры, а поделки-недоделки», то тогда с тем же успехом заявлю, что «лучшесть Game Maker для 2D» делать игры мне тоже не помогает, а при прочих равных см. выше.
Привет, Yuuri
Я тебе скажу что в GM столкновения сделаны по божески. Из того что я видел в других средах разработки (та же юнити) - небо и земля. В GM есть набор адекватных ВСТРОЕННЫХ функций проверки столкновения, чего нет во многих других языках и вот ТАМ приходится изобретать велосипеды.
Весь функционал есть. Без проблем пишется универсальная надстройка. Я ещё несколько лет назад выкладывал свою ACS систему (на встроенных функциях проверки нажатий клавиш) для этого, экспортировал в локальный пакет и сейчас спокойно включаю в каждый свой проект. Какие велосипеды? Да, можно сказать что вот дескать в Юнити всё работает из коробки. Так то да, только коробочный интерфейс там не кастомизируется и всё равно придётся писать своё. А уже если говорить про полуфабрикатыфреймворки - то там ваще атас.
Тут я могу согласиться. Но отчасти. Рукам всё это делать - знатная ёбань. Для такого случая есть ВСТРОЕННАЯ скелетная анимация и Spine, результаты которого как я помню импортируется в GMS2 без проблем. Так что снова мимо.
ЛОЛ. Ни в одном движке не видел нормальную физику из коробки. Она ВСЕГДА лагает. Физику всегда лучше самому писать как нужно. Иначе здравствуйте клипы, прохождения сквозь стены, распидорашивание объектов на сверхскоростях и прочие приколы кривой физики.
Система частиц в GM позволяет довольно много чего сделать по спецэффектам. Просто хочется конкретных примеров. Тут сразу хочу согласиться что в целом система частиц ГМ - это слабое место и она сосёт, много лишнего кода нужно писать. В юнити гораздо лучше сделано.
Чё-то я не совсем понял что ты подразумеваешь под "встроенные средства". Весь функционал, который доступен разработчику и является встроенным средством. И всего этого встроенного функционала в случае с ГМ хватает чтобы эффективно решить поставленные тобой задачи. Что-то посложнее ТРИВИАЛЬНЫХ задач всегда приходится дописывать ручками. Вопрос цены этих допилов и качество их работы, да.
А "не встроенные средства" - это внешние библиотеки, например. Мне бы хотелось услышать от тебя задачи, которые по твоему утверждение НЕ РЕШАЮТСЯ или РЕШАЮТСЯ ОЧЕНЬ СЛОЖНО при помощи встроенных средств.
Да, я знаю, что больше не комментирую на Гамине, а только пишу посты, но это уже клиника ради которой невозможно не сделать исключения: два человека якобы с 200600 годами опыта в ГМе не знают что в GM2.3 уже полгода как завезли новый тип встроенного ресурса - Sequences. Они позволяют анимировать любые составные объекты "как на флеше", с раскадровками и интерполяцией между кейфреймами.
https://www.yoyogames.com/blog/550/gamemaker-studio-2-3-new-ide-features
Аргумент "%встроенное 1% хорошо, пока хватает" применим абсолютно к любому движку, фреймворку, языку и IDE. Серебряная пуля бывает только в физическом мире, в виде буквальной серебряной пули. Без указанного круга жанров нет даже предмета спора, а без послужного списка - непонятно на чём базируется аргументация.
Насколько помню, главная проблема твоего (а ещё моего, но явно не Хейзеровского) геймдева, Юрри, это ни разу не прога, а графика. Вот круто было бы обсудить какой Пеинт отстойный, а Гимп/Крита/Сай/чтотам хороший, но дело в том что даже Пеинт не отстойный. В нём Пиксель рисовал Кейв Стори, а Эсдир - оба три Замка Невозврата, и ничего. Надо как-то заставить себя делать дела, и дела пойдут. Мне для этого помогали рамки типа 2-дневных джемов (Ludum Dare, Гаминовский КОД, Коленковский BAL). Динозавр недавно написал хороший пост в помощь желающим сесть на игру (на пункте "почитать математику" посмеялся конечно, у тебя явно её в уме предостаточно).
По правде говоря, в 2012 году, уставший от проблем ИРЛ, я уже не делал никакие инди-игры, и мог к этому вовсе никогда в жизни не вернуться. На Гамин меня привёл Эсдир, который интересовался, что там Хейзер в этот раз делает. Следом я позвал Дрейка, а Ксенедер, знакомый нам ранее, тут был вроде бы от Тенны. Если бы не эта экосистема людей с которыми я общаюсь, я бы:
Итого.
Чтобы что-то делать, надо общаться с конкретными людьми и о конкретных предметных вещах: как сделать механику_нейм, какую игру можно придумать на тему_нейм, за сколько времени (!) можно запрограммировать систему_нейм. А если годами спорить о том, что можно было бы быстрее сделать на вундервафле1 игры СТРАНЬШЕ чем на вундервафле2, то это фиг знает к чему способно конструктивному привести.
Можно конечно и не общаться, но я не знаю разработчиков которые пришли совсем изниоткуда, либо они вникуда же и ушли. У вас двоих в этой ветке - не предметное общение, это драка подушками.
Совсем мимо, графику я худо-бедно умею, и ты это прекрасно знаешь. Моя главная проблема – это перфекционизм и analysis paralysis.
Ну лол, это лишь предзаписанные анимации, которые не параметризуются даже. А я про ситуацию, когда объект состоит из некоторого числа различных, но связанных кусков, которые могут независимо (в том числе процедурно) анимироваться, и даже свои наборы подкомпонент иметь, не только графических. И это гораздо более полезная и широко применяемая возможность, чем ты можешь себе представить.
А, ну то есть делать анимацию в спайне, импортируя готовое в GMS - это зашквар и нихера не круто - изобретение велосипедов. А вот ебаться с процедурной анимацией - это типа норм и не изобретение велосипедов. Понятно всё с вами, понятно XD
И ты туда же? Сиквенсы это не обязательно анимации. Вы по ходу вообще не читали что я скинул.
По приведенной мной ссылке:
???
Ну прастити за невнимательность. Но про «полгода» это ты зря, 2.3 из беты только в июле вышла.
Как любит говаривать кое-кто, Очень Важные Подробности! XD
Это она из открытой беты вышла, а до того была закрытая ещё. (это тоже О.В.П.)
Если это про то как я собрал из кучи спрайтов один спрайт на GMS
, то конечно с одной стороны в том же Unity намного удобнее собирать, ибо всё сразу визуально видно
С другой стороны у меня есть ещё более сложные велосипеды, чем в GMS, в Tic-80 как-то собрал персонажа
из таких же частей, не знаю почему, но мне такой метод нравится, когда спрайты рисуешь программно:
1) может это лишь ностальгия по старому
2) а может потому-что не нужно все спрайты расставлять заранее, даже те которые должны быть скрыты, потом получать к ним доступ через GetComponent, и только потом можно изменять, кастомизировать или
прятать спрайт (если в данный момент он не нужен), когда в GMS в Tic-80 можно просто не рисовать спрайт или рисовать другой, это всё одной строкой делается
что-то типа псевдокодом
DrawSprite(Любая_Картинка_Спрайта , Координаты_Спрайта)
(в обоих случаях, что с велосипедом, что без, придётся писать много кода, если не само рисование спрайтов,
то доступ к самим спрайтам и управление спрайтами (скрыть/показать/кастомизировать) посредством кода)
Вот у меня на Tic-80 кучу спрайтов наложено друг на друга)
https://tic80.com/play?cart=1227
главная цель такого велосипеда (вместо рисования одного спрайта) - потом будет легко управлять кастомизацией, ну и экономия трудозатрат, потому-что каждый спрайт имеет свою анимацию, и эту анимацию можно использовать несколько раз в разных анимациях.
Но вообще я не защищаю свой метод) согласен что это извращение, и лучше такого никому не советовать, просто мне почему-то удобно с таким методом работать, лучше чем получать программный доступ к каждому спрайту, как приходится делать в юнити, да и чувство ламповости повышается от разработки)
> в GM2.3 уже полгода как завезли новый тип встроенного ресурса - Sequences. Они позволяют анимировать любые составные объекты "как на флеше", с раскадровками и интерполяцией между кейфреймами.
https://www.yoyogames.com/blog/550/gamemaker-studio-2-3-new-ide-features
Только не надо опять про "я на ГМ0.01 посижу потому что триалка закончилась". Возьми просто скачай новую, на другую почту, и увидишь. Может вообще не подойдёт, тогда и покупать незачем. А если подойдёт, так не знаю, я тебе могу купить, тебе ж для дела.
в GMS 2.3 там мне другие фичи нравятся, например изменение переменных объекта на текущем уровне,
очень удобно для создания уникальных дверей, сундуков и прочего, а в GMS 1 такого нет конечно)
Ты про Instance Creation Code, который можно задавать каждому экземпляру который стоит в комнате? В редакторе комнат? Так он ещё в GM8.1 до-студийном есть (может и в GM6.0 с которого я начинал, но дотуда уж не вспомню).
Другое, где руками вводить цифры, а не кодом, или я что-то путаю, как в юнити, где можешь переменным вводить другие параметры без кода Creation Code, в Creation Code запарно точно найти тот объект кому ты хочешь менять данные, надо держать в уме какие-то вещи, типа координат расположения или ещё что-то
Но ведь ты написал:
Я понял это как "в текущей комнате". Что значит "на текущем уровне" тогда?
Всё кажется я понял, я думал ты про Creation Code для целого уровня, вот этот:
А оказывается тут кажется есть отдельно для каждого объекта, если я не ошибся, ещё не тестировал.
Я раньше не замечал этой операции, и если оно работает отдельно для объектов, то круто:
Да, у каждого экземпляра объекта в комнате есть свой собственный Creation code. Поэтому я и написал именно "Instance Creation Code". Код создания комнаты, о котором ты уже знал, называется "Room Creation Code" соответственно.
-Здравствуйте, это "Клуб зануд"?
-Да, а вы, наверное, новый участник. Вот присаживайтесь на этот стул.
-У него нет спинки и три ноги, так что чисто технически это табурет.
-Оооо! Да у нас новый председатель!
Баян, эта шутка уже была, и, кажется даже 2 раза.
Даже баян хорош если он в тему =)
Object variables, судя по всему.
Крутая вещь, похоже про эту вещь я слышал.
Я рассказывал достаточно давно:
https://gamin.me/posts/20284
Creation Code - это уровень программиста, вручную.
Variables - уровень левел-дизайна, в редакторе.
Кстати про эти Variables. Всё время существования ГМС2 не использовал совсем их, а оказалось это удобно для настройки дочерних объектов (вероятно и для экземпляров в комнате). Собственно я протестировал это на одном прототипе и в паре случаев пока, но это куда удобнее конечно "наследовать и реализовывать" событие создание объекта*
В этих Variables есть даже тип "выражение", что по сути есть наверно любой код - например я использовал это для макросов и задание битовой маски.
* кроме случаев, когда нужна уникальная логика, понятное дело.
Всё так и есть. И для наследования и для задания значений в комнатах супер-удобная вещь.
Выражение (expression) – фрагмент кода, который можно посчитать и получить значение; это арифметика, обращения к переменным и вызовы функций. Предложения (statement), такие как объявления или присвоения переменных*,
if
, циклы и всё такое, выражениями не являются, и совать в Variables их нельзя.*в GML; во многих других языках присвоения тоже являются выражениями.
Так по-другому и не сделаешь. Либо придется делать много-много спрайтов целого персонажа с разными вариантами одежек.
Решил поменять пару пикселей на ботинках - придется их менять на всех спрайтах с этими ботинками.
Нет, лидировать будут разные движки для конкретных игр. Увы.
я ошибусь, если подумаю, что большинство из конкретных небольших игр вообще не могут быть сделаны на GM человеческими способами?
Это должны быть очень конкретные игры, лично я не встречался с такой игровой задачей, которую я себе ставил и которую не мог бы решить гамак, во всяком случае находились подходящие решения на том же реддите. Другое дело, что мозг затачивается под определенный способ работы с тем или иным инструментом, после чего сложно работать с принципиально другим. Я сейчас пытаюсь как-то освоить юнити (т.к. гамак слишком заморочен в 3д) и понимаю тех, кто пришёл из других языков и сред и возмущается на гамак - в юнити поначалу тоже всё кажется странно.
Ты так написал как бдуто юнити круче гамака и после того как ты поработал на юнити то гамак тебе стал казаться очень неудобным. Хотя подозреваю что ты имел в виду сам процесс перехода.
Юнити раньше была похожа на гамак когда там был JavaScript. Сейчас там только C# что порождает кучу деклараций ради деклараций, а не ради удобства написания и чтения программного кода.
Ошибёшься, да.
GM Studio надо покупать, потому что триал ограничен по времени.
Free-версия 1.4.9999 не ограничена по времени (у меня все еще работает), но там ограничения по ресурсам.
По сравнению с GM 8.1 у GMS отличий в лучшую сторону немного.
Собранные игры в последних версиях GMS (кажется, начиная с 2.x) не работают на WinXP.
Притом на гамаке я пока еще ничего толком не сделал.
Так что смысла покупать GMS, при условии что я пока не собираюсь продавать сделанные на нем игры, - не вижу.
Много. Ты слишком мало работал и с тем и с другим инструментом.
P.S. Сейчас придёт Кситилон и расскажет тебе про то как он проебался со своим дебаггером под GM8.1 =)
Он обещал теперь писать на Гамин только посты, так что не придёт :'(
Точно, он же теперь дохуя супер-занятый бизнесмен... Пошёл по пути Серёги Борьбова и yeo. Хуле со смердами общаться =)
Если бы тебе игры тоже приносили значительный доход, ты бы тоже им все свое основное время посвящал, а не общался на форуме, объясняя всяким нубам что они что-то делают не так.
Круто ты всех под одну гребёнку загребаешь.
Люди разные и ценности у них разные, хотя у большинства так как ты сказал.
У меня и сейчас доход в месяц измеряется в килобаксах. При том что работаю по 4 часа в день. Мог бы по 8 работать и получать ещё больше... Но увы, жадность - не моя стезя. Помимо работы охота с нубами на форме пообщаться, объясняя им что они делают не так, с женой время провести, с котами, прогуляться, сходить куда-нибудь. А то так вся жизнь за работой и пролетит.
Игры, надеюсь, будут приносить доход (как завещал великий Кситилон), но от меня так просто гамин не избавится.
Зная Хейзера, могу сказать что это у него натурально порыв альтруизма. Я бы тебе тоже объяснил, но мне уже есть кому объяснять из не-нубов, с которыми мы вместе работаем над коммерческими проектами в уже сложившейся системе командной разработки. У Хейзера такой системы нет (да и надо ли), вот и делится опытом просто так, в надежде что это намотают на ус и сделают прикольных инди-игр.
Поливать других матом, объясняя, как они не правы — так себе проявление альтруизма. Серьёзно, я уже боюсь ему что-либо отвечать, чтобы не быть обляпанной говном v_v
Мат это инструмент экспрессии, а не агрессии, особенно когда разговор идёт между 30+ летними мужыками. Если человек матом говорит правильно - это ценней того что тебе вежливо скажут неправильно, или не по сути вопроса.
С такими убеждениями вам куда-нибудь на стройку. Также могу предложить картинки с говном и расчленёнкой добавлять для пущей экспрессии.
Дилемма Эскобара.
А мы и так на стройке. Архитектуры думаем, по ним игры строим.
Чтобы не быть обляпанной говном - отвечай не глупостями. А по делу, с подтверждениями и пруфами.
Если собеседник не готов общаться конкретикой и начинается "Все прекрасно знают", "Встроенных средств недостаточно", "Есть задачи для которых этого будет мало", "Ни для кого не секрет" - меня злит, когда собеседник начинает аппелировать к общим фразам как к истине в последней инстанции. Теория ничего не стоит без практики. Я всегда стараюсь ссылаться к практическому опыту - то что делал сам, или где-то видел, стараюсь дать пруф (если прям не совсем лень). Я не вижу смысла сдерживать свои эмоции если со мной начинают так неуважительно общаться.
Ну Ксит ещё совсем недавно больше всех этим и занимался, только посмотри на его счётчик сообщений.
А что счётчик, я писал на Гамин и об играх тоже порядочно много. Так-то это сайт про инди-игры и играние в них, и обсуждали тут в 2012-2020 игровые механики, левелдизайн, "время койота", и мн., как говорится, др.
Я всё видел. >D
С вами не сильно-то поридонлишь, когда очевидные вещи пропускаете в дискуссии. Бобров и Йео всё равно нет-нет да и захаживают, стопудово ещё услышим и одного, и другого рано или поздно. Так что видимо я буду держать кулдаун типа 1 день в неделю могу комментировать, 6 остальных дней просто смотрю, или даже не смотрю какие там буквы возникают в интернете.
А вообще непонятно, зачем ты так страдаешь если тебе прям не нравится GM, пиши на Lua раз тебе удобнее.
Моё мнение, что GMS2 стоит своих денег. А так чтобы на хуй сесть и рыбку съесть - так не получится.
Для хоббиистов, даже с региональной стимовской ценой - не стоит. Я бы его никогда не купил просто так.
Полторы тыщи рублей — нормальная цена за хороший хобби-инструмент. Качественные рисовалки, помимо опенсорсных (которых полторы софтины) дороже стоят.
Часто софт покупаешь?
Гамак - не единственное моё приобретение. И цена за функционал очень даже божеская - 20 с нехером баксов. Тот же bandicam, например денег своих явно не стоит - ~30 баксов, но лучшего захвата видео я пока не встречал, к сожалению.
В ImageLine подохуевшие ребята, только один хаб 200баксов, а ещё каждый плагин отдельно покупай за сотку. Это хорошо что у них лайфтайм апдейты и вроде пока они это менять не собираются.
И да, это всё при том, что операционка (вин10) стоит 200 баксов, ага =)
А так большинство программ сейчас поставляются по подписке за охуевшие бабки. Фотожоп - 10 баксов в месяц минималка (только шоп и лайтрум). Хочешь премьер? Башляй ещё 10 баксов в месяц. Гамак для коммерции не исключение в этом плане, но там и без них можно много чего сделать.
И да, с гамаком ещё повезло что его апдейты не запарывают твою работу. Как новый фотожоп выйдёт - вся система колом встаёт, ресурсов не хватает(на 8 ядрах, с 4 гб видюхи и 32 оперативки, ага).
Всё это к тому что со своим опытом использования коммерческого софта - цена за гамак в Стиме - это просто подарок. То что в рунете не привыкли покупать софт в виду обнищания населения - это совсем другая тема.
Очень редко. Но купил https://www.goldwave.com - он значительно богаче фришного Audacity, и по сути можно его юзать без покупки, просто я уже много лет с ним работал, и как-то надоело не покупать.
С Виндой такое не прокатит - Майкрософт мне сам мог бы её предоставить, раз 30% жрёт со всего что я издаю на Иксбокс.
200 долларов стоит Про-версия Вин 10. Домашняя 140. Могу продать тебе, я официальный вендор. XDDDDD
Ты ничего не перепутал? 100 долларов оригинал, 45,99 для СНГ (не все живут в дефолтных странах, да).
https://obsproject.com умеет забесплатно всё то же самое ПЛЮС стримить.
А в Windows 10 вообще уже есть встроенный захват видео в оверлее Xbox Game Bar по Win+G.
Вот кстати Audacity мне не очень нравится, голдвейв пробовал очень давно, надо будет глянуть на досуге ещё раз.
Ну нет. 1600 рублей у меня в стиме, а по сегодняшнему курсу доллара это чуть больше 20 баксов.
Стримить да. Захват видео в файл не нравится на ней. Плюс бандикам у меня скрины нарезает каждые N секунд из которых я потом выбираю для сторов.
Так то есть Linux - мир с его многообразием...
Лицензию на GMS1 можно передавать? Могу подарить свою, всё равно лежит. А так кто-то, глядишь, игры делать будет ^_^
Отдай АндрейДолжен19 а то чё он на 8.1 мучается XD
Так я ему и пишу.
Так единицу он уже раскритиковал в самом посте)
Ну по крайней мере она всяко лучше, чем 8.1 (кроме
execute_string
, дадададада), даже если и несильно.он триалку же критиковал, а не полноценную версию...
Не, пока не надо.
Лучше отдать кому-нибудь новому.
Можно "гостевые ключи" создавать до 3х штук.
Про прям непосредственную передачу не уверен.
Вот этот код:
кушает проц на 10% (на столько уменьшается, если код закомментировать).
Что делать? Все статичные элементы ГУИ объединять в одну картинку?
Можно попробовать запечь статичные элементы в surface. Но можно запечь весь интерфейс, а перерисовывать его после изменений какого-то из параметров, если они не очень часто меняются.
Что за проц-то такой, Pentium II 233MHz с технологией MMX™? Не надо ничего трогать, 10% это 10%.
if (instance_exists(human)
в началеwith human
и автоматически замени всеhuman.
на пустую строку (таким образом убирая все обращения к объекту, потому что ты в его контекст уже перешёл с помощьюwith human
, и только в том случае если этот объект уже есть; иначе не выполняется ничего в этом блоке with.Спасибо, так и сделал.
Ссылки на human может и не быть, тогда и рисовать ничего не надо. Поэтому проверяю сначала что она есть прежде чем рисовать.
Нашел как отрисовывать предыдущий кадр: screen_refresh();
Сделал объект-паузу.
Событие нажатия кнопки:
Событие отрисовки можно оставить пустым.
А вы и дальше продолжайте скриншоты делать.
И будем продолжать, ведь в GMS2 нет screen_refresh() ровно как и screen_redraw().
Для старой версии неплохое решение, хоть и немного рсиковое.
В GMS2, наверное, можно попробовать отключить обновление/отрисовку app сурфейса чтобы добиться подобного эффекта.
Во-первых отключить аппсёрфейс можно.
А во-вторых всегда можно его закэшировать и отрисовывать поверх старый.
Что не отличается от метода "делать скриншоты" XD
В игре все экземпляры рисуются с сортировкой по Y, все объекты которые могут передвигаться по уровню имеют маленькую маску столкновений, на уровне земли.
Для столкновения с выстрелами мне нужно сделать эту маску (коллайдер) размером почти во весь спрайт, чтобы легче было в него попадать. Как лучше сделать?
- Сделать сферическую маску для пули диаметром больше чем ее спрайт?
- Создавать невидимый экземпляр с другой маской и таскать ее все время за перемещаемыми объектами?
- Высчитывать попадания вручную?
Что вообще в GM делать с ситуацией когда для столкновения с разными типами объектов нужно 2 разных коллайдера?
Делать 2 разных коллайдера. Можно подумать в других движках это не два разных инстанса. (а то щас начнётся - там лучше, потому что там якобы один, а не два)
Но честно говоря непонятно что за механика у тебя. Вот есть например Worms - там трудно попасть оружием без поражения по площади, но с этим никто ничего не делает, это просто часть игры.
В Unity можно повесить 2 коллайдера на один объект. Один сделать твердым (для столкновений при перемещении объекта по уровню), другой - триггером.
А для пули написать событие, срабатывающее по попаданию в триггер. И затем наносить урон объекту, чей это триггер и удалять пулю.
В Love2D я вообще могу жестко 2 разных коллайдера каждому объекту прописать, первый будет всегда для перемещения, второй - всегда для пуль.
Одному объекту нужно 2 коллайдера, разного размера и положения относительно спрайта. Один для столкновения с геометрией уровня, другой - для столкновения с пулями.
Вот тут картинка есть:
Я вначале так делал, но потом решил отказаться от 2-х коллайдеров на объект.
У меня кстати геометрия уровня сталкивается тем же коллайдером, что и персонажи между собой.
Но не уверен как в GMS лучше сделать, я в GMS пока делаю вид сбоку, а не с сортировкой.
Использовать два коллайдера очень удобно, сам так часто пользуюсь... При условии, что мы работаем в контексте физических тел.
В твоем случае мне видится правильным использование указанного тобой примера: коллайдер для физики у ног перса, коллайдер для логики на весь спрайт. Это стандартный вариант во многих играх.
Использовать два коллайдера = увеличение проверок столкновений, а значит падение fps с ростом количества объектов. Особенно в контексте физических тел.
Если бы их можно было поделить на группы, которые могут сталкиваться между собой (как в Unity), то не будет увеличиваться. В GM, а так понял все проверяются со всеми.
Причём тут это? Я вообще про то что "две головы хорошо, а одна - лучше"
Проверить область попадания в коллайдер дешевле по производительности чем поддерживать два коллайдера. То есть зачем прям два разных коллайдера я вообще ХЗ. Сколько игр сделал, если такое и требовалось то всего пару раз за свою практику.
Но я знаю, что ты любитель решений через жопу XD
А ты подумай головой прежде чем обзываться.
У тебя 2 противника - один высокого роста, другой низкого. Коллайдер земли у всех одинаковый.
Если делать как ты предлагаешь (коллайдер пули на месте ее тени) - то, пролетая рядом с головой противника, пуля будет задевать низкого противника, но не будет высокого.
Единственный надежный способ - сделать отдельный коллайдер подходящего размера для каждого объекта, куда могут попадать пули, учитывая размер спрайта.
Или оба соперника одинакового роста, но у одного коллайдер земли больше по вертикали. Тогда может получиться что пуля будет сталкиваться с ним, визуально не пересекаясь со спрайтом. Это то, что вы, геймеры, любите называть "кривыми коллизиями" и "непонятными хитбоксами".
Я бы не так сделал. Я бы сделал персонажам признак роста, а пуле высоту на которой она летит. При обработке столкновения просто учитывать этот факт и игнорировать событие столкновения если пуля не на той высоте.
А у тебя если будет десять разных персонажей с разным ростом и стреляющих на разной высоте - ты, наверное, будешь десять коллайдеров на каждого делать. Я же говорю, через жопу решаешь всё.
P.S. Но это не твоя вина, просто Unity сеет программистский разварт в умах подрастающего поколения.
P.P.S. А так ты верно говоришь, головой думать надо. Пару месяцев назад читал статью на офф-сайте YoYo на тему того как z-sorting делать в 3Д с настройкой камеры в 2D. Ебать best-practices, нахуя тогда depth вообще делали, спрашивается. С тех пор к статьям YoYo я отношусь скептически.
Это ты через жопу решаешь эту проблему. Вместо десяти коллайдеров ты предлагаешь 10 высот сделать. А если персонажи еще разной ширины? Еще и 10 ширин добавить когда пуля снизу/сверху летит?
Не проще один раз коллайдер сделать и не мучаться?
А потом ты захочешь поменять "высоту" пули над землей или ширину пули и тебе все ширины и высоты у спрайтов нужно будет изменить на то же значение со знаком "минус".
Почему я должен считать через арифметику то, что должен выполнять движок/конструктор, раз уж он берет обязанность на себя обнаруживать столкновения? Через арифметику я сам в Love2D посчитаю, только GM я не для этого в руки взял.
Твой подход напоминает разработку игр на Денди, когда было мало ресурсов и детектить кучу коллайдеров слишком медленно.
Тогда они сидели и считали - коллайдер пули лучше сделать точкой, вот этот коллайдер солдата в прыжке - меньше чем спрайт, вот этот - больше и т. д.
Но еще раз, я в руки GM не для этого взял. А чтобы ускорить разработку, за счет того что движок возьмет на себе часть вычислений и операций, которые мне раньше приходилось кодить самому. Ты сам по этой причине всем его рекомендуешь.
Ты меня тролишь что ли или в натуре на голову отбитый?
Конкретно в этом примере мне проще задать в Variables высоту персонажа чем менеджить 10 коллайдеров или в одном степе менять положение коллайдера чтобы проверить столкновения по всем высотам или ещё какие охуенные техники который ты придумаешь. Потому что я знаю что я в этих коллайдерах всё равно запутаюсь потом (будь то ГМ или юнити - совершенно не важно). Как я уже говорил, бритва Оккама - мой друг и плодить сущности без необходимости я не буду. Будет у меня задача сделать сложносоставной объект сложной формы - тогда мультиколлайдеры буду мутить без вопросов.
GM тебе и так ускоряет разработку. Всего одну переменную чекнуть в событи столкновения:
Всё блядь. Мой вопрос решён хоть на две высоты, хоть на 10. Остальное конфигами высот решается. И мне не нужно ещё настраивать по два коллайдера на каждый объект, чтобы потом лазить в скрипт на хуелион строк и искать там событие обработки столкновений, в котором ещё поди придётся покопаться чтобы поменеджить с каким именно коллайдером ты столкнулся.
Ты можешь дрелью сверлить стену, а можешь руку. Вопрос в том - умеешь ли ты правильно пользоваться инструментом, который у тебя в руках. А у тебя получается что ты пользовался пилой, взял топор и такой "Хуле он не пилит? Я привык пилить туда-сюда! Дерьмо, а не инструмент!".
Это не мой подход, а совершенно нормальный подход в серьёзном геймдеве. Если ты будешь норм игру делать - там у тебя и не такой дроч будет как ты описал. Чтобы сделать какие-нибудь скрытые UX механики ты будешь ещё не такие костыли делать и не так оптимизировать.
Я устал уже отвечать на твои подъёбы. В следующий раз поговорим с тобой после того как ты хотя бы один проект до релиза нормального доведёшь.
Короче, ты так толком и не прочитал что я написал, раз не понял чем коллайдеры удобнее.
Второй коллайдер - это не мультиколлайдер для создания сложной формы, а чтобы получить разную форму тела для столкновений с геометрией уровня и для столкновений с пулями.
В твоем примере надо сравнивать не =, а
если other - это объект, в который попала пуля.
И тебе так и так придется лазить в обработчик столкновения чтобы добавить туда эту строчку, не надо говорить что тебе надо лишний раз куда-то лазить.
У меня уже есть куча выпущенных игр. То что ты не считаешь их "нормальным" релизом - твои проблемы.
Смысл тебе писать если ты все равно не читаешь толком.
Троллингом я закончил заниматься после окончания института. Не интересно мне это.
тебе не будет сложно нарисовать, как это выглядит? а то чего то не могу в голове уложить, почему "пуля будет задевать низкого противника, но не будет высокого", если столкновение определяется только по тени. Мышку задевает ведь точно также, как букашку? А бочку и не должно задеть, они на разной глубине
Да, на словах плохо понятно. Сейчас попробую нарисовать.
Просто, ты же знаешь - я не люблю рисовать. Мне проще стену текста написать.
1 - низкий противник, 2 - высокий
Серый - коллайдеры для столкновения с геометрией (у 1 и 2 они должны быть чуть повыше, но мне лень было делать 2 слоя в картинке).
Вот, если делать серые коллайдеры, то пуля пролетит через спрайт 2, не задев коллайдер.
Игрок матюгнется "что за кривые коллизии - я же попал!".
В твоем рисунке все хорошо если тень рисуется, тогда игрок может ориентироваться по тени при выстрелах.
Если тени нет - игроку все равно как-то надо понимать попадет он или нет, а не методом тыка рассчитывать - на какой высоте от спрайта пули задевают каждого противника.
Хейзер предлагает, за отсутствием возможности сделать отдельный коллайдер, сделать маску для пули черного цвета, большего размера. Тогда она будет сталкиваться с обоими. Но вот когда пуля должна пролетать мимо 1, не задев его, вручную добавить еще проверку высоты коллайдера. И для ширины тоже (если ширина масок тоже отличается).
Я пишу что это ничем не отличается от ручного вычисления столкновения, чего я хотел бы избежать, переключившись на GM. И еще что при изменении хотя бы одной маски спрайтов 1 или 2 придется менять маску пули. Чего не было бы, если можно было повесить 2 отдельных коллайдера на один объект и обрабатывать столкновения с ними отдельно.
Лучше конечно не делать настолько длинного персонажа, как персонаж 2,
и пулю лучше так высоко не подымать от земли, чтобы меньше матюков было.
Если увеличивать по высоте персонажей, то хотя бы немного и по ширине.
А ещё я тут добавил коллайдер стен, стены тоже у меня по низкой координате считаются.
Синим - объекты, Красным - коллизия.
PS но если тут ещё считается высота, то конечно вообще жесть, предлагаю в подобных играх поменьше использовать высоту, я помню как в Mario RPG на GBA сильно путался, ибо непонятно где находится объект или платформа из-за того что 2D пространство, но с 3D высотами.
Высота - плохо решаемая проблема в 2D играх с 3-мя осями.
По-моему тут как раз образцовый случай, как надо делать - тени есть, по ним видно где вне зависимости от высоты находится объект в воздухе.
Это да, но тут много моментов, когда можно было легко запутаться, всё равно.
Вот это мне и не нравится. Натыкаешься на ограничение инструмента - ищешь как его обойти, либо ограничиваешь этот момент в игре.
Я понимаю, Хейзер пользуется GM уже лет 10, не меньше, и он уже давно привык делать все так, как разрешает движок. И просто не делает того, чего нельзя сделать в движке.
Но я-то - не 10 лет, и я хочу сделать вещь как правильно, а не как можно.
А надо я хочу сделать вещь
Кому «надо»?
Тому кто делает вещи, а не выясняет способы, разделяющиеся на правильные и неправильные по произвольно выбранным хотелкам.
я бы обошелся вообще без теней и рассчитывал столкновение как есть, по мешу(спрайту) объектов. Ничего страшного, если игрок получит от этого небольшое преимущество.
А коллайдер игрока уменьшил бы до ног и нижней части туловища. Игроку даст небольшое преимущество, что опять же ничего страшного и позволит больше наворотить визуальной рисковости челенджу.
Костылить тени нужно только когда 1) враг чрезмерно высок + 2) площадка слишком широка + 3) реализована стрельба в высоту через диагональ (или прыжок)
Ну ерунду сейчас написал же. Ты же не на калькуляторе собрался играть. В моей конкурсной игре Not a Dungeon, два коллайдера, один физический (kinematic) для tailmap из которой построен мир, а другой (area2D) для логики - группы enemy, props и etc. Настраиваем правильно слои и маски (нам незачем же логику проверять столкновение со стенами). Я тесты не делал и не буду, но на моем 2011 года ноутбуке спокойно 1000 ~380 объектов между собой контактируют, да у меня не 60 fps, но 30 стабильно, и это на карте G45, у которой даже сотни мегабайт памяти нет. Не хочу спорить, доказывать, но у меня есть свой опыт и имею право несогласиться. На примере Godot, с физическим коллайдером не просто работать, он очень продвинут и заморощен, чтобы на нем просто обрабатывать обычные сигналы столкновения.
Ерунду пока что только ты пишешь, видимо потому что игр толком то и не сделал. Я с этими столкновениями довольно много опыта хлебнул, в.т.ч. и с тормозами из-за обработки столкновений на большом количестве объектов. А если ты вдруг на консолях решишь игры делать, то тебя ждёт много удивительного и интересного. Например то, насколько там слабое железо. Я вот неделю потратил на то чтобы в Sig.NULL для иксбокса часть шейдеров переписать, просто потому что иксбокс их не тянул(а комп при этом даже не кряхтел). И если у тебя на компе всё летает, то не факт что будет на консоли. Такие дела.
Попадёшь пару раз в такие ситуации тоже начнёшь фейспалмить с решений "я на пулю навешаю коллайдеров для каждого вида противника по одному индивидуально".
Ну у тебя на любое возражение ответ "вы ни одну коммерческую игру не сделали - все ваши способы неправильные". Твоя аппеляция к "опыту" уже в печенках сидит.
И причем здесь твои мучения с тормознутыми шейдерами, когда речь идет о коллайдерах?
А ну ок, давай играть так как ты хочешь.
Получается, что я все 17 лет делал неправильно, а ты за полгода работы с инструментом нашёл верный способ(свежий незамыленный взгляд как говорится). Конечно, тогда лучше с десятью коллайдерами. Твой способ единственно верный и правильный, разумеется. Чего это я.
С чего ты все время кидаешься в крайности - "либо правильно, либо неправильно"?
Нет правильных и неправильных способов. Главное - устраивает разработчика этот метод и приводит он к нужному результату или нет.
У каждого способа есть свои минусы и плюсы. В сложности реализации, точности результата, нагрузке на проц и видеокарту.
Все началось с того что мне оказался нужен 2-ой коллайдер (не 10!).
Ты говоришь что в GM такого нет - делай маску побольше и считай втолкновения с пулями вручную.
Ну ок. Я остался этим недоволен. Написал чем этот способ мне аукнется - при изменении маски любого кто с пулей может сталкиваться мне придется каждый раз проверять - не придется ли менять маску пули.
Да еще и заводить "ширину", "высоту" для каждого спрайта чтобы пропускать столкновения если пуля должна пролететь мимо.
Раньше не понимал - "Почему игроделы делают 2D-игры на трехмерном Юнити? У них же есть нормальный двухмерный GM, специально сделанный для 2D-игр, пусть на нем 2D-игры делают!" и все время ныл по этому поводу.
А все потому что Юнити более гибкий и на нем сделать 2D-игру в 3D-мире проще чем на GM. И можно сделать 3D-игру, которая выглядит как 2D, с 3D-коллайдерами (например, первая Party Hard). И никаких вышеописанных проблем с пулями не будет, если коллайдеры в 3D.
Да, 2D немного не к месту в 3D-движке, зато движок удобнее.
EDIT: ой, так ты это и предлагал в исходном комментарии :o) Ладно, пусть остаётся.
А если такое решение для второго коллайдера?
1. Когда вылетает пуля, она создаёт специальный объект со своей маской и своим набором событий столкновения — так заодно группы столкновений можно имитировать — и устанавливает ему поле «главный» в свой
id
. Этот прокси-объект и служит для пули вторым (при необходимости также третьим/пятым/десятым) коллайдером, и сможет обращаться к ней по сохранённомуid
.2. В
Step
прокси-объект неустанно следует за пулей, просто копируя себе её координаты.3. При столкновениях прокси-объект дёргает у пули соответствующее событие или вызывает скрипт.
Вуаля!
Единственный подводный камень — прокси-объекты должны с главным не только синхронно создаваться, но и уничтожаться. Либо в
Step
'е у прокси проверять, жив ли главный черезinstance_exists
, либо главному также помнить о всех своих проксях и убивать их в своёмDestroy
.Был вариант создавать вместо с каждым противником невидимый объект со своей маской и двигать его все время вместе с противником, а все попадания в него - переносить на противника.
В любом случае все предложенные варианты - это попытка сымитировать 2-ой коллайдер.
Ну если по-простому прикрепить второй коллайдер нельзя, приходится имитировать. По крайней мере, как мне кажется, это лучше, чем вручную считать высоты.
Честно говоря не совсем понял этот спор про коллайдеры и вообще в правильную ли ветку комментов отвечаю, но почему никто не вспомнил про ГМ-овские collision_* функции? Этой функцией можно и ограничить список объектов с которыми будет идти проверка (класс\объект врага, например), а сама функция по сути не зависит от позиции самой пули - можно выше, ниже да хоть где проверить коллизию некоторого примитива (прямоугольника хватит всем) с другими объектами на сцене.
Я думала, AndreyMust19 под «высчитывать попадания вручную» что-то вроде этого и имел в виду.
C
collision_xxx
проблема только в том, что сообщать, с какими именно объектами обнаружено пересечение (чтобы вызвать у них обработчики), умеют только версии с суффиксом_list
, а их в GMS1 и ранее не было. В остальном этот способ лучший, наверное.Я знаю про них, это cast коллизии, одноразовая проверка.
Это не голая математика, но больше подходит для взрывов и ударов.
Если пуль будет много, думаю, нагрузка на ЦП сильно возрастет.
Ну что тебе опять не нравится?
"cast коллизия" - это что? Такой термин не гуглится.
Голая математика - где вообще в движках голая математика? Почему одна математика в движке для тебя голая, а другая не голая? Какая разница, где голая, а где не голая, если все варианты решают задачу?
При чём тут взрывы? При чём удары? Коллизии со всем этим прекрасно можно обнаруживать встроенным механизмом с событиями.
Не включай дурака и не притворяйся что ты не понял о чем речь.
Я бы с радостью, но "cast коллизия" действительно не гуглится, а взрывы тут непонятны.
Cast-функции проверяют, находится ли в момент вызова функции в указанной области какой-нибудь коллайдер и возвращают ссылки на их объекты. Это как бы однократная проверка физики - ты узнаешь кто бы столкнулся с коллайдером в указанной точке, если бы он там был.
Эти функции используются для проверки свободы пространства перед созданием объектов / выбрасывания предметов, во время ударов и взрывов, чтобы узнать кто попал под удар/взрыв.
Для этой цели можно использовать триггер-коллайдер, но не нужно, это неправильно. Потому что движок будет искать пересечения с этим триггером каждое обновление, постоянно, а тебе надо только в определенный момент, что лишняя трата вычислительных ресурсов и при большом кол-ве таких триггеров скажется на производительности.
Можно этот триггер выключать и включать перед проверкой, но тогда результат пересечения ты получишь только во время следующего обновления движка, с задержкой, а не прямо в тот момент когда тебе надо.
Так что нужно именно Cast-функции использовать.
Но это не единственный способ обрабатывать ни взрыв, ни удар. Можно просто спаунить маску повреждений и по ней сверять. В файтингах делается именно так, например, просто это жанр относительно непопулярен.
Ты сначала замеряй сколько именно их тратится. От того что ты сэкономишь 100КГц в чьём-то процессоре, мир во всём мире не наступит. Если бы это хоть что-то по факту улучшало, я бы уже рассчитывал с точностью до пикселя и бита сколько где экономится, но увы.
Этот тот же коллайдер. А сверять ты будешь во время следующего update игры.
Но правильно именно вызывать Cast-функции.
Вот именно из-за такого подхода и появляются убогие игры, которые жрут 4 Гб оперативы, 1 Гб видеопамяти.
Есть экономия (сокращение расходов), а есть излишнее расточительство и ненужные вычисления (трата того, чего вообще можно не тратить). Сейчас речь именно про второе.
Нет, они появляются из-за другого подхода, а 100 КГц о которых говоришь ты, это не 1 ГГц о котором говорят в ААА-играх или даже уже в некоторых инди - тех которые используют слишком разожранные движки для простейших вещей типа двухмерных коллайдеров. Ты вот говоришь что в ГМе этого делать не нужно, а ты проверял сколько это требует вычислений в Юнити? Или в Годоте? Замеров-то нет.
Я за подход "не делать лишних вычислений", а не замерять сколько это будет в конкретных движках.
Если эти "идеологически лишние" вычисления никак не влияют на количество кадров в игре и на износ железа, то ты просто удлиняешь разработку своей игры и сделаешь её позже и/или хуже чем мог бы, если б этим не занимался.
Как говорил мой учитель - "я твой учитель" - "не стоит заниматься преждевременной оптимизаций" (ну или такой смысл был)
Кстати, это вроде называется sweep. А cast - это кидать фигуру вдаль по лучу до первого столкновения.
Теперь посмотри на себя со стороны. Нашёл одну проблему с коллайдерами и уже расписываешься за все жанры всех двухмерных игр. Ты делал когда-нибудь стратегию, симулятор, файтинг? Игр много разных, и в Юнити из них делаются легче только трёхмерные. Ручная проверка коллизий в паре мест не означает ни что в ГМе нужно делать вручную всё, ни что в Юнити всё остальное тоже делается так легко как коллайдеры.
Я понимаю что Хейзер достал всех материть и ЧСВшничать, но он только один ГМщик, и не стоит судить по его разговору ни о ГМе, ни о ГМщиках в целом.
Для твоей задачи нужно правильно разделить ответственность - вот пуля, а вот коллизия. И не менять маски по две сразу при смене оружия. А пол проверять вообще не коллайдером, а например через
collision_line(x,y+sprite_height, x+sprite_width, y+sprite_height, ... )
. И ничего в этом нет ни зазорного, ни умственно отсталого, ни не-гибкого. Это называется просто использовать встроенные средства движка по назначению. Прокси-объекты - такая же глупость как вручную считать высоты, смешно читать как наш апологет всего чистого и правильного в программировании (Yuuri) ратует за костыление костылей там где они не нужны.Тут не одна только проблема с коллизиями.
Это не мое решение и я так точно не буду делать, ибо знаком с layers и masks для коллайдеров, знаком с groups.
Перегибаешь палку, речь идет о двух коллайдерах и только, все остальное решается слоями и масками, группами обьектов. Я не знаю зачем ты завел разговор про консоли, но это такой себе пример.
Надеюсь я правильно понял. У меня в игре коллайдер всего один для игр с сортировкой, и он действительно маленький. Но это на Юнити, в GMS ещё не пытался создать игру с сортировкой.
Красным у меня тут обозначены границы коллайдера (маска столкновения?),
обычно коллайдер примерно там где тени от объекта.
Коллайдеры обычно в виде прямоугольников или овалов.
Слева направо: персонаж, пуля, камень.
А чтобы легче попадать, лучше всего делать дизайн персонажей намного ниже, как чиби
или под другим углом, чтобы персонажи больше сливались с маской столкновения.
Также слева направо: персонаж (чиби, голова огромная), пуля (почти у земли), камень
Я так же делаю. Размер коллайдера подстраиваю в зависимости от ощущения в геймплее. Если бесят частые промахи - увеличиваю коллайдеры, если вижу что пули исчезают не долетев до цели - уменьшаю.
Спасибо, попробую сделать такой коллайдер у пули.
можно проверять столкновение по "тени пули" и затем проверять высоту. примерно так вроде в исааке работает.
собственно самое простое избежать такой ситуации =)
В TDS без учёта высоты по классике все столкновения считаются по теням или теневым маскам.
Ну вообще мне кажется на восьмибитке коллайдер рассчитывался примерно так:
весь коллайдер = весь спрайт, а коллизия стен немного смещена вверх, чтобы можно было немного спрайту пересекаться, но я не уверен на 100%, просто по ощущениям, что тут 1 коллайдер, возможно тут есть фокус со стенами.
И тогда расчёт столкновения с пулей можно делать не по тени, а прямо по спрайту.
Синим - коллизия стен (как мне показалось). Красным - коллизия персов.
Такой вариант тоже возможен, но тут приходится выбирать - кто на себя берет ответственность за столкновения.
В случае со вторым коллайдером - это движок.
Ручной расчет попадания, как предлагал Хейзер - программист.
Твой вариант - левел-дизайнер. Тут если вдруг автор решит все спрайты врагов сделать больше или меньше, то левел-дизайнеру придется переделывать все стены на всех уровнях под новый размер коллайдера у персонажей.
Как в одну строку инициализировать массив?
Пример со скриптом из интернета не работает:
При обращении к элементам такого возвращенного массива пишет ошибку:
Писать вот так влом:
Вопрос про инициализацию или копирование? Для инициализации в GMS2 (в 8.1 нет, насчёт GMS1 точно не знаю) есть литералы для массивов, можно просто
arr = [23, 35, 64];
В ГМС1 кажись такого ещё не было, новая штука это для ГМС2.
Точно не? Ну на крайний случай попробуй ещё var arr = array_create(argument_count) сделать или прям продебажить этот момент пошагово.
В старых ГМах такого нет, в новых есть. Но ты можешь сделать
arr=explode_real("23,35,64")
, гдеexplode_real
это скрипт создающий массив из указанных чисел.https://www.gmlscripts.com/script/explode_real
Ну или переименовать его в, скажем,
csv
, тогда будетarr=csv("23,35,64")
.Почитал тут комментарии и такая интересная путаница получается. Особенно когда пользователи GMS и Godot спорят. Из-за очень разного внутреннего устройства движков, получается, что истинно для GMS не истинно для Godot и наоборот. Читаешь, сравниваешь и такой абсурд получается. Если кто со стороны придет и начнет в это вникать, скажет какие-то идиоты собрались🤣 Кароч, бесполезный флейм плодим, господа.
Надо ещё подключить активных Юнитиводов и Анрилоюзеров (если такие есть у нас на Гамине) :yak:
На каждого умника найдется кто-то по-умнее. Пока таких нет.
GM 8.1
У объекта objGUI есть ссылки на игрока (global.player) и босса (global.boss).
Макс. здоровье игрока в Draw объекта objGUI выводится правильно.
А вот макс. здоровье босса (по такой же ссылке) = 0.
Над самим боссом выводится 6.
РЕШЕНО
ссылка на игрока возвращается вот так:
а на босса так:
а надо:
На мой взгляд лучше тогда при создании записать,
Персонаж уже в комнате.
Да и вообще глобальная ссылка означает что управляемого персонажа можно менять.