Jirr を使ったキーボード・イベント処理
Jirr を使った,キーボードイベント処理の簡単なサンプルプログラムです. Jirr のインストールについては,jirr インストールの Web ページを見てください.
キーボード・イベント処理について: MyEventReceiver で,イベントの種類を判別し,所定のイベント(この場合は4つの矢印キー)のとき,内部状態を更新,というプログラムです.
Eclipseでの Jirr プログラム作成手順
- 新規の Java プロジェクトの作成
「ファイル」→「新規」→「その他」→「Java」→「Javaプロジェクト」と操作して, Javaプロジェクト を新規に作成する.プロジェクト名は何でも良い.
- ディレクトリの作成
いま作成した新規プロジェクトを右クリック, 「新規」→「フォルダー」と操作して,ディレクトリを作成する.(ディレクトリ名 mediaにしておくのが良い)
- ディレクトリへのインポート
作成したディレクトリを右クリック.インポートを選び,「ファイルシステム」を選び, C:\Program Files\JIRR\1.4.2\media 下の全ファイルをインポート. ここには,デモプログラムの実行に必要な各種ファイルが入っている.
- ライブラリーの設定
プロジェクトを右クリック, 「プロパティー」→「Java のビルド・パス」→「ライブラリー」→「外部 JAR の追加」と操作し,C:\Program Files\JIRR\1.4.2\lib\jirr142.jar を追加
- (オプション)Java ソースの添付と,Javadoc の設定
- プロジェクト名の下の「参照ライブラリー」を展開すると「jirr142.jar」のような名前の jar ファイルがあるはずなので,右クリック
- まず,「Javaソースの添付」を選び,
「外部フォルダー」をクリックし,ロケーション・パスとして,「Jirr ソースコード・インストールディレクトリ」c:\Program Files\JIRR\<バージョン名>\classes を指定
- 次に,「Javadoc ロケーション」を選び,
「外部フォルダー」をクリックし,Javadocロケーション・パス(アーカイブ内のJavadocで無い方)に,c:\Program Files\JIRR\<バージョン名>\classes\javadoc を指定
- クラスの作成
src を右クリック.次の 2つのクラスを作る.その後,下記のソースコードを貼り付ける.(あとでクラス名を変えるのは,Eclipse のリファクタリングの機能を使って簡単にできる)
- Demo
- システム内部状態
Demo.java
<機能の要点>
- キーボード・イベントの発生により,イベントハンドラ MyEventHandler が呼び出されるように設定
- 矢印キー(4方向)を押すと, add_x(), sub_x(), add_y(), sub_y() が呼び出される(「システム内部状態」の x, y の値が変化する)
- 「システム内部状態」の x, y の値を使い,シーン内に箱 (cube) を置く.その後,描画と,「システム内部状態」の x, y の値による cube の位置の設定を繰り返す.
- q キーを押すと終了
import net.sf.jirr.*;
public class Demo {
// 決まり文句
static {
System.loadLibrary("irrlicht_wrap");
}
// window properties
static String window_caption = "Java@Hello World!";
static int window_width = 640;
static int window_height = 480;
static E_DRIVER_TYPE driver_type = E_DRIVER_TYPE.EDT_OPENGL; // EDT_OPENGL or EDT_DIREXT3D8 or EDT_DIRECT3D9
static boolean is_full_screen = false;
// camera properties
static boolean use_fps_camera = false; // true or false
// 補助的なメソッド
private static IrrlichtDevice create_device( E_DRIVER_TYPE deviceType, int width, int height, boolean fullscreen, IEventReceiver receiver ) {
// デバイスの取得
if ( ( deviceType != E_DRIVER_TYPE.EDT_DIRECT3D9 ) && ( deviceType != E_DRIVER_TYPE.EDT_DIRECT3D8 ) && ( deviceType != E_DRIVER_TYPE.EDT_OPENGL ) && ( deviceType != E_DRIVER_TYPE.EDT_SOFTWARE ) ) {
return null;
}
IrrlichtDevice device = Jirr.createDevice( deviceType,
new dimension2di(width, height), /* bits */ 32, fullscreen, /* stencilbuffer */ false, /* vsync */ false, receiver);
return device;
}
private static IGUIStaticText add_static_text( IGUIEnvironment guienv, int x, int y, int x2, int y2 ) {
// スタティック・テキストの描画
recti rect = new recti(x, y, x2, y2);
IGUIStaticText staticText = guienv.addStaticText( new String(""), rect, true, true, null, -1);
return staticText;
}
private static void font_draw( IGUIFont font, String text, int x, int y, int x2, int y2, long a, long r, long g, long b ) {
//
font.draw( text, new recti(x, y, x2, y2), new SColor( a, r, g, b) );
return;
}
private static ISceneNode add_cube_scene_node( ISceneManager scene, float x, float y, float z ) {
// 立方体 (cube)
// x, y, z は位置, 「光源」を置いていない場合黒くなります
ISceneNode cube = scene.addCubeSceneNode();
cube.setMaterialFlag(E_MATERIAL_FLAG.EMF_LIGHTING, true);
cube.setPosition( new vector3df( x, y, z ) );
return cube;
}
private static ICameraSceneNode add_camera_scene_node( ISceneManager scene, float px, float py, float pz, float tx, float ty, float tz, boolean isFPS ) {
// カメラ
ICameraSceneNode camera;
if ( isFPS ) {
camera = scene.addCameraSceneNodeFPS( /* parent */ null, /* torate speed */ 100.0f, /* move speed */ 300.0f );
} else {
camera = scene.addCameraSceneNode( /* parent */ null );
}
camera.setPosition(new vector3df(px, py, pz));
camera.setTarget( new vector3df(tx, ty, tz));
return camera;
}
static class MyEventReceiver extends IEventReceiver
{
private システム内部状態 state = null;
public void setState(システム内部状態 state) {
this.state = state;
}
public boolean OnEvent(SEvent event)
{
/*
* キーボード・イベントの表示(デバッグ用)
*/
if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT &&
event.isKeyInputPressedDown())
{
// キーが押された.あるいは押し続けられている.
System.out.println( "Press Down: " + event.getKeyInputKey() );
}
if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT &&
!event.isKeyInputPressedDown())
{
// キーが上がった.
System.out.println( "Up: " + event.getKeyInputKey() );
}
/*
* マウス・イベントの表示
*/
if (event.getEventType() == EEVENT_TYPE.EET_MOUSE_INPUT_EVENT) {
System.out.println( "Mouse Event: " + event.getMouseInputEvent() );
}
/*
* ■ キーコードは,マニュアルの Enum EKEY_CODE の項目を見てください ■
*/
if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT &&
event.isKeyInputPressedDown())
{
// 矢印キー(4方向)を押すと, add_x(), sub_x(), add_y(), sub_y() が呼び出される
if ( event.getKeyInputKey() == EKEY_CODE.KEY_KEY_Q ) {
System.exit(0);
} else if( event.getKeyInputKey() == EKEY_CODE.KEY_RIGHT ) {
state.add_x();
}
else if ( event.getKeyInputKey() == EKEY_CODE.KEY_LEFT ) {
state.sub_x();
}
else if ( event.getKeyInputKey() == EKEY_CODE.KEY_UP ) {
state.sub_y();
}
else if ( event.getKeyInputKey() == EKEY_CODE.KEY_DOWN ) {
state.add_y();
}
}
// マウス・イベントが無いときは,マウスホイールの値は 0 にしたい
state.setマウスホイール(0);
if (event.getEventType() == EEVENT_TYPE.EET_MOUSE_INPUT_EVENT) {
switch(event.getMouseInputEvent()) {
case EMIE_MOUSE_MOVED: {
state.setマウスX( event.getMouseInputX() );
state.setマウスY( event.getMouseInputY() );
break;
}
case EMIE_LMOUSE_PRESSED_DOWN: {
state.setマウス左ボタン(true);
break;
}
case EMIE_LMOUSE_LEFT_UP: {
state.setマウス左ボタン(false);
break;
}
case EMIE_RMOUSE_PRESSED_DOWN: {
state.setマウス右ボタン(true);
break;
}
case EMIE_RMOUSE_LEFT_UP: {
state.setマウス右ボタン(false);
break;
}
case EMIE_MOUSE_WHEEL: {
state.setマウスホイール( event.getMouseInputWheel() );
break;
}
}
}
return false;
}
}
public static void main(String argv[]) {
// イベント・レシーバ
システム内部状態 state = new システム内部状態();
MyEventReceiver receiver = new MyEventReceiver();
receiver.setState(state);
IrrlichtDevice device = create_device( driver_type, window_width, window_height, is_full_screen, receiver );
System.out.println("idevice = " + device);
String windowCaption = window_caption;
device.setWindowCaption(windowCaption);
IVideoDriver driver = device.getVideoDriver();
ISceneManager scene = device.getSceneManager();
IGUIEnvironment guienv = device.getGUIEnvironment();
IGUIFont font = guienv.getBuiltInFont();
IGUIStaticText staticText = add_static_text( guienv, /* x */ 10, /* y */ 10, /* x2 */ 280, /* y2 */ 30);
ISceneNode cube = add_cube_scene_node( scene, /* x */ state.getX(), /* y */ state.getY(), /* z */ 0 );
/*
To look at the mesh, we place a camera into 3d space at the position
(0, 10, -40). The camera looks from there to (0,0,0).
*/
ICameraSceneNode camera = add_camera_scene_node( scene, 0, 10, -40, 0, 0, 0, use_fps_camera );
final int step = 1000;
int counter = 0;
double diff = 0;
long timer1 = System.currentTimeMillis();
long timer2 = 0;
while (device.run()) {
int a = 0;
int r = 100;
int g = 100;
int b = 100;
driver.beginScene(true, true, new SColor(a, r, g, b));
scene.drawAll();
guienv.drawAll();
driver.endScene();
try {
// Thread.sleep(5);
} catch (Exception e) {
}
counter++;
if (counter >= step) {
/* FPS の計測 */
timer2 = System.currentTimeMillis();
diff = 1000.0 / ((timer2 - timer1) / (double) step);
counter = 0;
timer1 = System.currentTimeMillis();
/* シーンの更新 */
/* 箱の場所が,矢印キー(4方向)を押すと動く */
cube.setPosition( new vector3df( state.getX(), state.getY(), 0 ) );
/* テキスト描画 */
String text = "x = " + state.getX() + ", y = " + state.getY() + ", FPS: " + (int)diff;
staticText.setText(text);
}
}
device.closeDevice();
}
}
システム内部状態.java
public class システム内部状態 {
private int x = 0;
private int y = 0;
// マウスの状態保持
private int マウスX = 0;
private int マウスY = 0;
private float マウスホイール = 0;
private boolean マウス右ボタン = false;
private boolean マウス左ボタン = false;
public void sub_x() {
x = x - 1;
}
public void add_x() {
x = x + 1;
}
public void sub_y() {
y = y - 1;
}
public void add_y() {
y = y + 1;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getマウスX() {
return マウスX;
}
public void setマウスX(int マウスx) {
マウスX = マウスx;
}
public int getマウスY() {
return マウスY;
}
public void setマウスY(int マウスy) {
マウスY = マウスy;
}
public float getマウスホイール() {
return マウスホイール;
}
public void setマウスホイール(float マウスホイール) {
this.マウスホイール = マウスホイール;
}
public boolean isマウス右ボタン() {
return マウス右ボタン;
}
public void setマウス右ボタン(boolean マウス右ボタン) {
this.マウス右ボタン = マウス右ボタン;
}
public boolean isマウス左ボタン() {
return マウス左ボタン;
}
public void setマウス左ボタン(boolean マウス左ボタン) {
this.マウス左ボタン = マウス左ボタン;
}
}
実行結果の例
実行すると,ウインドウが現れる.そのウインドウをクリックしておく. その後,キーボードを押したり,離したり,押し続けたりすると,そうしたキー操作がイベントとして検出される.
矢印キーにより箱(cube)が動く