mieki256's diary



2016/01/11(月) [n年前の日記]

#1 [dxruby][dxrubyws] DXRubyWSを試してみる

自作キャラグラエディタを書いてる際、「これがもし、DXRubyWS を使っていたら、もう少し楽に書けるのだろうか…」と気になってきたわけで。ということで、少し触ってみて雰囲気だけでも掴んでみようかなと。

DXRubyWS って何だ? …Ruby + DXRuby を使って、GUIアプリを書けるようにするためのライブラリ、という説明でいいのでしょうか。ちょっと違う気もするけど。

初心者向けに、入門記事っぽくなるように、少し細かくメモっていきますよ、と。いや、自分がそもそも初心者だけど。

環境構築その1。 :

DXRubyWS は、以下から入手。

_mirichi/DXRubyWS

右上のほうに「Download ZIP」というボタンがあるのでクリック。DXRubyWS-master.zip をDL(ダウンロード)。

ちなみに、そのうち DXRubyWSの開発が進んで、どの時期の版か分からなくなると困るので、DXRubyWS-master_20160111.zip てな感じに日付を入れてリネームしておくことにする。

さて。DXRubyWS の readme.md には、 「DXRuby1.5.16dev用」 と書いてある。どうやら、動かすためには DXRuby 1.5 開発版(dev版)が必要らしい。

DXRuby開発版(dev版)は、以下から入手できる。

_DXRuby プロジェクトWiki - ファイル置き場

現在公開されてるのは、DXRuby 1.5.19dev (Ruby 2.1.0, 32bit用)。上記ページ内の該当リンクをクリックすれば、dxruby1519dev-mswin32-ruby21.zip をDLできる。

もし、Ruby 2.1 をインストール済みで、かつ、常用してる環境なら…。dxruby1519dev-mswin32-ruby21.zip を解凍後、中に入ってる install.rb を実行するだけで DXRuby dev版のインストールは終了して、DXRubyWS を動かせる状態にできる。

が、しかし。

環境構築の続き。複数のRubyバージョンを共存させる。 :

自分は普段、Ruby 2.0.0 + DXRuby 1.4.2 を使っていて。

DXRuby 1.5.19dev は、Ruby 2.1 用なので、Ruby 2.0.0 を常用してる自分の環境ではインストールできない。

なので、Ruby 2.1 もインストールして、Ruby 2.0.0 と共存させることにする。

以下から、Ruby 2.1 Windows版を ―― rubyinstaller-2.1.7.exe をDLして実行してインストールする。

_Downloads - RubyInstaller for Windows

注意点としては…。
  • Ruby 2.0.0 とは違う場所を指定してインストールする。Ruby 2.0.0と共存させたいので。
  • 「Rubyの実行ファイルへ環境変数PATHを設定する」「.rbと.rbwファイルをRubyに関連付ける」のチェックは外す。普段は Ruby 2.1 ではなく、Ruby 2.0.0 を使いたいため。

Ruby 2.0.0 と 2.1 の切り替えは、pik か uru を使う。以下の記事を参考にして、インストール方法や使い方を把握。

_pikの替わりにuru〜windowsで複数バージョンのrubyを切り替える〜 - Qiita
_Windows7にRubyInstaller+Pikで複数バージョンのRuby環境を整える - ひろうぃんの雑記

ところで、pik や uru を使って Ruby のバージョンを切り替えた時は、Rubyスクリプト(.rb) をいきなり実行せず、
ruby hoge.rb
といった形で実行しないといけない。.rb をいきなり実行すると、常用してる Ruby のほうが使われてしまうので。

とりあえず、これで Ruby 2.1 を使えるようになったはず。pik か uru で、Ruby 2.1 に切り替えて、Ruby のバージョンを確認。ruby --version で確認できる。ruby 2.1.7p400 と表示されたら、Ruby 2.1 に切り替えができてる。

DXRuby dev版を、ruby install.rb を実行してインストール。

インストールされた DXRuby のバージョンを、irb上で確認してみる。

irb は、Rubyを対話的に入力して実行するためのツール。…「対話的」って、どゆこと? インタラクティブってこと。(命令を伝えたら)その場で反応が返ってくるものを、「対話的」とか「インタラクティブ」と呼んだりします。たぶん。
> irb
irb(main):001:0> require 'dxruby'
=> true
irb(main):002:0> DXRuby::VERSION
=> "1.5.19dev"
irb(main):003:0> exit
DXRuby::VERSION には、"1.5.19dev" が入ってたので、ちゃんと DXRuby dev版がインストールできていることが分かる。

