RubySketch - A game engine based on the Processing API

May 15, 2026 ยท View on GitHub

Ask DeepWiki License Build Status Gem Version

โš ๏ธ Notice

This repository is a read-only mirror of our monorepo. We do not accept pull requests or direct contributions here.

๐Ÿ”„ Where to Contribute?

All development happens in our xord/all monorepo, which contains all our main libraries. If you'd like to contribute, please submit your changes there.

For more details, check out our Contribution Guidelines.

Thanks for your support! ๐Ÿ™Œ

๐Ÿš€ About

RubySketch is a 2D game engine for Ruby. It takes the Processing for CRuby sketch loop โ€” setup / draw / mousePressed / ... โ€” and layers a game-oriented vocabulary on top of it: Sprite, world-based 2D physics (via Box2D), Sound and MML (Music Macro Language) for audio, animation timers (animate, setInterval, setTimeout), and a small library of easing curves.

๐Ÿ“‹ Requirements

  • Ruby 3.0.0 or later
  • All the runtime requirements of Reflex (Rays, Rucy, Xot, plus the platform GUI backend โ€” AppKit / UIKit / Win32 / SDL2 โ€” and OpenGL)
  • The dependent gems are installed automatically: xot, rucy, beeps, rays, reflexion, processing

There is no native C/C++ extension in this gem; the heavy lifting is done by the underlying gems' extensions.

๐Ÿ“ฆ Installation

Add this line to your Gemfile:

gem 'rubysketch'

Then install:

$ bundle install

Or install it directly:

$ gem install rubysketch

๐Ÿ“š What's Provided

require 'rubysketch' and using RubySketch make the whole Processing API (camelCase) plus the RubySketch additions available as top-level methods in your file. As with Processing, a window opens and the sketch runs automatically on file exit; you do not need an explicit start call.

using RubySketch(snake_case: true) adds snake_case aliases (create_sprite, set_interval, ...) alongside the camelCase originals.

On top of Processing, RubySketch adds:

Sprites โ€” RubySketch::Sprite

createSprite returns a Sprite whose position, size, angle, velocity, image, offset, pivot, shape, draw block, and per-sprite mouse events you can drive directly.

CapabilityAPI
Position / sizepos, x, y, z, left, top, right, bottom, center, size, width, height
Motionvelocity, vx, vy, angle, fixAngle, pivot
Appearanceimage, offset (texture offset), draw block
Physicsdynamic = true, static = true, restitution, density, friction, shape
InteractionmousePressed, mouseReleased, mouseMoved, mouseDragged, mouseClicked (per-sprite)
Lifecycleupdate { ... }, draw { ... }, show, hide, capture = true/false

Sprites can be sorted by z and drawn in bulk via the top-level sprite(*sprites) call.

2D physics

APIPurpose
gravity(x, y) / gravity(vec)Set the gravity of the active world
Sprite#shape =Box2D fixture shape (rect, ellipse, polygon)

Sound

APIPurpose
loadSound(path)Load a sample (WAV / AIFF / ...) into a RubySketch::Sound
Sound#play(gain:)Play; returns a handle exposing stop, playing?, seconds
Sound#stopStop all instances

Music Macro Language (MML)

A tiny MML compiler (RubySketch::MML) that turns a string like "t120 l4 cdefgab>c" into a RubySketch::Sound.

  • MML.compile(str, streaming = false) โ€” compile and return a Sound you can play later.
  • MML.play(str) โ€” shortcut for compile(str).play.

Animation and timers

APIPurpose
setTimeout(seconds) { ... }Run a block once after a delay; returns an id usable with clearTimer
setInterval(seconds, now:) { ... }Run a block every N seconds
clearTimer(id)Cancel a timer
animate(seconds, easing:) { ... }Drive a block from 0.0 to 1.0 over time, optionally with an easing curve
animateValue(seconds, from:, to:, easing:) { ... }Same but yields the interpolated value

Easing names: linear, sineIn / sineOut / sineInOut, quadIn / ... / cubicIn / ..., expoIn / expoOut / expoInOut, circIn / ..., backIn / backOut / backInOut, elasticIn / elasticOut / elasticInOut, bounceIn / bounceOut / bounceInOut. See lib/rubysketch/easings.rb.

MIDI input (forwarded from Reflex)

notePressed, noteReleased, controlChange blocks; noteNumber, noteFrequency, noteVelocity, controllerIndex, controllerValue accessors during a callback.

Miscellaneous

  • vibrate (mobile)
  • Vector, Image, WheelEvent โ€” re-exported from Processing for convenience

๐Ÿ’ก Usage

Hello, RubySketch

require 'rubysketch'
using RubySketch

draw do
  background 0
  textSize 30
  text 'hello, rubysketch!', 10, 100
end

Sprites and per-sprite input

require 'rubysketch'
using RubySketch

player = createSprite 200, 200, 40, 40
player.image = loadImage 'player.png'

player.update do
  player.x += 2 if keyIsDown(RIGHT)
  player.x -= 2 if keyIsDown(LEFT)
end

player.mouseClicked do
  player.z += 10              # bring forward on click
end

draw do
  background 30
  sprite player
end

2D physics

require 'rubysketch'
using RubySketch

noStroke
gravity 0, 1000              # pixels / s^2 downward

ground  = createSprite 0, height - 10, width, 10   # static by default
sprites = []

draw do
  background 100
  sprite ground, *sprites
end

mousePressed do
  sp             = createSprite mouseX + rand, mouseY + rand,
                                shape: Circle.new(0, 0, 20)
  sp.dynamic     = true
  sp.restitution = 0.5
  sprites << sp
end

Sound and MML

require 'rubysketch'
using RubySketch

bgm = loadSound 'bgm.wav'

setup do
  bgm.play(gain: 0.6)
end

# play an MML phrase on every click
mousePressed do
  RubySketch::MML.play 't140 l8 ccggaag4 ffeeddc4'
end

Animation with easing

require 'rubysketch'
using RubySketch

x = 0
animateValue(2.0, from: 0, to: width, easing: :elasticOut) {|v| x = v }

draw do
  background 0
  fill 1
  ellipse x, height / 2, 40, 40
end

See examples/ for hello.rb, sprite.rb, physics.rb, and toon.rb.

๐Ÿ› ๏ธ Development

$ rake test    # run the test suite
$ rake doc     # generate YARD docs
$ rake         # default tasks

In the xord/all monorepo you can scope by module, e.g. rake rubysketch test.

๐Ÿ“œ License

RubySketch is licensed under the MIT License. See the LICENSE file for details.