Opal.rb: Ruby in the Browser

I fell in love with the idea of writing Ruby code in my browser long ago. I promptly wrote that dream off as impossible and learned coffeescript. But while coffeescript makes javascript much nicer to work with, it still doesn’t flow as nicely as good ‘ol Ruby. Opal.rb attempts to solve this problem. Opal.rb is a Ruby-to-javascript, source-to-source compiler. Opal supports most of Ruby already, including classes, modules, blocks and method_missing.

Opal has been under development for a couple of years now by Adam Beynon. There is an active community of people working to improve Opal and build extension libraries like opal-jquery, opal-sprockets, and vienna. I’ve started my own little Opal project while writing this blog post. I ported a basic Pixi.js example to Ruby via Opal.

I plan on cleaning up and completing the Pixi.js wrapper, but that’s a post for another day. Give Opal.rb a try online!

Here’s the example code:

include PIXI
stage = Stage.new 0x66FF99
renderer = WebGLRenderer.new 400, 300

Native(`window.document.body`).appendChild renderer.view

texture = Texture.from_image "bunny.png"
bunny = Sprite.new texture
bunny.anchor = Point.new(0.5, 0.5)
bunny.position = Point.new(300, 150)

stage.add_child(bunny)

animate = proc do
  `requestAnimFrame(animate)`
  bunny.rotation += 0.1
  renderer.render stage
end
`requestAnimFrame(animate)`

and here’s the supporting wrapper code:

require 'opal'
# require 'opal-jquery'
module PIXI
  class Stage
    %x{
      #{self}._proto = window.PIXI.Stage.prototype, def = #{self}._proto;
      window.PIXI.Stage.prototype._klass = #{self};
    }

    def self.new(color)
      `new window.PIXI.Stage(color)`
    end

    def add_child(child)
      `#{self}.addChild(child)`
    end
  end

  class WebGLRenderer
    %x{
       #{self}._proto = window.PIXI.WebGLRenderer.prototype, def = #{self}._proto;
      window.PIXI.WebGLRenderer.prototype._klass = #{self};
    }
    def self.new(width, height)
      `new window.PIXI.WebGLRenderer(width, height)`
    end

    def render(stage)
      `self.render(stage)`
    end

    def view
      `self.view`
    end
  end
  class Texture
    %x{
       #{self}._proto = window.PIXI.Texture.prototype, def = #{self}._proto;
      window.PIXI.Texture.prototype._klass = #{self};
    }
    def self.from_image(name)
      `window.PIXI.Texture.fromImage(name)`
    end
  end
  class Sprite
    %x{
       #{self}._proto = window.PIXI.Sprite.prototype, def = #{self}._proto;
      window.PIXI.Sprite.prototype._klass = #{self};
    }
    def self.new(texture)
      `new window.PIXI.Sprite(texture)`
    end
    def anchor
      Point.new `#{self}.anchor.x`,`#{self}.anchor.y`
    end
    def rotation
      `self.rotation`
    end
    def rotation=(r)
      `self.rotation = r`
    end
    def anchor=(a)
      `self.anchor = a`
    end
    def position=(p)
      `self.position = p`
    end
  end
  class Point
    %x{
       #{self}._proto = window.PIXI.Point.prototype, def = #{self}._proto;
      window.PIXI.Point.prototype._klass = #{self};
    }
    def self.new(x,y)
      `new window.PIXI.Point(x,y)`
    end
  end
end

And here’s what it draws:

pixijs_opalrb
 

 

Conversation
  • anon says:

    Your bunny looks dangerously similar to pedobear.

  • Comments are closed.