トップページ -> コンピュータ実習 -> ゲームエンジン IRRLICHT による画像とグラフィックス -> Jirr を使った文字描画2 (月面着陸ゲーム)
[サイトマップへ]  

Jirr を使った文字描画2 (月面着陸ゲーム)

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

Jirr を使った,文字列表示の簡単なサンプルプログラムです. 矢印キーで,文字列 "A" が動きます. Jirr のインストールについては,jirr インストールの Web ページを見てください.

要点

MyEventReceiver で,イベントの種類を判別し,所定のイベント(この場合は4つの矢印キー)のとき,内部状態 x, y を更新します. 同時に,x, y の位置に所定の文字列 "A" を表示す.また,噴射を表す「煙」を表示す.

(参考) Eclipseでの Jirr プログラム作成手順

  1. Java プロジェクトの作成: プロジェクト名は何でもよい
  2. クラスの作成: クラス名は下記の通り
  3. 外部JARの追加

    プロジェクト名を右クリック → Java のビルド・パス → ライブラリー → 外部JARの追加 C:\1.3.1\lib/jirr131.jar を追加

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

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

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

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


Demo.java

import net.sf.jirr.*;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

public class Demo {

   static {
      System.loadLibrary("irrlicht_wrap");
   }
  
   static class MyEventReceiver extends IEventReceiver
	{
        private モデル model = null;
		public void setModel(モデル model) {
			this.model = model;
		}
		
		public boolean OnEvent(SEvent event)
		{
		    /*
             * キーコードは,マニュアルの Enum EKEY_CODE の項目を見てください
             */
			if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT &&
					event.isKeyInputPressedDown())
			{
				if ( event.getKeyInputKey() == EKEY_CODE.KEY_RIGHT ) {
                    model.right();
				}
				else if ( event.getKeyInputKey() == EKEY_CODE.KEY_LEFT ) {
                    model.left();
				}
				else if ( event.getKeyInputKey() == EKEY_CODE.KEY_UP ) {
                    model.upper();
				}
				else if ( event.getKeyInputKey() == EKEY_CODE.KEY_DOWN ) {
                    model.lower();
				}
			     
			    // エスケープキー
			    else if ( event.getKeyInputKey() == EKEY_CODE.KEY_ESCAPE ) {
				    System.exit(0);
			    }
			    // Qキー
			    else if ( event.getKeyInputKey() == EKEY_CODE.KEY_KEY_Q ) {
				    System.exit(0);
			    }
			}
			if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT &&
					!event.isKeyInputPressedDown())
			{
				model.neutral();
			}
			return false;
		}
	}		

   // メイン
   public static void main(String argv[]) {
	  // イベントレシーバ
	  MyEventReceiver receiver = new MyEventReceiver();
	  // 内部状態
	  内部状態 state = new 内部状態();
      state.create_mountain();
	  // 表示
	  表示 view = new 表示();
	  view.setState(state);
	  // モデル
      モデル model = new モデル();
	  model.setState(state);
	  receiver.setModel(model);
	 
	 
	  // デバイス・オープン
	  IrrlichtDevice device = Jirr.createDevice(E_DRIVER_TYPE.EDT_DIRECT3D9,
	            new dimension2di(state.width, state.height),
                /* bits */ 16,
                /* fullscreen */ false,
                /* stencilbuffer */ false,
                /* vsync */ false,
                /* receiver */ receiver);
	 
      System.out.println("idevice = " + device);
      String windowCaption = "Landing Game Demo";
      device.setWindowCaption(windowCaption);
      IVideoDriver driver = device.getVideoDriver();
     
      view.setDevice( device );
      view.buildGUIs();

      while (device.run()) {
        
         driver.beginScene( /* backbuffer */ true,
                 /* zbuffer */ true,
                 new SColor(/* a */ 0, 30, 30, 30));
         model.tick();
         view.drawAll();
         driver.endScene();
         if ( model.landing() ) {
             System.exit(0);
         }
         if ( model.collision() ) {
             System.exit(0);
         }
         try {
            // Thread.sleep(5);
         } catch (Exception e) {
        	 // do Nothing
         }
      }

      device.closeDevice();
   }
}

内部状態.java


public class 内部状態 {
	// width, height は画面サイズ
	public final int width = 640;
	public final int height = 320;
	// 地面
	public int mountain[] = null;
	
	// 着陸船の振る舞い
	// x, y 座標値
	private double x = 0;
	private double y = 30;
	private double vx = 0.2;
	private double vy = 0;
	private double ax = 0;
	private double ay = 0;

    /*
     * 正規分布に近い乱数の発生
     */
    private double my_random( int n ) {
        int i;
        double r;
        r = 0;
        for ( i = 0; i < n; i++ ) {
        	// Math.random()は0以上1未満の乱数
        	r = r + Math.random();
        }
        return r;
    }
    public void create_mountain() {
    	int DIST = 30; // 分散値
    	double HH = height / 8; // 平均高さ
        mountain = new int[ width ];
        mountain[0] = height - (int)my_random( height / 2 );
        for ( int i = 1; i < width; i++ ) {
            mountain[i] =
            	(int)( (double)mountain[i-1] + my_random( height / DIST ) - ( height / ( 2 * DIST ) )
                + ( ( height - mountain[i-1] ) / HH ) - 1 );
        }
    }
   
