金子邦彦研究室人工知能,実世界DBJava でキーボード,マウス,テキスト描画,2次元グラフィックス,画像描画(Java, Jirr を使用)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.マウス左ボタン = マウス左ボタン;
    }
}

実行結果の例

実行すると,ウインドウが現れる.そのウインドウをクリックしておく. その後,キーボードを押したり,離したり,押し続けたりすると,そうしたキー操作がイベントとして検出される.

[image]

矢印キーにより箱(cube)が動く

[image]