Death Mask – Cyberpunk Roguelike Game

[Translation may be some day]

С сегодняшнего дня я начинают разработку roguelike игры в киберпанк сеттинге – Death Mask.
На самом деле это должна была быть первая игра на новом тулчейне Flame Steel Engine, но движок пришлось дорабатывать до появления полноценного 3D.
Изначальное название “Flame Steel: Call Of The Death Mask”, потом я решил упростить задачу и выпустить лишь часть игры – “Flame Steel: Zombie Night”
Однако мысль о создании нормального полноценного проекта не давала мне покоя, также название было перегружено названием вселенной Flame Steel.
За вдохновение в визуальном плане я беру мангу Biomega и Blame! сама вселенная Flame Steel очень похожа на Shadowrun в космосе.
Поэтому не удивляйтесь, если в этой игры вы встретите инопланетного мага, стреляющего в оборотня магическими пулями из револьвера, точной наводкой из кибер-импланта в глазу.

Игра разрабатывается под MIT лицензией с открытым кодом на GitHub, с использованием тулчейна Flame Steel Engine и свободных фреймворков.

GitHub:
https://github.com/demensdeum/Death-Mask

Bright Future – WebAssembly

[Translation may be some day]

Несколько лет назад я прочитал о начале проекта WebAssembly (wasm), идея разработчиков звучала примерно так – разработать байт-код для запуска приложений на разных платформах, архитектурах, акцент делается на запуске приложений в браузере.

Желание выкинуть медленный и непредсказуемый javascript, у меня созрело давно. Уже вчера я собрал и запустил свою тестовую игрушку на WebAssembly.

Здесь я опишу как мне это удалось.

Компиляция WebAssembly с помощью Emscripten

Установка Emscripten описана в прошлой заметке. Допустим у вас уже есть проект который корректно собирается из C++ в javascript, для сборки в wasm вам нужно добавить ключи:

-s WASM=1 -s ""BINARYEN_METHOD='native-wasm'""

Можете также попробовать другие ключи сборки описанные в официальной документации, я выбрал native-wasm как самый производительный вариант.

Включение WebAssembly

На данный момент идет процесс активной разработки, поэтому в стабильных версиях браузеров поддержки последней версии wasm нет. Для запуска wasm кода я использовал браузер Firefox Nightly для Ubuntu. Для включения wasm, нужно зайти в about:config и включить его:

Также заявлена поддержка в других браузерах (Chrome).

WebAssembly в действии

Проверить как работает WebAssembly вы можете открыв страницу игры Tanks движка Unity. Есть подозрение что там используется fallback на javascript, т.к. работает даже в обычном браузере.

Также можете попробовать запустить тестовую версию моей игры Bad Robots для wasm.

Если ваш браузер показывает черный экран и ошибку “Exception thrown, see JavaScript console” и в отладочной консоли текст “uncaught exception: no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods“, тогда устанавливайте лучший браузер Firefox Nightly и включайте WebAssembly по инструкции выше.

Всем удачной компиляции.

Porting SDL C++ Game to HTML5 (Emscripten)

[Translation may be some day]

За последний год я написал простейший движок Flame Steel Engine и набор классов для игровой разработки Flame Steel Engine Game Toolkit. В данной статье я опишу как производил портирование движка и SDL игры Bad Robots на HTML 5, с использованием компилятора Emscripten.

Установка Hello World – Emscripten

Для начала нужно установить Emscripten. Простейшим вариантом оказалось использование скрипта emsdk для Linux. На официальном сайте данный тип установки называется как “Portable Emscripten SDK for Linux and OS X“. Внутри архива есть инструкция по установке с использованием скрипта. Я производил установку в директорию ~/emsdk/emsdk_portable.

После установки emscripten нужно проверить корректность работы компилятора, для этого создаем простейший hello_world.cpp и собираем его в hello_world.html с помощью команд:

source ~/emsdk/emsdk_portable/emsdk_env.sh
emcc hello_world.cpp -o hello_world.html

