トップページ -> コンピュータ実習 -> ゲームエンジン IRRLICHT による画像とグラフィックス -> Jirr を使ったキーボード・イベント処理
[サイトマップへ]  

Jirr を使ったキーボード・イベント処理

サイト構成 連絡先,業績など コンピュータ実習 データの扱い コンピュータ設定 教材(公開) サポートページ

Jirr を使った,キーボードイベント処理の簡単なサンプルプログラムです. Jirr のインストールについては,jirr インストールの Web ページを見てください.

キーボード・イベント処理について: MyEventReceiver で,イベントの種類を判別し,所定のイベント(この場合は4つの矢印キー)のとき,内部状態を更新,というプログラムです.


Eclipseでの Jirr プログラム作成手順

  1. 新規の Java プロジェクトの作成

    「ファイル」→「新規」→「その他」→「Java」→「Javaプロジェクト」と操作して, Javaプロジェクト を新規に作成する.プロジェクト名は何でも良い

  2. ディレクトリの作成

    いま作成した新規プロジェクトを右クリック, 「新規」→「フォルダー」と操作して,ディレクトリを作成する.(ディレクトリ名 mediaにしておくのが良い)

  3. ディレクトリへのインポート

    作成したディレクトリを右クリック.インポートを選び,「ファイルシステム」を選び, C:\Program Files\JIRR\1.4.2\media 下の全ファイルをインポート. ここには,デモプログラムの実行に必要な各種ファイルが入っている.

  4. ライブラリーの設定

    プロジェクトを右クリック, 「プロパティー」→「Java のビルド・パス」→「ライブラリー」→「外部 JAR の追加」と操作し,C:\Program Files\JIRR\1.4.2\lib\jirr142.jar を追加

  5. (オプション)Java ソースの添付と,Javadoc の設定
    1. プロジェクト名の下の「参照ライブラリー」を展開すると「jirr142.jar」のような名前の jar ファイルがあるはずなので,右クリック
    2. まず,「Javaソースの添付」を選び,

      「外部フォルダー」をクリックし,ロケーション・パスとして,「Jirr ソースコード・インストールディレクトリ」c:\Program Files\JIRR\<バージョン名>\classes を指定

    3. 次に,「Javadoc ロケーション」を選び,

      「外部フォルダー」をクリックし,Javadocロケーション・パス(アーカイブ内のJavadocで無い方)に,c:\Program Files\JIRR\<バージョン名>\classes\javadoc を指定

  6. クラスの作成

    src を右クリック.次の 2つのクラスを作る.その後,下記のソースコードを貼り付ける.(あとでクラス名を変えるのは,Eclipse のリファクタリングの機能を使って簡単にできる)

    1. Demo
    2. システム内部状態

Demo.java

<機能の要点>

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)が動く