Почему пиксели в Game Maker искажаются?
Делаю свою первую мини игру на Гейм Мейкере GMS 1,
насколько я понял не легко сделать pixelperfect на гамаке с динамическим окном,
и решил вначале потренироваться, вроде всё сделал правильно,
использовал функцию
surface_resize(application_surface, x, y);
здесь Source Demo
Но почему-то часть пикселей пилообразно искажаются:
- 30 апреля 2020, 09:30
- 01
Это пуфыстость кошкодевочки просто:3
Так и запишем: "пуфыстость лучше" :3
D:
Ажурные трусики!
surface_resize(surface_id, w, h);
я думаю, использование функции немного некорректно...
А как корректнее?
ЗЫ в конечном итоге я кажется разобрался, добавил округление в этот код, не факт что полностью исправил, но на моём компе кажется проблема исчезла:
раньше последние строки выглядели без округления, видимо дело было во float значениях:
Пиксель-perfect с масштабирование достигается только если вьюпорт так же меняется в игре. Все эти шаманста с сурфэйсами не сработают. В лучшем случае - у тебя будет мыло, в среднем - укрупнённые пиксели разного размера, в худшем - то что в посте.
На своей практике я прописываю зависимость размера вида в игре от ширины окна/монитора так чтобы оно было кратно пикселям, т.е х2, х3, х4. Там всё достаточно просто на самом деле. Но это не всегда получается в играх сделать, особенно если игра поделена на комнаты - там можно сделать как в Gato Roboto, т.е. сделать вид внутри вида и внутренний вид масшатибировать по х1, х2, х3 которые влезают в окно игры.
Я пока мало знаю про движок, мне например не понравилось, что надо отдельно каждый раз при создании нового уровня менять вьюпорт и размер экрана, это странно, это реально странно!
Но в целом я так и сделал, проверяю скриптом, какой размер дисплея, и если можно то увеличиваем в x2, x3, x4 и более раз, хотя в то же время, я всё таки работал с surface, но теперь понял как решить проблему, добавил в последние две строки round.
Мне начинает нравится концепция скриптинга в GM, ибо это очень похоже на JS, который я на юнити осваивал.
Да, в GMS слабая типизация, примерно как в JS, нов JS структуры данных гибче, правда есть подвохи с замыканиями, которые на ES5 только через жопу решаются.
В 2.3 студии вообще полноценный JSON завезли с объявлением своих функций в переменных. Пока эксперименталка, через пару месяцев должна будет выйти. Ну и там ещё много клёвых фич такие как кривые анимации, группировки ассетов как угодно а не по типу. Нормальное гнездование аксессоров для дата-структур. В общем, виден рост дивжка. Причём именно в сторону общепринятого профессионального инструмента.
А насчёт комнат - в GMS2 их вообще наследовать можно. Я не совсем понял что ты имеешь в виду под создание уровня. Если в самой IDE то вот как раз наследование поможет- - делаешь комнату-темплейт со всеми настройками и слоями а потом наследуешь от неё другие комнаты, заполняя объектами. Для вьюпорта лучше завести объект view_handler и сделать ему persistent, в событии "room start" (а лучше step) делать подгонку вьюпортов под экран/окно
У меня первый гамак, по каким-то причинам он стал для меня бесплатным, я так и не понял. То ли я давно в акцию какую-то попал, то ли GMS 1 бесплатный. Я не уверен. Но точно кряки никакие не юзал, мне и юнити хватало, а тут установил демку GMS1, и она оказывается бесплатная (хотя я вспомнил что давно заводил аккаунт гамака и на мой аккаунт тут оказывается есть лицензия, что странно), ну грех не пользоваться, раз дают)
Про 2.3 видел в твиттере, много фич перечисляют) может позже куплю вторую студию, если понравится первая, но пока всё нравится в целом, кроме того что надо на каждую комнату отдельно менять разрешение экрана)
Ну если тебе первая студия нравится, то вторую ты вообще полюбишь, т.к. там очень много фич сделано для белых людей. И с комнатами работать стало удобнее и слоии появились и редактор спрайтов стал пиздатый. В общем, много полезностей. Правда часть функций устарело и с камерой так себе работает.
Если захочешь проект с первой студии портировать то там проблем никаких не будет - он сам все полифилы создаст.
А что, в Юнити не так?
Плюс я тебе уже приводил скрипт которым можно задать вьюпорты автоматически. Ты если не пользуешься ответами на свои вопросы, зачем вообще спрашиваешь? Делай уже свой юнитевский проект или нормально на ГМ переключись, совмещать их нереально.
И насчёт "динамического окна" - никому в реальном мире эта фича не нужна кроме ленивых офисных работников. Люди платят за полноэкранные игры, а на консолях, как и на мобилках (а это уже большая часть рынка игр) окон нет вовсе. Если тебе нужны деньги, не занимайся ерундой. Хотя, думаю, тебе это уже очень много раз в жизни говорили, и мои слова тут по барабану.
Я хоть задавал вопросы, но пока сам не начну руками код вводить, то не смогу их запомнить,
сейчас полез в гейм мейкер уже кодить, и теперь некоторые вещи стали уже более понятнее,
но всё ещё есть и много вопросов.
Все ответы я скриню, чтоб потом можно было поднять инфу, но может где что потерял или запутался в своих скринах, ибо их уже не мало, пока практики не было, инфа сложно приживается, но теперь же уже первый код написал, какой никакой, концепцию начинаю понимать по тихой. Спасибо Ксит за ту инфу, всё равно много что пригодилось, хоть я и ещё тот разгильдяй и кое-что походу потерял. :3
Ну всё же мне кажется для Windows приложений это актуально, ведь во всех играх на Game Maker (на винде) делают дополнительные кнопки в опциях по увеличению размера экрана, множители: x2 x3 x4,
так зачем эти кнопки вообще, если можно просто сделать свободное окно и в зависимости от того как сильно его увеличил, такой множитель и получил, естественно в целых числах, чтоб были красивые пиксели, заодно и за пределами игрового окна не будет видно часть рабочего стола, потому-что окно будет растянуто на весь экран, хоть и в оконном режиме.
В целом согласен, что за переделами винды это не будет нужно, но на винде норм, мне нравится играть в маленькие инди игры и эмуляторы не в полноэкранном режиме.
Ни в одной моей игре этого нет, а в других это есть далеко не везде.
Моё дело тебе сказать, на чём ты можешь заработать, а не что тебе нравится. Это разные вещи.
Походу Views сохраняется для всех уровней, это хорошо, я просто вначале не понял, думал для каждого уровня отдельно надо менять цифры)
Всё, я наконец-то разобрался. Доделал полноценный автоматический множитель экрана в зависимости от размера окна. Просто вначале не учёл, что надо ещё отдельно нажимать галочку на включение Enable the use of Views, иначе всё разрешение окна зависело от разрешения уровня. Теперь можно и игру начать делать :3