После компиляции в папке появится hello_world.html и вспомогательные файлы, откройте его в лучшем браузере Firefox, проверьте что все работает корректно.

Портирование кода игры

В javascript нежелательно вызывать бесконечный цикл – это приводит к зависанию браузера. На данный момент корректная стратегия – запрашивать один шаг цикла у браузера с помощью вызова window.requestAnimationFrame(callback)

В Emscripten данное обстоятельство решено с помощью вызова:

emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop);

Таким образом, нужно изменить код игры для корректного вызова метода emscripten. Для этого я сделал глобальный метод GLOBAL_fsegt_emscripten_gameLoop, в котором вызываю шаг цикла игрового контроллера. Главный игровой контроллер также вынесен в глобальную видимость:

#ifdef __EMSCRIPTEN__

void GLOBAL_fsegt_emscripten_gameLoop() {

GLOBAL_fsegt_emscripten_gameController->gameLoop();

}
#endif

Также для обработки специфических для Emscripten моментов, нужно использовать макрос __EMSCRIPTEN__.

Ресурсы и оптимизация

Emscripten поддерживает ресурсы и сборку с оптимизацией.

Для добавления изображений, музыки и прочего, положите все файлы в одну папку, например data. Далее в скрипт сборки добавьте:

emcc <файлы для сборки> –use-preload-plugins –preload-file data

Флаг –use-preload-plugins включает красивый прелоадер в углу экрана, –preload-file добавляет указанный ресурс в файл <имя проекта>.data
Код постоянно останавливался с ошибками доступа к ресурсам, пока я не включил оба этих флага. Также стоит заметить что для корректного доступа к ресурсам, желательно запускать игру на https (возможно и http) сервере, или отключить защиту локального доступа к файлам в вашем браузере.

Для включения оптимизации добавьте флаги:

-s TOTAL_MEMORY=67108864 -O3 -ffast-math

TOTAL_MEMORY – оперативная память в байтах(?) необходимая для корректной работы игры. Вы можете использовать флаг для динамического выделения памяти, но тогда часть оптимизаций работать не будет.

Производительность

Код javascript из C++ работает гораздо медленнее, даже со включенными оптимизациями. Поэтому если ваша цель это разработка для HTML5, то приготовьтесь к ручной оптимизации алгоритмов игры, паралелльному тестированию, также к написанию javascript кода вручную в особо узких местах. Для написания javascript кода используется макрос EM_ASM. Во время реализации рейкастера на emscripten, мне удалось добиться повышения fps с 2-4 до 30 с помощью прямого использования методов canvas.drawImage, в обход обертки SDL->Canvas, что почти приравнялось к написанию всего на javascript.

Поддержка SDL

На данный момент почти не работает SDL_TTF, поэтому отрисовка шрифта для Game Score в BadRobots очень проста. SDL_Image, SDL_Mixer работают корректно, в mixer я проверил только проигрывание музыки.

Исходный код Flame Steel Engine, Flame Steel Engine Game Toolkit, игры Bad Robots:

https://github.com/demensdeum/BadRobots
https://github.com/demensdeum/FlameSteelEngine
https://github.com/demensdeum/FlameSteelEngineGameToolkit

Статья на эту тему:

https://hacks.mozilla.org/2012/04/porting-me-my-shadow-to-the-web-c-to-javascriptcanvas-via-emscripten/

Bad Robots – HTML 5 Game

First game on Flame Steel Engine.

http://demensdeum.com/games/BadRobots/BadRobots.html

Shoot all robots on the screen!

Credits:

Robot sprite – http://opengameart.org/content/xeon-ultimate-smash-friends
Music – Killers Kevin MacLeod (incompetech.com)

Source code:

https://gitlab.com/demensdeum/BadRobots
https://gitlab.com/demensdeum/FlameSteelEngine
https://gitlab.com/demensdeum/FlameSteelEngineGameToolkit