Thursday, March 10, 2016

JRuby for game development

So I have been pretty active in using Ruby for the past several years. I have found it a great resource for writing less code and producing more results. So why not use it for game development. Build some DSLs or better syntax for writing game logic code. So in this post I am going to run through a couple of ways to accomplish writing a game in ruby by using java for graphics and additional functionality.

So first we start off by needing to package everything up nicely in a single jar file so it appears as though we're just using java. Unfortunately this comes with a bit of a space cost. And that space is that of jruby the complete jar is ~20mb you can find them at http://jruby.org/downloads so no way to avoid this although you can do something like write an install script that downloads it and then puts your source into it afterwards.

Ok once you have the jar file you will add your code to it and it will become your executable from java.

Make a copy of the complete jar.

$ cp jruby-complete-9.0.5.0.jar mygame.jar

Create a file that jruby will launch called jar-bootstrap.rb

#!/usr/bin/env ruby
puts "Hello, I am jar-bootstrap.rb from inside the jar file"

Update the jar (-u) by first modifying the manifest to run a specific java class using option -e to override the Main-Class entry in the manifest already inside the jar.

$ jar ufe mygame.jar org.jruby.JarBootstrapMain

Then you can use the -u option to add files to the jar file or update existing ones.

$ jar uf mygame.jar jar-bootstrap.rb

Then viola:

 $ java -jar mygame.jar
Hello, I am jar-bootstrap.rb from inside the jar file.

Ok we've entered the ruby~java land woot woot.

Now for lets rubify java to do our game-logics bidding!!!


Lets switch the jar-bootstrap.rb to load our game which we will start in a game.rb file:

jar-boostrap.rb becomes
#!/usr/bin/env ruby
require './game.rb'

Then we make our game.rb file with a simple example of loading a java swing window and rendering loop

game.rb is
#!/usr/bin/env ruby
include Java

import javax.swing.JFrame
import javax.swing.JPanel
import java.awt.BorderLayout
import java.awt.Dimension

class MyDrawPane < JPanel
  def initialize
    super
    setDoubleBuffered true
    setPreferredSize Dimension.new(800,600)
  end

  def paintComponent(g)
    g = g.create
    g.drawString 'Hello from ruby', 0, self.height / 2
    g.dispose
  end
end

class MyGame < JFrame

  def initialize
    super "My Game Window Title"

    self.setLayout BorderLayout.new
    self.add ::MyDrawPane.new
    self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
    self.pack
    self.setLocationRelativeTo nil
    self.setVisible true
  end

end

MyGame.new

And with all this we have a simple window to start from but now we can use the power of ruby to rule the world. Uh I mean we'll use the power of ruby to make games...

...to rule the world...


So this is all great but maybe we want easier iterations with our game development because updating the jar all the time isn't that fast. So for development just execute your game.rb file from jruby directly. You can use the original one you downloaded.

$ java -jar ../jruby-complete-9.0.5.0.jar game.rb

Or if you use rvm or rbenv then just execute the game script. And Q.E.D.