Warning: This software is currently in alpha and is only intended for experimental use.
Joy is a 2D game engine inspired by Love2D, using JavaScript instead of Lua as the scripting language. The engine is portable and cross-platform, targeting macOS, Windows, Linux, Web, iOS, and Android.
- Love2D-compatible API: JavaScript API designed to match Love2D's Lua API as closely as possible.
- Multiple JavaScript engines: QuickJS (lightweight) or V8 (higher peak performance).
- ES module support: Modern JavaScript with ES6+ features.
- Cross-platform rendering: Metal on macOS, OpenGL on other desktop platforms, WebGL on the web.
- Spatial audio: 3D positional audio via miniaudio.
- Built-in GUI: Immediate-mode GUI via Nuklear.
- Web Platform APIs: WebSocket and Web Worker support.
- Single-file distribution: Package games as
.joybundles.
Joy provides the following modules under the joy.* namespace:
| Module | Description |
|---|---|
joy.audio |
Audio playback, sources, and mixing |
joy.data |
Compression, hashing, and encoding |
joy.filesystem |
Virtual filesystem (files, directories, archives) |
joy.graphics |
2D drawing primitives, textures, and text rendering |
joy.gui |
Immediate-mode GUI widgets and layouts |
joy.image |
Image loading and manipulation |
joy.joystick |
Joystick and gamepad input |
joy.keyboard |
Keyboard state and events |
joy.math |
Random numbers, noise, transforms, and Bezier curves |
joy.mouse |
Mouse state and position |
joy.sound |
Sound data loading |
joy.system |
OS information and environment |
joy.timer |
Frame timing |
joy.window |
Window management |
Additionally, standard Web APIs are available globally:
WebSocket- WebSocket client for network communication.Worker- Web Worker-like threading for background tasks.
Create a main.js file:
joy.load = function() {
// Called once at startup
}
joy.update = function(dt) {
// Called every frame with delta time
}
joy.draw = function() {
joy.graphics.print("Hello, Joy!", 100, 100);
}Run your game:
./joy /path/to/your/gameJoy uses CMake and Ninja as the build system.
# Configure and build with QuickJS (default)
cmake -B build -G Ninja
ninja -C build
# Or build with V8
cmake -B build -G Ninja -DJOY_ENABLE_V8=ON
ninja -C buildNote: V8 is only supported on the following platforms: macOS (aarch64), Linux
(x86_64 and aarch64), Windows (x86_64 and aarch64). The build system uses
prebuilt V8 libraries from v8-build,
which may not link properly on systems older than Ubuntu 24.04. You can use
that repository to build V8 from source manually and point the Joy build to
your local installation with -DV8_LOCAL_PATH=....
Install Emscripten, then:
emcmake cmake -B build-web -G Ninja
cd build-web
ninjaThis produces:
joy.html- The HTML pagejoy.js- JavaScript glue codejoy.wasm- WebAssembly game engine binary
Place your game as game.joy alongside these files and serve the web page:
python3 -m http.server 8080Navigate to http://localhost:8080
Package your game directory into a distributable .joy bundle:
./joy -b /path/to/game output.joyExample games demonstrating various features are available in the examples/ directory.
All dependencies are automatically cloned and compiled during the build process.
- SDL3 - Window and input management.
- Sokol (sokol_gfx) - Cross-platform rendering.
- miniaudio - Audio engine.
- Nuklear - Immediate-mode GUI.
- QuickJS-ng or V8 - JavaScript runtime.
- PhysFS - Virtual filesystem.
- Box2D v3 - Physics engine (for the physics module).
- Curl - WebSocket implementation.
Joy's API is designed to match Love2D 11.5. Refer to the Love2D Wiki for API documentation, keeping in mind:
- Replace
love.*withjoy.* - Replace Lua syntax with JavaScript syntax
- The physics module uses Box2D v3 instead of v2, with some API differences
- Some deprecated Love2D functions have been removed (e.g., use
joy.filesystem.getInfoinstead ofjoy.filesystem.exists)
There are some other API differences, documentation TBD.
This codebase was written with assistance from Claude Opus 4.5.