MapEdit の出力ファイルで背景を描画します。

前田稔の超初心者のプログラム入門

プログラムの作成

  1. Rpg_04.java の名前で保存して下さい。
    //★ MapEdit の出力ファイルで背景を描画    前田 稔
    import java.awt.*;
    import javax.swing.*;
    import java.io.*;
    import java.awt.Image;
    import javax.imageio.ImageIO;
    import java.util.StringTokenizer;
    
    class Rpg_04 extends JFrame
    {   MAP     map;
    
        // Main
        public static void main(String args[])
        {   new Rpg_04();
        }
    
        // Constructor
        public Rpg_04()
        {   super("MAP File");
            map = new MAP("BgMap.txt");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(460,400);
            setVisible(true);
        }
    
        // Paint Method
        public void paint(Graphics g)
        {   super.paint(g);
            map.MapView(g);
        }
    }
    
    //★ MAP Object Class
    class MAP extends JFrame
    {   String      Imgfile;    // image file
        Image       Img;        // Image Object
        Dimension   size= new Dimension(32,32); // Sprite Size
        Dimension   num= new Dimension(1,1);    // Sprite 並び数
        int         TT[][];     // MAP Table
        Dimension   Tn= new Dimension(1,1);     // TT[H][W] Size
        int         Tnum;       // H*W
    
        //※ Work Area
        BufferedReader  br;     // Reader
        String          str;    // Input Buffer
        StringTokenizer token;  // トークン Object
    
        // Constructor
        MAP(String fname)
        {   int     i,wk;
            File    file = new File(fname);
            if (checkBeforeReadfile(file)==false)
            {   System.out.println("Input File Open Error");
                return;
            }
            try
            {   br = new BufferedReader(new FileReader(file));
                // Check File ID
                LineRead();
                if ("//Map".equals(str.substring(0,5))==false)
                {   System.out.println("Map File Error");
                    return;
                }
                // Set Image file
                LineRead();
                Imgfile= (str.substring(2,str.length()));
                // Set W,H,width,height
                LineRead();
                token = new StringTokenizer(str, " ,;\t", false);
                token.nextToken();
                Tn.width= Val();
                Tn.height= Val();
                size.width= Val();
                size.height= Val();
                //画像ロード
                File infile = new File(Imgfile);
                Img = loadImage(infile);
                num.width= Img.getWidth(null)/size.width;
                num.height= Img.getHeight(null)/size.height;
                if (num.width<1 || num.height<1)
                {   System.out.println("Image File Error" + Imgfile);
                    return;
                }
                //TT[H][W] に MapData を格納
                TT= new int[Tn.height][Tn.width];
                Tnum= Tn.height*Tn.width;
                NextRead();
                for(i=0; i<Tnum; i++)
                {   wk= Val();
                    TT[i/Tn.width][i%Tn.width]= wk;
                    if (wk==-1) break;
                }
                br.close();
            }
            catch(FileNotFoundException e)
            {   System.out.println(e);  }
            catch(IOException e)
            {   System.out.println(e);  }
        }
    
        // File Open Check
        private boolean checkBeforeReadfile(File file)
        {   if (file.exists())
            {   if (file.isFile() && file.canRead())
                {   return true;  }
            }
            return false;
        }
    
        // Read Line(次の行)
        private boolean LineRead()
        {
            try
            {   str = br.readLine();  }
            catch(IOException e)
            {   System.out.println(e);  }
            if (str == null)
            {   System.out.println("End of file");
                return false;
            }
            return true;
        }
    
        // Read Next Line(/をスキップ, Token を設定)
        private boolean NextRead()
        {
            while(LineRead())
            {   if (str.charAt(0)!='/')
                {   token = new StringTokenizer(str, " ,;\t", false);
                    return true;
                }
            }
            return false;
        }
    
        // Next Val(Buf から次の値を取得)
        private int Val()
        {   if (token.hasMoreTokens()==false)
                if (NextRead()==false)  return -1;
            return Integer.parseInt(token.nextToken());
        }
    
        // Sprite View
        public void View(Graphics g, int n, int dx, int dy)
        {   int sx, sy;
            if (n >= Tnum)
            {   System.out.println("Sprite Number Error" + n);
                return;
            }
            sx = (n%num.width) * size.width;
            sy = (n/num.width) * size.height;
            if (Img != null)
            {   g.drawImage(Img,dx,dy,dx+size.width,dy+size.height,
                            sx,sy,sx+size.width,sy+size.height,this);
            }
        }
        public void MapView(Graphics g)
        {   int x,y;
            if (Img==null)  return;
            for(y=0; y<Tn.height; y++)
            {   for(x=0; x<Tn.width; x++)
                {   View(g,TT[y][x],x*size.width+40,y*size.height+40);
                    System.out.print(" " + TT[y][x]);
                }
                System.out.println();
            }
        }
    
        // Load Image
        public static Image loadImage(File f)
        {   try
            {   Image img = ImageIO.read(f);
                return img;
            }
            catch (IOException e)
            {   throw new RuntimeException(e);  }
        }
    }
    
  2. プロジェクトのフォルダーに MapEditor で出力した TEXT 形式のファイル(BgMap.txt)と MapChip の画像ファイル(chip.gif)を格納して下さい。
    "BgMap.txt" は Mapchip を並べて背景画像を表示 に掲載しています。
    "chip.gif" は「このページ先頭」の画像です。
    Sprite(Mapchip)を組み合わせた背景画像が描画されたら完成です。

