MAGI JAVA -Make a game in Java-
JAVA Game作成講座 008回
マップチップからマップを描画する


kouza008 jarファイル



[今回追加したもの]
・GameDataクラスにマップチップ関連の変数を用意
・GameDataクラス内にGraphicSetクラスを作成
・maptipNumberを元にマップを描画

今回の処理は文字にすると簡単だが、かなりややこしい事をやっている。
自分でも作っていて頭がショートしそうになった。
上手く説明できるか分からないが、出来る限り解説を入れていく。

[GameDataクラスの変更点]
PlayerPlatform pPlatformしかなかったが、一気に増える。

public class GameData {

public PlayerPlatform pPlatform=null;
//障壁データ。
public ArrayList blocks=new ArrayList();
public String[][] maptipNumber=null;
public int[] mapNumber=null; //0map ,1floor ,2roomの3つで管理する。
public int[] mapSize=null; //[0]width tip数 [1]height tip数
public BufferedImage maptipGra=null;
public GraphicSet gSet=null;


blocksというArrayListは後々使う。ついでに定義した。

maptipNumberがキモの変数。これを元にマップチップの絵を読み込む。
なぜStringで定義しているかというと、2ケタでまとめたかったから。
x 0-9 * y 0-9の81では表示できる絵が少なすぎる。
0-z * 0-z まで拡張できるようにしたので、
00-zzまで多彩なマップチップを使える。
欠点として比較がめんどくさいという手間があるが、
一度作れば使いまわせるので問題ない。

mapNumberは今の所使わない。複数マップをまたぐテストに入った時に使う。

mapSizeにはマップチップ単位の数値が格納される。
実座標サイズではないので注意。
x800 * y 608が一画面。mapSize[0]=800/32=25 mapSize[1]=608/32=19 を入れる。

maptipGraにはこの後の処理でマップチップセットの絵を読み込ませる。
この巨大なチップセットの一部を切り貼りしてマップを描画する事になる。

GraphicSetクラス gSetはこのあとすぐ使う。
maptipGraに絵を読み込ませるときにこのクラスを利用するのだ。

新しく作った変数を初期化する。

public void blocksInit() {
blocks=new ArrayList();
}

public void mapTipNumberInit() {
maptipNumber=new String[101][101];
for (int i=0;i<=100;i++) {
for (int j=0;j<=100;j++) {
maptipNumber[i][j]="00";
}
}
}

//仮データを打ち込み、マップ表示テストを行う
public void maptipKariSet() {
maptipNumber=new String[101][101];
//草原チップでうめつくす
for (int i=0;i<=100;i++) {
for (int j=0;j<=100;j++) {
maptipNumber[i][j]="01"; //[x][y]の順にチップを記憶する
}
}
//y0, x0-100を丘チップにする
//同じくx0,y 0-100を丘チップにする
for (int i=0;i<=100;i++) {
maptipNumber[i][0]="00";
maptipNumber[0][i]="00";
}

}


[PlayerPlatform 初期化 init]
public void init() {

pPlatform=new PlayerPlatform();
blocksInit(); //ブロックデータの初期化
mapTipNumberInit(); //マップチップデータの初期化
mapSize=new int[3];
mapSize[0]=25;
mapSize[1]=19;

gSet=new GraphicSet();
//マップチップのタイルセットをmaptipGraイメージに読み込む。
//町から簡単なダンジョンまで作れるので、絵は一枚でいい。
maptipGra=gSet.maptipGraSet(0);

}

ほとんど先に解説したのであまり書く事は無い。
maptipGra=gSet.maptipGraSet(0);
が新処理。その中身は次の項目。


[GraphicSetクラス]
public BufferedImage maptipGraSet(int num) {

BufferedImage gra=null;
String fileName="";
try {
if (num<=1) {
fileName="Tile1.gif";
gra=gSet(fileName);
}
}catch(Exception ex){
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "ERROR : " + ex.toString());
}
return gra;


}

キャラクターの絵を読み込む時と要領は同じ。
0を指定して読み込ませるため、自動的にTile1の絵をセットする。

今回のキモとなる処理、paintの追加部分