Ещё одна странность с гейм мейкером или моей виндой (я хз), что у меня на винде, если включить полноэкранно игру, то будут другие цвета, в отличии от оконного режима.
Возможно монитор переключается на другой цветовой профиль, проверь его экранное меню когда в игре.
Пошёл гуглить, ибо не понял, что за цветовой профиль такой, у меня давно были подозрения что тут иногда на вторую гамму переключается, но раньше просто думал, что показалось
Не только в гамаке. Прринцип везде одинаковый. У тебя в целом не будет pixel-perfect если ты не собираешься делать х1-х2-х3
То что на каком-нибудь godot/unity ты не видишь - не значит что они у тебя прям perfect. Здесь кто-то выкладывал с годота пиксельарт и я показывал что там крупнопиксели разного размера то в 2х2 то 3х3, то 3х2.
Вообще если ты готов поизвращаться то нужно настройки gpu_ смотреть. Как минимум проверить чтоб интерполяция была в false.
P.S. Лично меня результат через surface не устроил
Да я понимаю, что надо обязательно кратно увеличивать!
Сейчас даже Pixelperfect наладился (использовал округление), хотя я не тестировал в нормальной игре,
может быть при динамике, это все сломается, или на другом мониторе, но на моём мониторе пока
всё красиво выглядит, и не надо париться с опциями в игре, где есть отдельные кнопки x2 x3 x4,
а просто окно как хочешь увеличиваешь, как на моих любимых эмуляторах или в Pico-8 и Tic-80.
Хотя может быть это не оптимизировано получилось, я ещё не особо знаю, как surface работают:
потестите плиз исходник ^_^'
С gpu_ я пока даже не знаком. Спасибо, посмотрю!
В gpu много опций полезных есть. В частности бывает альфа-канал подключивает у сурфэйсов. Если он не нужен -его можно вообще выключить при помощи функции gpu_set_colorwriteenable
А gpu_set_blendmode - это типа мини-версия шейдера - рисует спрайт со смещиванием.
Во, теперь работает хорошо:

осталось только понять, как автоматически во всех комнатах выставлять это значение,