と、ここまでメモったところで気が付いた。DXRubyWS の readme.md には「DXRuby1.5.16dev用」と書いてある…。DXRuby 1.5.19dev、じゃなくて、1.5.16dev…。

_DXRuby プロジェクトWiki - ファイル置き場 には、DXRuby1.5.16dev ruby2.0.0(32bit)用があるわけで。

つまり、Ruby 2.0.0 を使ってるなら、1.5.16dev をインストールすれば DXRubyWS を使えた可能性が。わざわざ Ruby 2.1 までインストールする必要は無かったのかもしれない…。

まあ、何かしらで Ruby 2.1 が必要になる時もあるだろうから、各バージョンを共存させといても別にいいよな。などと嘯いて自分を納得させるのでした。

DXRubyWSのサンプルを動かしてみる。 :

DXRubyWS-master.zip を解凍すると、sampleフォルダが入ってる。中に入って、一通り動かしてみる。

ruby minsample.rb
minsample_ss.png
色んなウィジェット(GUI部品/コントロール)が出てきた。
  • ボタン
  • ラベル
  • テキストボックス
  • ドロップダウンリスト
  • チェックボックス
  • ラジオボタン
  • リストボックス
  • リストビュー
少なくとも、これだけのウィジェット種類が、用意されているのだな…。

各ウインドウは、位置変更のみならず、サイズ変更もできる。サイズ変更に追随しないレイアウトと、サイズ変更に追随するレイアウトが実現できているらしい。

ただし、一番大元の、背景色が黒のウインドウは、サイズ変更ができなかった…。

DXRubyを使ったスクリプトも、ウインドウサイズを変更すると中の描画がおかしくなる時があるので、DXRubyWSも似たような制限があるのかもしれない。が、それってつまり、デスクトップサイズに合わせてウインドウサイズを変更できない、作業しやすいウインドウサイズに変更できないということで、GUIアプリを作る場合は少々厳しい場面が出てくるような気もするのだけど、今はそのあたり考えないことにする。


ruby rubima.rb
rubima_ss.png
ウインドウの中で、おそらくは60FPSのゲームが動いてる…。敵オブジェクトをクリックすると、そのオブジェクトが選択されて、右側のウインドウ内に敵の情報(HP)が表示される。自爆ボタンを押すと選択中の敵が爆発して画面から消えたので、ゲーム内のオブジェクトに対して外部から制御ができるよ、というデモなのかもしれない。


ruby rubima3.rb
rubima3_ss.png
ウインドウの中でゲームを動かしながら、BGの表示位置を別ウインドウ内に表示できている。しかも、タイルチップを選んで、真ん中のウインドウ内でBGマップに書き込むと、ゲーム内のBG表示もソレに合わせて変化する。

ゲームを動かしながら、リアルタイムでその見た目を変更できてしまうあたり、凄いというか、面白いというか。Unityも、ここまではできなかったような気がする。…と言っても、Unityは、GUIでかなりの設定・指定ができるあたりが売りだろうから、比べるのもおかしい気がするけど。提供してる便利さが、そもそも違うというか。


ruby soundblock.rb
soundblock_ss.png
音の波形っぽいものが出てきた。Playボタンを押すと音が鳴る。スライダー、スピンボタン(スピンボックス?)が表示されていて、それぞれを変更してからPlayボタンを押すと音が変化することが分かる。

ソース内には、「簡易FM音源」と書いてあった。FM音源…懐かしい…。いや、今もDTMの世界ではフツーに現役ですが。


ruby splitcontainertest.rb
splitcontainertest_ss.png
もしかすると、コンテナを実現できているというデモだろうか…。「パネルE」と書かれてる部分はグループボックス? ラベル付パネル? なのかもしれない。パネルの中に、複数のウィジェットを配置できますよ、ということなのかな。


ruby statuswindow.rb
statuswindow_ss.png
これは何のデモか分からなかった…。


ruby tabtest.rb
tabtest_ss.png
タブの表示ができていて、かつ、スクロールバーもついていて中身をスクロールできる。


ruby test_autolayout.rb
test_autolayout_ss.png
各ウインドウのサイズを変更すると、中のウィジェットのサイズもソレに合わせて追随する。自動レイアウトのデモだろうか。


てなわけで、既に色々なウィジェットが使えそうなことが伝わってきた。

長くなってきたので、続きは別記事に分けて書こう…。