[ARPanel]
public void paint(Graphics g){
g.setColor(Color.black);
g.fillRect(0, 0, 800, 800);

//プレイヤーよりも奥に描画したいので、まずマップチップを描画する。
maptipPaint(g);//←これがメインの追加部分。内部処理は関数に飛ぶ。
//ポイントは"g"を引数として渡している事。これがないと描画できない。

public void maptipPaint(Graphics g) {

int mwidth=gData.mapSize[0];
int mheight=gData.mapSize[1];
for (int y=0;y<=mheight;y++) {
for (int x=0;x<=mwidth;x++) {
//左上から順にチップの位置を探し、適合した座標を抜き取る。
String tString=gData.maptipNumber[x][y];
int[] txy=maptipSearch(tString);
int zx=x*32;
int zy=y*32;
int dx=txy[0]*32;
int dy=txy[1]*32;
g.drawImage(gData.maptipGra,zx,zy,zx+32,zy+32,dx,dy,dx+32,dy+32,this);
}
}

}

maptipSearchでやることは、マップチップグラフィック群のなかから、
どの絵を取り出したらいいのかを割り出して戻すこと。
00-zzまでの二つの数値をもとにx,y座標を求めて戻してくる処理になる。


public int[] maptipSearch(String ts) {

String[] tss=new String[3];
//00-99までのチップをサーチする。00-zzまで最終的に配置できる。
//String[] sList= {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g"};
//tsを一文字ずつ分解し、10のケタをtss[0],1のケタを[1]に格納する 10なら[0]=1 [1]=0が入る。
//[0]ケタ目*32でチップ画像のx座標 [1]桁目*32がy座標に対応する。0-9,a-zの順に並んでいるとイメージする。
tss[0]=String.valueOf(ts.charAt(0));
tss[1]=String.valueOf(ts.charAt(1));

int[] keepNum=new int[3];
for (int i=0;i<=2;i++) {
keepNum[i]=999; //有り得ない数で初期化しておく
}
//10のケタ、1のケタが画像ファイルのどこに当たるかを割り出す。
//00ならx 0*32 y 0*32の丘チップ 10ならx 0*32 y 1*32の草原チップを引き出したい
//文字変数をasciiコードに変換し、intにキャスト。取得したコードの10進数から座標を割り出す。
for (int i=0;i<=1;i++) {
int num=tss[i].charAt(0); //char型にキャストしたものをintにつっこむと asciiコードの数値を取れる
if (num>=48 && num<=57) keepNum[i]=num-48; //0-9なら-48で座標が出せる
if (num>=97 && num<=122) keepNum[i]=num-87;//a-zなら-87 (a=10 b=11で扱う)
}
//上のと同じ処理だが、sListを0から探っていくので効率が悪い。
//コメントアウトして使えないようにしてあるが、こういう方法もある、という例として残す。
/*for (int i=0;i<=1;i++) {
for (int j=0;j<=sList.length-1;j++) {
//System.out.print(tss[i]+" vs "+sList[j]+" / ");
if (tss[i].equals (sList[j])) {
keepNum[i]=j;
//System.out.print(keepNum[i]+",");
j=99;
}
}
}*/
//10のケタか1のケタが初期値のまま通過してしまったら、仮ナンバー0で代用する。
if (keepNum[0]>=900 || keepNum[1]>=900) {System.out.print("mismatch");
keepNum[0]=0;
keepNum[1]=0;
}
//完成した結果を戻す。
return keepNum;

}

ソースコード自体に極力コメントをつけたので補足することはあまりない。
思いつたらつけ足す。




次はマップをスクロールさせる。

カメラの導入が必要になるので、
今回作った草原マップでスクロールのテストをする。

やること自体は今回よりはるかに簡単だが、
プレイヤーの描画とマップチップの描画に
カメラ座標の補正値を加えるので、
描画方法が少し変わる。

カメラとか言っても実際は大したことをしない。
イメージ的にはマップという画用紙の上にプレイヤーやキャラをのっけて、
画用紙ごと動かすイメージ。
見える範囲は固定されているので、
カメラを動かすというより、カメラ固定で画用紙を上下左右に動かす、
と言った方が近い表現になる。
能書きばかり垂れていても仕方ないので、実際に作って見せます。

・トップページへ戻る
inserted by FC2 system