アットウィキロゴ

メニューの表示(改)

新しい手法で作成する

  • サンプルのJARファイルはページの一番下(スポンサーリンクよりも↓)に張ってあるので自由にダウンロードしてくださぃ♪
まずはLikeWizardryでのプログラムの効率の悪さを反省&それを参考にしていただいた方にも反省。。。
今回は汎用性が期待できるソースに書き直しましたっ!ものすごく長ぃので、部分的に説明します。
最初に、今回はクラスが5つに分かれてます。なぜそんなに多いのか?
それは各処理に対して役割を分担したからです。キーの処理・共通処理・実行処理・判断処理・描画処理と言った感じでしょうか。
キーの処理に当たるのがActionKeyクラス。(この手法はJavaでゲーム作りますが何か?のサイト様のものです)
共通処理に当たるのがCommonインターフェース。
実行処理に当たるのがLikeWizardryクラス。
判断処理に当たるのがMenuクラス。
描画処理に当たるのはMainPanelクラスになってます。
実行処理に当たるLikeWizardryクラスは処理の変更がないため説明はしません。

まずMainPanelクラスから見ていきます。
基本的にメニューの描画はファイルからの読み取りとなり、クラス内で配列にメニューを定義したりはしません。
ただ、読み込んだファイルを描画しやすくするためにファイルの中を配列に格納する作業はしてます。
つまり{"冒険者の登録","道具屋へ行く",・・・};みたぃな処理はクラス内で行ないませんってことです。

//メニューを読み込む
public void loadMenu(String menuname){
	//メニューの初期化
	showMenu.clear();
	try{
		BufferedReader br=new BufferedReader(new InputStreamReader(
				getClass().getResourceAsStream(menuname)));
		
		String line;
		
		while((line=br.readLine())!=null){
			StringTokenizer st=new StringTokenizer(line,",");
			showMenu.add(st.nextToken());
		}
		
	}catch(IOException ioe){
		ioe.printStackTrace();
	}
}

最初に行なっているshowMenu.clear( );というのはArrayListクラスのshowMenuに格納されている
リストを全て消去するという処理をします。
そしてBufferedReaderからファイルを読み込んでStringTokenizerによってshowMenuに
1行ずつ格納していきます。
今回新しい点は引数にString menunameを受け取っているところです。
これによって描画したいファイルの名前を渡すだけでメニューの描画が切り替わるようになり汎用性のあるものになってます。
続いてMainPanelクラスのpaintComponentです。

public void paintComponent(Graphics g){
	super.paintComponent(g);
	
	//メニューの描画
	for(int i=0;i<showMenu.size();i++){
		g.drawString(showMenu.get(i).toString(),x,y+CL*i);
	}
	
	//カーソルの描画
	g.drawImage(image,dx-CL,dy-CL,this);
	//メニューウィンドウ表示
	g.drawRect(MENU_RECT.x,MENU_RECT.y,MENU_RECT.width,MENU_RECT.height);
	//パーティーウィンドウ表示
	g.drawRect(PT_RECT.x,PT_RECT.y,PT_RECT.width,PT_RECT.height);
}

メニューの描画はArrayListクラスのshowMenuから順番に読み込んでtoString( )で変換してます。
今回の変更点はメニューウィンドウの表示部分です。これをメニューのサイズに合わせてイチイチ書き換えるのは手間です。
そこで今回はMainPanelのrun( )に以下のような処理を加えました。

	//画面に合わせてウィンド位置を変更
	MENU_RECT.height=menu.setRect(MENU_RECT.height);

画面が切り替わったときにそこに表示されるメニューの数を数えて、そのメニュー数に合わせて枠を自動調整する処理です。
この処理の行き先はMenuクラスになってます。以下に処理内容を掲載します。

//画面に合わせてウィンドウ位置を計算する
public int setRect(int rectHeight){
	rectHeight=panel.getMenuSize()*CL+ST;
	return rectHeight;
}