а не вручную все уровни править
ЗЫ если честно, я запутался, из-за размеров комнаты меняется и то - будет ли pixel perfect или нет, а размер комнаты по идее не должен на это вообще влиять... Видимо придётся гуглить по части gpu
Есть функции room_set_width и room_set_height насколько я помню для изменения размеров комнаты.
А ещё есть вкладка views - это то что тебе нужно как раз. Тебе нужно поставить галку на том чтобы их использовать, и для нужного вида ставишь галку enable this view, далее ты указываешь размер вида в комнате width/height и размер вьюпорта - как раз x1,x2,x3 от того что тебе нужно
Есть функции для кода все аналогочние. Типа views_enabled, view_visible[0] ну и на размеры и порты в справке посмотри. Так же есть фунции для изменения размеров окна. Только там нюанс есть. Если меняешь размер вида (не вьюпорт, а именно размер) или размер окна - тебе нужно будет cсделать surface_resize(application_surface,<width>,<height>) по новым размерам. Почему-то по дефолту этого не происходит, причём даже в GMS2.
Спасибо!
Рисовать по целым координатам и масштабировать на целое число.
Либо использовать линейное сглаживание, но тогда забудь про четкие границы пикселей - появится хотя бы маленькое ощущение размытости картинки.
То есть надо корректировать координаты персонажей, объектов и камеры, чтобы у них не были плавающие числа (float)?
Хз как сделать, если например я хочу сделать плавный разгон и плавное торможение персонажа, там полюбому нужны плавающие координаты.
PS линейное сглаживание ужасно визуально, особенно для очень низких разрешений
Раньше, когда игры были на приставках, все спрайты рисовались по целым координатам и никто не жаловался. Как-то же делали. В Mario, например.
Понимаешь, ты не можешь нарисовать полпикселя. И 3/4 не можешь. Но такое возникает когда координаты границы спрайта не совпадают с границами пикселей уровня или когда общая рисуемая картинка не совпадает с границами пикселей монитора (например, масштабирование на нецелое число).
Когда такое происходит, движок должен решать что сделать:
- Нарисовать цвет ближайшего пикселя (метод ближайшего соседа)
- Нарисовать цвет средний между соседними пикселями (линейное сглаживание)
Чтобы такого не было - нужно устранить саму причину, а именно - использовать целые числа для координат спрайтов и масштаба игровой картинки (viewport).
Ну так координаты считай дробные (по сути ничего не меняй), а рисуй в округлённых. Я так делаю, например. И вид тоже в округлённых двигаю. У меня обычно есть центр вида, который я двигаю плавно, а саму каамеру (view) относительно центра (у неё это верхний левый угол) выставляю в округлённых. Там же кстати и тряску экрана можно сделать. Я обычно создаю отдельный объект, который отвечает за движение и тряску вида.
Получается для всех движущихся объектов нужно иметь дополнительные переменные (float), и всегда округлять реальные координаты на основе дополнительных. Жаль это нельзя автоматически сделать, человеческий фактор не всегда хорош, можно ошибиться или забыть, и не раз.
PS попробовал сейчас ради теста поставить координаты типа
x= 40.5;
y = 50.3;
и да, опять появились пилообразные моменты на пикселях объекта.
Просто в draw напиши округление.
Можешь использовать наследование - создай объект percise_draw и в событии рисования напиши draw_sprite_ext с округлёнными координатами и всё. Ничё хранить не нужно. А потом у тех объектов которые движутся - сделать parent-ом вот этот precise_draw. В GMS1 по сравнению с GMS2 наследование не очень удобно сделано, но пользоваться в целом можно. В GMS1 не отображаются события родителя, к сожалению и нет опций по inherit/override
Ещё один вопрос по Game Maker:
Можно ли запустить код/создать объект после старта игры, не ставя этот объект или код на сам уровень?
Я просто хочу тестировать в игре любой уровень (тот который в данный момент редактирую), а не только начиная с первого системного уровня. Да и на каждом уровне расставлять пустые объекты с системными скриптами как-то не очень хочется, могу запутаться где расставлял системные объекты, а где нет.
Хотя, придумал кое-какие костыли:
1) первый уровень сделать системным, где будут важные установки (и он автоматически перекидывает на следующий уровень)
2) а второй уровень будет тот который в данный момент редактирую (в финальной версии там будет главное меню)
ЗЫ правда придётся туда сюда постоянно двигать уровни
Так сделать - это абсолютно нормальная практика.
В первой комнате у меня обычно объект loader, который заводит глобальные переменные, читает настройки игры из файла, инициализирует подсистемы (частицы, свет и т.д.). И сразу переходит в следующую комнату.
Более того я в этой же комнате ставлю persistent объект resources_manager, и его смысл в том чтобы управлять некоторыми ресурсами во время всей игры. Например управление сурфейсами. Я ХЗ как сейчас с этим дела у GMS2, но в первой студии там точно проёбываются айдишники если сурфейс сдох. А дохнут сурфейсы часто, например свернул-развернул окно. ЧТобы их в правильно порядке пересоздать - вот такая штука. Так же в этом объекте я инициализирую и поддерживаю систему управления. Я делал набор скриптов для унификации управления(примерно как в юнити) - виртуальные клавиши, которые привязываются к клаве и геймпаду одновременно. В отличие от штатных функций геймпада у меня так же есть фунции на release для стиков, и gamepad_eny_key. Если нужно, могу поделиться кодом.
Переставлять комнаты местами во время тестирования - тоже нормальная практика.
А вообще есть событие Game Start. Вот только что в GMS2 посмотрел, так что за GMS1 ничё не могу сказать.