Само голосование является отличной иллюстрацией того, почему A/B-тесты так важны.
Показывая иконку друзьям, обсуждая с дизайнерами и делая опросы, мы находим самую красивую иконку, ту, что эстетически нравится больше.
В таких обсуждениях можно услышать много доводов о том, что эта иконка лучше отражает суть игры или является более чистой и понятной. Все они, чаще всего, верны.
Но задача иконки привлечь пользователя в игру. И не просто абстрактного пользователя, а того, кому игра действительно понравится и он будет играть в нее дальше.
По итогу, перед нами стоит задача не эстетического плана, что является первой, рефлекторной оценкой любого графического изображения, что попадается нам на глаза.
Это задача, скорее, ближе к поведенческой психологии с очень хорошим знанием своей целевой аудитории. Специалистом в этой области я точно не являюсь и, честно говоря, я не знаю людей способных предугадать 3 из 3 результатов A/B тестов. Но это и не нужно именно благодаря тому, что этот инструмент у нас есть, нужно просто не забывать им пользоваться.
Показывая иконку друзьям, обсуждая с дизайнерами и делая опросы, мы находим самую красивую иконку, ту, что эстетически нравится больше.
В таких обсуждениях можно услышать много доводов о том, что эта иконка лучше отражает суть игры или является более чистой и понятной. Все они, чаще всего, верны.
Но задача иконки привлечь пользователя в игру. И не просто абстрактного пользователя, а того, кому игра действительно понравится и он будет играть в нее дальше.
По итогу, перед нами стоит задача не эстетического плана, что является первой, рефлекторной оценкой любого графического изображения, что попадается нам на глаза.
Это задача, скорее, ближе к поведенческой психологии с очень хорошим знанием своей целевой аудитории. Специалистом в этой области я точно не являюсь и, честно говоря, я не знаю людей способных предугадать 3 из 3 результатов A/B тестов. Но это и не нужно именно благодаря тому, что этот инструмент у нас есть, нужно просто не забывать им пользоваться.
Иконка №3 - это первая версия иконки. Она, конечно, не идеальна, но отражала суть игры, на момент ее выхода.
Иконка №1 - это результат большого количества итераций и обсуждений. Все четко и выверено. У нас было много доводов, почему она намного лучше, чем текущая.
Иконку №2 мы решили добавить в последний момент, т.к. мы заметили, что в Google Play можно задать больше двух иконок для A/B теста - почему бы не проверить, как это работает. Сделана она за 5 минут без каких-либо заморочек и обсуждений. Просто филлер.
Как можно догадаться из моего описания выше, именно иконка №2 победила с большим отрывом. Причем отрыв был более чем в 2 раза как для First-time installers, так и по Retained installers 1st day.
Вывод, что мы для себя сделали.
Не всегда стоит безоговорочно доверять своей "чуйке" или чувству вкуса.
Иногда стоит проверять даже самые странные варианты и не быть такими увереннымы в себе, лишний раз подвергая сомнению свои знания.
Иконка №1 - это результат большого количества итераций и обсуждений. Все четко и выверено. У нас было много доводов, почему она намного лучше, чем текущая.
Иконку №2 мы решили добавить в последний момент, т.к. мы заметили, что в Google Play можно задать больше двух иконок для A/B теста - почему бы не проверить, как это работает. Сделана она за 5 минут без каких-либо заморочек и обсуждений. Просто филлер.
Как можно догадаться из моего описания выше, именно иконка №2 победила с большим отрывом. Причем отрыв был более чем в 2 раза как для First-time installers, так и по Retained installers 1st day.
Вывод, что мы для себя сделали.
Не всегда стоит безоговорочно доверять своей "чуйке" или чувству вкуса.
Иногда стоит проверять даже самые странные варианты и не быть такими увереннымы в себе, лишний раз подвергая сомнению свои знания.
Немножко поною, но надеюсь кому-то это будет полезно и своевременно.
Сегодня получил письмо от Google Play, суть которого:
...
Your app contains content that doesn't comply with the User Ratings, Reviews, and Installs policy.
...
App status: Removed
...
Что же такого страшного мы натворили?
Прежде чем раскрыть причину, давайте в паре слов расскажу про само приложение.
Итак, у нас полностью бесплатная игра по классической механике.
Полностью бесплатная - знаичт ПОЛНОСТЬЮ бесплатная =) т.е. никаких платежей и никакой рекламы.
- 2.2M+ установок.
- 300k+ активных установок
- рейтинг 4.5+
- Очень маленький билд: 1.6 Mb
- Игра даже не запрашивает permission на доступ в интернет, а значит не собирает никаких данных совсем.
Еще важно упомянуть, что мы обновляем эту игру очень редко. Последнее обновление было Jul 30, 2020.
Но люди любят нашу версию т.к. она очень маленькая, действительно бесплатная и не высасывает батарею как большинство игр.
Итак, что же случилось.
А случилось “злостное” нарушение правил: слово "free" в названии приложения.
За то время, что мы не обновляли приложение, правила изменились и теперь это нарушение правил.
И казалось бы, ну дайте предупреждение с дедлайном на исправление? Нет! Лови удаление до исправления.
Причем исправление - это дело трех минут, а пройти модерацию дней 7.
Если у вас есть игра на Google Play, то обязательно прочитайте эту страницу очень внимательно.
А еще можно подержать меня в twi лайком и/или ретвитом, вдруг это кому-то поможет избежать проблем:
https://twitter.com/AGulev/status/1488595290395451393
UPD: happy(?)end этой истории в комментариях к записи.
Сегодня получил письмо от Google Play, суть которого:
...
Your app contains content that doesn't comply with the User Ratings, Reviews, and Installs policy.
...
App status: Removed
...
Что же такого страшного мы натворили?
Прежде чем раскрыть причину, давайте в паре слов расскажу про само приложение.
Итак, у нас полностью бесплатная игра по классической механике.
Полностью бесплатная - знаичт ПОЛНОСТЬЮ бесплатная =) т.е. никаких платежей и никакой рекламы.
- 2.2M+ установок.
- 300k+ активных установок
- рейтинг 4.5+
- Очень маленький билд: 1.6 Mb
- Игра даже не запрашивает permission на доступ в интернет, а значит не собирает никаких данных совсем.
Еще важно упомянуть, что мы обновляем эту игру очень редко. Последнее обновление было Jul 30, 2020.
Но люди любят нашу версию т.к. она очень маленькая, действительно бесплатная и не высасывает батарею как большинство игр.
Итак, что же случилось.
А случилось “злостное” нарушение правил: слово "free" в названии приложения.
За то время, что мы не обновляли приложение, правила изменились и теперь это нарушение правил.
И казалось бы, ну дайте предупреждение с дедлайном на исправление? Нет! Лови удаление до исправления.
Причем исправление - это дело трех минут, а пройти модерацию дней 7.
Если у вас есть игра на Google Play, то обязательно прочитайте эту страницу очень внимательно.
А еще можно подержать меня в twi лайком и/или ретвитом, вдруг это кому-то поможет избежать проблем:
https://twitter.com/AGulev/status/1488595290395451393
UPD: happy(?)end этой истории в комментариях к записи.
Опытным разработчикам пояснять не нужно, что нет смысла смотреть eCPM когда у тебя довольно маленькое количество показов.
Но вот среди начинающих, я часто вижу попытки сравнивать или пытаться рассчитывать потенциальный доход, исходя из eCPM на 500-1000 показов в сутки.
Вот 2 показательных графика.
На первом графике eCPM на платформе Яндекс, где игра перенесена на другой аккаунт и очень наглядно видно, как количество показов падает (зеленый), а eCPM стремится ввысь(желтый).
На втором скриншот из AdMob. Игра тоже переехала на другой аккаунт и некоторая часть игроков все еще обновляется. Видно как просмотры падают. При этом могут случаться вот такие аномалии, из которых никакие выводы делать точно не стоит.
Но вот среди начинающих, я часто вижу попытки сравнивать или пытаться рассчитывать потенциальный доход, исходя из eCPM на 500-1000 показов в сутки.
Вот 2 показательных графика.
На первом графике eCPM на платформе Яндекс, где игра перенесена на другой аккаунт и очень наглядно видно, как количество показов падает (зеленый), а eCPM стремится ввысь(желтый).
На втором скриншот из AdMob. Игра тоже переехала на другой аккаунт и некоторая часть игроков все еще обновляется. Видно как просмотры падают. При этом могут случаться вот такие аномалии, из которых никакие выводы делать точно не стоит.
В чате возник вопрос: "А как понять тяжелый шейдер или нет?".
Давайте попробуем разобраться.
Для начала нужно понять, сколько примерно циклов займет исполнение шейдера.
Для этого берем оффлайн компилятор шейдеров (чаще всего это Mali offline compiler) и “скармливаем” ему наш шейдер. Обычно, у движков есть модуль или ассет, который упрощает этот процесс. Как например у Defold это вот такой скрипт для редактора.
Увидели чиселки из которых ничего не ясно? Это нормально, так и должно быть. Желательно пойти в этот раздел документации и внимательно прочитать, что это за чиселки.
Теперь важно понять, что эти значение не абсолютные, на разных GPU будут разные наборы инструкций и оптимизации, а так же версии компилятора, что влияет на конечное значение. Именно поэтому модель GPU задается параметром к офлайн компилятору.
Кроме того, у шейдера могут быть ветвления логики, а значит будет некий очень оптимальный путь, где операций минимум и самый неоптимальный, где всё наоборот.
К чему я это всё? К тому, что это не абсолютные значения высеченные в камне, а относительные, которые удобнее сравнивать между собой, а не рассчитывать, что так оно и будет на каждом устройстве, на которым вы запускаете игру.
Ну вот мы знаем некое условное количество циклов, которое нужно для исполнения нашего фрагментного (пиксельного) шейдера. А дальше то что? Как понять много это или мало?
Давайте посчитаем условный максимум который можно выжать с вашего мобильного GPU.
Допустим, что ваше минимальное целевое устройство это телефон с Adreno 330 на борту и экраном 1920 на 1080 точек.
Пусть это будет хороший Adreno 330 на хорошем чипсете у которого частота 578 Mhz (а не его хилый родственник с 450 MHz).
Мы помним, что MHz - это частота в секунду, поэтому на кадр у нас 578/60 ~ 9,33 Mhz, что примерно 9,33 * 1 000 000 = 9 330 000 Hz (циклов) на кадр.
Это много? Как бы не так.
Размер экране 1920 * 1080 = 2 073 600 пикселей.
т.е. если картинку размером с экран прогонять через наш фрагментный шейдер исполнение которого требует 1 цикл, то сделать мы это сможем 9 330 000 / 2 073 600 ~ 4.5 раза.
Или в идеальных условиях, без учета вертекс шейдера и других нюансов о которых можно прочитать по ссылке выше, можно иметь 4.5 цикла в пиксель шейдере на каждый пиксель экрана.
А теперь смотрим на то, что нам выдал оффлайн компилятор и сравниваем с расчетами. Например мы видим там 4, а мы насчитали 4.5, так что будет 60 FPS и все отлично? Конечно нет, я же говорил, что это прикидка.
Есть много нюансов, к примеру:
- выводиться на экран может значительно больше пикселей, т.к. что-то может выходить за пределы камеры и все равно рендериться;
- где-то могут быть перекрытия и в один и тот же пиксель на экране отрендериться несколько пикселей перекрывая друг-друга;
- а еще мобильный GPU не может работать на пиковой мощности долго и начнет снижать напряжение чтобы остыть, если его сильно нагружать. Поэтому всегда должен быть задел на бездействие GPU, чтобы было время “перекурить” между кадрами;
- а есть же еще вертексный шейдер…
и еще огромное количество нюансов.
Но и в обратную сторону, это тоже работает. Ведь не обязательно графику отрисовывать пиксель в пиксель с разрешением экрана, а можно брать например 0.75 от размера экрана и получившийся результат растягивать и т.д и т.п.
Давайте попробуем разобраться.
Для начала нужно понять, сколько примерно циклов займет исполнение шейдера.
Для этого берем оффлайн компилятор шейдеров (чаще всего это Mali offline compiler) и “скармливаем” ему наш шейдер. Обычно, у движков есть модуль или ассет, который упрощает этот процесс. Как например у Defold это вот такой скрипт для редактора.
Увидели чиселки из которых ничего не ясно? Это нормально, так и должно быть. Желательно пойти в этот раздел документации и внимательно прочитать, что это за чиселки.
Теперь важно понять, что эти значение не абсолютные, на разных GPU будут разные наборы инструкций и оптимизации, а так же версии компилятора, что влияет на конечное значение. Именно поэтому модель GPU задается параметром к офлайн компилятору.
Кроме того, у шейдера могут быть ветвления логики, а значит будет некий очень оптимальный путь, где операций минимум и самый неоптимальный, где всё наоборот.
К чему я это всё? К тому, что это не абсолютные значения высеченные в камне, а относительные, которые удобнее сравнивать между собой, а не рассчитывать, что так оно и будет на каждом устройстве, на которым вы запускаете игру.
Ну вот мы знаем некое условное количество циклов, которое нужно для исполнения нашего фрагментного (пиксельного) шейдера. А дальше то что? Как понять много это или мало?
Давайте посчитаем условный максимум который можно выжать с вашего мобильного GPU.
Допустим, что ваше минимальное целевое устройство это телефон с Adreno 330 на борту и экраном 1920 на 1080 точек.
Пусть это будет хороший Adreno 330 на хорошем чипсете у которого частота 578 Mhz (а не его хилый родственник с 450 MHz).
Мы помним, что MHz - это частота в секунду, поэтому на кадр у нас 578/60 ~ 9,33 Mhz, что примерно 9,33 * 1 000 000 = 9 330 000 Hz (циклов) на кадр.
Это много? Как бы не так.
Размер экране 1920 * 1080 = 2 073 600 пикселей.
т.е. если картинку размером с экран прогонять через наш фрагментный шейдер исполнение которого требует 1 цикл, то сделать мы это сможем 9 330 000 / 2 073 600 ~ 4.5 раза.
Или в идеальных условиях, без учета вертекс шейдера и других нюансов о которых можно прочитать по ссылке выше, можно иметь 4.5 цикла в пиксель шейдере на каждый пиксель экрана.
А теперь смотрим на то, что нам выдал оффлайн компилятор и сравниваем с расчетами. Например мы видим там 4, а мы насчитали 4.5, так что будет 60 FPS и все отлично? Конечно нет, я же говорил, что это прикидка.
Есть много нюансов, к примеру:
- выводиться на экран может значительно больше пикселей, т.к. что-то может выходить за пределы камеры и все равно рендериться;
- где-то могут быть перекрытия и в один и тот же пиксель на экране отрендериться несколько пикселей перекрывая друг-друга;
- а еще мобильный GPU не может работать на пиковой мощности долго и начнет снижать напряжение чтобы остыть, если его сильно нагружать. Поэтому всегда должен быть задел на бездействие GPU, чтобы было время “перекурить” между кадрами;
- а есть же еще вертексный шейдер…
и еще огромное количество нюансов.
Но и в обратную сторону, это тоже работает. Ведь не обязательно графику отрисовывать пиксель в пиксель с разрешением экрана, а можно брать например 0.75 от размера экрана и получившийся результат растягивать и т.д и т.п.
Так а зачем это всё тогда?
В целом, это исключительно теоретическое упражнение, чтобы понимать, что вы делаете и зачем. Подогнать ваши шейдеры цикл в цикл с производительностью GPU и рассчитать, что у вас будет 60 FPS, не выйдет. Зато можно понимать относительную “тяжесть” шейдера с развитием проекта или изменения в результате оптимизаций. Думать над тем, какие рендер фичи сделать опциональными, а какие по умолчанию и т.д.
Оптимизация производительности, это всегда про баланс.
Вот увидели вы, что расчет какого-либо параметра для рендера тяжелый и нагружает GPU. И, допустим, запекли все результаты расчетов в текстуру, которую передаете в шейдер. После этого обнаружили проблемы с memory bandwidth от того, что стали передавать на GPU больше данных. ОООок, выбрали какой-либо формат GPU компрессии, чтобы уменьшить размер передаваемых данных. Но теперь подрос размер билда т.к. до этого вы использовали png, которые почти не занимали места и т.д.
Вопрос всегда только в том, какой компромисс вас устраивает, его всегда придется искать.
Именно поэтому, учитывая мобильность устройства, такое балансирование, на больших проектах, принято начинать от количества энергии которое считается нормальным для целевого SoC, Но это уже совсем другая история…
В целом, это исключительно теоретическое упражнение, чтобы понимать, что вы делаете и зачем. Подогнать ваши шейдеры цикл в цикл с производительностью GPU и рассчитать, что у вас будет 60 FPS, не выйдет. Зато можно понимать относительную “тяжесть” шейдера с развитием проекта или изменения в результате оптимизаций. Думать над тем, какие рендер фичи сделать опциональными, а какие по умолчанию и т.д.
Оптимизация производительности, это всегда про баланс.
Вот увидели вы, что расчет какого-либо параметра для рендера тяжелый и нагружает GPU. И, допустим, запекли все результаты расчетов в текстуру, которую передаете в шейдер. После этого обнаружили проблемы с memory bandwidth от того, что стали передавать на GPU больше данных. ОООок, выбрали какой-либо формат GPU компрессии, чтобы уменьшить размер передаваемых данных. Но теперь подрос размер билда т.к. до этого вы использовали png, которые почти не занимали места и т.д.
Вопрос всегда только в том, какой компромисс вас устраивает, его всегда придется искать.
Именно поэтому, учитывая мобильность устройства, такое балансирование, на больших проектах, принято начинать от количества энергии которое считается нормальным для целевого SoC, Но это уже совсем другая история…
Давайте опять про рекламу, ради разнообразия (в следующий раз обещаю опять техническую тему ;) ).
Есть ли смысл от межстраничной рекламы, если ее почти всегда пропускают и редко по ней кликают?
Рекламные сети учитывают, что пропуск рекламы - обычное поведение. Можно сказать, что сеть собирает статистику и примерно "знает" как часто кликают на рекламу и как часто её пропускают(все сложнее, но для простоты пусть так).
Например, если кликов значительно больше чем обычно или пропусков значительно меньше чем обычно, то такие источники трафика проверяются дополнительно, чтобы не допустить недобросовестных разработчиков, когда банер вставлен неправильно и пользователь кликает на него случайно или как-то хакнут, чтобы крестик не появлялся и т.п. То есть предпринимаются меры по поиску некачественных источников трафика.
Рекламу за вознаграждение игрок смотрит всегда, если она запустилась, да, но он и запускается реже т.к. игрок взвешивает, а так ли хороша награда, нужна ли она ему сейчас и т.д.
Поэтому я бы сказал так, что дешевизна межстраничной рекламы компенсируется количеством показов.
Выглядит это обычно примерно так, как на скриншоте. Одна и та же игра, на одной и той же платформе.
Важно сказать, что реклама в игре настроена так, что межстраничка показывается не всегда, а где-то каждый 3й вызов (есть несколько точек вызова). И если игрок смотрит рекламу с наградой этот счетчик отматывается т.е. если игрок часто смотрит рекламу с наградой, он может не увидеть межстраничную рекламу совсем.
Это логика сделана, чтобы не надоедать игроку и не было ситуаций, когда игрок пострел одну рекламу за награду, сделал клик и ему тут же показывается другая, уже межстраничная
К примеру: попап победы, на нем можно удвоить очки, игрок смотрит, удваивает. Затем нажимает кнопку перехода к следующему уровню, а там опять реклама, но уже межстраничная на начало уровня.
Такие недоработки - это прямой путь нахватать плохих отзывов.
Есть ли смысл от межстраничной рекламы, если ее почти всегда пропускают и редко по ней кликают?
Рекламные сети учитывают, что пропуск рекламы - обычное поведение. Можно сказать, что сеть собирает статистику и примерно "знает" как часто кликают на рекламу и как часто её пропускают(все сложнее, но для простоты пусть так).
Например, если кликов значительно больше чем обычно или пропусков значительно меньше чем обычно, то такие источники трафика проверяются дополнительно, чтобы не допустить недобросовестных разработчиков, когда банер вставлен неправильно и пользователь кликает на него случайно или как-то хакнут, чтобы крестик не появлялся и т.п. То есть предпринимаются меры по поиску некачественных источников трафика.
Рекламу за вознаграждение игрок смотрит всегда, если она запустилась, да, но он и запускается реже т.к. игрок взвешивает, а так ли хороша награда, нужна ли она ему сейчас и т.д.
Поэтому я бы сказал так, что дешевизна межстраничной рекламы компенсируется количеством показов.
Выглядит это обычно примерно так, как на скриншоте. Одна и та же игра, на одной и той же платформе.
Важно сказать, что реклама в игре настроена так, что межстраничка показывается не всегда, а где-то каждый 3й вызов (есть несколько точек вызова). И если игрок смотрит рекламу с наградой этот счетчик отматывается т.е. если игрок часто смотрит рекламу с наградой, он может не увидеть межстраничную рекламу совсем.
Это логика сделана, чтобы не надоедать игроку и не было ситуаций, когда игрок пострел одну рекламу за награду, сделал клик и ему тут же показывается другая, уже межстраничная
К примеру: попап победы, на нем можно удвоить очки, игрок смотрит, удваивает. Затем нажимает кнопку перехода к следующему уровню, а там опять реклама, но уже межстраничная на начало уровня.
Такие недоработки - это прямой путь нахватать плохих отзывов.
Пообещал, что следующий пост будет технический и пропал. Молодец, слов нет.
Давайте немного расскажу про байтики. Бородатым программистам это будет неинтересно.
Сколько бит нужно, чтобы сохранить информацию о трансформации тайла в тайловой карте?
Если вы любите прочитать истории как изгалялись разработчики игр на Famicom, чтобы сделать "красиво", то вы знаете что нам нужен как минимум:
- 1 бит для того, чтобы знать есть ли отражение по вертикале;
- 1 бит для того, чтобы знать отражен ли тайл по горизонтали;
- чего на Famicom не было, так это поворота тайла и нам достаточно 1 бита, чтобы знать повернут тайл на 90 градусов или нет.
А как же 180°, 270° и вот это вот всё. На самом деле если подумать и условиться, что сначала применяется отражение, а затем поворот, то этих данных достаточно для всех возможных вариаций. Высчитать это просто: всего у нас 4 возможных поворота в каждом из которых тайл может быть отражен т.е. 2 * 4 = 8. Мы знаем что один бит это 1 или 0 (т.е. хранит 2 состояния). Каждый следующий бит увеличивает квадратично количество информации, которое мы можем хранить (да-да, квадратично, нельзя просто разделить 8 на 2). Собственно 2*2*2 = 8 наших состояний. Ой, да вы и сами в двоичной системе разбираетесь, что я в самом деле.
Можно, конечно, применить и другую схему: 90°, 180°, горизонтальное отражение. Но тогда нам придется поменять порядок применения трансформации. Сначала применять поворот, а затем flip.
Итого, вся информация от трансформации помещается в 3 байта, что в Defold например,
К чему я это всё. Человеку в своей голове проще, когда действий меньше. Представить конечный результат того, что ты тайл поворачиваешь, а затем отражаешь куда проще, чем применить два отражения и затем поворот по необходимости.
Второй нюанс состоит в том, что в Lua битовых операторов нет, а битовые операции делаются через
Как же это сделать дружелюбно и для того, как это себе представляет пользователь (поворот + отражение) и для записи в коде?
При этом конечный результат должен быть битовой маской использующей 2 отражения и поворот 90°.
Давайте для себя запишем таблицу соответствия всех наших состояний используя повороты и оба отражения:
Мы знаем что H = 1(001), V = 2 (010), R_90 = 4 (100)
Это никак не система уравнений, но можно заметить, что значение отражено т.е. в уравнении не хватает модуля.
А это значит использование отрицательных значений констант для R_180 и R_270, -3 и -7 соответственно.
Что это дает? Из скрипта пользователь записывает трансформацию тайла как сумму поворота и отражений без необходимости использовать битовые маски, например:
А на стороне движка мы получаем маску используя только одну операцию модуль.
Так, а зачем маска?
Используя маску очень легко заполнять вертекс буфер просто итерируя по-небольшому массиву с шагом bitmask * 6, посмотреть на это можно тут.
На следующий пост ничего обещать не буду, так выше шансы, что что-то расскажу.
Давайте немного расскажу про байтики. Бородатым программистам это будет неинтересно.
Сколько бит нужно, чтобы сохранить информацию о трансформации тайла в тайловой карте?
Если вы любите прочитать истории как изгалялись разработчики игр на Famicom, чтобы сделать "красиво", то вы знаете что нам нужен как минимум:
- 1 бит для того, чтобы знать есть ли отражение по вертикале;
- 1 бит для того, чтобы знать отражен ли тайл по горизонтали;
- чего на Famicom не было, так это поворота тайла и нам достаточно 1 бита, чтобы знать повернут тайл на 90 градусов или нет.
А как же 180°, 270° и вот это вот всё. На самом деле если подумать и условиться, что сначала применяется отражение, а затем поворот, то этих данных достаточно для всех возможных вариаций. Высчитать это просто: всего у нас 4 возможных поворота в каждом из которых тайл может быть отражен т.е. 2 * 4 = 8. Мы знаем что один бит это 1 или 0 (т.е. хранит 2 состояния). Каждый следующий бит увеличивает квадратично количество информации, которое мы можем хранить (да-да, квадратично, нельзя просто разделить 8 на 2). Собственно 2*2*2 = 8 наших состояний. Ой, да вы и сами в двоичной системе разбираетесь, что я в самом деле.
Можно, конечно, применить и другую схему: 90°, 180°, горизонтальное отражение. Но тогда нам придется поменять порядок применения трансформации. Сначала применять поворот, а затем flip.
Итого, вся информация от трансформации помещается в 3 байта, что в Defold например,
uint8_t
(аж целых 5 байт остается про запас).К чему я это всё. Человеку в своей голове проще, когда действий меньше. Представить конечный результат того, что ты тайл поворачиваешь, а затем отражаешь куда проще, чем применить два отражения и затем поворот по необходимости.
Второй нюанс состоит в том, что в Lua битовых операторов нет, а битовые операции делаются через
bit
модуль: bit.band(0x12345678, 0xff)
. Это не супер удобно. Да и в целом битовые операции не всем и всегда интуитивно понятны.Как же это сделать дружелюбно и для того, как это себе представляет пользователь (поворот + отражение) и для записи в коде?
При этом конечный результат должен быть битовой маской использующей 2 отражения и поворот 90°.
Давайте для себя запишем таблицу соответствия всех наших состояний используя повороты и оба отражения:
R_0 = R_180 + H + V (0 в двоичной системе 000)
H = R_180 + V (1 в двоичной системе 001)
V = R_180 + H (2 в двоичной системе 010)
V + H = R_180 (3 в двоичной системе 011)
R_90 = R_270 + H + V (4 в двоичной системе 100)
H + R_90 = R_270 + V (5 в двоичной системе 101)
V + R_90 = R_270 + H (6 в двоичной системе 110)
V + H + R_90 = R_270 (7 в двоичной системе 111)
Мы знаем что H = 1(001), V = 2 (010), R_90 = 4 (100)
0 = R_180 + 3
1 = R_180 + 2
2 = R_180 + 1
3 = R_180
4 = R_270 + 3
5 = R_270 + 2
6 = R_270 + 1
7 = R_270
Это никак не система уравнений, но можно заметить, что значение отражено т.е. в уравнении не хватает модуля.
А это значит использование отрицательных значений констант для R_180 и R_270, -3 и -7 соответственно.
Что это дает? Из скрипта пользователь записывает трансформацию тайла как сумму поворота и отражений без необходимости использовать битовые маски, например:
H_FLIP + ROTATE_90
V_FLIP + ROTATE_270
ROTATE_180
А на стороне движка мы получаем маску используя только одну операцию модуль.
Так, а зачем маска?
Используя маску очень легко заполнять вертекс буфер просто итерируя по-небольшому массиву с шагом bitmask * 6, посмотреть на это можно тут.
На следующий пост ничего обещать не буду, так выше шансы, что что-то расскажу.
GitHub
defold/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp at e5eaa0c0dd1c087b81e8f63a86596636502605b8 · defold/defold
Defold is a completely free to use game engine for development of desktop, mobile and web games. - defold/defold
У меня просто крутиться в голове одна мысль, от которой я не могу отделаться. Она про LLM модели.
ChatGPT - это довольно общая модель и довольно требовательная к железу. Конечно технология и хайп вокруг нее летят к пику и сейчас на это пофиг. Но пофиг перестанет быть довольно скоро и следующим шагом будет “как скейлить” или “как удешевить”. Кроме того со скейлом сети, появляется больше проблем с модерацией и ограничениями, чтобы не давать пользователям делать фигню, на это тоже нужны ресурсы.
Мне кажется, что одним из оптимальных решений дать моделям специализацию.
OpenAI идет по пути плагинов через доп промпты, это то, что они продают: ты им платишь за количество токенов в промпте т.е. будет логично давать тебе возможность расширять функционал добавляя возможность быстро и просто добавлять в промпты большие объемы данных (в качестве контекста запроса). И тогда ты получаешь специфический функционал за счет больших вложений средств.
Я же думаю о специализации за счет добучения, подход при котором общая модель это бекенд, дающий базовые правила взаимодействия и т д
А верхний слой это то, чему ты сеть дообучил для своих задач
собственно, как и с SD, когда ты дообучаешь модель на своих артах.
Это поможет решить и проблемы “цензуры” т.к. если сеть специализирована, то определить “не релевантный” запрос куда проще. А так же поможет и с требованиями к железу, ведь сеть уже будет в контексте интересующей тебя темы т.к. до обучена на нужных именно для этой конкретной задачи материалах.
Пока я вижу эксперименты с этим с llama, как, например, вот этот репозиторий: https://github.com/bublint/ue5-llama-lora
Что думаете? Долетим на волне текущего хайпа прямиком к сильному AI или всё-таки пойдем на очередную итерацию, с оптимизацией и более вдумчивой утилизацией того, что уже есть?
ChatGPT - это довольно общая модель и довольно требовательная к железу. Конечно технология и хайп вокруг нее летят к пику и сейчас на это пофиг. Но пофиг перестанет быть довольно скоро и следующим шагом будет “как скейлить” или “как удешевить”. Кроме того со скейлом сети, появляется больше проблем с модерацией и ограничениями, чтобы не давать пользователям делать фигню, на это тоже нужны ресурсы.
Мне кажется, что одним из оптимальных решений дать моделям специализацию.
OpenAI идет по пути плагинов через доп промпты, это то, что они продают: ты им платишь за количество токенов в промпте т.е. будет логично давать тебе возможность расширять функционал добавляя возможность быстро и просто добавлять в промпты большие объемы данных (в качестве контекста запроса). И тогда ты получаешь специфический функционал за счет больших вложений средств.
Я же думаю о специализации за счет добучения, подход при котором общая модель это бекенд, дающий базовые правила взаимодействия и т д
А верхний слой это то, чему ты сеть дообучил для своих задач
собственно, как и с SD, когда ты дообучаешь модель на своих артах.
Это поможет решить и проблемы “цензуры” т.к. если сеть специализирована, то определить “не релевантный” запрос куда проще. А так же поможет и с требованиями к железу, ведь сеть уже будет в контексте интересующей тебя темы т.к. до обучена на нужных именно для этой конкретной задачи материалах.
Пока я вижу эксперименты с этим с llama, как, например, вот этот репозиторий: https://github.com/bublint/ue5-llama-lora
Что думаете? Долетим на волне текущего хайпа прямиком к сильному AI или всё-таки пойдем на очередную итерацию, с оптимизацией и более вдумчивой утилизацией того, что уже есть?
GitHub
GitHub - bublint/ue5-llama-lora: A proof-of-concept project that showcases the potential for using small, locally trainable LLMs…
A proof-of-concept project that showcases the potential for using small, locally trainable LLMs to create next-generation documentation tools. - bublint/ue5-llama-lora
В чате Defold обещал поделиться есть ли смысл тратить время на поддержку портретного режима в игре разработанной для альбомного режима на Poki.
Для тех кто не в курсе стоит отметить, что на Poki на мобильных устройствах банеры показывюатся только в портретном режиме, поэтому добавление такой поддержки имеет вполне измеримые финансовые результаты.
Вводные такие:
- Казуальная игра, где-то 40-50% аудитории используют мобильные устройства (телефоны и планшеты);
- Время в игре на игрока ~ 14 min;
- Игра сделана давно и много где не использовались gui компоненты и т.д. поэтому добавление нормальной поддержки портретного режима и тестирование заняло примерно 13 часов.
Результат за 5 дней с выхода версии где добавлен портреный режим:
- Вовлеченность +4.5%;
- Доходы +9.5%;
- Количество показываемых банеров выросло в 3 раза (до этого портретный режим не блокировался, люди могли играть в нем, но всё было мелким и неудобным).
Стоит оно того или нет, решайте для себя сами.
В новых играх мы делаем поддержку портретного режима изначально и это почти ничего нам не стоит.
Старые игры, где добавлиние такой поддержки можно сделать быстро и просто - я, скорее всего, буду дорабатывать. Но те игры на которые нужно больше 10 часов рабочего времени - оставлю как есть.
Для тех кто не в курсе стоит отметить, что на Poki на мобильных устройствах банеры показывюатся только в портретном режиме, поэтому добавление такой поддержки имеет вполне измеримые финансовые результаты.
Вводные такие:
- Казуальная игра, где-то 40-50% аудитории используют мобильные устройства (телефоны и планшеты);
- Время в игре на игрока ~ 14 min;
- Игра сделана давно и много где не использовались gui компоненты и т.д. поэтому добавление нормальной поддержки портретного режима и тестирование заняло примерно 13 часов.
Результат за 5 дней с выхода версии где добавлен портреный режим:
- Вовлеченность +4.5%;
- Доходы +9.5%;
- Количество показываемых банеров выросло в 3 раза (до этого портретный режим не блокировался, люди могли играть в нем, но всё было мелким и неудобным).
Стоит оно того или нет, решайте для себя сами.
В новых играх мы делаем поддержку портретного режима изначально и это почти ничего нам не стоит.
Старые игры, где добавлиние такой поддержки можно сделать быстро и просто - я, скорее всего, буду дорабатывать. Но те игры на которые нужно больше 10 часов рабочего времени - оставлю как есть.
This media is not supported in your browser
VIEW IN TELEGRAM
Друг поделился забавной гифкой.
Я с физическими движками не очень дружу, но быстренько собрал похожую демку на Defold.
HTML5 демка (если браузер не даст фокус канвасу - может тормозить, нужно кликнуть/тапнуть по черному экрану сразу после загрузки)
Код
Я с физическими движками не очень дружу, но быстренько собрал похожую демку на Defold.
HTML5 демка (если браузер не даст фокус канвасу - может тормозить, нужно кликнуть/тапнуть по черному экрану сразу после загрузки)
Код
Мое личное мнение о площадках для web(html5) игр, но ТОЛЬКО с рекламной монетизацией.
Универсальным для всех платформ будут следующие советы:
* поиграть в игры на платформе и попытаться составить свое понимание качества и уровня полировки проектов на платформе;
* понять жанры и какая у платформы аудитория (может быть максимально широкая, но не факт);
* всегда плюс, если есть возможность где-то познакомиться с представителями платформы и пообщаться про вашу игру (например, на конфах или митапах, иногда проходят онлайн).
Теперь немного о платформах.
* Если есть опыт создания игр под вэб и понимание, что такое качественная отполированная игра, то лучше идти на #poki. Это одна из лучших вэб платформ на сегодняшний день. Классные инструменты и команда, НО ручной отбор игр. Это значит, что с любой случайной игрой или не достаточно отполированной или не достаточно веселой игрой туда попасть будет сложно. Не получится прийти туда с игрой вида “я сделалъ”. Еще вариант туда идти если у вас есть мобильный хит и вы хотите попытаться выйти в web. Можно собрать web сборку и закинуть, проконсультироваться и договориться, что и как. Всегда есть вариант, что предложат протестировать как есть или помочь найти кого-то на портирование игры под вэб. Но опять же, игра должна быть клевой и уже хорошо себя показать. Кроме того площадка предпочитает эксклюзивные игры т.е. игры не должны быть опубликованы где-то еще.
* Если опыта мало или нет, но в вэб хочется или по каким-то причинам у вас не получается с poki (не берут игру или не можете работать с европейской компанией). Лучше пойти на Яндекс Игры. Они берут почти всё и это хороший шанс поучится делать игры, полировать их и т.д. Плохие игры там утонут без шансов. Хорошие могут зарабатывать хорошо и даже ОЧЕНЬ хорошо. Из минусов модерация, что лезет не в свои дела и “какбэ” четкие правила, которые, на самом деле, могут интерпретироваться каждым модератором рандомно, что приводит к фрустрации и жутко демотивирует.
* GameDistribution - есть смысл идти только если либо
1) у вас есть классное мобильное IP (Intellectual property), которое вы хотите распространить как можно на большем количестве сайтов и можете выбить у них условия продвижения (временная эксклюзивность и они добавляют игру в рассылку + помечают как эксклюзив и т д). У них только публичный договор оферты, все договоренности только по переписке и нигде не прописаны, а это значит их невозможно проконтролировать или потребовать. Всё на вот таких личных договорённостях и отношениях.
2) вы начинающий, особо никуда не берут, на яндекс вы уже вышли и хочется еще куда-то.
* у меня нет опыта с СrazyGames, но те цифры, что я вижу у @mewton_games, скажу честно, меня не впечатляют. Я бы попытал удачу с ними, если не получится с Poki т.к. знаю, что временная эксклюзивность может помочь с продвижением на площадке.
Остальные площадки менее заметны и менее прибыльны. Если у вас нет эксклюзивной сделки, то можно идти хоть везде и сразу, чтобы выжать из игры максимум, но оценивать трудозатраты/выгоды вам придется самостоятельно.
Лично я бы следовал следующему алгоритму:
* посмотрел все площадки, поиграл в игры. Сравнил уровень полировки с тем что есть у меня, чтобы понимать есть ли у меня шанс попасть на площадку. Посмотрел, найдется ли аудитория для моей игры на этой площадке;
* если игра дотягивает по полировке до игр на Poki - подался бы к ним в первую очередь;
* если игру не примут, я бы рассмотрел бы площадки на которых есть возможность получить бонусы от временной эксклюзивности и получить от этого бонусы продвижения: CrazyGames и GameDistribution (можно связаться и обсуждать параллельно с заявкой на poki);
* к концу эксклюзивного периода, если договорится получиться, готовил бы игру к релизу на остальные площадки, если нет, релизил бы везде где берут сразу;
* ну и так как игры у меня на Defold, то выпустил бы на мобилы (не в последнюю очередь, а просто когда бы появилось время).
Напомню, что это про игры с рекламной монетизацией. За информацией про игры с платежами лучше сходить сюда @html5center
Универсальным для всех платформ будут следующие советы:
* поиграть в игры на платформе и попытаться составить свое понимание качества и уровня полировки проектов на платформе;
* понять жанры и какая у платформы аудитория (может быть максимально широкая, но не факт);
* всегда плюс, если есть возможность где-то познакомиться с представителями платформы и пообщаться про вашу игру (например, на конфах или митапах, иногда проходят онлайн).
Теперь немного о платформах.
* Если есть опыт создания игр под вэб и понимание, что такое качественная отполированная игра, то лучше идти на #poki. Это одна из лучших вэб платформ на сегодняшний день. Классные инструменты и команда, НО ручной отбор игр. Это значит, что с любой случайной игрой или не достаточно отполированной или не достаточно веселой игрой туда попасть будет сложно. Не получится прийти туда с игрой вида “я сделалъ”. Еще вариант туда идти если у вас есть мобильный хит и вы хотите попытаться выйти в web. Можно собрать web сборку и закинуть, проконсультироваться и договориться, что и как. Всегда есть вариант, что предложат протестировать как есть или помочь найти кого-то на портирование игры под вэб. Но опять же, игра должна быть клевой и уже хорошо себя показать. Кроме того площадка предпочитает эксклюзивные игры т.е. игры не должны быть опубликованы где-то еще.
* Если опыта мало или нет, но в вэб хочется или по каким-то причинам у вас не получается с poki (не берут игру или не можете работать с европейской компанией). Лучше пойти на Яндекс Игры. Они берут почти всё и это хороший шанс поучится делать игры, полировать их и т.д. Плохие игры там утонут без шансов. Хорошие могут зарабатывать хорошо и даже ОЧЕНЬ хорошо. Из минусов модерация, что лезет не в свои дела и “какбэ” четкие правила, которые, на самом деле, могут интерпретироваться каждым модератором рандомно, что приводит к фрустрации и жутко демотивирует.
* GameDistribution - есть смысл идти только если либо
1) у вас есть классное мобильное IP (Intellectual property), которое вы хотите распространить как можно на большем количестве сайтов и можете выбить у них условия продвижения (временная эксклюзивность и они добавляют игру в рассылку + помечают как эксклюзив и т д). У них только публичный договор оферты, все договоренности только по переписке и нигде не прописаны, а это значит их невозможно проконтролировать или потребовать. Всё на вот таких личных договорённостях и отношениях.
2) вы начинающий, особо никуда не берут, на яндекс вы уже вышли и хочется еще куда-то.
* у меня нет опыта с СrazyGames, но те цифры, что я вижу у @mewton_games, скажу честно, меня не впечатляют. Я бы попытал удачу с ними, если не получится с Poki т.к. знаю, что временная эксклюзивность может помочь с продвижением на площадке.
Остальные площадки менее заметны и менее прибыльны. Если у вас нет эксклюзивной сделки, то можно идти хоть везде и сразу, чтобы выжать из игры максимум, но оценивать трудозатраты/выгоды вам придется самостоятельно.
Лично я бы следовал следующему алгоритму:
* посмотрел все площадки, поиграл в игры. Сравнил уровень полировки с тем что есть у меня, чтобы понимать есть ли у меня шанс попасть на площадку. Посмотрел, найдется ли аудитория для моей игры на этой площадке;
* если игра дотягивает по полировке до игр на Poki - подался бы к ним в первую очередь;
* если игру не примут, я бы рассмотрел бы площадки на которых есть возможность получить бонусы от временной эксклюзивности и получить от этого бонусы продвижения: CrazyGames и GameDistribution (можно связаться и обсуждать параллельно с заявкой на poki);
* к концу эксклюзивного периода, если договорится получиться, готовил бы игру к релизу на остальные площадки, если нет, релизил бы везде где берут сразу;
* ну и так как игры у меня на Defold, то выпустил бы на мобилы (не в последнюю очередь, а просто когда бы появилось время).
Напомню, что это про игры с рекламной монетизацией. За информацией про игры с платежами лучше сходить сюда @html5center
Мне очень понравилась Дюна и я с нетерпением ждал вторую часть, которая не разочаровала.
Думаю, всем бросилась в глаза планета Харконенов, которая выглядела зловеще и уже в кинотеатре было понятно, что это точно не просто картинка в оттенках серого.
Поискал в интернете и нашел, что это инфракрасная съемка.
Попытался воссоздать подобный эффект шейдерами, но т.к. я в этом не очень силен, результат получился лишь отдаленно напоминающий эффект в кино.
Похоже, что автор модели использовал bloom, чтобы быть ближе к результату, но как по мне - это слишком смягчает картинку и добавляет типичное свечение.
То что у меня получилось можно посмотреть в этой web демке.
А можно покрутить параметры и собрать свою версию проекта.
UPD: Всем спасибо за помощь, обновил проект. Стало красивее.
Думаю, всем бросилась в глаза планета Харконенов, которая выглядела зловеще и уже в кинотеатре было понятно, что это точно не просто картинка в оттенках серого.
Поискал в интернете и нашел, что это инфракрасная съемка.
Попытался воссоздать подобный эффект шейдерами, но т.к. я в этом не очень силен, результат получился лишь отдаленно напоминающий эффект в кино.
Похоже, что автор модели использовал bloom, чтобы быть ближе к результату, но как по мне - это слишком смягчает картинку и добавляет типичное свечение.
То что у меня получилось можно посмотреть в этой web демке.
А можно покрутить параметры и собрать свою версию проекта.
UPD: Всем спасибо за помощь, обновил проект. Стало красивее.
Встретил мнение о том, что баннеры плохо заходят “на зарубежных платформах".
Хммм...
Вспомнил, что писал про баннеры и решил подвести итоги с цифрами.
Напомню, что речь идет про HTML5 игры на poki.com, где баннеры есть только на телефонах в портретном режиме.
Игры, в которые я добавил эту поддержку, сейчас зарабатывают на баннерах (значения взяты за последние 30 дней):
игра №1 - 19.5% от общего заработка и 56% от заработка на телефонах,
игра №2 - 15% от общего заработка и 55% от заработка на телефонах.
К сожалению, нет возможности оценить, как появление дополнительной монетизации игр, которая по сути добавилась к существующей монетизации, а также улучшения метрик при игре на телефоне, повлияло на алгоритмы платформы. Но могу предположить, что более чем удвоение доходов с мобильных игроков должно было повлиять самым лучшим образом.
Еще несколько игр, которые изначально поддерживали портретный режим и сколько в них зарабатывают баннеры:
игра №3 - 36.5% от общего заработка и 66% от заработка на телефонах,
игра №4 - 28% от общего заработка и 54% от заработка на телефонах,
игра №5 - 12% от общего заработка и 46% от заработка на телефонах,
игра №6 - 11% от общего заработка и 100% от заработка на телефонах (в игре нет rewarded рекламы, а interstitial не поддерживаются на телефонах на Poki).
Добавил график, чтобы эти цифры было проще читать.
Итак, в моем случае баннеры дают от 10 до ~40% общих доходов в зависимости от игры, и это примерно удвоение мобильных доходов.
Лично для меня этих значений достаточно, чтобы обеспечивать одинаково качественную поддержку как в альбомной, так и в портретной ориентации экрана для моих игр. И это не учитывая, что для алгоритмов важны не столько абсолютные значения, сколько то, насколько твои показатели лучше, чем у других игр на платформе.
Хммм...
Вспомнил, что писал про баннеры и решил подвести итоги с цифрами.
Напомню, что речь идет про HTML5 игры на poki.com, где баннеры есть только на телефонах в портретном режиме.
Игры, в которые я добавил эту поддержку, сейчас зарабатывают на баннерах (значения взяты за последние 30 дней):
игра №1 - 19.5% от общего заработка и 56% от заработка на телефонах,
игра №2 - 15% от общего заработка и 55% от заработка на телефонах.
К сожалению, нет возможности оценить, как появление дополнительной монетизации игр, которая по сути добавилась к существующей монетизации, а также улучшения метрик при игре на телефоне, повлияло на алгоритмы платформы. Но могу предположить, что более чем удвоение доходов с мобильных игроков должно было повлиять самым лучшим образом.
Еще несколько игр, которые изначально поддерживали портретный режим и сколько в них зарабатывают баннеры:
игра №3 - 36.5% от общего заработка и 66% от заработка на телефонах,
игра №4 - 28% от общего заработка и 54% от заработка на телефонах,
игра №5 - 12% от общего заработка и 46% от заработка на телефонах,
игра №6 - 11% от общего заработка и 100% от заработка на телефонах (в игре нет rewarded рекламы, а interstitial не поддерживаются на телефонах на Poki).
Добавил график, чтобы эти цифры было проще читать.
Итак, в моем случае баннеры дают от 10 до ~40% общих доходов в зависимости от игры, и это примерно удвоение мобильных доходов.
Лично для меня этих значений достаточно, чтобы обеспечивать одинаково качественную поддержку как в альбомной, так и в портретной ориентации экрана для моих игр. И это не учитывая, что для алгоритмов важны не столько абсолютные значения, сколько то, насколько твои показатели лучше, чем у других игр на платформе.
Случилась классическая ситуация: пообещал писать чаще и пропал на полгода.
За это время накопилось немного, о чем можно рассказать. Чтобы решить, в каком порядке это делать, я проведу голосование. Начнем с этих четырёх тем:
За это время накопилось немного, о чем можно рассказать. Чтобы решить, в каком порядке это делать, я проведу голосование. Начнем с этих четырёх тем:
Anonymous Poll
26%
Поддержка старых игр на Poki и мобильных устройствах: как, зачем и стоит ли это того?
42%
От чего я выгорел, и что с этим делаю
28%
Как я использую нейросети: практика без хайпа и эзотерики
5%
Что не так с Dropbox и чем его заменить
Я не ожидал, что проголосует ТАКОЕ количество людей (больше трети от людей на канале) и не думал, что кому-то будет интересно читать про выгорание (ставил на хайп по AI).
Ну раз так, держите, вы сами попросили🧑💻
https://telegra.ph/Gori-gori-yasno-09-22
Ну раз так, держите, вы сами попросили
https://telegra.ph/Gori-gori-yasno-09-22
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegraph
Гори, гори ясно.
Иногда нужно время для саморефлексии. По-настоящему свободное время. Безделье. Это время появилось из-за того, что я заболел и неделю чувствовал себя как разбитое корыто: с температурой, практически постоянной головной болью и невозможностью из-за этого что…