	/*
	 * セッター,ゲッター
	 */
	public double getX() {
		return x;
	}
	public void setX(double x) {
		this.x = x;
	}
	public double getY() {
		return y;
	}
	public void setY(double y) {
		this.y = y;
	}
	public double getVx() {
		return vx;
	}
	public void setVx(double vx) {
		this.vx = vx;
	}
	public double getVy() {
		return vy;
	}
	public void setVy(double vy) {
		this.vy = vy;
	}
	public double getAx() {
		return ax;
	}
	public void setAx(double ax) {
		this.ax = ax;
	}
	public double getAy() {
		return ay;
	}
	public void setAy(double ay) {
		this.ay = ay;
	}
}

モデル.java

import net.sf.jirr.SColor;
import net.sf.jirr.recti;

public class モデル {

	// エンジンパワー
	public final double power = 0.0002;
	// 重力
	public final double gravity = 0.0001;

    private 内部状態 state = null;
	public void setState(内部状態 state) {
		this.state = state;
	}
	
	/*
	 * 噴射
	 */
	public void upper() {
		this.state.setAx( 0 );
		this.state.setAy( this.power );
	}
	public void lower() {
		this.state.setAx( 0 );
		this.state.setAy( -this.power );
	}
	public void left() {
		this.state.setAx( this.power );
		this.state.setAy( 0 );
	}
	public void right() {
		this.state.setAx( -this.power );
		this.state.setAy( 0 );
	}
	public void neutral() {
		this.state.setAx( 0 );
		this.state.setAy( 0 );
	}
	/*
	 * 単位時間進める処理
	 */
	void tick() {
        state.setVx( state.getVx() + state.getAx() );
        state.setVy( state.getVy() + state.getAy() + gravity );
        state.setX( state.getX() + state.getVx() );
        state.setY( state.getY() + state.getVy() );
	}
	/*
	 * 衝突判定
	 *
	 */
    public boolean collision() {
    	if ( state.getY() > ( state.mountain[(int)state.getX()] - 4 ) ) { return true; };
    	if ( state.getX() < 0 ) { return true; };
    	if ( state.getX() > state.width ) { return true; };
    	if ( state.getY() < 0 ) { return true; };
        if ( state.getY() > state.height ) { return true; };
        return false;
    }
    public boolean landing() {
    	if ( state.getY() > ( state.mountain[(int)state.getX()] - 4 ) && ( state.getVy() > -0.001 ) && ( state.getVx() < 0.001 ) && ( state.getVy() < 0.001 )) {
    		return true;
    	}
    	return false;
    }

}

表示.java

import net.sf.jirr.*;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

public class 表示 {
    private 内部状態 state = null;
	public void setState(内部状態 state) {
		this.state = state;
	}
	/*
	 * Irrlicht 関係
	 */
	private IrrlichtDevice device = null;
	private IVideoDriver driver = null;
	private ISceneManager smgr = null;
	private IGUIEnvironment guienv = null;
	private IGUIFont font = null;
	public void setDevice(IrrlichtDevice device) {
		this.driver = device.getVideoDriver();
	    this.smgr = device.getSceneManager();
	    this.guienv = device.getGUIEnvironment();
        this.font = guienv.getBuiltInFont();
	}
	void buildGUIs() {
        // このプログラムでは,GUI は無い.書き方の見本をコメント形式で載せている.
	      // String text = new String();
	      // recti rect = new recti(10, 10, 400, 30);
	      // IGUIStaticText staticText = this.guienv.addStaticText(text, rect, true, true, null, -1);
	}
	void drawAll() {
        smgr.drawAll();
        guienv.drawAll();
        this.font.draw("x = " + state.getX() + ", y = " + state.getY(), new recti( 10, 10, 300, 30 ), new SColor(/* a */255, 255, 255, 255));
        // 着陸船
        this.font.draw("A", new recti( (int)state.getX(), (int)state.getY(), 30, 30 ), new SColor(/* a */255, 255, 255, 255));
        // 噴射
        if ( state.getAx() < 0 ) {
        	this.font.draw("<", new recti( (int)state.getX() + 8, (int)state.getY(), 30, 30 ), new SColor(/* a */255, 255, 255, 255));
        }
        if ( state.getAx() > 0 ) {
        	this.font.draw(">", new recti( (int)state.getX() - 8, (int)state.getY(), 30, 30 ), new SColor(/* a */255, 255, 255, 255));
        }
        if ( state.getAy() < 0 ) {
        	this.font.draw("||", new recti( (int)state.getX() + 1, (int)state.getY() + 8, 30, 30 ), new SColor(/* a */255, 255, 255, 255));
        }
        if ( state.getAy() > 0 ) {
        	this.font.draw("||", new recti( (int)state.getX() + 1, (int)state.getY() - 8, 30, 30 ), new SColor(/* a */255, 255, 255, 255));
        }
        // 地面
        for ( int i = 1; i < state.width; i++ ) {
            if ( ( state.mountain[i-1] < state.height ) && ( state.mountain[i] < state.height ) ) {
                driver.draw2DLine(new position2di(i-1,state.mountain[i-1]), new position2di(i,state.mountain[i]));
            }
        }
	}
}