Emscripten, SDL2, and Lib2D

Being light-weight, Lib2D works great for targeting web browsers using Emscripten. If you're not familiar with Emscripten, it's a toolchain for compiling C and C++ code to asm.js and WebAssembly.

To get started you'll need to download the latest build of Emscripten:

$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
$ source ./emsdk_env.sh

You may need to install some prerequisites depending on your platform.

Compile using:

$ LIB2D=path/to/lib2d/
$ emcc -O2 $LIB2D/src/*.c -I $LIB2D/include/ -s FULL_ES2=1 -DGLES -o lib2d.bc
$ emcc -O2 my_game.c -s USE_SDL=2 -I $LIB2D/include/ -o game.bc
$ emcc -O2 game.bc lib2d.bc -s USE_SDL=2 --embed-file assets -o index.html

my_game.c:

#include <SDL2/SDL.h>
#include <lib2d.h>
#include <GLES2/gl2.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

lib2d_drawable logo;
SDL_Window* window;
SDL_Renderer* renderer;

void loop() {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
            case SDL_QUIT:
                exit(0);
                break;
            case SDL_WINDOWEVENT:
                if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
                    SDL_Rect vp;
                    vp.w =  event.window.data1;
                    vp.h =  event.window.data2;
                    lib2d_viewport(vp.w, vp.h);
                    SDL_RenderSetViewport(renderer, &vp);
                }
                break;
            // ...
        }
    }

    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    lib2d_draw(&logo);
    lib2d_render();
    SDL_GL_SwapWindow(window);
}

int main() {
    // Setup SDL2
    SDL_Init(SDL_INIT_VIDEO);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
    SDL_GL_SetSwapInterval(1);
    window = SDL_CreateWindow("Lib2D",
            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
            800, 600, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
    SDL_GL_CreateContext(window);

    // Setup Lib2D
    if (lib2d_init(LIB2D_RENDER_BACKEND_GL, 0) != 0) {
        fprintf(stderr, "%s\n", lib2d_get_error());
        return -1;
    }
    lib2d_viewport(800, 600);

    // Setup a Lib2D drawable
    lib2d_image im;
    lib2d_image_info info;
    if (lib2d_image_load("assets/logo.png", &im, &info) != 0) {
        fprintf(stderr, "%s\n", lib2d_get_error());
        return -1;
    }
    logo.image = im;
    logo.color = 0xffffffff;
    logo.w = info.w;
    logo.h = info.h;
    logo.x = 40;
    logo.y = 30;

#ifdef __EMSCRIPTEN__
    // Loop forever
    emscripten_set_main_loop(loop, 0, 1);
#else
    while (1) loop();
#endif

    return 0;
}