Screentendo – это приложение для настольных компьютеров, которое превращает выделенную область экрана в играбельный уровень для игры Super Mario Bros.
Я раньше не делал приложений для Cocoa app и не использовал Sprite Kit, и это стало для меня отличным упражнением. Исходный код доступен по ссылке.
Как это работает?
При запуске приложения появляется полупрозрачное окно, которое можно двигать и изменять его размер. После размещения окошка над какой-то областью экрана клик внутри него приведёт к тому, что приложение создаст уровень на базе контента, находящегося под ним.
У Screentendo есть два основных этапа работы: обработка картинки для определения структуры выбранного района, и создание уровня.
Обработка картинки
Первый шаг – получить выбранный район экрана под окном. Следующее описание – пример выбора графика внутри Google Sheets внутри Safari:
Приложение использует API CGWindowListCopyWindowInfo API (из Quartz Window Services) для получения списка окон в текущей сессии, в той последовательности, в которой они появляются на экране.
Из этого списка берутся данные окон (id, размеры, и т.п.) для окна Screentendo, и для следующего окна в иерархии (у нас это окно Safari).
Используя информацию об окне, CGWindowListCreateImage делает скриншот из Safari
Скриншот обрезается по границам окна Screentendo, используя разницу между окном Safari и окном Screentendo, и высоту и ширину окна Screentendo.
Screentendo находится над целевым окном (график в Google Sheets)
Обрезанная картинка
Обрезанная картинка проходит несколько фильтров, перед тем, как её сконвертируют в формат, который Screentendo может использовать для создания игрового уровня.
Motion blur – уменьшает общий шум и визуальные артефакты.
Luminance filter – вычисляется средний порог яркости изображения, и уменьшается до двух цветов.
Pixellation filter – фильтр пикселизации упрощает детализацию картинки и подготавливает её к разделению на подблоки.
Sub-blocking – картинка разбивается на подблоки, по умолчанию размером 10х10 пикселей.
Average block colour to array – для каждого подблока вычисляется средний цвет. Создаётся двумерный массив, и каждый подблок, примущественно состоящий из чёрного цвета, принимает значение 1, а каждый подблок преимущественно белого цвета, принимает значение 0.
Создание уровня и игровая логика
Представление картинки в виде двумерного массива передаётся в класс GameScene, создающий игровой уровень. Он проходит по массиву, и создаёт блоки из значений 1, игнорируя значения 0.
Спрайты блоков, облаков, фона и игрока
Когда массив обработан, к сцене добавляются фон, облака и игрок. Остаток игры основан на основных физических принципах, представленных в физическом движке Sprite Kit (физика игрока, обработка столкновений, анимация летящих остатков блоков, и т.п.).
У приложения есть меню для изменения размера блока. Уменьшение размеров увеличивает разрешение и время на обработку.
Ограничения
Приложение является доказательством концепции, и у него есть несколько недостатков. Обработка картинки пока происходит очень медленно, разбиение картинки на подблоки медленное (каждый подблок превращается в NSImage, что является не очень эффективным способом решения, но зато быстрым в реализации). Также требуется достаточно сильный контраст в цветах исходной картинки. Физика немного кривая – я не писал эмулятор Super Mario Bros, а просто нечто, что будет работать «достаточно хорошо». Поэтому иногда наблюдаются некие призрачные вершины, которые я пока не поборол.
Код доступен в репозитории github.
BubaVV
Зашел почитать о перекомпиляции образа нинтендовского картриджа, но обломался
stas404
Thank you Mario, but your princess is in another castle!
Yuuri
За что человека заминусовали? В первом же абзаце написано «в играбельный уровень для Super Mario Bros.», а это вполне конкретная игра. А в нынешнем виде статья с тем же успехом могла называться «Генерация ЧБ-изображений низкого разрешения на основе содержимого экрана».