
Build a browser-based 2D game engine with C++20, WebAssembly, and Emscripten. Implement SDL2/OpenGL rendering, ENT-based entity systems, box2D physics, and Lua scripting across a Tetris-style game and platformer.
Install and set up emscripten by installing git and python, cloning the emsdk, and activating the latest. Configure windows environment variables and path for command-line access.
Install CMake on Windows using the Windows installer, add CMake to the path, and verify the version, comparing 3.31 and 4.0, to prepare a small CMake project in scripting.
Create a small C++ project with cmake and emscripten, setting C++20, adding an executable, and building an HTML output to run a hello emscripten program.
Learn to render a 50x50 red rectangle in the browser by integrating SDL with Emscripten and CMake in a C++ project, including window setup, a render loop, and HTML output.
Download Lua from GitHub, integrate it into a dependencies folder, build a static Lua library with CMake and Emscripten, and prepare for sol two scripting.
Learn to bind lua with c++ using sol2 by cloning sol2, exposing a hello function, organizing assets and scripts, and running lua scripts in the browser via emscripten.
Move the block in the browser by binding Lua with sol two to C++, update box x and y using get x and get y, and call move_box from main.lua.
In this video we start changing over from using the SDL Renderer and move over to using OpenGL and shaders. We also start the main engine project that will be used for all of our games.
Practice loading and compiling vertex and fragment shaders from memory in an OpenGL context with SDL, then link, validate, and render a triangle, swap buffers, and adjust the viewport.
Instead of having to always open and run the project from the command line. We are going to create a helper batch file that will run the command and start up the project in the browser for us.
Load textures in the browser game with SDL_image and libpng, map them with UVs in shaders, and use a memory-based OpenGL loader with clamp-to-edge and nearest filtering for pixel art.
Enable blending in OpenGL and use glBlendFuncSeparate for color and alpha, then load character texture, update quad vertices with vec2 position and uv, and flip coordinates to correct upside-down texture.
Create a simple shader class to manage a GL program, enable and disable it, expose its id, and integrate a shared-pointer shader loader into main.cpp with cmake updates.
Create a texture class to hold the texture id, width, height, and file path, with enable and disable methods to bind textures in OpenGL and prepare for the asset loader.
Organize rendering and utilities by adding a rendering folder and a utilities folder, with an asset loader offering static load shader from memory and load texture functions for Jadite assets.
Move the shaders into a new default shaders file under rendering, and define a jadeite default shaders struct with static const char* members basic shader vert and basic shader frag.
Add the GLM library to your engine by downloading, extracting, and placing it in dependencies, then update CMake and test GLM usage with vec2 for camera matrices.
Create a camera class using glm, implementing an orthographic projection and a top-left origin for a 2d game, with position, scale, and a dirty flag to control updates.
Add a camera to the browser game by wiring it into cmake, creating and initializing a unique camera pointer, updating every frame, and passing the projection matrix to the shader.
Add Lua bindings for the camera using sol to expose a camera user type with get position, set position, and set scale, then test by moving the camera in main.lua.
Create a vertex struct with position, UVs, and color (plus UV width/height for texture atlases) and bind it to Lua with Sol, including presets for white, red, green, blue.
Integrate ENT as a fast entity component system, add the header-only NTT library for resource management and reflection, then configure CMake, create a registry, and instantiate an entity to verify.
Create a wrapper around the NTT registry to manage entities, components, and queries in an ECS, and introduce a registry context for shared state like the Lua state.
Create a registry wrapper in main.cpp, instantiate two entities, and attach a shared lua state to the registry context for later access.
Wrap the registry with an entity wrapper to manage components, using templated add, get, replace, try get, and remove operations; expose Lua bindings and integrate with main and build.
Add default components to entities, including identification, transform, sprite, animation, colliders, and rigidbody, and prepare Lua bindings for component creation; demonstrate adding a transform and logging its position.
Bind all components to Lua by creating Lua user types and constructors; test bindings from main.lua using transform, animation, and collider components.
Explore how entt::meta enables runtime reflection to register C++ types and expose them to Lua via the soul two bridge, reducing boilerplate and enabling script-driven games.
This lecture builds meta utilities for runtime reflection using entity meta and the soul 2 library, implementing get id type and invoke meta function with templates.
Add the entity type hash to every component to enable entity meta reflection, using a compile-time utility to generate deterministic ids, and update the CMake list and build to verify.
Learn to register entity meta bindings for components in C++ using soul and Lua, exposing add, get, has, and remove component operations.
Register the registry and the entity runtime view for Lua bindings, enabling dynamic runtime views and refining them with add and exclude components.
Learn how to create and manage entities in Lua using a registry, attach transform components with position, and iterate through a runtime view to access and print entity positions.
Develop Lua bindings for glm types (vec2/vec3/vec4) in a browser game framework, exposing vector operations from glm (length, normalize, distance, dot, cross) and helpers (lerp, clamp, constants like pi).
Learn batch rendering as a crucial 2D optimization and build a C++ OpenGL batch renderer with batch and sprite glyph structures, VBO, VAO, and IBO usage.
Prepare the batch renderer by allocating vertex data for all sprites, batching by texture, and uploading to OpenGL via VAO, VBO, and EBO with color attributes.
Put the batch renderer into action by wiring render sprites to collect transform and sprite components, compute destination rects and UVs, and batch draw.
Learn how to add font support by building a font class that wraps STB TrueType, manages a font atlas texture and glyph data, while deferring loading to the asset loader.
Load a ttf font from a file into a 1024x1024 bitmap atlas with stb_truetype, bake glyphs, upload as an alpha OpenGL texture, and return a font object for rendering.
Create a text component to display text with font name, text content, color, and a hidden flag, bind it to Lua, and register it with entity meta for console testing.
Create a text batch renderer to batch text by font, convert text to glyphs, and render via the gpu using a vao, a vbo, and font atlas ids.
Learn to implement a text rendering pipeline by creating a font shader, integrating a texture atlas for fonts, and rendering text with a text batch renderer using the camera matrix.
Define a button class with pressed, just pressed, and just released states, then implement a keyboard class using SDL key bindings and a map of buttons for input handling.
Create Lua bindings for the keyboard class, expose key constants, and drive on key events from Lua; integrate with the engine update loop and the main Lua script.
Create a mouse class and Lua bindings to track button states, cursor position, and wheel, integrating SDL input and a single mouse instance.
Create a gamepad class wrapping an SDL controller with a custom deleter and shared pointer, supporting d-pad, buttons, axes, hat values, modeled on the Logitech F310, bound to Lua.
Integrate the GamePad class into the browser game and bind an SDL controller for input handling. Manage controller add/remove, axis and hat motions, and map d-pad inputs to Lua-driven gameplay.
Move the main loop from main.cpp into a new game class that handles inputs, updates, and rendering, and initialize SDL, load the main Lua script, and register meta components.
Refactor the game architecture by moving main script loading, shader setup, and rendering into the game class, and integrate temp assets, Lua bindings, and input context.
Develop a music player class that wraps SDL_mixer to load, play, pause, stop, and adjust volume, with audio device initialization and a Lua binding for one music player.
Create a sound player class to handle sound effects with SDL_mixer using mix chunks for in memory playback on channels, with play, loops, volume, stop, and Lua bindings.
Explore loading and playing sounds in a browser game with SDL_mixer. Create music and chunk loaders, build an audio context, and test with town theme and switch.wav.
Create an asset manager to centralize textures, shaders, fonts, music, and sound effects, with Lua bindings for script access and robust add/get operations using unordered maps.
Pivot to a centralized asset manager to load textures, shaders, fonts, music, and sounds, replacing temporary assets and streamlining game initialization.
Add script bindings to expose engine functions to Lua, enabling running scripts and loading script tables from assets with wrappers for j2d run script and j2d load script.
Remove hard-coded assets by loading textures, fonts, sound effects, and music from Lua via an asset defs file and Lua bindings to the asset manager.
Create Lua bindings for music and sound players, access assets via the asset manager, and expose play, stop, pause, resume, set volume, and is playing to scripts.
Introduce helpful text utilities with Lua bindings to measure and align text, supporting a playable Tetris game prototype in C++ using a font and asset manager.
Learn to build a timer utility in C++ with std chrono, including start, stop, pause, resume, and restart, for timing levels, countdowns, and elapsed milliseconds in browser games.
Learn to speed up asset updates by adding a reload assets batch file, generate game data with a packager, and use a game-specific index.html for browser-based games.
Bring the power of modern C++20, OpenGL, and SDL2 straight to the browser with WebAssembly, and build your own 2D game engine from the ground up. In this course, you’ll learn how to combine native C++ performance with the accessibility of the web, using Emscripten to compile your engine to WASM so it runs directly in any modern browser.
You’ll go beyond just drawing sprites — we’ll architect a real engine with:
Entity Component System (ECS) using EnTT
Physics and collisions powered by Box2D
Lua scripting for flexible and dynamic gameplay logic
OpenGL rendering for efficient graphics
SDL2 for input, windowing, and audio
Hot-reloadable assets and a modular architecture ready for expansion
By the end of the course, you’ll have built a complete, browser-based game framework capable of running complex 2D games — all coded in modern, clean C++20 and easily extended through Lua scripts.
We’ll start with a simple Tetris-style game, then evolve into a platformer using physics, tilemaps, and real scripting control. Along the way, you’ll learn core engine design patterns, modern C++ techniques, and real-world practices for cross-compiling and optimizing games for the web.
What You’ll Learn:
How to compile modern C++20 to WebAssembly using Emscripten
How to use SDL2 and OpenGL for cross-platform rendering in the browser
How to build an Entity Component System (ECS) with EnTT
How to add physics using Box2D
How to embed and use Lua for scripting gameplay
How to organize your game engine architecture cleanly and efficiently
How to create real browser-based 2D games with C++ performance
Technologies Used:
C++20
WebAssembly (WASM)
Emscripten
SDL2
OpenGL
Box2D
Lua
EnTT (ECS)
Who This Course Is For:
C++ developers who want to bring their games to the web
Game developers interested in building their own 2D engine
Programmers who want to learn Emscripten and WebAssembly in a real-world project
Anyone who wants to combine native performance with web deployment
Why Take This Course:
Most WebAssembly tutorials stop at “Hello World.” In this course, you’ll build something real — a fully functional 2D game engine capable of running in the browser. You’ll understand every layer: from C++20 compilation, ECS architecture, and physics integration, to scripting, rendering, and deployment.
This is modern game engine design for the web, taught step-by-step, with clean, maintainable C++ and production-quality techniques.