#2 [dxruby][dxrubyws] DXRubyWSのチュートリアル文書に従って試してみる

DXRubyWS を解凍すると、中に doc フォルダが入っていて、そこに説明文書が置いてある。

_tutorial01.txt と、 _tutorial02.txt が、チュートリアル文書(= 使用方法や機能を解説する教材のようなもの)らしい。

まずは、tutorial01.txt を写経して動作確認してみることにする。

ちなみに、スクリプトの置き場所は、libフォルダと同じ階層。
place.png

最も簡単なコード。 :

_tuto01.rb
require_relative './lib/dxrubyws'

Window.loop do
  WS.update
end
tuto01.png
真っ黒な画面が表示された。

要するに、DXRubyWS を使いたい時は、
  • 最初のほうに、「require_relative './lib/dxrubyws'」と書いておく。
  • 最後のほうで、「Window.loop do」「WS.update」「end」と書いておく。
としておけばいいんだよ、ってことなんだろう…。

マウスに反応させてみる。 :

_tuto02.rb
require_relative './lib/dxrubyws'

font = Font.new(32)

WS.desktop.add_handler(:mouse_push) do
  # マウスボタンが押されたら(「:mouse_push」のシグナルが来たら)…
  
  # 画面に「click!」と表示する
  Window.draw_font(0, 0, "click!", font)
end

Window.loop do
  WS.update
end
tuto02.gif
マウスボタンを押すと、画面に「click!」と表示された。たしかに、マウスに反応している。

DXRubyWS は、 _イベントドリブン で書いていく、らしい。…イベントドリブンって何だ? 何かのイベントが起きた時、そのイベントに対応した処理をするよ、ってこと。

例えば、このサンプルの場合は、「マウスボタンが押された」というイベントが発生したら、「画面に文字を描画する」という処理をしろや、と、WS.desktop.add_handler 〜 end のあたりで設定してある。だから、マウスボタンを押すと、画面に「click!」と表示されたわけで。

もし、イベントドリブンでは無い書き方をするとしたら…。例えば DXRuby で同じ処理を書くとしたら、たぶんこうなる。

_tuto02_b.rb
require 'dxruby'

font = Font.new(32)

Window.loop do
  
  # マウスボタンが押されたか、毎フレームチェックし続けて
  if Input.mousePush?(M_LBUTTON)
    # ボタンが押されてたら、画面に「click!」と表示する
    Window.draw_font(0, 0, "click!", font)
  end
  
end
毎フレーム、毎フレーム、「マウスボタンが押されたか?」「マウスボタンが押されたか?」と、飽きもせず、毎回毎回、延々と監視し続けて、もし押されてたら…という感じになる。

まあ、おそらく内部的には、イベントドリブンとやらも似たようなことを ―― 何かしらをずっと監視し続けて、とかやってると思うのだけど。プログラムを書く人間様としては、「○○が起きた時に、○○せよ」てな感覚でソースを書いていったほうが分かりやすいところがあるので、イベントドリブンなる概念があるのだろうな、などと想像してみたり。人間様が分かるように、面倒臭いところを上手に隠して、分かりやすいところだけ提供するってのは、プログラミングにおいては大事。

コントロールを作って、マウスで動かす。 :

コントロールって何だ? GUI部品、ウィジェットのこと。ボタンとか、ラベルとか、チェックボックスとか、そういうGUI部品を、ウィジェットとかコントロールとか呼んだりする、のだと思います。たぶん。ちょっと自信ないけど。

tuto03.rb
require_relative './lib/dxrubyws'

control = WS::WSControl.new(200, 100, 100, 100)
control.image = Image.new(100, 100, C_WHITE)
WS.desktop.add_control(control)

Window.loop do
  WS.update
end
tuto03.png
画面の真ん中に、白い何かが表示された。たぶん、この白い何かが、コントロール、なんだろう。

このサンブルの場合、
  • WS::WSControl.new() でコントロールを作って、
  • Image.new() で真っ白な画像を作り、ソレをコントロールが持ってる画像として設定して
  • WS.desktop.add_control() で、画面に登録。
しているのだろうな…。

このコントロールを、マウスで動かしてみる。

_tuto03_b.rb
require_relative './lib/dxrubyws'

control = WS::WSControl.new(200, 100, 100, 100)
control.image = Image.new(100, 100, C_WHITE)

control.extend WS::Draggable
control.add_handler(:drag_move) do |obj, dx, dy|
  control.x += dx
  control.y += dy
end

