人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

キャラクターイベント

簡単イベントを導入します。キャラクターイベントです。今までは王様や兵士などの追加はMainPanelに直接書き込んでいました。今回は、キャラクターを外部のイベントファイルから読み込んで簡単に追加できるようにしてみます。

rpg14.jar

イベントファイルの形式

イベントファイルは下のようなファイルです。

#イベントファイル
CHARA,6,6,1,3,0,よくぞきた ゆうしゃよ。
CHARA,6,9,2,1,1,ぶきは そうびしないと いみがないぞ。
CHARA,8,9,2,0,1,おうさまに しつれいのないようにな。

各行が1つのイベントを表しています。といっても今はキャラクターの追加しかできないので1つの行が1人のキャラクターと考えてください。各行は、左からイベントの種類、X座標、Y座標、キャラクター番号、向き、移動タイプ、はなしたときのメッセージを表しています。それぞれはカンマで区切られています。また、#で始まる行はコメントでイベントをロードするときには無視されます。

2行目を見てください。これは王様です。CHARAはキャラクターイベントであることを示してます。後でいろいろなイベントを追加する(TREASURE、DOOR、MOVEなど)ときにどのイベントか区別できるようにつけてます。次の6,6は王様の初期位置です。マップの(6,6)の位置に置かれます。もちろんマス単位です。次の1はキャラクター番号です。前回解説したchara.gifの番号に対応しています。王様は1番でした。次の3はキャラクターの向きを表しています。これはCommonクラスで定義されている定数に対応しています。

    // 方向を表す定数
    public static final int LEFT = 0;
    public static final int RIGHT = 1;
    public static final int UP = 2;
    public static final int DOWN = 3;

3は下向きです。スタートすると王様は下を向いてますね。次の0は移動タイプです。0だと静止して、1だとランダム移動します。ランダム移動は王様登場(2005/10/22)で解説しました。

最後に「よくぞきた ゆうしゃよ。」は、勇者がはなしたときに表示されるメッセージです。王様の定番台詞ですね。まだメッセージを表示する処理は追加してないですが一応用意しました。これだけ設定すればさまざまなキャラクターが簡単に追加できます。

イベントファイルのロード

次に上で書いたイベントファイルをロードする処理を見てみます。イベントはマップごとにロードされるのでMapクラスに処理を加えます。 loadEvent()を見てください。

    /**
     * イベントをロードする
     * @param filename イベントファイル
     */
    private void loadEvent(String filename) {
        try {
            BufferedReader br = new BufferedReader(
                new InputStreamReader(
                    getClass().getResourceAsStream(filename)));
            String line;
            while ((line = br.readLine()) != null) {
                // 空行は読み飛ばす
                if (line.equals("")) continue;
                // コメント行は読み飛ばす
                if (line.startsWith("#")) continue;
                StringTokenizer st = new StringTokenizer(line, ",");
                // イベント情報を取得する
                // イベントタイプを取得してイベントごとに処理する
                String eventType = st.nextToken();
                if (eventType.equals("CHARA")) {  // キャラクターイベント
                    makeCharacter(st);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

コメントに書いてあるとおりです。イベントファイルを1行ずつ読み込んで順番に処理しています。空行や#で始まるコメントはcontinueで無視しています。もしそれ以外だったらカンマで分割するStringTokenizerを使ってイベントの属性を順に読み込みます。ここでは、イベントタイプが CHARAだった場合だけ処理しています。makeCharacter()はイベントに書かれた情報を使ってキャラクターを作る処理です。すぐ後で解説します。

キャラクターの作成

最後にキャラクターの作成を見てみます。Charaクラスのコンストラクタを見てください。

    public Chara(int x, int y, int charaNo, int direction, int moveType, Map map);

今回からイベントファイルからキャラクターが作れるようにしたので、direction(向き)やmoveType(移動タイプ)が追加されています。キャラクター作成時に自由に決められるようにしました。makeCharacter()は次のようになってます。

    /**
     * キャラクターイベントを作成
     */
    private void makeCharacter(StringTokenizer st) {
        // イベントの座標
        int x = Integer.parseInt(st.nextToken());
        int y = Integer.parseInt(st.nextToken());
        // キャラクタ番号
        int charaNo = Integer.parseInt(st.nextToken());
        // 向き
        int dir = Integer.parseInt(st.nextToken());
        // 移動タイプ
        int moveType = Integer.parseInt(st.nextToken());
        // メッセージ
        String message = st.nextToken();
        // キャラクターを作成
        Chara c = new Chara(x, y, charaNo, dir, moveType, this);
        // メッセージを登録
        c.setMessage(message);
        // キャラクターベクトルに登録
        charas.add(c);
    }

まあコメントの通りです。イベントファイルから順に属性を読み取ってます。StringTokenizerで読み取ると全部String型になってしまうので数値の場合はInteger.parseInt()でint型に変換します。イベントの座標からメッセージまですべて読み取ったら、キャラクターを作成してメッセージを登録します。最後にマップのcharasベクトルにキャラクターを登録すれば完成です。イベントファイルからキャラクターが作成されるようにしたので、前回までMainPanelに書いていたキャラクター作成処理は勇者を除いてすべて削除してあります。