Main プログラムの説明

  1. 前回までの説明は Mapchip を並べて背景画像を表示 を参照して下さい。
    マップチップを組み合わせた背景画像は、一般的には MapEditor などと呼ばれる専用のツールで作成します。
    私が開発した MapEditor で出力した TEXT 形式のファイル "BgMap.txt" を読んで背景を描画してみましょう。
    MapEditor は「超初心者のプログラム入門/Game Program & 各種 Tool/Map Editor」から提供しています。
  2. BgMap.txt には、画像ファイルの名前やセルのサイズやインデックス情報など背景を描画するのに必要な情報が含まれています。
    Main の Constructor で "BgMap.txt" を指定して MAP Class をインスタンス化します。
        // Constructor
        public Rpg_04()
        {   super("MAP File");
            map = new MAP("BgMap.txt");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(460,400);
            setVisible(true);
        }
        
  3. 後は paint() メソッドから map.MapView(g) で背景を描画するだけです。
        // Paint Method
        public void paint(Graphics g)
        {   super.paint(g);
            map.MapView(g);
        }
        

MAP Object Class の説明

  1. Map Editor で出力された TEXT 形式のファイル(BgMap.txt) を入力して背景を描画します。
    Java には String からトークン(文字列)を切り出す StringTokenizer Object Class が用意されています。
    これを利用して TEXT 形式のファイルから Mapchip の並び情報を取得して背景画像を描画してみましょう。
    java.util.StringTokenizer; を import して下さい。
    Imgfile は MapChip が格納された画像ファイルの名前で、Img が画像の領域です。
    size は MapChip 一枚分の幅と高さです。
    num は縦方向と横方向に並んでいる MapChip(Sprite)の枚数です。
    TT[][] は MapChip の並び情報(Index)を格納する二次元配列で、Tn がその大きさです。
    Tnum には二次元配列の要素の総数を格納します。
    str は BgMap.txt の一行分の入力バッファで token がトークンを切り出す Object です。
        class MAP extends JFrame
        {   String      Imgfile;    // image file
            Image       Img;        // Image Object
            Dimension   size= new Dimension(32,32); // Sprite Size
            Dimension   num= new Dimension(1,1);    // Sprite 並び数
            int         TT[][];     // MAP Table
            Dimension   Tn= new Dimension(1,1);     // TT[H][W] Size
            int         Tnum;       // H*W
    
            //※ Work Area
            BufferedReader  br;     // Reader
            String          str;    // Input Buffer
            StringTokenizer token;  // トークン Object
        
  2. MAP Class の Constructor で Map Editor で出力した TEXT 形式のファイル名を受け取ります。
    ファイルが入力可能かチェックします。
    詳細は 入力ファイル→コンソール(行単位) を参照して下さい。
        // Constructor
        MAP(String fname)
        {   int     i,wk;
            File    file = new File(fname);
            if (checkBeforeReadfile(file)==false)
            {   System.out.println("Input File Open Error");
                return;
            }
        
    BgMap.txt の最初の部分です。
    //Map  Ver 3.2  前田 稔
    //chip.gif
    //  24,   20,   16,   16,  Map の幅と高さ, Mapchip の幅と高さ
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
    
  3. LineRead() で先頭行を入力してID("//Map")をチェックします。
    次の行を入力して画像ファイルの名前を取得します。
            try
            {   br = new BufferedReader(new FileReader(file));
                // Check File ID
                LineRead();
                if ("//Map".equals(str.substring(0,5))==false)
                {   System.out.println("Map File Error");
                    return;
                }
                // Set Image file
                LineRead();
                Imgfile= (str.substring(2,str.length()));
        
  4. 次の行を入力してマップのサイズ情報を取得します。
    token = new StringTokenizer(str, " ,;\t", false); でトークンを切り出します。
    " ,;\t" がセパレータの設定です。
    token.nextToken(); で先頭の "// " を読み捨てます。
    Tn.width= Val(); と Tn.height= Val(); で TT[H][W] のサイズを取得します。
    次に size.width= Val(); と size.height= Val(); で MapChip の幅と高さを取得します。
                // Set W,H,width,height
                LineRead();
                token = new StringTokenizer(str, " ,;\t", false);
                token.nextToken();
                Tn.width= Val();
                Tn.height= Val();
                size.width= Val();
                size.height= Val();
        
  5. 画像ファイルをロードして num.width と num.height を計算します。
                //画像ロード
                File infile = new File(Imgfile);
                Img = loadImage(infile);
                num.width= Img.getWidth(null)/size.width;
                num.height= Img.getHeight(null)/size.height;
                if (num.width<1 || num.height<1)
                {   System.out.println("Image File Error" + Imgfile);
                    return;
                }
        
  6. 二次元配列 TT[H][W] を割り当てて Map Chip の並び情報を格納します。
    詳細は Text File を二次元配列(int)に格納 を参照して下さい。
                //TT[H][W] に MapData を格納
                TT= new int[Tn.height][Tn.width];
                Tnum= Tn.height*Tn.width;
                NextRead();
                for(i=0; i<Tnum; i++)
                {   wk= Val();
                    TT[i/Tn.width][i%Tn.width]= wk;
                    if (wk==-1) break;
                }
                br.close();
        
  7. TEXT ファイルから次の行を入力するメソッドです。
        // Read Line(次の行)
        private boolean LineRead()
        {
            try
            {   str = br.readLine();  }
            catch(IOException e)
            {   System.out.println(e);  }
            if (str == null)
            {   System.out.println("End of file");
                return false;
            }
            return true;
        }
        
  8. 先頭カラムが '/' の行を読み飛ばして、有効な行を入力するメソッドです。
    token = new StringTokenizer(str, " ,;\t", false); でトークンを設定します。
        // Read Next Line(/をスキップ, Token を設定)
        private boolean NextRead()
        {
            while(LineRead())
            {   if (str.charAt(0)!='/')
                {   token = new StringTokenizer(str, " ,;\t", false);
                    return true;
                }
            }
            return false;
        }
        
  9. トークンを切り出して、次の int値を取得するメソッドです。
    token.hasMoreTokens() でトークンが残っているかを調べます。
        // Next Val(Buf から次の値を取得)
        private int Val()
        {   if (token.hasMoreTokens()==false)
                if (NextRead()==false)  return -1;
            return Integer.parseInt(token.nextToken());
        }
        
  10. 一個のセルを表示するメソッドと、二次元配列 TT[H][W] に従って背景を描画するメソッドです。
        // Sprite View
        public void View(Graphics g, int n, int dx, int dy)
        {   int sx, sy;
            if (n >= Tnum)
            {   System.out.println("Sprite Number Error" + n);
                return;
            }
            sx = (n%num.width) * size.width;
            sy = (n/num.width) * size.height;
            if (Img != null)
            {   g.drawImage(Img,dx,dy,dx+size.width,dy+size.height,
                            sx,sy,sx+size.width,sy+size.height,this);
            }
        }
        public void MapView(Graphics g)
        {   int x,y;
            if (Img==null)  return;
            for(y=0; y<Tn.height; y++)
            {   for(x=0; x<Tn.width; x++)
                {   View(g,TT[y][x],x*size.width+40,y*size.height+40);
                    System.out.print(" " + TT[y][x]);
                }
                System.out.println();
            }
        }
        

超初心者のプログラム入門(Java2)