引数でrectHeight(枠線の下のラインの値)を受け取ってます。
このrectHeightをメニュー項目数*文字の高さ+不足分の追加の値にして呼び出し元にその値を返してます。
これによってイチイチメニュー項目数に合わせて処理を行わなくても自動で調整されるわけです。
説明が長いですが、まだまだお付き合いくださぃねっ!
続いてMainPanelクラスのキー処理です。

	//キーが押された時の処理
	if(key==KeyEvent.VK_LEFT){
		leftKey.press();
		
	//キーが離された時の処理
	if(key==KeyEvent.VK_LEFT){
		leftKey.release();
	

それぞれ別の処理ですが、まとめて掲載してます。
これはキーが押された時と離されたときでキー処理を担当しているActionKeyクラスを呼び出してます。
処理内容としてはキーが押されている状態にする。キーが離されている状態にする。というものです。
キー処理に関してはJavaでゲーム作りますが何か?のサイト様のものをそのまま使っているので掲載は控えます。
最後にMenuクラスになります。もう少しなのでお付き合いくださぃっ!
短いのでほぼ全て掲載します。

//メニューの初期化
public Menu(MainPanel panel){
	this.panel=panel;
	flag_Main=true;
}

//メニューの判断
public void selectMenu(){
	//メインメニュー
	if(flag_Main){
		panel.loadMenu("/menu/main01.dat");
		
		//登録メニュー
	}else if(flag_Registration){
		panel.loadMenu("/menu/regist01.dat");
	}
}

//カーソルのdy移動処理
public int dyMove(int dy){

	//dyの最小値は共通
	if(dy<y)dy=y;
	
	//dyの最大値はgetMenuSize()により変化
	if(dy>y+CL*panel.getMenuSize()-CL)
		dy=y+CL*panel.getMenuSize()-CL;

	//dyの値を返す
	return dy;
}

//カーソルのdx移動処理
public int dxMove(int dx){
	//メインメニューの処理
	if(flag_Main){
		dx=x;
	}
	
	//dxの値を返す
	return dx;
}

//スペースキーの処理
public int setSpace(int dy){
	//メインメニュー
	if(flag_Main){
		if(dy==y){
			flag_Registration=true;
			flag_Main=false;
		}
		//登録画面
	}else if(flag_Registration){
		if(dy==y){
		}
		
		if(dy==y+CL*panel.getMenuSize()-CL){
			flag_Main=true;
			flag_Registration=false;
		}
	}
	
	//メニューの判断をし再描画
	selectMenu();
	//再描画後のy位置を初期化
	dy=y;
	//dyの位置を返す
	return dy;
}

新しい手法が盛りだくさんですねっ!(笑)
私的には汎用性があると思って書いているのですがいかがでしょうか?
まず1番の変化はカーソルの移動範囲の制限方法だと思います。コメントに書いてあるので探してもらえると助かりますが
dyの最小値・最大値の表示の部分ですね。
dyの最小値・・・つまりカーソルの移動範囲の最上段の処理です。これは共通してメニューの1番目のラインですょね?
だからメニュー毎に処理を変更する必要はなく常にdy=yでいいのです。(もちろん表示するメニューの位置を変えたら処理も必要です。)
そしてdyの最大値・・・つまりメニューの最下段の位置を求める処理です。
これも共通していてメニューの一番下のラインです。つまり.size( )などでメニューの数を取得できますので、
その数に合わせればいいのです。そして初期位置がメニューの1番目なので、1行分数を引いてやるとぴったりとなります。
ついでにCommonインターフェースも乗せておきます。

//文字サイズの設定
public static final int CL=16;

//座標の初期設定
public static int x=50;
public static int y=50;


これだけですっ!で、これが何かというと、各クラスにimplementsすることで共通して
この値が使えるようになります。なので、MainPanelクラスでCL=16;を定義してMenuクラスでまたCL=16;を定義・・・なんて
面倒なことしなくてもimplementsしたクラスならCLとそのまま使えます。かなり便利ですっ!
以上。その他にも変更点はありますが長すぎて説明できなぃので実際にサンプルを取り込んでみて見て下さい。
最終更新:2008年06月30日 02:33
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。
添付ファイル