Development Archives
01.09.2018
Благодаря LORу узнал о менеджере пакетов Conan C/C++ package manager . Это консольныя, децентрализованаая и кроссплатформенная (заявлена поддержка Windows, Linux, OSX, FreeBSD, и SunOS) утилита предназначенная для упрощения жизни разработчика.
Поддеживаются различные билд-системы – Visual Studio MSBuild, CMake, Makefiles, SCons, и многие другие. Как сказано в документации, Conan’у вообще монопенисуально, какую били-систему вы используете.
И все это под лицензией MIT. То, чего так давно ждут разрабочики от “нового” стандарта C++.
Мой обновленный способ инициализации. В целом он почти не отличается от использованного мною все эти годы. И является практически дефольтным, согласно документации. Но, на одном параметре стоит заострить внимание.
Moving Past Failure in Game Development
По-умолчанию этот параметр установлен в TRUE. И сегодня я получил слайд-шоу, установив его в значение по-умолчанию.
EmscriptenWebGLContextAttributes attr; emscripten_webgl_init_context_attributes(&attr); attr.alpha = EM_FALSE; attr.depth = EM_FALSE; attr.stencil = EM_FALSE; attr.antialias = EM_FALSE; // <-- this should be set to FALSE! attr.preserveDrawingBuffer = EM_FALSE; attr.preferLowPowerToHighPerformance = EM_FALSE; attr.failIfMajorPerformanceCaveat = EM_FALSE; attr.enableExtensionsByDefault = EM_TRUE; attr.premultipliedAlpha = EM_TRUE; attr.majorVersion = 1; attr.minorVersion = 0; EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(nullptr, &attr); emscripten_webgl_make_context_current(ctx);На HiDPI мониторах downscaled текстуры выглядят мягко говоря не очень красиво. Искал способ решить эту проблему. В итоге мои исследования привели к такому не самому легковесному решению.
AT&T Archives: Submarine Cable Systems Development
Получить device pixel ratio для настройки размров canvas. Получить размер canvas и разрешение css. На их основе вычислить отношение. Использовать это отношение для расчета координат мыши и тача.
После этого все будет выглядеть красиво на HiDPI мониторах. Но есть одна “особенность” – увеличенный (в зависимости от отношения размеров css и canvas) в несколько раз фреймбуфер. При отношении равном 2, получаем размер фреймбуфера в четыре раза больший, со всеми вытекающими.
Немного кода
CSS
canvas { width: 100vw; height: 100vh; display: block; }JavaScript
window.addEventListener('resize', resizeCanvas, false); function resizeCanvas() { var realToCSSPixels = window.devicePixelRatio; var displayWidth = Math.floor(canvas.clientWidth * realToCSSPixels); var displayHeight = Math.floor(canvas.clientHeight * realToCSSPixels); if (canvas.width !== displayWidth || canvas.height !== displayHeight) { canvas.width = displayWidth; canvas.height = displayHeight; } } resizeCanvas();C++
int width, height; emscripten_get_canvas_element_size(nullptr, &width, &height); double cssWidth, cssHeight; emscripten_get_element_css_size(nullptr, &cssWidth, &cssHeight); const auto ratiox = (float)(width / cssWidth); const auto ration = (float)(height / cssHeight);Можно сделать настройку, доступную пользователю – пусть он сам решает, что ему лучше – производительность или качество рендеринга.
Некоторые пользователи моего вьювера жаловались на медленное проигрывание GIF -анимации во вьювере. И чем больше по размеру GIF -файл, тем медленнее происходит загрузка следующего фрейма. И проблема была явно не в медленном декодировании фрейма и его загрузке в GL -текстуру. Все оказалось проще. Каждый раз, когда вьювер запрашивал следующий фрейм, он заново инициализировал giflib , скармливал ему заново путь к файлу, выбирал нужный фрейм и только потом загружал его GL -текстуру.
Фикс получился прост как валенок. Хотя нет, из шерсти делать войлок я не умею, а вот исправить способ работы с GIF -анимацией удалось за пару минут. Теперь и большие анимации проигрываются без тормозов.
А еще я добавил экспериментальную поддержку JPEG 2000 , основанную на библиотеке OpenJPEG . А так же написал загрузчик Apple Icon Image . Заодно сделал небольшой рефакторинг PNG , дабы унифицировать код загрузки, т.к. он используется и для загрузки PNG , и для ICO , а теперь и для ICNS .
Подробнее о Simpel Viewer GL .
Довольно много времени потратил на поиск “плавающего” бага. За это время успел отрефакторить кучу кода, до которого руки не доходили ранее. Но баг не ловился. И в его поимке не смогли помочь ни Xcode Instruments, ни Xcode Analyzer (фронтэнд к статическому анализатору llvm).
Баг проявлялся редко и далеко не на всех девайсах. Я никак не мог понять условия его проявления. Пробовал записывать направление и температуру ветра, положение звезд на небе и длительность соседского ора. Но это никак не помогало в поиске проблемы.
Падения игры под отладчиком и backtrace давали BAD EXC, что как бы намекало на испорченную где-то ранее память. Но где именно? Статический анализатор, по идее, должен на раз находить access out of bounds. Но анализатор молчал, типа вообще все пучком.
От безысходности и обиды на самого себя, решил синхронизировать линуксовую версию с main branch, т.к. в процессе поиска бага был сделан серьезный рефакторинг кода. Ну и очевидно, что погонять движок под valgrind никогда лишним не будет.
И valgrind сразу же нашел memory corruption (тот самый “плавающий” баг, на поиски которого я убил много времени. И мелкий ничего не значащий memory leak.Linux и valgrind рулят!
Столкнулся с проблемой на itch.io , когда приложение запущенной внутри iframe не получает события клавиатуры. Придумал вот такой workaround:
postRun: (function() { window.addEventListener('mousedown', function(evt) { window.focus(); evt.preventDefault(); evt.stopPropagation(); evt.target.style.cursor = 'default'; }, false); })(),К событию postRun добавляем установку листенера на событие mousedown. Теперь при клике мышью на канавасе с игрой события от клавиатуры будут передаваться в наше приложение.
Давно использую декодер, состоящий из кучи бранчей и логических операций. Вот вариант без бренча (тернарный оператор в данном случае брачнем не является), двух логических операций и таблицы – Flexible and Economical UTF-8 Decode
Texture Packer для Linux и macOS – утилита, которая упаковывает набор входных изображений в один большой атлас. Утилита консольная, что удобно для автоматизации.
Из возможностей:
Достаточно шустрая. Сравнивал с “обычным платным” (с) пакером. Умеет создавать Power of Two атлас. Можно ограничить максимальный размер атласа. Умеет отрезать “лишние” пиксели (trim) у входных изображений. Может добавить бордюр нужного размера вокруг изображений при размещении в атласе.Утилита делалась для себя, а теперь доступна на Bitbucket – Texture Packer .
Наверняка многие используют макрос, подобный нижеприведенному:
#define countof(array) (sizeof(array)/sizeof(array[0]))Он хорош до тех пор, пока в качестве array в него не будет передан указатель на array. Компилятор проглотит и ничего не скажет, а результат будет совсем не тот, которого ожидает разработчик.
Благодаря constexpr появившемуся в C++11 есть возможность сделать безопасный countof.
template <class T, size_t N> constexpr size_t countof(const T (&)[N]) noexcept { return N; }Теперь на этапе компиляции произойдет ошибка:
const int values[] = { 42, 76, 16, 11, 31 }; void foo(const int v[]) { for (size_t i = 0; i < countof(v); ++i) // <-- compilation error! { bar(v[i]); } }Версия для C++98 может быть такой:
template <typename T, size_t N> char (&CountOfHelper(T(&)[N]))[N]; #define countof(x) sizeof(CountOfHelper(x))Emscripten is an LLVM-based project that compiles C and C++ into highly-optimizable JavaScript in asm.js format. This lets you run C and C++ on the web at near-native speed, without plugins.
Решил еще раз установить Emscripten с помощью brew, на сей раз все оказалось гораздо проще. Возможно это работало и раньше, но я только сегодня обратил на это внимание.
Правильный способ установки Emscripten с помощью brew:
# устанавливаем emscripten как обычно: $ brew install emscripten # запускаем emcc, что бы он создал файл ~/.emscripten $ emcc # исправляем LLVM_ROOT: $ vim ~/.emscriptenДолжно получиться как-то так:
LLVM_ROOT = '/usr/local/opt/emscripten/libexec/llvm/bin'
К сожалению с помощью brew правильно установить emscripten под OS X El Capitan мне не удалось.
Я не смог найти какую-либо информацию по правильной установке emscripten с помощью brew, поэтому получилась вот такая магическая инструкция.Список шагов для установки emscripten из-под OS X :
С официального сайта качаем портабельную версию emscripten – http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#sdk-download-and-install Распаковываем и запускаем ./emsdk update . С помощью команды ./emsdk list можно посмотреть список доступных пакетов, утилит и sdk. С помощью комады ./emsdk install latest устанавливаем самые последние версии. Командой ./emsdk activate активируем переменные окружения emscripten. Теперь при необходимости сборки проекта инициализируем переменные окружения с помощью команды source ./emsdk_env.sh . По желанию можно прописать путь к директории с emsdk.