A downloadable game engine for Windows, macOS, and Linux

Buy Now$40.00 USD or more

DragonRuby GTK is a professional grade (yet beginner friendly) 2D game engine. It's tiny (~3MB), fast as hell, and cross-platform (including consoles).

If your income is below $1000 per month, are a "student", or are a "big time Raspberry PI enthusiast", contact Amir at ar@amirrajan.net with a short explanation of your current situation, and he'll set you up with a free license, no questions asked.

So what's so great about DragonRuby Game Toolkit?

  • Dirt simple apis capable of creating complex 2D games.
  • Fast as hell. Powered by highly optimized C code written by Ryan C. Gordon, the creator of SDL (a library that powers every commercial game engine in the world).
  • Battle tested by Amir Rajan, a critically acclaimed indie game dev.
  • Tiny. Like really tiny. The entire engine is a few megabytes.
  • Hot loaded, realtime coding, optimized to provide constant feedback to the dev. Productive and an absolute joy to use.
  • Turn key builds for Windows, MacOS, and Linux with seamless publishing to Itch.io.
  • Cross platform: PC, Mac, Linux, iOS, Android, Nintendo Switch, XBOX One, and PS4 (mobile and console compilation requires a business entity, NDA verification, and a Professional GTK License, contact us).

Ryan put together a 5-minute intro to DragonRuby GTK, to give you a whirlwind tour of the big ideas:

This is a tech demo sample app that ships with DragonRuby. The GTK's entire API is displayed here.

The developers behind DragonRuby GTK.

This is Ryan C. Gordon (Wikipedia), he is the juggernaut behind Simple DirectMedia Layer (Wikipedia). Ya know... SDL... that low level library that powers literally every commercial game engine out there?

And this is Amir Rajan, he is an indie game dev with titles on iOS, Android, desktop, and Nintendo Switch... amassing 4 million downloads and counting (New York Times, Kill Screen, Nintendo).

Both of these guys hate the complexity of today's engines. And as luck would have it, their paths ended up crossing. Six months and 50,000 lines of code later, they are ready to share the fruits of their labor. 

Hello World is one file, three lines.

This is all you need to create a game. One file. One method called tick. Here we render the current step value as a label:

def tick args
  args.outputs.labels << [100, 100, args.game.tick_count]

That's it. If you know how to use the array datatype in any language, you know how to use the DragonRuby Game Toolkit.

Output: Six rendering primitives is all you need.

Here the six draw primitives you need to know: solids, sprites, labels, lines, borders, and sounds. Here is how you use them:

def tick args  
  # draw a blue square that's half way faded out
  args.outputs.solids << [100, 100, 50, 50, 0, 0, 255, 128]
  # draw a red label  
  args.outputs.labels << [100, 100, "This is a label.", 255, 0, 0]
  # draw a sprite turned 45 degrees and half way faded out
  args.outputs.sprites << [200, 200, 50, 50, 'ninja.png', 45, 128]
  # draw a diagonal green line from bottom left to top right
  args.outputs.lines << [0, 0, 1280, 720, 0, 255, 0]
  # draw a black border (unfilled square)
  args.outputs.borders << [100, 100, 50, 50, 0, 0, 0, 255]
  # play a sound every second
  args.outputs.sounds << "ping.wav" if args.game.tick_count % 60 == 0

That's it. You now know the entire render api for DragonRuby GTK.

Here's a more complicated example. This is how you create a night time scene, with a title, and a ninja:

  1. solids: A black background, and two hundred stars made of tiny squares.
  2. labels: Display some smokey-white text.
  3. sounds: Play a sound when the game starts up.
  4. sprites: Render a sprite on the screen.
  5. lines: Draw a line representing the floor
  6. borders: Frame the entire scene with a white border.
def tick args
  game, outputs, grid = args.game, args.outputs, args.grid
  game.colors.background ||= [0, 0, 0]
  game.colors.star       ||= [128, 200, 255]
  game.colors.text       ||= [200, 200, 200]
  game.colors.landmarks  ||= [255, 255, 255]
  game.night             ||= [grid.rect, game.colors.background]
  game.stars             ||= 200.map do
    [rand * grid.w,
     rand * grid.h,
     rand * 2 + 2,
     rand * 2 + 2,
  outputs.sounds  << "opening_fx.wav" if game.tick_count == 0
  outputs.solids  << game.night
  outputs.solids  << game.stars
  outputs.labels  << [grid.left + 50, grid.top  - 50, "Ninja Game", game.colors.text]
  outputs.sprites << [50, 50, 50, 50, 'ninja.png']
  outputs.lines   << [grid.left, 
                      grid.bottom + 50, 
                      grid.bottom + 50, 
  outputs.borders << [grid.left + 1,
                      grid.bottom + 1, 
                      grid.right - 1, 
                      grid.top - 1, 

Input: Controllers, Mouse, and Keyboard.

This is how you move a sprite using your gamepad:

args.game.ninja.x ||= 100
args.outputs.sprites << [args.game.ninja.x, 300,
                         50, 50,
if args.inputs.controller_one.key_held.right
  args.game.ninja.x += 10
elsif args.inputs.controller_one.key_held.left
  args.game.ninja.x -= 10

This is how you move a sprite using your mouse:

args.game.ninja.x ||= 100
args.outputs.sprites << [args.game.ninja.x, 300, 50, 50, 'ninja.png']
if args.inputs.mouse.click  
  args.game.ninja.x = args.inputs.mouse.click.point.x

This is how you move a sprite using your keyboard:

args.game.ninja.x ||= 100
args.outputs.sprites << [args.game.ninja.x, 300, 50, 50, 'ninja.png']
if inputs.keyboard.key_held.right
  game.ninja.x += 10
elsif inputs.keyboard.key_held.left
  game.ninja.x -= 10

Game State: Entities and Collision.

Randomly create 500 ninjas on the screen. Create a lookup table that contains the alpha property of ninjas that have collided. Present all ninjas with their alpha properties set.

def tick args
  grid, game, outputs = args.grid, args.game, args.outputs
  game.ninjas ||= 500.map do
                    { rect: [grid.w.-(50) * rand,
                             grid.h.-(50) * rand,
                             50] })
  game.collisions ||= game.ninjas
                          .reject { |n, n2| n == n2 }
                          .find_all { |n, n2| n.rect.intersects_rect?(n2.rect) }
                          .map { |n, _| [n.entity_id, 128] }
  outputs.sprites << game.ninjas.map do |n|
    [n.rect, 'dragonruby.png', 0,
     game.collisions[n.entity_id] || 255]

Support for aspiring game devs.

Need a bit more guidance in learning how to program? We're starting to build training videos for DragonRuby GTK. Check those out at dragonruby.school.

Updated 15 hours ago
StatusIn development
PlatformsWindows, macOS, Linux
Tags2D, dragonruby, Game engine, Moddable, ruby


Buy Now$40.00 USD or more

In order to download this game engine you must purchase it at or above the minimum price of $40 USD. You will get access to the following files:

dragonruby-gtk-macos.zip 30 MB
Version 20
dragonruby-gtk-linux-amd64.zip 29 MB
Version 20
dragonruby-gtk-linux-raspberrypi.zip 29 MB
Version 12
dragonruby-gtk-windows-amd64.zip 30 MB
Version 20

Development log