wasmcart

Ruby

Write games in Ruby. Ship them as cartridges.

An mruby runtime with DragonRuby-style APIs — def tick args, args.outputs, args.inputs, args.state.

the wasmcart-mruby release licence

Try it in one command

Prebuilt carts ship with every release — Flappy Wyvern, Neon Blocks, and an API showcase. Download a .wasc and run it:

npx wasmcart flappy-wyvern.wasc

Nothing to install but Node 22+. The cart carries the mruby engine, the game, and its assets.

Start your own game

Everything below lives in wasmcart/wasmcart-mruby.

No compiler, no toolchain. Copy the template and run it:

git clone https://github.com/wasmcart/wasmcart-mruby
cp -r wasmcart-mruby/template my-game
cd my-game
cp ../wasmcart-mruby/build/main.wasm main.wasm

npx wasmcart .

That opens a window. Edit app/main.rb and run npx wasmcart . again — that is the whole loop. The template also ships a run.sh that does exactly those two steps if you would rather type less.

A complete game

Everything happens in tick args, 60 times a second, on a bottom-left-origin canvas:

def tick args
  args.state.x ||= 600
  args.state.x += 5 if args.inputs.keyboard.right
  args.outputs.solids << [args.state.x, 300, 80, 80, 90, 220, 130]
  args.outputs.labels << { x: 640, y: 600, text: 'hello from ruby!',
                           size_px: 6, alignment_enum: 1 }
end

wasmcart games are gamepad games: design for d-pad, face buttons and sticks. On a desktop the arrows and space map onto pad 1 so you can test without a controller.

What you get

Shovel-based outputs

solids, sprites, labels, lines, borders and primitives, redrawn every tick. static_* variants persist so you shovel them once.

Render targets

Shovel into args.outputs[:name], then draw the whole thing as a sprite with path: :name — rotate, scale and tint it like any other sprite.

Primitives as objects

class Foo; attr_sprite; end and shovel instances directly, the OO idiom. attr_rect, attr_label and attr_line work the same way.

State and helpers

Open-struct persistence via args.state, plus args.geometry for intersection tests, args.easing for animation, and Numeric#to_radians.

Cart SRAM

args.gtk.save_u32 slot, v writes to 64 persistent slots, saved as a .sav beside the cart. That is how the flappy example keeps its high score.

Exceptions never crash

A Ruby error is logged, marked in the debug trace, and shown on screen rather than taking the cart down — you see the message instead of a black window.

Ship it

When you want a single shippable file:

npx wasmcart pack --wasm cart.wasm --assets app --name my-game \
  --width 1280 --height 720 -o my-game.wasc

On DragonRuby

If you want a mature, batteries-included commercial Ruby game engine, go buy DragonRuby GTK — it is excellent, and its API idioms are the reason this project speaks the same dialect. This is an unaffiliated, experimental runtime that contains none of DragonRuby's code and does not claim compatibility. Both are built on mruby.

← All languages