WebSDL - Ruby/SDL × WebSocket/Canvas

投稿者 nanki 2010-06-23 02:42:00 GMT

Ruby勉強会@関西44の懇親会にて @cyross, @KazkiMatz さんらとSDLをWebSocketと組み合わせて…という話をしていておもしろそうだったので実装してみた。

websdl
青は@nanki, 赤は@ujm

github - WebSDL

  1. Ruby/SDLの画面描画を全て文字列としてシリアライズし、WebSocketで送信、Canvasに描画する。
  2. ブラウザ上で発生したイベントをWebSocketで送信、SDLのイベントモデルの中に還元してやる。

というのが基本的な仕組み。

# samples/sample1.rb
require 'rubygems'
gem 'rubysdl'
require 'sdl'
require 'websdl'

class TestFrame < Frame
  attr_reader :mx, :my, :color

  def initialize
    @color = 0xff000000 | (1..3).inject(0){|r,i|r << 8 | rand(0xff)}
    @mx = -100
    @my = -100
  end

  def open_screen
    SDL::Screen.open(640, 480, 32, SDL::HWSURFACE || SDL::DOUBLEBUF)
  end

  def mainloop(screen)
    screen.fill_rect(0, 0, screen.w, screen.h, 0)

    while event = SDL::Event.poll
      @mx, @my = event.x, event.y if SDL::Event::MouseMotion === event
    end

    frames.each do |f|
      screen.fill_rect(f.mx - 15, f.my - 15, 30, 30, f.color)
    end
    
    screen.flip
  end
end


SDL = WebSDL if ARGV.first == 'web'

SDL.init(SDL::INIT_VIDEO)
SDL.run(TestFrame, :host => '0.0.0.0', :port => 3000)

上記のようなコードで、

$ rsdl -Ilib samples/sample1.rb

ではSDLのウィンドウが起動し、

$ ruby -Ilib samples/sample1.rb web

でWebSDL版が起動するようになっている。 WebSDL版はsamples/test.html をWebSocket, Canvasに対応したブラウザで開く。

ただCanvasを使うだけでは芸が無いので、マルチユーザに対応、ユーザ間の情報共有にも対応してみた。

言うまでもなくProof of Conceptの段階であり、SDLの機能もdraw_rect, MouseMotion くらいしか実装していない。

また、0.1秒毎に更新しているのがかっこわるいが、適切なイベントに基づいた処理をすれば、パズルゲームやアドベンチャーゲームなど頻繁に画面更新のないものなら実用的なものができる可能性がある。 ウェブへぇボタンとかね。

問題点

一方、SDLのAPIは同期的なものもあり、SDL::Surface#get_pixel (画面上のピクセルの色を返す) などは現在の方法では実現が困難である。

参考:

これを動かしてみたくなった。

スーパーマリオブラザーズをRubyで作ってみた - I am Cruby!

まず、portsでSDLを入れる。

℗ sudo port install libsdl +quartz
℗ sudo port install libsdl_image libsdl_mixer libsdl_ttf rb-rubysdl

つぎに、こちらのサイトを参考にrsdlのソースをコンパイルして、バイナリをパスの通ったどこかに置く。

℗ wget http://www.kum...
℗ tar zxf rsdl[TAB]
rsdl/        rsdl.tar.gz

あ、あれ?

℗ which rsdl
/opt/local/bin/rsdl

ひゃぁ、入ってる。

本来はこうなったはず。

$ ./configure.rb
$ make
$ cp ./rsdl ....#どこかパスの通ったところ。

これで、

ꐪ rsdl -Irskit main.rb  

で起動できて遊べるのだが、ブロックの上のクリボーを下からたたくと落ちる。 SGEが無いらしい。

macportsにはいらっしゃらないうえに、素直にはmakeできないとか。 こちらこちらを参考に、Makefileにパッチを当てればOKらしい。 二度と見たくないので、Portfileを作ってcodereposに置いておいた。

適当な場所にsvn coして、

/opt/local/etc/macports/sources.confに次の一行を加える。(パスはcoしたパス)

# /opt/local/etc/macports/sources.conf
file:///Users/.../coderepos/config/ports/ [nosync]

さらに、portsディレクトリの中でportindexすれば使えるようになる。

ꐪ sudo port install libsdl_sge

念のためRuby/SDLを入れ直して、めでたしめでたし。 動いた。 mariobros

参考:


Thinkpad の加速度センサをRubyから使う

投稿者 nanki 2006-03-13 01:36:00 GMT

今回の第9回 Ruby勉強会@関西での初級者レッスンは、「わかりやすいRubyのコードを書こう」という題で、小波ゼミの学生さんのコードを元に、わかりやすくしていく、という内容。

元々のソースコードがLeap-Frog法という数値計算の手法で運動方程式を解く、というものだったので、前日に調べておいたThinkpadの加速度を読む方法を早速組み込んでみた。 (前日に調べたのは読み出す方法までで、結果がどう値に対応してるのか調べるために、こっそりPCを振るのに苦労した)

Thinkpadを傾けると、そっちの方向に重力が働くというもの。

Rubyでの情報の可視化や入力インターフェースのものめずらしさもあってか、懇親会での受けが結構よかったので公開します。 * leap-frog.zip

加速度が変わりまくるので、コード中の方法ではあんまり意味がないような。

会場からは、最適化に関する質問や、誤差に関する指摘が多かっただけにちょっと心配だけど、本質はそっちじゃないので目を瞑ってください。

  • ドライバと直接通信、しかも仕様がよくわかってないから適当、ということをやっているので、加速度センサ付きThinkpadでも動かない可能性があります。
  • 昔 mimio と通信してた時は、変なデータを送ると画面が真っ青になったりしました。
  • sensor.dllのAPIを呼び出すのが正当なやり方。

  • テスト環境は、T43,WindowsXP,ActiveScriptRuby1.8.4,Ruby/SDL1.0.0Windows用binary。

Thinkpad以外のノートPCにも加速度センサを搭載しているものがあるらしいので、頑張れば動くかも。

次回の勉強会、みんなでThinkpadをフリフリしましょう。

参考

Ruby/SDL

ActiveScriptRuby

Thinkpad加速度センサを使ったソフトウェア・リンク集