Jirr を使った文字列描画
Jirr を使った,文字列表示の簡単なサンプルプログラムです. 矢印キーで,文字列 "A" が動く. Jirr のインストールについては,jirr インストールの Web ページを見てください.
要点
MyEventReceiver で,イベントの種類を判別し,所定のイベント(この場合は4つの矢印キー)のとき,システム内部状態 x, y を更新します. 同時に,x, y の位置に所定の文字列 "A" を表示します. また,(0,0)から(x, y)に線分を描きます.
- 文字列の描画: メインメソッド内の beginScene() と endScene() で囲まれた中に,描画命令を「font.draw(...)」のように書いて行う.
- 線の描画: 「driver.draw2DLine(...)」のように書いて行う.
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 の値を使い,文字の描画と,線分の描画を行う.
- 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(); font_draw( font, "A", state.getX(), state.getY(), /* x2 */ 30, /* y2 */ 30, /* a */ 255, /* r */ 255, /* g */ 255, /* b */ 255 ); /* ついでに,線の描画 */ driver.draw2DLine(new position2di(0,0), new position2di(state.getX(),state.getY())); 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(); /* シーンの更新 */ // none /* テキスト描画 */ 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.マウス左ボタン = マウス左ボタン; } }
実行結果の例
矢印キーにより文字「A」と線分の端点が動く
