Introduction

A brief introduction to asm.js and emscripten

asm.js is a highly optimized subset of Javascript designed to allow near-native and consistent performance. So, how do you start writing asm.js? You don’t! asm.js is not designed for us mere mortals to write directly. Instead, you write your game in C, C++, or any other language that has a compiler that will generate asm.js. Right now the primary compiler is emscripten. Emscripten is a little more than just a compiler – it is also a platform! Emscripten provides a modified LLVM + Clang compiler suite to build your code into asm.js along with a core set of standard libraries you would expect to come with an operating system. Emscripten provides libc, libstdc++, a virtual filesystem layer, the OpenAL sound API, and much more. The reason for this is to allow your game, which may already run on Windows, Mac, and Linux, to essentially “recompile” and work on emscripten.

A brief introduction to SDL2

SDL2 is a cross-platform library designed to provide a consistent interface to many common hardware subsystems including audio, keyboard, mouse, joysticks, graphics, etc. At Humble Bundle, we use SDL2 for all of our game ports because it removes a significant amount of prep work in getting a game running on a new platform. We simply port the game to SDL2 and then compile it on Windows, Mac, Linux, iOS, Android, and now asm.js. This simplifies the game code as it only needs to know about one new platform, SDL2, instead of two or more platforms. SDL2 is highly portable and written in C, so it can be easily used by any other language.

Getting started

To get started in building your first game for asm.js, we first need to get your development system set up. It is preferred that you also have a native development kit set up on your system as well as emscripten, as sometimes it’s easier to develop and debug natively than in the browser. So make sure you have the following software already installed on your development platform:

For Windows (64bit install only)

Xcode 6 or newer

The latest GCC compiler, and development packages for libc, libstdc++, OpenGL, etc.

Latest CMake - or from your distribution package. It must be 2.8.12 or newer.

The emscripten SDK

Setting up cmake

On Mac OS X, run cmake once and choose the “Tools” menu and then “Install For Command Line Use.” This will set up several links in your path to make it easier to use with emscripten. If you get a warning when running cmake, that it is from an unidentified developer. Simply click OK, and then control-click (or right-click) on CMake and choose Open. This will allow you to bypass Gatekeeper for this one application only.

On Windows, make sure to add cmake to the system path. There is an option in the installer.

Setting up emscripten

emsdk install mingw-4.6.2-32bit

emsdk activate mingw-4.6.2-32bit

cd Projects/emsdk-portable

./emsdk list



./emsdk install sdk-1.29.0-64bit

./emsdk activate sdk-1.29.0-64bit



./emsdk install sdk-master-64bit

./emsdk activate sdk-master.64bit



source ./emsdk_env.sh



We will use emscripten in the command line most of the time. The emscripten team has done a very good job on the “portable SDK” to largely make things work without much fuss. There are only a few platform oddities that you’ll have to fiddle with to get you started. The general instructions are simply to install/extract the portable SDK into a folder on your system.Simply use the installer. Once it finishes installing, open up your file browser to the emscripten folder on C: and run the emcmdprompt.bat. This will set up the environment for building with emscripten. Now we need to install the mingw-32 tools. First run “emsdk list.” This will display a list of installed and available tools you can install. We are looking for “mingw.” When you see that list item, note the version and type the following:That will install mingw in the emscripten directory. Next, we need to activate that version.After that, exit and re-run the emcmdprompt.batAfter extracting the portable SDK to a folder, you will need to open a terminal window and navigate to that folder and then install the latest SDK.The above will list the available SDKs. For OS X, you will see versioned and unversioned. For Linux, you will only see unversioned (master and incoming). So on OS X, simply run:For Linux, you will need to install the master entry, which will take a while as it is compiling LLVM/Clang from scratch. Also, this will consume approximately 3 GB of hard-drive space for the compilation of LLVM and ClangFor OS X and Linux, you will need to include the emscripten environment in your shell. To do that, simply runand that will set up all the paths for you based on the active SDK.

Actually compiling something

cd C:\Projects\ASMDemo





cd ~/Projects/ASMDemo

mkdir build

cd build

mkdir asm

cd asm

emcmake cmake ../../ -DCMAKE_BUILD_TYPE=Debug





make





mingw32-make





To make things easier to get up and going, we have set up a base project located here , which you can use as a base to start playing with emscripten and understand how it works. This project uses CMake as the build system so that it can generate projects for all platforms. Since we’re using SDL2 Renderer API (an accelerated 2d rendering API), we don’t have to worry about OpenGL desktop vs OpenGL ES 2/WebGL in this post. Simply check the project out on your system using your favorite git tool, and then run CMake. In the CMake GUI, select the project checkout folder as the source directory. For the binary directory we are going to specify a different sub-folder, for example: build/osx, build/linux or build/windows. Later, we will build emscripten in build/asm. After you have set both the source and binary directories, click the “Generate” button at the bottom.Cmake will ask you what generator to use. For example: On Windows, you can choose the version of Visual Studio you have installed (2010, 2012, etc.). (NOTE: The prebuilt SDL2 libs for Windows only include 32bit builds for now). After this completes, you will now have a Visual studio project in the build/windows folder – simply open it up in Visual Studio and hit run. Likewise, you can do this with Xcode on the Mac, or GNU make, Ninja, or Code::Blocks on Linux. Next, we’ll get your asm.js build working. Go back to your terminal/cmd prompt that has the emscripten shell and cd to where you checked out the ASMdemo.or for Mac and LinuxMake the build directoryfor Mac and Linuxfor Windowsemrun –browser=firefox index.htmlAnd now you should have the demo running in your browser.

Understanding the emscripten run loop

#ifdef EMSCRIPTEN

emscripten_set_main_loop_arg((em_arg_callback_func)loop_iteration, game.get(), 0, 1);

#else

while (!done) {

loop_iteration(game.get());

}

#endif





An asm.js game can not run inside an infinite loop like we do on the desktop. Instead we have to register a loop function with emscripten that is called “once per frame.” Looking at the main method of the demo, you will see this set of code:This handles the non-emscripten infinite loop approach as well as the emscripten required callback approach. All of the shared logic for handling input and rendering is done in loop_iteration so that we reduce code duplication. Due to how emscripten simulates an infinite loop, no code after the call to emscripten_set_main_loop_arg will be executed.

Is that all?

Believe it or not, that is all that is needed to get up and running with emscripten. Since we are utilizing SDL2, everything else is being handled for us. Our audio is going through SDL2, our keyboard and mouse input is from SDL2, and our rendering is currently being handled by the SDL2 renderer API. In future blog posts, we will cover topics such as OpenGL ES 2/WebGL, and the Humble API to get your game ready for the Humble Widget.