前置き
RGSS3みたいな「ゲーム系のアプリケーションでキー入力を取得したい」
そういう時に使えるかもしれないお話。
※古いRuby1.9ぐらいの話なので、Win32APIみたいなdllの呼び出しは
また新しいバージョンだと話が変わってきたりすると思う。自分は詳しくないけど。
Win32APIの概要
APIとは略さずに言うと "Application Programming Interfaces" と言うらしく、
Win32APIとはなんぞやというのをざっくりとまとめるなら、
「Windowsの機能をプログラムから簡単に呼び出すための仕組み」と言える。
Rubyの「Win32API」クラス
Rubyには「Win32API」というクラスがある。
これはその名の通りWin32APIを介してWindowsの機能を呼び出すことができる。
実際には単純にdllファイルの機能を呼び出すことが出来るクラスであるため、
自作したdllをRubyで読み込んで使用するといったことも可能。
Win32APIで出来ること
Windowsのアプリケーションで出来ること、と言ったら
多岐に渡りすぎるので全て紹介することは不可能だが、簡単な所で言うと
- ウィンドウの作成、移動
- ファイル・ディレクトリの操作
- マウス・キーボード入力の取得
などが挙げられる。
他にもなんやかんやと描画したり、IMEに入力された文字を取得したりとか…
挙げてたらキリがないと言えば、その通りである。
Rubyは基本、コンソール上で動かすので、Win32APIと関わることは通常、無い。
RPGツクールの「RGSS」みたいに「Rubyの延長線上でWindowsアプリケーションを動かす」
といった場合に、必要になる技術と言える。
実装
とりあえず簡単に。
キーボードの「A」が押されたら"A"と出力するだけのコード。
# encoding: utf-8 require "win32api" get_key_state = Win32API.new('user32', 'GetKeyState', 'i', 'i') while true state = get_key_state.call(65) if state & 0xFF00 > 0 puts "A" end sleep(0.01) end
解説
とりあえずRubyのWin32APIは組み込みではないのでrequireを忘れずに。
(RGSS3では要らないよ!)
Win32APIクラスの初期化
new時には以下の4つの引数が必要。
引数 | 型 | 説明 |
---|---|---|
dll_name | String | 機能(関数)を呼び出すdllの名称 |
func | String | 呼び出す関数の名前 |
import | String またはStringの配列 |
関数に渡す引数の「型」 |
export | String | 関数が返す値の「型」 |
import, exportで指定する型には以下の文字列を使用。
型 | 文字 |
---|---|
ポインタ | 'p' |
long | 'l' |
int | 'i' |
void | 'v' |
今回のキーボード入力の取得に使うWin32APIクラスの初期化は以下のようになる。
get_key_state = Win32API.new('user32', 'GetKeyState', 'i', 'i')
キーボード入力の取得にはUser32.dll内のGetKeyState関数を使用する。*1
引数には入力を取得したいキーの「仮想キーコード」を渡す。
仮想キーコードはキーボード上の各キーを識別するための数値である。int型。
例えばEnterキーの入力取得をしたければ13、
アルファベットのAキーを取得したければ65などと細かく決まっている。
仮想キーコード一覧は調べれば出てくる。
返り値は指定したキーの入力状態が返ってくる。
関数の呼び出し
では早速GetKeyState関数を呼び出してみる。
呼び出しには「.call」するだけ。そのまんまだね。
get_key_state.call(65)
引数には取得したいキーの仮想キーコードを指定。
今回はAキーを取得したいので65を指定。
キーの押下判定
取得したキーの状態は16Bitの整数で表されており、
キーが押されている場合は、16Bitの内の上側8Bitが全て立つ。*2
つまり、キーが押下中かどうかを判定するには、ビット演算で上側8Bitを抽出し、
その値が0を超えているかで判定すればいい、ということになる。
state = get_key_state.call(65) if state & 0xFF00 > 0 # キーが押されている場合の処理 end
…と、このようにしてキー入力が取得できる。意外と簡単?
まとめ
意外とキー取得は回りくどい!!
まぁRubyはWindowsアプリケーションであることを
前提としてない?ので当然といえば当然だが。
余談だがこのdll呼び出しは結構重い。ので、
「Rubyで計算するのは遅いから、dll上はC++だしそっちで動かせば速いんじゃね?」
とかいう邪道に手を出そうとして失敗したことがあったりする。
もうそれ、Ruby使ってる意味よ…?
おまけ(役立ちそうなリンク)
● User32の関数一覧
Winuser.h ヘッダー - Win32 apps | Microsoft Learn
● Kernel32の関数一覧
Winbase.h ヘッダー - Win32 apps | Microsoft Learn
● 仮想キーコード一覧
KT Software - 仮想キーコード一覧
仮想キーコード (Winuser.h) - Win32 apps | Microsoft Learn