2007年 01月 23日

rubyclr を使って、Ruby から joystick を扱ってみる

require 'rubygems'
require 'rubyclr'

reference 'System'
reference 'System.Drawing'
reference 'System.Windows.Forms'

include System::Drawing
include System::Drawing::Drawing2D
include System::Windows::Forms

# Timer 付き Form のセットアップ
Application.enable_visual_styles
Application.set_compatible_text_rendering_default false
form = Form.new
form.StartPosition = FormStartPosition::CenterScreen
form.Text = "><ノ"
form.Size = Size.new(120, 0)

timer = Timer.new
timer.Interval = 50
timer.Enabled = true

# ManagedDirectX Input # DirectX SDK が必要
reference 'Microsoft.DirectX'
reference 'Microsoft.DirectX.DirectInput'

include Microsoft::DirectX
include Microsoft::DirectX::DirectInput

joystick = nil
devices = Manager.GetDevices(DeviceClass::GameControl, EnumDevicesFlags::AttachedOnly)
while devices.MoveNext
	joystick = Device.new(devices.Current.InstanceGuid)
	break
end

joystick.Properties.AxisModeAbsolute = true
joystick.SetCooperativeLevel(form, CooperativeLevelFlags::NonExclusive | CooperativeLevelFlags::Background)
joystick.Acquire

prev = ''
timer.Tick do |sender, args|
	state = joystick.CurrentJoystickState

	on = []
	state.GetButtons.each_with_index do |b,i|
		on << i if b.nonzero?
	end

	out = "X:%s, Y:%s, Z:%s, Buttons:%p" % [state.X, state.Y, state.Z, on]
	unless prev == out
		puts out
		prev = out
	end
end

Application.run form

ManagedDirectX とかいうらしい。
http://web.sfc.keio.ac.jp/~t03792sh/archives/2005/10/manageddirectxj.html を参考にした。

どうも Enumerable なやつがうまくいかなくて困った。.each とか使えるはずなんだけど、エラーがでて使えない。しかたないので普通のイテレータ使ってる。
あと joystick.Objects をイテレータでまわしてると Ruby オブジェクトに変換できないだかなんだかで落ちてしまうのでそこは書いてない。どうするんだろ。

SDL のほうが簡単そう。