WS.desktop.add_control(control)

Window.loop do
  WS.update
end
tuto03_b.gif
白い画像を、マウスドラッグで移動できるようになった。

そろそろ分からなくなってきた。以下が追加された部分。
control.extend WS::Draggable
control.add_handler(:drag_move) do |obj, dx, dy|
  control.x += dx
  control.y += dy
end
tutorial01.txt によると…。control.extend WS::Draggable てのが、サポートモジュールとやらを使う指定っぽい。名前からしてマウスドラッグ関係の何かなんだろうな。

:drag_move というシグナルが来たら(イベントが発生したら)、マウスカーソルの移動量を得られるから、それをコントロールの座標値に加算してやることで、コントロールの表示位置が変更できている、のだろう。

ドラッガブル豆腐クラスを作る。 :

tutorial01.txt によると、この後、「ドラッガブル豆腐クラス」とやらを作ってみるよ、てことになってるのですが。ここで問題発生。

ちなみに、豆腐って何? …DXRubyでは、例の白い画像を「豆腐」と呼んでることが多くて。要するに、「ドラッガブル豆腐」=「マウスでドラッグできる白い画像」、なんだと思います。たぶん。

_tuto04.rb
require_relative './lib/dxrubyws'

module WS
  class DraggableTofu < WSControl
    include Draggable

    def initialize(x, y, width, height)
      super
      self.image = Image.new(width, height, C_WHITE)
      self.add_handler(:drag_move, self.method(:on_drag_move))
    end

    def on_drag_move(obj, dx, dy)
      self.x += dx
      self.y += dy
    end
  end
end

tofu = WS::DraggableTofu.new(200, 100, 100, 100)
WS.desktop.add_control(tofu)

Window.loop do
  WS.update
end

動かしてみたら、エラーが。
> ruby tuto04.rb

tuto04.rb:17:in `on_drag_move': wrong number of arguments (2 for 3) (ArgumentError)
        from C:/home/prg/ruby/test_dxruby/dxrubyws_test/lib/module.rb:132:in `on_mouse_move'
        from C:/home/prg/ruby/test_dxruby/dxrubyws_test/lib/core.rb:112:in `mouse_event_dispatch'
        from C:/home/prg/ruby/test_dxruby/dxrubyws_test/lib/dxrubyws.rb:118:in `update'
        from C:/home/prg/ruby/test_dxruby/dxrubyws_test/lib/dxrubyws.rb:165:in `update'
        from tuto04.rb:28:in `block in <main>'
        from tuto04.rb:27:in `loop'
        from tuto04.rb:27:in `<main>'
on_drag_move ってところで、何かを間違えてるっぽいけど…。

_Rubyのエラーメッセージwrong number of arguments (a for b)の意味 - Qiita によると、
tuto04.rb:17:in `on_drag_move': wrong number of arguments (2 for 3) (ArgumentError)
てのは、3つ引数が来るはずなのに、2つ来たよ、という意味なのかな…。

つまり、def on_drag_move(obj, dx, dy) は、obj, dx, dy の、3つの引数が書いてあるけど、この名前のメソッドは、本当は2つしか引数が無いはずやで? 間違えてるで? みたいな?

lib/module.rb を開いて、on_drag_move で検索してみたり。

    def on_drag_move(tx, ty)
      signal(:drag_move, tx, ty)
    end
うむ。引数は2つですね。なら、2つに修正すればいいのかな。

_tuto04_b.rb
require_relative './lib/dxrubyws'

module WS
  class DraggableTofu < WSControl
    include Draggable

    def initialize(x, y, width, height)
      super
      self.image = Image.new(width, height, C_WHITE)
      self.add_handler(:drag_move, self.method(:on_drag_move))
    end

    # def on_drag_move(obj, dx, dy)
    def on_drag_move(dx, dy)
      self.x += dx
      self.y += dy
    end
  end
end

tofu = WS::DraggableTofu.new(200, 100, 100, 100)
WS.desktop.add_control(tofu)

Window.loop do
  WS.update
end
tuto04_b.gif
動いた。豆腐をマウスでドラッグできてる。

要するに、こんな感じでコントロール(ウィジェット/GUI部品)を、クラスとして作って増やしていけますよ、ということなのかな…。

これで _tutorial01.txt の内容は一通り試せた。

_tutorial02.txt では標準GUIの使い方が説明されているらしい。明日、眺めてみることにしよう…。

以上、1 日分です。

過去ログ表示

Prev - 2016/01 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project